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 "../graphics/graphics.h"
24 #include "../init.h"
25 #include "../system/error.h"
26 #include "cheat_menu.h"
27 #include "control_menu.h"
28 #include "label.h"
29 #include "main_menu.h"
30 #include "ok_menu.h"
31 #include "sound_menu.h"
32 #include "widget.h"
33
34 extern Input input, menuInput;
35 extern Game game;
36
37 static Menu menu;
38 static char lastKeys[MAX_VALUE_LENGTH];
39 static int lastKeysIndex = 0;
40
41 static void loadMenuLayout(void);
42 static void toggleHints(void);
43 static void showControlMenu(void);
44 static void showSoundMenu(void);
45 static void showMainMenu(void);
46 static void showCheatMenu(void);
47 static void showCheatMenuWarn(void);
48 static void doMenu(void);
49 static void toggleFullscreen(void);
50 static void enableCheatMenu(void);
51 static void showOptionsMenu(void);
52
drawOptionsMenu()53 void drawOptionsMenu()
54 {
55 int i;
56
57 drawImage(menu.background, menu.x, menu.y, FALSE, 196);
58
59 for (i=0;i<menu.widgetCount;i++)
60 {
61 drawWidget(menu.widgets[i], &menu, menu.index == i);
62 }
63 }
64
doMenu()65 static void doMenu()
66 {
67 int i, left, right, up, down, attack, xAxisMoved, yAxisMoved;
68 char c;
69 Widget *w;
70
71 if (game.cheatsEnabled == FALSE && input.lastPressedKey >= 'A' && input.lastPressedKey <= 'z')
72 {
73 c = tolower(input.lastPressedKey);
74
75 lastKeys[lastKeysIndex] = c;
76
77 lastKeysIndex++;
78
79 lastKeys[lastKeysIndex] = '\0';
80
81 if (lastKeysIndex + 1 >= MAX_VALUE_LENGTH)
82 {
83 for (i=1;i<MAX_VALUE_LENGTH;i++)
84 {
85 lastKeys[i - 1] = lastKeys[i];
86
87 lastKeys[i] = '\0';
88 }
89
90 lastKeysIndex = MAX_VALUE_LENGTH - 2;
91 }
92
93 if (strstr(lastKeys, MENU_CODE) != NULL)
94 {
95 enableCheatMenu();
96
97 playSound("sound/common/faster");
98 }
99 }
100
101 left = FALSE;
102 right = FALSE;
103 up = FALSE;
104 down = FALSE;
105 attack = FALSE;
106
107 if (menuInput.left == TRUE)
108 {
109 left = TRUE;
110 }
111
112 else if (menuInput.right == TRUE)
113 {
114 right = TRUE;
115 }
116
117 else if (menuInput.up == TRUE)
118 {
119 up = TRUE;
120 }
121
122 else if (menuInput.down == TRUE)
123 {
124 down = TRUE;
125 }
126
127 else if (menuInput.attack == TRUE)
128 {
129 attack = TRUE;
130 }
131
132 else if (input.left == TRUE)
133 {
134 left = TRUE;
135 }
136
137 else if (input.right == TRUE)
138 {
139 right = TRUE;
140 }
141
142 else if (input.up == TRUE)
143 {
144 up = TRUE;
145 }
146
147 else if (input.down == TRUE)
148 {
149 down = TRUE;
150 }
151
152 else if (input.attack == TRUE)
153 {
154 attack = TRUE;
155 }
156
157 if (down == TRUE)
158 {
159 do
160 {
161 menu.index++;
162
163 if (menu.index >= menu.widgetCount)
164 {
165 menu.index = 0;
166 }
167 }
168
169 while (menu.widgets[menu.index]->hidden == TRUE);
170
171 playSound("sound/common/click");
172 }
173
174 else if (up == TRUE)
175 {
176 do
177 {
178 menu.index--;
179
180 if (menu.index < 0)
181 {
182 menu.index = menu.widgetCount - 1;
183 }
184 }
185
186 while (menu.widgets[menu.index]->hidden == TRUE);
187
188 playSound("sound/common/click");
189 }
190
191 else if (attack == TRUE)
192 {
193 w = menu.widgets[menu.index];
194
195 if (w->clickAction != NULL)
196 {
197 playSound("sound/common/click");
198
199 w->clickAction();
200 }
201 }
202
203 else if (left == TRUE)
204 {
205 w = menu.widgets[menu.index];
206
207 if (w->rightAction != NULL)
208 {
209 playSound("sound/common/click");
210
211 w->rightAction();
212 }
213 }
214
215 else if (right == TRUE)
216 {
217 w = menu.widgets[menu.index];
218
219 if (w->leftAction != NULL)
220 {
221 playSound("sound/common/click");
222
223 w->leftAction();
224 }
225 }
226
227 xAxisMoved = input.xAxisMoved;
228 yAxisMoved = input.yAxisMoved;
229
230 memset(&menuInput, 0, sizeof(Input));
231 memset(&input, 0, sizeof(Input));
232
233 input.lastPressedKey = -1;
234
235 input.xAxisMoved = xAxisMoved;
236 input.yAxisMoved = yAxisMoved;
237 }
238
loadMenuLayout()239 static void loadMenuLayout()
240 {
241 int x, y, w, i, maxWidth;
242
243 menu.widgetCount = 6;
244
245 menu.widgets = malloc(sizeof(Widget *) * menu.widgetCount);
246
247 if (menu.widgets == NULL)
248 {
249 showErrorAndExit("Ran out of memory when creating Options Menu");
250 }
251
252 y = x = 0;
253
254 menu.widgets[0] = createWidget(_("Configure Controls"), NULL, NULL, NULL, &showControlMenu, -1, y, TRUE, 255, 255, 255);
255
256 menu.widgets[1] = createWidget(_("Configure Sound"), NULL, NULL, NULL, &showSoundMenu, -1, y, TRUE, 255, 255, 255);
257
258 menu.widgets[2] = createWidget(_("Fullscreen"), NULL, &toggleFullscreen, &toggleFullscreen, &toggleFullscreen, x, y, TRUE, 255, 255, 255);
259
260 menu.widgets[2]->label = createLabel(game.fullscreen == TRUE ? _("Yes") : _("No"), menu.widgets[2]->x + menu.widgets[2]->normalState->w + 10, y);
261
262 menu.widgets[3] = createWidget(_("Show Hints"), NULL, &toggleHints, &toggleHints, &toggleHints, x, y, TRUE, 255, 255, 255);
263
264 menu.widgets[3]->label = createLabel(game.showHints == TRUE ? _("Yes") : _("No"), menu.widgets[3]->x + menu.widgets[3]->normalState->w + 10, y);
265
266 menu.widgets[4] = createWidget(_("Cheats"), NULL, NULL, NULL, &showCheatMenuWarn, -1, y, TRUE, 255, 255, 255);
267
268 menu.widgets[4]->hidden = game.cheatsEnabled == TRUE ? FALSE : TRUE;
269
270 menu.widgets[5] = createWidget(_("Back"), NULL, NULL, NULL, &showMainMenu, -1, y, TRUE, 255, 255, 255);
271
272 y = BUTTON_PADDING + BORDER_PADDING;
273
274 w = 0;
275
276 maxWidth = 0;
277
278 for (i=0;i<menu.widgetCount;i++)
279 {
280 if (menu.widgets[i]->label != NULL && menu.widgets[i]->normalState->w > maxWidth)
281 {
282 maxWidth = menu.widgets[i]->normalState->w;
283 }
284 }
285
286 for (i=0;i<menu.widgetCount;i++)
287 {
288 menu.widgets[i]->y = y;
289
290 if (menu.widgets[i]->x != -1)
291 {
292 menu.widgets[i]->x = BUTTON_PADDING + BORDER_PADDING;
293 }
294
295 if (menu.widgets[i]->label != NULL)
296 {
297 menu.widgets[i]->label->y = y;
298
299 menu.widgets[i]->label->x = menu.widgets[i]->x + maxWidth + 10;
300
301 if (menu.widgets[i]->label->x + menu.widgets[i]->label->text->w > w)
302 {
303 w = menu.widgets[i]->label->x + menu.widgets[i]->label->text->w;
304 }
305 }
306
307 else
308 {
309 if (menu.widgets[i]->x + menu.widgets[i]->selectedState->w > w)
310 {
311 w = menu.widgets[i]->x + menu.widgets[i]->selectedState->w;
312 }
313 }
314
315 y += menu.widgets[i]->selectedState->h + BUTTON_PADDING;
316 }
317
318 menu.w = w + BUTTON_PADDING;
319 menu.h = y - BORDER_PADDING;
320
321 menu.background = addBorder(createSurface(menu.w, menu.h, FALSE), 255, 255, 255, 0, 0, 0);
322
323 menu.x = (SCREEN_WIDTH - menu.background->w) / 2;
324 menu.y = (SCREEN_HEIGHT - menu.background->h) / 2;
325 }
326
initOptionsMenu()327 Menu *initOptionsMenu()
328 {
329 menu.action = &doMenu;
330
331 if (menu.widgets == NULL)
332 {
333 loadMenuLayout();
334 }
335
336 input.lastPressedKey = -1;
337
338 lastKeysIndex = 0;
339
340 lastKeys[lastKeysIndex] = '\0';
341
342 menu.returnAction = &showMainMenu;
343
344 return &menu;
345 }
346
freeOptionsMenu()347 void freeOptionsMenu()
348 {
349 int i;
350
351 if (menu.widgets != NULL)
352 {
353 for (i=0;i<menu.widgetCount;i++)
354 {
355 freeWidget(menu.widgets[i]);
356 }
357
358 free(menu.widgets);
359
360 menu.widgets = NULL;
361 }
362
363 if (menu.background != NULL)
364 {
365 destroyTexture(menu.background);
366
367 menu.background = NULL;
368 }
369 }
370
toggleHints()371 static void toggleHints()
372 {
373 Widget *w = menu.widgets[menu.index];
374
375 game.showHints = game.showHints == TRUE ? FALSE : TRUE;
376
377 updateLabelText(w->label, game.showHints == TRUE ? _("Yes") : _("No"));
378 }
379
toggleFullscreen()380 static void toggleFullscreen()
381 {
382 Widget *w = menu.widgets[menu.index];
383
384 game.fullscreen = game.fullscreen == TRUE ? FALSE : TRUE;
385
386 toggleFullScreen();
387
388 updateLabelText(w->label, game.fullscreen == TRUE ? _("Yes") : _("No"));
389 }
390
showControlMenu()391 static void showControlMenu()
392 {
393 game.menu = initControlMenu();
394
395 game.drawMenu = &drawControlMenu;
396 }
397
showSoundMenu()398 static void showSoundMenu()
399 {
400 game.menu = initSoundMenu();
401
402 game.drawMenu = &drawSoundMenu;
403 }
404
showMainMenu()405 static void showMainMenu()
406 {
407 game.menu = initMainMenu();
408
409 game.drawMenu = &drawMainMenu;
410 }
411
showCheatMenuWarn()412 static void showCheatMenuWarn()
413 {
414 if (game.previousStatus == IN_TITLE)
415 {
416 game.menu = initOKMenu(_("Cheats can only be enabled in-game"), &showOptionsMenu);
417 }
418
419 else
420 {
421 game.menu = initOKMenu(_("Enabling cheats will not allow you to achieve 100% completion in the game"), &showCheatMenu);
422 }
423
424 game.drawMenu = &drawOKMenu;
425 }
426
showCheatMenu()427 static void showCheatMenu()
428 {
429 game.menu = initCheatMenu();
430
431 game.drawMenu = &drawCheatMenu;
432 }
433
enableCheatMenu()434 static void enableCheatMenu()
435 {
436 int i;
437
438 for (i=0;i<menu.widgetCount;i++)
439 {
440 if (menu.widgets[i]->hidden == TRUE)
441 {
442 menu.widgets[i]->hidden = FALSE;
443 }
444 }
445
446 game.cheatsEnabled = TRUE;
447 }
448
showOptionsMenu()449 static void showOptionsMenu()
450 {
451 game.menu = initOptionsMenu();
452
453 game.drawMenu = &drawOptionsMenu;
454 }
455