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