1 /*
2 Copyright (C) 2009-2021 Parallel Realities
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (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.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
18 */
19
20 #include "../headers.h"
21
22 #include "../audio/audio.h"
23 #include "../audio/music.h"
24 #include "../game.h"
25 #include "../graphics/graphics.h"
26 #include "../hud.h"
27 #include "../init.h"
28 #include "../system/error.h"
29 #include "../system/load_save.h"
30 #include "about_menu.h"
31 #include "io_menu.h"
32 #include "medals_menu.h"
33 #include "ok_menu.h"
34 #include "options_menu.h"
35 #include "stats_menu.h"
36 #include "widget.h"
37 #include "yes_no_menu.h"
38
39 extern Input input, menuInput;
40 extern Game game;
41
42 static Menu menu;
43
44 static void loadMenuLayout(void);
45 static void showOptionsMenu(void);
46 static void doMenu(void);
47 static void showIOMenu(void);
48 static void doNewGame(void);
49 static void doTutorial(void);
50 static void doQuit(void);
51 static void showMainMenu(void);
52 static void showAboutMenu(void);
53 static void showStatsMenu(void);
54 static void showMedalsMenu(void);
55 static void quitToTitle(void);
56 static void continueGame(void);
57 static void restartCheckpoint(void);
58
drawMainMenu()59 void drawMainMenu()
60 {
61 int i;
62
63 drawImage(menu.background, menu.x, menu.y, FALSE, 196);
64
65 for (i=0;i<menu.widgetCount;i++)
66 {
67 drawWidget(menu.widgets[i], &menu, menu.index == i);
68 }
69 }
70
doMenu()71 static void doMenu()
72 {
73 Widget *w;
74 int left, right, up, down, attack, xAxisMoved, yAxisMoved;
75
76 left = FALSE;
77 right = FALSE;
78 up = FALSE;
79 down = FALSE;
80 attack = FALSE;
81
82 if (menuInput.left == TRUE)
83 {
84 left = TRUE;
85 }
86
87 else if (menuInput.right == TRUE)
88 {
89 right = TRUE;
90 }
91
92 else if (menuInput.up == TRUE)
93 {
94 up = TRUE;
95 }
96
97 else if (menuInput.down == TRUE)
98 {
99 down = TRUE;
100 }
101
102 else if (menuInput.attack == TRUE)
103 {
104 attack = TRUE;
105 }
106
107 else if (input.left == TRUE)
108 {
109 left = TRUE;
110 }
111
112 else if (input.right == TRUE)
113 {
114 right = TRUE;
115 }
116
117 else if (input.up == TRUE)
118 {
119 up = TRUE;
120 }
121
122 else if (input.down == TRUE)
123 {
124 down = TRUE;
125 }
126
127 else if (input.attack == TRUE)
128 {
129 attack = TRUE;
130 }
131
132 if (down == TRUE)
133 {
134 do
135 {
136 menu.index++;
137
138 if (menu.index >= menu.widgetCount)
139 {
140 menu.index = 0;
141 }
142 }
143
144 while (menu.widgets[menu.index]->disabled == TRUE || menu.widgets[menu.index]->hidden == TRUE);
145
146 playSound("sound/common/click");
147 }
148
149 else if (up == TRUE)
150 {
151 do
152 {
153 menu.index--;
154
155 if (menu.index < 0)
156 {
157 menu.index = menu.widgetCount - 1;
158 }
159 }
160
161 while (menu.widgets[menu.index]->disabled == TRUE || menu.widgets[menu.index]->hidden == TRUE);
162
163 playSound("sound/common/click");
164 }
165
166 else if (attack == TRUE)
167 {
168 w = menu.widgets[menu.index];
169
170 if (w->clickAction != NULL)
171 {
172 playSound("sound/common/click");
173
174 w->clickAction();
175 }
176 }
177
178 else if (left == TRUE)
179 {
180 w = menu.widgets[menu.index];
181
182 if (w->rightAction != NULL)
183 {
184 playSound("sound/common/click");
185
186 w->rightAction();
187 }
188 }
189
190 else if (right == TRUE)
191 {
192 w = menu.widgets[menu.index];
193
194 if (w->leftAction != NULL)
195 {
196 playSound("sound/common/click");
197
198 w->leftAction();
199 }
200 }
201
202 xAxisMoved = input.xAxisMoved;
203 yAxisMoved = input.yAxisMoved;
204
205 memset(&menuInput, 0, sizeof(Input));
206 memset(&input, 0, sizeof(Input));
207
208 input.xAxisMoved = xAxisMoved;
209 input.yAxisMoved = yAxisMoved;
210 }
211
loadMenuLayout()212 static void loadMenuLayout()
213 {
214 int i, x, y, w, maxWidth;
215
216 y = x = -1;
217
218 menu.widgetCount = 10;
219
220 menu.widgets = malloc(sizeof(Widget *) * menu.widgetCount);
221
222 if (menu.widgets == NULL)
223 {
224 showErrorAndExit("Ran out of memory when creating Main Menu");
225 }
226
227 menu.widgets[0] = createWidget(_("New Game"), NULL, NULL, NULL, &doNewGame, x, y, TRUE, 255, 255, 255);
228
229 menu.widgets[1] = createWidget(_("Continue"), NULL, NULL, NULL, &continueGame, x, y, TRUE, 255, 255, 255);
230
231 menu.widgets[1]->disabled = game.canContinue == TRUE ? FALSE : TRUE;
232
233 menu.widgets[2] = createWidget(_("Restart Checkpoint"), NULL, NULL, NULL, &restartCheckpoint, x, y, TRUE, 255, 255, 255);
234
235 menu.widgets[2]->disabled = game.canContinue == TRUE ? FALSE : TRUE;
236
237 menu.widgets[3] = createWidget(_("Tutorial"), NULL, NULL, NULL, &doTutorial, x, y, TRUE, 255, 255, 255);
238
239 menu.widgets[4] = createWidget(_("Load Game"), NULL, NULL, NULL, &showIOMenu, x, y, TRUE, 255, 255, 255);
240
241 menu.widgets[5] = createWidget(_("Options"), NULL, NULL, NULL, &showOptionsMenu, x, y, TRUE, 255, 255, 255);
242
243 menu.widgets[6] = createWidget(_("Statistics"), NULL, NULL, NULL, &showStatsMenu, x, y, TRUE, 255, 255, 255);
244
245 menu.widgets[7] = createWidget(_("Medals"), NULL, NULL, NULL, &showMedalsMenu, x, y, TRUE, 255, 255, 255);
246
247 menu.widgets[8] = createWidget(_("About"), NULL, NULL, NULL, &showAboutMenu, x, y, TRUE, 255, 255, 255);
248
249 menu.widgets[9] = createWidget(_("Quit"), NULL, NULL, NULL, &doQuit, x, y, TRUE, 255, 255, 255);
250
251 y = BUTTON_PADDING + BORDER_PADDING;
252
253 w = 0;
254
255 maxWidth = 0;
256
257 for (i=0;i<menu.widgetCount;i++)
258 {
259 if (menu.widgets[i]->label != NULL && menu.widgets[i]->normalState->w > maxWidth)
260 {
261 maxWidth = menu.widgets[i]->normalState->w;
262 }
263 }
264
265 for (i=0;i<menu.widgetCount;i++)
266 {
267 menu.widgets[i]->y = y;
268
269 if (menu.widgets[i]->x != -1)
270 {
271 menu.widgets[i]->x = BUTTON_PADDING + BORDER_PADDING;
272 }
273
274 if (menu.widgets[i]->label != NULL)
275 {
276 menu.widgets[i]->label->y = y;
277
278 menu.widgets[i]->label->x = menu.widgets[i]->x + maxWidth + 10;
279
280 if (menu.widgets[i]->label->x + menu.widgets[i]->label->text->w > w)
281 {
282 w = menu.widgets[i]->label->x + menu.widgets[i]->label->text->w;
283 }
284 }
285
286 else
287 {
288 if (menu.widgets[i]->x + menu.widgets[i]->selectedState->w > w)
289 {
290 w = menu.widgets[i]->x + menu.widgets[i]->selectedState->w;
291 }
292 }
293
294 if (i != 1)
295 {
296 y += menu.widgets[i]->selectedState->h + BUTTON_PADDING;
297 }
298 }
299
300 menu.w = w + BUTTON_PADDING;
301 menu.h = y - BORDER_PADDING;
302
303 menu.background = addBorder(createSurface(menu.w, menu.h, FALSE), 255, 255, 255, 0, 0, 0);
304
305 menu.x = (SCREEN_WIDTH - menu.background->w) / 2;
306 menu.y = (SCREEN_HEIGHT - menu.background->h) / 2;
307 }
308
freeMainMenu()309 void freeMainMenu()
310 {
311 int i;
312
313 if (menu.widgets != NULL)
314 {
315 for (i=0;i<menu.widgetCount;i++)
316 {
317 freeWidget(menu.widgets[i]);
318 }
319
320 free(menu.widgets);
321
322 menu.widgets = NULL;
323 }
324
325 if (menu.background != NULL)
326 {
327 destroyTexture(menu.background);
328
329 menu.background = NULL;
330 }
331 }
332
initMainMenu()333 Menu *initMainMenu()
334 {
335 menu.action = &doMenu;
336
337 if (menu.widgets == NULL)
338 {
339 loadMenuLayout();
340 }
341
342 menu.widgets[1]->disabled = game.canContinue == TRUE ? FALSE : TRUE;
343
344 menu.widgets[1]->hidden = game.previousStatus == IN_TITLE ? FALSE : TRUE;
345
346 menu.widgets[2]->disabled = game.canContinue == TRUE ? FALSE : TRUE;
347
348 menu.widgets[2]->hidden = game.previousStatus == IN_GAME ? FALSE : TRUE;
349
350 menu.widgets[6]->disabled = game.previousStatus == IN_GAME ? FALSE : TRUE;
351
352 menu.returnAction = NULL;
353
354 return &menu;
355 }
356
showOptionsMenu()357 static void showOptionsMenu()
358 {
359 game.menu = initOptionsMenu();
360
361 game.drawMenu = &drawOptionsMenu;
362 }
363
showAboutMenu()364 static void showAboutMenu()
365 {
366 game.menu = initAboutMenu();
367
368 game.drawMenu = &drawAboutMenu;
369 }
370
showStatsMenu()371 static void showStatsMenu()
372 {
373 game.menu = initStatsMenu();
374
375 game.drawMenu = &drawStatsMenu;
376 }
377
showIOMenu()378 static void showIOMenu()
379 {
380 game.menu = initIOMenu(FALSE);
381
382 game.drawMenu = &drawIOMenu;
383 }
384
showMedalsMenu()385 static void showMedalsMenu()
386 {
387 game.menu = initMedalsMenu();
388
389 game.drawMenu = &drawMedalsMenu;
390 }
391
doNewGame()392 static void doNewGame()
393 {
394 if (game.previousStatus == IN_TITLE)
395 {
396 newGame();
397 }
398
399 else
400 {
401 game.menu = initYesNoMenu(_("Start a new game?"), &newGame, &showMainMenu);
402
403 game.drawMenu = &drawYesNoMenu;
404 }
405 }
406
doTutorial()407 static void doTutorial()
408 {
409 if (game.previousStatus == IN_TITLE)
410 {
411 tutorial();
412 }
413
414 else
415 {
416 game.menu = initYesNoMenu(_("Play the tutorial?"), &tutorial, &showMainMenu);
417
418 game.drawMenu = &drawYesNoMenu;
419 }
420 }
421
doQuit()422 static void doQuit()
423 {
424 if (game.previousStatus == IN_TITLE)
425 {
426 quitGame();
427 }
428
429 else
430 {
431 game.menu = initYesNoMenu(_("Exit the game?"), &quitToTitle, &showMainMenu);
432
433 game.drawMenu = &drawYesNoMenu;
434 }
435 }
436
continueGame()437 static void continueGame()
438 {
439 if (loadGame(getMostRecentSave()) == TRUE)
440 {
441 menu.index = 0;
442
443 menu.returnAction = NULL;
444
445 freeMessageQueue();
446
447 setInfoBoxMessage(60, 255, 255, 255, _("Game Loaded"));
448
449 game.paused = FALSE;
450 }
451
452 else
453 {
454 game.menu = initOKMenu(_("Failed to load game"), &showIOMenu);
455
456 game.drawMenu = &drawOKMenu;
457 }
458 }
459
restartCheckpoint()460 static void restartCheckpoint()
461 {
462 getContinuePoint();
463 }
464
quitToTitle()465 static void quitToTitle()
466 {
467 menu.index = 0;
468
469 pauseGame();
470
471 setTransition(TRANSITION_OUT, &titleScreen);
472
473 fadeOutMusic(500);
474 }
475
showMainMenu()476 static void showMainMenu()
477 {
478 game.menu = initMainMenu();
479
480 game.drawMenu = &drawMainMenu;
481 }
482