1
2 /**
3 * @file gamemenu.cpp
4 *
5 * Implementation of the in-game menu functions.
6 */
7 #include "all.h"
8 #include "options.h"
9
10 DEVILUTION_BEGIN_NAMESPACE
11
12 bool gbRunInTown = false;
13
14 /** Contains the game menu items of the single player menu. */
15 TMenuItem sgSingleMenu[] = {
16 // clang-format off
17 // dwFlags, pszStr, fnMenu
18 { GMENU_ENABLED, "Save Game", &gamemenu_save_game },
19 { GMENU_ENABLED, "Options", &gamemenu_options },
20 { GMENU_ENABLED, "New Game", &gamemenu_new_game },
21 { GMENU_ENABLED, "Load Game", &gamemenu_load_game },
22 { GMENU_ENABLED, "Quit Game", &gamemenu_quit_game },
23 { GMENU_ENABLED, NULL, NULL }
24 // clang-format on
25 };
26 /** Contains the game menu items of the multi player menu. */
27 TMenuItem sgMultiMenu[] = {
28 // clang-format off
29 // dwFlags, pszStr, fnMenu
30 { GMENU_ENABLED, "Options", &gamemenu_options },
31 { GMENU_ENABLED, "New Game", &gamemenu_new_game },
32 { GMENU_ENABLED, "Restart In Town", &gamemenu_restart_town },
33 { GMENU_ENABLED, "Quit Game", &gamemenu_quit_game },
34 { GMENU_ENABLED, NULL, NULL },
35 // clang-format on
36 };
37 TMenuItem sgOptionsMenu[] = {
38 // clang-format off
39 // dwFlags, pszStr, fnMenu
40 { GMENU_ENABLED | GMENU_SLIDER, NULL, &gamemenu_music_volume },
41 { GMENU_ENABLED | GMENU_SLIDER, NULL, &gamemenu_sound_volume },
42 { GMENU_ENABLED | GMENU_SLIDER, "Gamma", &gamemenu_gamma },
43 // { GMENU_ENABLED , NULL, &gamemenu_color_cycling },
44 { GMENU_ENABLED | GMENU_SLIDER, "Speed", &gamemenu_speed },
45 // { GMENU_ENABLED | GMENU_SLIDER, NULL, &gamemenu_loadjog },
46 { GMENU_ENABLED , "Previous Menu", &gamemenu_previous },
47 { GMENU_ENABLED , NULL, NULL },
48 // clang-format on
49 };
50 /** Specifies the menu names for music enabled and disabled. */
51 const char *const music_toggle_names[] = {
52 "Music",
53 "Music Disabled",
54 };
55 /** Specifies the menu names for sound enabled and disabled. */
56 const char *const sound_toggle_names[] = {
57 "Sound",
58 "Sound Disabled",
59 };
60 const char *jogging_toggle_names[] = {
61 "Jog",
62 "Walk",
63 };
64 /** Specifies the menu names for color cycling disabled and enabled. */
65 const char *const color_cycling_toggle_names[] = { "Color Cycling Off", "Color Cycling On" };
66
gamemenu_update_single(TMenuItem * pMenuItems)67 static void gamemenu_update_single(TMenuItem *pMenuItems)
68 {
69 BOOL enable;
70
71 gmenu_enable(&sgSingleMenu[3], gbValidSaveFile);
72
73 enable = FALSE;
74 if (plr[myplr]._pmode != PM_DEATH && !deathflag)
75 enable = TRUE;
76
77 gmenu_enable(&sgSingleMenu[0], enable);
78 }
79
gamemenu_update_multi(TMenuItem * pMenuItems)80 static void gamemenu_update_multi(TMenuItem *pMenuItems)
81 {
82 gmenu_enable(&sgMultiMenu[2], deathflag);
83 }
84
gamemenu_on()85 void gamemenu_on()
86 {
87 if (!gbIsMultiplayer) {
88 gmenu_set_items(sgSingleMenu, gamemenu_update_single);
89 } else {
90 gmenu_set_items(sgMultiMenu, gamemenu_update_multi);
91 }
92 PressEscKey();
93 }
94
gamemenu_off()95 void gamemenu_off()
96 {
97 gmenu_set_items(NULL, NULL);
98 }
99
gamemenu_handle_previous()100 void gamemenu_handle_previous()
101 {
102 if (gmenu_is_active())
103 gamemenu_off();
104 else
105 gamemenu_on();
106 }
107
gamemenu_previous(BOOL bActivate)108 void gamemenu_previous(BOOL bActivate)
109 {
110 gamemenu_on();
111 }
112
gamemenu_new_game(BOOL bActivate)113 void gamemenu_new_game(BOOL bActivate)
114 {
115 int i;
116
117 for (i = 0; i < MAX_PLRS; i++) {
118 plr[i]._pmode = PM_QUIT;
119 plr[i]._pInvincible = TRUE;
120 }
121
122 deathflag = FALSE;
123 force_redraw = 255;
124 scrollrt_draw_game_screen(TRUE);
125 CornerStone.activated = FALSE;
126 gbRunGame = FALSE;
127 gamemenu_off();
128 }
129
gamemenu_quit_game(BOOL bActivate)130 void gamemenu_quit_game(BOOL bActivate)
131 {
132 gamemenu_new_game(bActivate);
133 gbRunGameResult = FALSE;
134 }
135
gamemenu_load_game(BOOL bActivate)136 void gamemenu_load_game(BOOL bActivate)
137 {
138 WNDPROC saveProc = SetWindowProc(DisableInputWndProc);
139 gamemenu_off();
140 SetCursor_(CURSOR_NONE);
141 InitDiabloMsg(EMSG_LOADING);
142 force_redraw = 255;
143 DrawAndBlit();
144 LoadGame(FALSE);
145 ClrDiabloMsg();
146 CornerStone.activated = FALSE;
147 PaletteFadeOut(8);
148 deathflag = FALSE;
149 force_redraw = 255;
150 DrawAndBlit();
151 LoadPWaterPalette();
152 PaletteFadeIn(8);
153 SetCursor_(CURSOR_HAND);
154 interface_msg_pump();
155 SetWindowProc(saveProc);
156 }
157
gamemenu_save_game(BOOL bActivate)158 void gamemenu_save_game(BOOL bActivate)
159 {
160 if (pcurs != CURSOR_HAND) {
161 return;
162 }
163
164 if (plr[myplr]._pmode == PM_DEATH || deathflag) {
165 gamemenu_off();
166 return;
167 }
168
169 WNDPROC saveProc = SetWindowProc(DisableInputWndProc);
170 SetCursor_(CURSOR_NONE);
171 gamemenu_off();
172 InitDiabloMsg(EMSG_SAVING);
173 force_redraw = 255;
174 DrawAndBlit();
175 SaveGame();
176 ClrDiabloMsg();
177 force_redraw = 255;
178 SetCursor_(CURSOR_HAND);
179 if (CornerStone.activated) {
180 items_427A72();
181 }
182 interface_msg_pump();
183 SetWindowProc(saveProc);
184 }
185
gamemenu_restart_town(BOOL bActivate)186 void gamemenu_restart_town(BOOL bActivate)
187 {
188 NetSendCmd(TRUE, CMD_RETOWN);
189 }
190
gamemenu_sound_music_toggle(const char * const * names,TMenuItem * menu_item,int volume)191 static void gamemenu_sound_music_toggle(const char *const *names, TMenuItem *menu_item, int volume)
192 {
193 if (gbSndInited) {
194 menu_item->dwFlags |= GMENU_ENABLED | GMENU_SLIDER;
195 menu_item->pszStr = *names;
196 gmenu_slider_steps(menu_item, 17);
197 gmenu_slider_set(menu_item, VOLUME_MIN, VOLUME_MAX, volume);
198 return;
199 }
200
201 menu_item->dwFlags &= ~(GMENU_ENABLED | GMENU_SLIDER);
202 menu_item->pszStr = names[1];
203 }
204
gamemenu_slider_music_sound(TMenuItem * menu_item)205 static int gamemenu_slider_music_sound(TMenuItem *menu_item)
206 {
207 return gmenu_slider_get(menu_item, VOLUME_MIN, VOLUME_MAX);
208 }
209
gamemenu_get_music()210 static void gamemenu_get_music()
211 {
212 gamemenu_sound_music_toggle(music_toggle_names, sgOptionsMenu, sound_get_or_set_music_volume(1));
213 }
214
gamemenu_get_sound()215 static void gamemenu_get_sound()
216 {
217 gamemenu_sound_music_toggle(sound_toggle_names, &sgOptionsMenu[1], sound_get_or_set_sound_volume(1));
218 }
219
gamemenu_jogging()220 static void gamemenu_jogging()
221 {
222 gmenu_slider_steps(&sgOptionsMenu[3], 2);
223 gmenu_slider_set(&sgOptionsMenu[3], 0, 1, sgOptions.Gameplay.bRunInTown);
224 sgOptionsMenu[3].pszStr = jogging_toggle_names[!sgOptions.Gameplay.bRunInTown ? 1 : 0];
225 }
226
gamemenu_get_gamma()227 static void gamemenu_get_gamma()
228 {
229 gmenu_slider_steps(&sgOptionsMenu[2], 15);
230 gmenu_slider_set(&sgOptionsMenu[2], 30, 100, UpdateGamma(0));
231 }
232
gamemenu_get_speed()233 static void gamemenu_get_speed()
234 {
235 if (gbIsMultiplayer) {
236 sgOptionsMenu[3].dwFlags &= ~(GMENU_ENABLED | GMENU_SLIDER);
237 if (gnTickRate >= 50)
238 sgOptionsMenu[3].pszStr = "Speed: Fastest";
239 else if (gnTickRate >= 40)
240 sgOptionsMenu[3].pszStr = "Speed: Faster";
241 else if (gnTickRate >= 30)
242 sgOptionsMenu[3].pszStr = "Speed: Fast";
243 else if (gnTickRate == 20)
244 sgOptionsMenu[3].pszStr = "Speed: Normal";
245 return;
246 }
247
248 sgOptionsMenu[3].dwFlags |= GMENU_ENABLED | GMENU_SLIDER;
249
250 sgOptionsMenu[3].pszStr = "Speed";
251 gmenu_slider_steps(&sgOptionsMenu[3], 46);
252 gmenu_slider_set(&sgOptionsMenu[3], 20, 50, gnTickRate);
253 }
254
gamemenu_get_color_cycling()255 static void gamemenu_get_color_cycling()
256 {
257 sgOptionsMenu[3].pszStr = color_cycling_toggle_names[sgOptions.Graphics.bColorCycling ? 1 : 0];
258 }
259
gamemenu_slider_gamma()260 static int gamemenu_slider_gamma()
261 {
262 return gmenu_slider_get(&sgOptionsMenu[2], 30, 100);
263 }
264
gamemenu_options(BOOL bActivate)265 void gamemenu_options(BOOL bActivate)
266 {
267 gamemenu_get_music();
268 gamemenu_get_sound();
269 //gamemenu_jogging();
270 gamemenu_get_gamma();
271 gamemenu_get_speed();
272 //gamemenu_get_color_cycling();
273 gmenu_set_items(sgOptionsMenu, NULL);
274 }
275
gamemenu_music_volume(BOOL bActivate)276 void gamemenu_music_volume(BOOL bActivate)
277 {
278 int volume;
279
280 if (bActivate) {
281 if (gbMusicOn) {
282 gbMusicOn = FALSE;
283 music_stop();
284 sound_get_or_set_music_volume(VOLUME_MIN);
285 } else {
286 gbMusicOn = TRUE;
287 sound_get_or_set_music_volume(VOLUME_MAX);
288 int lt;
289 if (currlevel >= 17) {
290 if (currlevel > 20)
291 lt = TMUSIC_L5;
292 else
293 lt = TMUSIC_L6;
294 } else
295 lt = leveltype;
296 music_start(lt);
297 }
298 } else {
299 volume = gamemenu_slider_music_sound(&sgOptionsMenu[0]);
300 sound_get_or_set_music_volume(volume);
301 if (volume == VOLUME_MIN) {
302 if (gbMusicOn) {
303 gbMusicOn = FALSE;
304 music_stop();
305 }
306 } else if (!gbMusicOn) {
307 gbMusicOn = TRUE;
308 int lt;
309 if (currlevel >= 17) {
310 if (currlevel > 20)
311 lt = TMUSIC_L5;
312 else
313 lt = TMUSIC_L6;
314 } else
315 lt = leveltype;
316 music_start(lt);
317 }
318 }
319 gamemenu_get_music();
320 }
321
gamemenu_sound_volume(BOOL bActivate)322 void gamemenu_sound_volume(BOOL bActivate)
323 {
324 int volume;
325 if (bActivate) {
326 if (gbSoundOn) {
327 gbSoundOn = FALSE;
328 sound_stop();
329 sound_get_or_set_sound_volume(VOLUME_MIN);
330 } else {
331 gbSoundOn = TRUE;
332 sound_get_or_set_sound_volume(VOLUME_MAX);
333 }
334 } else {
335 volume = gamemenu_slider_music_sound(&sgOptionsMenu[1]);
336 sound_get_or_set_sound_volume(volume);
337 if (volume == VOLUME_MIN) {
338 if (gbSoundOn) {
339 gbSoundOn = FALSE;
340 sound_stop();
341 }
342 } else if (!gbSoundOn) {
343 gbSoundOn = TRUE;
344 }
345 }
346 PlaySFX(IS_TITLEMOV);
347 gamemenu_get_sound();
348 }
349
gamemenu_loadjog(BOOL bActivate)350 void gamemenu_loadjog(BOOL bActivate)
351 {
352 if (!gbIsMultiplayer) {
353 sgOptions.Gameplay.bRunInTown = !sgOptions.Gameplay.bRunInTown;
354 gbRunInTown = sgOptions.Gameplay.bRunInTown;
355 PlaySFX(IS_TITLEMOV);
356 gamemenu_jogging();
357 }
358 }
359
gamemenu_gamma(BOOL bActivate)360 void gamemenu_gamma(BOOL bActivate)
361 {
362 int gamma;
363 if (bActivate) {
364 gamma = UpdateGamma(0);
365 if (gamma == 30)
366 gamma = 100;
367 else
368 gamma = 30;
369 } else {
370 gamma = gamemenu_slider_gamma();
371 }
372
373 UpdateGamma(gamma);
374 gamemenu_get_gamma();
375 }
376
gamemenu_speed(BOOL bActivate)377 void gamemenu_speed(BOOL bActivate)
378 {
379 if (bActivate) {
380 if (gnTickRate != 20)
381 gnTickRate = 20;
382 else
383 gnTickRate = 50;
384 gmenu_slider_set(&sgOptionsMenu[3], 20, 50, gnTickRate);
385 } else {
386 gnTickRate = gmenu_slider_get(&sgOptionsMenu[3], 20, 50);
387 }
388
389 sgOptions.Gameplay.nTickRate = gnTickRate;
390 gnTickDelay = 1000 / gnTickRate;
391 }
392
gamemenu_color_cycling(BOOL bActivate)393 void gamemenu_color_cycling(BOOL bActivate)
394 {
395 sgOptions.Graphics.bColorCycling = !sgOptions.Graphics.bColorCycling;
396 sgOptionsMenu[3].pszStr = color_cycling_toggle_names[sgOptions.Graphics.bColorCycling ? 1 : 0];
397 }
398
399 DEVILUTION_END_NAMESPACE
400