1 //Copyright Paul Reiche, Fred Ford. 1992-2002
2
3 /*
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 #include "../colors.h"
20 #include "../controls.h"
21 #include "../gamestr.h"
22 #include "../shipcont.h"
23 #include "../setup.h"
24 #include "../sounds.h"
25 #include "../util.h"
26 #include "../sis.h"
27 // for ClearSISRect(), DrawStatusMessage()
28 #include "planets.h"
29 #include "libs/graphics/drawable.h"
30 // for GetFrameBounds()
31
32
33 #define ELEMENT_ORG_Y 35
34 #define FREE_ORG_Y (ELEMENT_ORG_Y + (NUM_ELEMENT_CATEGORIES \
35 * ELEMENT_SPACING_Y))
36 #define BIO_ORG_Y 119
37 #define ELEMENT_SPACING_Y 9
38
39 #define ELEMENT_COL_0 7
40 #define ELEMENT_COL_1 32
41 #define ELEMENT_COL_2 58
42
43 #define ELEMENT_SEL_ORG_X (ELEMENT_COL_0 + 7 + 5)
44 #define ELEMENT_SEL_WIDTH (ELEMENT_COL_2 - ELEMENT_SEL_ORG_X + 1)
45
46 #define TEXT_BASELINE 6
47
48
49 void
ShowRemainingCapacity(void)50 ShowRemainingCapacity (void)
51 {
52 RECT r;
53 TEXT t;
54 CONTEXT OldContext;
55 UNICODE buf[40];
56
57 OldContext = SetContext (StatusContext);
58 SetContextFont (TinyFont);
59
60 r.corner.x = 40;
61 r.corner.y = FREE_ORG_Y;
62
63 snprintf (buf, sizeof buf, "%u",
64 GetStorageBayCapacity () - GLOBAL_SIS (TotalElementMass));
65 t.baseline.x = ELEMENT_COL_2 + 1;
66 t.baseline.y = r.corner.y + TEXT_BASELINE;
67 t.align = ALIGN_RIGHT;
68 t.pStr = buf;
69 t.CharCount = (COUNT)~0;
70
71 r.extent.width = t.baseline.x - r.corner.x + 1;
72 r.extent.height = ELEMENT_SPACING_Y - 2;
73
74 BatchGraphics ();
75 // erase previous free amount
76 SetContextForeGroundColor (CARGO_BACK_COLOR);
77 DrawFilledRectangle (&r);
78 // print the new free amount
79 SetContextForeGroundColor (CARGO_WORTH_COLOR);
80 font_DrawText (&t);
81 UnbatchGraphics ();
82
83 SetContext (OldContext);
84 }
85
86 static void
DrawElementAmount(COUNT element,bool selected)87 DrawElementAmount (COUNT element, bool selected)
88 {
89 RECT r;
90 TEXT t;
91 UNICODE buf[40];
92
93 r.corner.x = ELEMENT_SEL_ORG_X;
94 r.extent.width = ELEMENT_SEL_WIDTH;
95 r.extent.height = ELEMENT_SPACING_Y - 2;
96
97 if (element == NUM_ELEMENT_CATEGORIES)
98 r.corner.y = BIO_ORG_Y;
99 else
100 r.corner.y = ELEMENT_ORG_Y + (element * ELEMENT_SPACING_Y);
101
102 // draw line background
103 SetContextForeGroundColor (selected ?
104 CARGO_SELECTED_BACK_COLOR : CARGO_BACK_COLOR);
105 DrawFilledRectangle (&r);
106
107 t.align = ALIGN_RIGHT;
108 t.pStr = buf;
109 t.baseline.y = r.corner.y + TEXT_BASELINE;
110
111 if (element == NUM_ELEMENT_CATEGORIES)
112 { // Bio
113 snprintf (buf, sizeof buf, "%u", GLOBAL_SIS (TotalBioMass));
114 }
115 else
116 { // Element
117 // print element's worth
118 SetContextForeGroundColor (selected ?
119 CARGO_SELECTED_WORTH_COLOR : CARGO_WORTH_COLOR);
120 t.baseline.x = ELEMENT_COL_1;
121 snprintf (buf, sizeof buf, "%u", GLOBAL (ElementWorth[element]));
122 t.CharCount = (COUNT)~0;
123 font_DrawText (&t);
124
125 snprintf (buf, sizeof buf, "%u", GLOBAL_SIS (ElementAmounts[element]));
126 }
127
128 // print the element/bio amount
129 SetContextForeGroundColor (selected ?
130 CARGO_SELECTED_AMOUNT_COLOR : CARGO_AMOUNT_COLOR);
131 t.baseline.x = ELEMENT_COL_2;
132 t.CharCount = (COUNT)~0;
133 font_DrawText (&t);
134 }
135
136 static void
DrawCargoDisplay(void)137 DrawCargoDisplay (void)
138 {
139 STAMP s;
140 TEXT t;
141 RECT r;
142 COORD cy;
143 COUNT i;
144
145 r.corner.x = 2;
146 r.extent.width = FIELD_WIDTH + 1;
147 r.corner.y = 20;
148 // XXX: Shouldn't the height be 1 less? This draws the bottom border
149 // 1 pixel too low. Or if not, why do we need another box anyway?
150 r.extent.height = 129 - r.corner.y;
151 DrawStarConBox (&r, 1,
152 SHADOWBOX_MEDIUM_COLOR, SHADOWBOX_DARK_COLOR,
153 TRUE, CARGO_BACK_COLOR);
154
155 // draw the "CARGO" title
156 SetContextFont (StarConFont);
157 t.baseline.x = (STATUS_WIDTH >> 1) - 1;
158 t.baseline.y = 27;
159 t.align = ALIGN_CENTER;
160 t.pStr = GAME_STRING (CARGO_STRING_BASE);
161 t.CharCount = (COUNT)~0;
162 SetContextForeGroundColor (CARGO_SELECTED_AMOUNT_COLOR);
163 font_DrawText (&t);
164
165 SetContextFont (TinyFont);
166
167 s.frame = SetAbsFrameIndex (MiscDataFrame,
168 (NUM_SCANDOT_TRANSITIONS * 2) + 3);
169 r.corner.x = ELEMENT_COL_0;
170 r.extent = GetFrameBounds (s.frame);
171 s.origin.x = r.corner.x + (r.extent.width >> 1);
172
173 cy = ELEMENT_ORG_Y;
174
175 // print element column headings
176 t.align = ALIGN_RIGHT;
177 t.baseline.y = cy - 1;
178 t.CharCount = (COUNT)~0;
179
180 SetContextForeGroundColor (CARGO_WORTH_COLOR);
181 t.baseline.x = ELEMENT_COL_1;
182 t.pStr = "$";
183 font_DrawText (&t);
184
185 t.baseline.x = ELEMENT_COL_2;
186 t.pStr = "#";
187 font_DrawText (&t);
188
189 // draw element icons and print amounts
190 for (i = 0; i < NUM_ELEMENT_CATEGORIES; ++i, cy += ELEMENT_SPACING_Y)
191 {
192 // erase background under an element icon
193 SetContextForeGroundColor (BLACK_COLOR);
194 r.corner.y = cy;
195 DrawFilledRectangle (&r);
196
197 // draw an element icon
198 s.origin.y = r.corner.y + (r.extent.height >> 1);
199 DrawStamp (&s);
200 s.frame = SetRelFrameIndex (s.frame, 5);
201
202 DrawElementAmount (i, false);
203 }
204
205 // erase background under the Bio icon
206 SetContextForeGroundColor (BLACK_COLOR);
207 r.corner.y = BIO_ORG_Y;
208 DrawFilledRectangle (&r);
209
210 // draw the Bio icon
211 s.origin.y = r.corner.y + (r.extent.height >> 1);
212 s.frame = SetAbsFrameIndex (s.frame, 68);
213 DrawStamp (&s);
214
215 // print the Bio amount
216 DrawElementAmount (NUM_ELEMENT_CATEGORIES, false);
217
218 // draw the line over the Bio amount
219 r.corner.x = 4;
220 r.corner.y = BIO_ORG_Y - 2;
221 r.extent.width = FIELD_WIDTH - 3;
222 r.extent.height = 1;
223 SetContextForeGroundColor (CARGO_SELECTED_BACK_COLOR);
224 DrawFilledRectangle (&r);
225
226 // print "Free"
227 t.baseline.x = 5;
228 t.baseline.y = FREE_ORG_Y + TEXT_BASELINE;
229 t.align = ALIGN_LEFT;
230 t.pStr = GAME_STRING (CARGO_STRING_BASE + 1);
231 t.CharCount = (COUNT)~0;
232 font_DrawText (&t);
233
234 ShowRemainingCapacity ();
235 }
236
237 void
DrawCargoStrings(BYTE OldElement,BYTE NewElement)238 DrawCargoStrings (BYTE OldElement, BYTE NewElement)
239 {
240 CONTEXT OldContext;
241
242 OldContext = SetContext (StatusContext);
243 SetContextFont (TinyFont);
244
245 BatchGraphics ();
246
247 if (OldElement > NUM_ELEMENT_CATEGORIES)
248 { // Asked for the initial display
249 DrawCargoDisplay ();
250
251 // do not draw unselected again this time
252 OldElement = NewElement;
253 }
254
255 if (OldElement != NewElement)
256 { // unselect the previous element
257 DrawElementAmount (OldElement, false);
258 }
259
260 if (NewElement != (BYTE)~0)
261 { // select the new element
262 DrawElementAmount (NewElement, true);
263 }
264
265 UnbatchGraphics ();
266 SetContext (OldContext);
267 }
268
269 static void
DrawElementDescription(COUNT element)270 DrawElementDescription (COUNT element)
271 {
272 DrawStatusMessage (GAME_STRING (element + (CARGO_STRING_BASE + 2)));
273 }
274
275 static BOOLEAN
DoDiscardCargo(MENU_STATE * pMS)276 DoDiscardCargo (MENU_STATE *pMS)
277 {
278 BYTE NewState;
279 BOOLEAN select, cancel, back, forward;
280
281 select = PulsedInputState.menu[KEY_MENU_SELECT];
282 cancel = PulsedInputState.menu[KEY_MENU_CANCEL];
283 back = PulsedInputState.menu[KEY_MENU_UP] || PulsedInputState.menu[KEY_MENU_LEFT];
284 forward = PulsedInputState.menu[KEY_MENU_DOWN] || PulsedInputState.menu[KEY_MENU_RIGHT];
285
286 if (GLOBAL (CurrentActivity) & CHECK_ABORT)
287 return FALSE;
288
289 if (cancel)
290 {
291 return FALSE;
292 }
293 else if (select)
294 {
295 if (GLOBAL_SIS (ElementAmounts[pMS->CurState]))
296 {
297 --GLOBAL_SIS (ElementAmounts[pMS->CurState]);
298 DrawCargoStrings (pMS->CurState, pMS->CurState);
299
300 --GLOBAL_SIS (TotalElementMass);
301 ShowRemainingCapacity ();
302 }
303 else
304 { // no element left in cargo hold
305 PlayMenuSound (MENU_SOUND_FAILURE);
306 }
307 }
308 else
309 {
310 NewState = pMS->CurState;
311 if (back)
312 {
313 if (NewState == 0)
314 NewState += NUM_ELEMENT_CATEGORIES;
315 --NewState;
316 }
317 else if (forward)
318 {
319 ++NewState;
320 if (NewState == NUM_ELEMENT_CATEGORIES)
321 NewState = 0;
322 }
323
324 if (NewState != pMS->CurState)
325 {
326 DrawCargoStrings (pMS->CurState, NewState);
327 DrawElementDescription (NewState);
328 pMS->CurState = NewState;
329 }
330 }
331
332 SleepThread (ONE_SECOND / 30);
333
334 return (TRUE);
335 }
336
337 void
CargoMenu(void)338 CargoMenu (void)
339 {
340 MENU_STATE MenuState;
341
342 memset (&MenuState, 0, sizeof MenuState);
343
344 // draw the initial cargo display
345 DrawCargoStrings ((BYTE)~0, MenuState.CurState);
346 DrawElementDescription (MenuState.CurState);
347
348 SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT);
349
350 MenuState.InputFunc = DoDiscardCargo;
351 DoInput (&MenuState, TRUE);
352
353 // erase the cargo display
354 ClearSISRect (DRAW_SIS_DISPLAY);
355 }
356
357