Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
298 | serge | 1 | // Emacs style mode select -*- C++ -*- |
2 | //----------------------------------------------------------------------------- |
||
3 | // |
||
4 | // $Id:$ |
||
5 | // |
||
6 | // Copyright (C) 1993-1996 by id Software, Inc. |
||
7 | // |
||
8 | // This source is available for distribution and/or modification |
||
9 | // only under the terms of the DOOM Source Code License as |
||
10 | // published by id Software. All rights reserved. |
||
11 | // |
||
12 | // The source is distributed in the hope that it will be useful, |
||
13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
14 | // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License |
||
15 | // for more details. |
||
16 | // |
||
17 | // $Log:$ |
||
18 | // |
||
19 | // DESCRIPTION: |
||
550 | serge | 20 | // DOOM selection menu, options, episode etc. |
21 | // Sliders and icons. Kinda widget stuff. |
||
298 | serge | 22 | // |
23 | //----------------------------------------------------------------------------- |
||
24 | |||
25 | static const char |
||
26 | rcsid[] = "$Id: m_menu.c,v 1.7 1997/02/03 22:45:10 b1 Exp $"; |
||
27 | |||
28 | #include |
||
29 | #include |
||
30 | |||
31 | #include "m_swap.h" |
||
32 | #include "doomdef.h" |
||
33 | #include "dstrings.h" |
||
34 | |||
35 | #include "d_main.h" |
||
36 | |||
37 | #include "i_system.h" |
||
38 | #include "i_video.h" |
||
39 | #include "z_zone.h" |
||
40 | #include "v_video.h" |
||
41 | #include "w_wad.h" |
||
42 | |||
43 | #include "r_local.h" |
||
44 | |||
45 | |||
46 | #include "hu_stuff.h" |
||
47 | |||
48 | #include "g_game.h" |
||
49 | |||
50 | #include "m_argv.h" |
||
51 | |||
52 | #include "s_sound.h" |
||
53 | |||
54 | #include "doomstat.h" |
||
55 | |||
56 | // Data. |
||
57 | #include "sounds.h" |
||
58 | |||
59 | #include "m_menu.h" |
||
60 | |||
61 | |||
62 | |||
550 | serge | 63 | extern patch_t* hu_font[HU_FONTSIZE]; |
64 | extern boolean message_dontfuckwithme; |
||
298 | serge | 65 | |
550 | serge | 66 | extern boolean chat_on; // in heads-up code |
298 | serge | 67 | |
68 | // |
||
69 | // defaulted values |
||
70 | // |
||
550 | serge | 71 | int mouseSensitivity; // has default |
298 | serge | 72 | |
73 | // Show messages has default, 0 = off, 1 = on |
||
550 | serge | 74 | int showMessages; |
75 | |||
298 | serge | 76 | |
77 | // Blocky mode, has default, 0 = high, 1 = normal |
||
550 | serge | 78 | int detailLevel; |
79 | int screenblocks; // has default |
||
298 | serge | 80 | |
81 | // temp for screenblocks (0-9) |
||
550 | serge | 82 | int screenSize; |
298 | serge | 83 | |
84 | // -1 = no quicksave slot picked! |
||
550 | serge | 85 | int quickSaveSlot; |
298 | serge | 86 | |
87 | // 1 = message to be printed |
||
550 | serge | 88 | int messageToPrint; |
298 | serge | 89 | // ...and here is the message string! |
550 | serge | 90 | char* messageString; |
298 | serge | 91 | |
92 | // message x & y |
||
550 | serge | 93 | int messx; |
94 | int messy; |
||
95 | int messageLastMenuActive; |
||
298 | serge | 96 | |
97 | // timed message = no input from user |
||
550 | serge | 98 | boolean messageNeedsInput; |
298 | serge | 99 | |
100 | void (*messageRoutine)(int response); |
||
101 | |||
550 | serge | 102 | #define SAVESTRINGSIZE 24 |
298 | serge | 103 | |
104 | char gammamsg[5][26] = |
||
105 | { |
||
106 | GAMMALVL0, |
||
107 | GAMMALVL1, |
||
108 | GAMMALVL2, |
||
109 | GAMMALVL3, |
||
110 | GAMMALVL4 |
||
111 | }; |
||
112 | |||
113 | // we are going to be entering a savegame string |
||
550 | serge | 114 | int saveStringEnter; |
115 | int saveSlot; // which slot to save in |
||
116 | int saveCharIndex; // which char we're editing |
||
298 | serge | 117 | // old save description before edit |
550 | serge | 118 | char saveOldString[SAVESTRINGSIZE]; |
298 | serge | 119 | |
550 | serge | 120 | boolean inhelpscreens; |
121 | boolean menuactive; |
||
298 | serge | 122 | |
550 | serge | 123 | #define SKULLXOFF -32 |
124 | #define LINEHEIGHT 16 |
||
298 | serge | 125 | |
550 | serge | 126 | extern boolean sendpause; |
127 | char savegamestrings[10][SAVESTRINGSIZE]; |
||
298 | serge | 128 | |
550 | serge | 129 | char endstring[160]; |
298 | serge | 130 | |
131 | |||
132 | // |
||
133 | // MENU TYPEDEFS |
||
134 | // |
||
135 | typedef struct |
||
136 | { |
||
137 | // 0 = no cursor here, 1 = ok, 2 = arrows ok |
||
550 | serge | 138 | short status; |
298 | serge | 139 | |
550 | serge | 140 | char name[10]; |
298 | serge | 141 | |
142 | // choice = menu item #. |
||
143 | // if status = 2, |
||
144 | // choice=0:leftarrow,1:rightarrow |
||
550 | serge | 145 | void (*routine)(int choice); |
298 | serge | 146 | |
147 | // hotkey in menu |
||
550 | serge | 148 | char alphaKey; |
298 | serge | 149 | } menuitem_t; |
150 | |||
151 | |||
152 | |||
153 | typedef struct menu_s |
||
154 | { |
||
550 | serge | 155 | short numitems; // # of menu items |
156 | struct menu_s* prevMenu; // previous menu |
||
157 | menuitem_t* menuitems; // menu items |
||
158 | void (*routine)(); // draw routine |
||
159 | short x; |
||
160 | short y; // x,y of menu |
||
161 | short lastOn; // last item user was on in menu |
||
298 | serge | 162 | } menu_t; |
163 | |||
550 | serge | 164 | short itemOn; // menu item skull is on |
165 | short skullAnimCounter; // skull animation counter |
||
166 | short whichSkull; // which skull to draw |
||
298 | serge | 167 | |
168 | // graphic name of skulls |
||
169 | // warning: initializer-string for array of chars is too long |
||
170 | char skullName[2][/*8*/9] = {"M_SKULL1","M_SKULL2"}; |
||
171 | |||
172 | // current menudef |
||
550 | serge | 173 | menu_t* currentMenu; |
298 | serge | 174 | |
175 | // |
||
176 | // PROTOTYPES |
||
177 | // |
||
178 | void M_NewGame(int choice); |
||
179 | void M_Episode(int choice); |
||
180 | void M_ChooseSkill(int choice); |
||
181 | void M_LoadGame(int choice); |
||
182 | void M_SaveGame(int choice); |
||
183 | void M_Options(int choice); |
||
184 | void M_EndGame(int choice); |
||
185 | void M_ReadThis(int choice); |
||
186 | void M_ReadThis2(int choice); |
||
187 | void M_QuitDOOM(int choice); |
||
188 | |||
189 | void M_ChangeMessages(int choice); |
||
190 | void M_ChangeSensitivity(int choice); |
||
191 | void M_SfxVol(int choice); |
||
192 | void M_MusicVol(int choice); |
||
193 | void M_ChangeDetail(int choice); |
||
194 | void M_SizeDisplay(int choice); |
||
195 | void M_StartGame(int choice); |
||
196 | void M_Sound(int choice); |
||
197 | |||
198 | void M_FinishReadThis(int choice); |
||
199 | void M_LoadSelect(int choice); |
||
200 | void M_SaveSelect(int choice); |
||
201 | void M_ReadSaveStrings(void); |
||
202 | void M_QuickSave(void); |
||
203 | void M_QuickLoad(void); |
||
204 | |||
205 | void M_DrawMainMenu(void); |
||
206 | void M_DrawReadThis1(void); |
||
207 | void M_DrawReadThis2(void); |
||
208 | void M_DrawNewGame(void); |
||
209 | void M_DrawEpisode(void); |
||
210 | void M_DrawOptions(void); |
||
211 | void M_DrawSound(void); |
||
212 | void M_DrawLoad(void); |
||
213 | void M_DrawSave(void); |
||
214 | |||
215 | void M_DrawSaveLoadBorder(int x,int y); |
||
216 | void M_SetupNextMenu(menu_t *menudef); |
||
217 | void M_DrawThermo(int x,int y,int thermWidth,int thermDot); |
||
218 | void M_DrawEmptyCell(menu_t *menu,int item); |
||
219 | void M_DrawSelCell(menu_t *menu,int item); |
||
220 | void M_WriteText(int x, int y, char *string); |
||
221 | int M_StringWidth(char *string); |
||
222 | int M_StringHeight(char *string); |
||
223 | void M_StartControlPanel(void); |
||
224 | void M_StartMessage(char *string,void *routine,boolean input); |
||
225 | void M_StopMessage(void); |
||
226 | void M_ClearMenus (void); |
||
227 | |||
228 | |||
229 | |||
230 | |||
231 | // |
||
232 | // DOOM MENU |
||
233 | // |
||
234 | enum |
||
235 | { |
||
236 | newgame = 0, |
||
237 | options, |
||
238 | loadgame, |
||
239 | savegame, |
||
240 | readthis, |
||
241 | quitdoom, |
||
242 | main_end |
||
243 | } main_e; |
||
244 | |||
245 | menuitem_t MainMenu[]= |
||
246 | { |
||
247 | {1,"M_NGAME",M_NewGame,'n'}, |
||
248 | {1,"M_OPTION",M_Options,'o'}, |
||
249 | {1,"M_LOADG",M_LoadGame,'l'}, |
||
250 | {1,"M_SAVEG",M_SaveGame,'s'}, |
||
251 | // Another hickup with Special edition. |
||
252 | {1,"M_RDTHIS",M_ReadThis,'r'}, |
||
253 | {1,"M_QUITG",M_QuitDOOM,'q'} |
||
254 | }; |
||
255 | |||
256 | menu_t MainDef = |
||
257 | { |
||
258 | main_end, |
||
259 | NULL, |
||
260 | MainMenu, |
||
261 | M_DrawMainMenu, |
||
262 | 97,64, |
||
263 | |||
264 | }; |
||
265 | |||
266 | |||
267 | // |
||
268 | // EPISODE SELECT |
||
269 | // |
||
270 | enum |
||
271 | { |
||
272 | ep1, |
||
273 | ep2, |
||
274 | ep3, |
||
275 | ep4, |
||
276 | ep_end |
||
277 | } episodes_e; |
||
278 | |||
279 | menuitem_t EpisodeMenu[]= |
||
280 | { |
||
281 | {1,"M_EPI1", M_Episode,'k'}, |
||
282 | {1,"M_EPI2", M_Episode,'t'}, |
||
283 | {1,"M_EPI3", M_Episode,'i'}, |
||
284 | {1,"M_EPI4", M_Episode,'t'} |
||
285 | }; |
||
286 | |||
287 | menu_t EpiDef = |
||
288 | { |
||
550 | serge | 289 | ep_end, // # of menu items |
290 | &MainDef, // previous menu |
||
291 | EpisodeMenu, // menuitem_t -> |
||
292 | M_DrawEpisode, // drawing routine -> |
||
298 | serge | 293 | 48,63, // x,y |
550 | serge | 294 | ep1 // lastOn |
298 | serge | 295 | }; |
296 | |||
297 | // |
||
298 | // NEW GAME |
||
299 | // |
||
300 | enum |
||
301 | { |
||
302 | killthings, |
||
303 | toorough, |
||
304 | hurtme, |
||
305 | violence, |
||
306 | nightmare, |
||
307 | newg_end |
||
308 | } newgame_e; |
||
309 | |||
310 | menuitem_t NewGameMenu[]= |
||
311 | { |
||
550 | serge | 312 | {1,"M_JKILL", M_ChooseSkill, 'i'}, |
313 | {1,"M_ROUGH", M_ChooseSkill, 'h'}, |
||
314 | {1,"M_HURT", M_ChooseSkill, 'h'}, |
||
315 | {1,"M_ULTRA", M_ChooseSkill, 'u'}, |
||
316 | {1,"M_NMARE", M_ChooseSkill, 'n'} |
||
298 | serge | 317 | }; |
318 | |||
319 | menu_t NewDef = |
||
320 | { |
||
550 | serge | 321 | newg_end, // # of menu items |
322 | &EpiDef, // previous menu |
||
323 | NewGameMenu, // menuitem_t -> |
||
324 | M_DrawNewGame, // drawing routine -> |
||
298 | serge | 325 | 48,63, // x,y |
550 | serge | 326 | hurtme // lastOn |
298 | serge | 327 | }; |
328 | |||
329 | |||
330 | |||
331 | // |
||
332 | // OPTIONS MENU |
||
333 | // |
||
334 | enum |
||
335 | { |
||
336 | endgame, |
||
337 | messages, |
||
338 | detail, |
||
339 | scrnsize, |
||
340 | option_empty1, |
||
341 | mousesens, |
||
342 | option_empty2, |
||
343 | soundvol, |
||
344 | opt_end |
||
345 | } options_e; |
||
346 | |||
347 | menuitem_t OptionsMenu[]= |
||
348 | { |
||
550 | serge | 349 | {1,"M_ENDGAM", M_EndGame,'e'}, |
350 | {1,"M_MESSG", M_ChangeMessages,'m'}, |
||
351 | {1,"M_DETAIL", M_ChangeDetail,'g'}, |
||
352 | {2,"M_SCRNSZ", M_SizeDisplay,'s'}, |
||
298 | serge | 353 | {-1,"",0}, |
550 | serge | 354 | {2,"M_MSENS", M_ChangeSensitivity,'m'}, |
298 | serge | 355 | {-1,"",0}, |
550 | serge | 356 | {1,"M_SVOL", M_Sound,'s'} |
298 | serge | 357 | }; |
358 | |||
359 | menu_t OptionsDef = |
||
360 | { |
||
361 | opt_end, |
||
362 | &MainDef, |
||
363 | OptionsMenu, |
||
364 | M_DrawOptions, |
||
365 | 60,37, |
||
366 | |||
367 | }; |
||
368 | |||
369 | // |
||
370 | // Read This! MENU 1 & 2 |
||
371 | // |
||
372 | enum |
||
373 | { |
||
374 | rdthsempty1, |
||
375 | read1_end |
||
376 | } read_e; |
||
377 | |||
378 | menuitem_t ReadMenu1[] = |
||
379 | { |
||
380 | {1,"",M_ReadThis2,0} |
||
381 | }; |
||
382 | |||
383 | menu_t ReadDef1 = |
||
384 | { |
||
385 | read1_end, |
||
386 | &MainDef, |
||
387 | ReadMenu1, |
||
388 | M_DrawReadThis1, |
||
389 | 280,185, |
||
390 | |||
391 | }; |
||
392 | |||
393 | enum |
||
394 | { |
||
395 | rdthsempty2, |
||
396 | read2_end |
||
397 | } read_e2; |
||
398 | |||
399 | menuitem_t ReadMenu2[]= |
||
400 | { |
||
401 | {1,"",M_FinishReadThis,0} |
||
402 | }; |
||
403 | |||
404 | menu_t ReadDef2 = |
||
405 | { |
||
406 | read2_end, |
||
407 | &ReadDef1, |
||
408 | ReadMenu2, |
||
409 | M_DrawReadThis2, |
||
410 | 330,175, |
||
411 | |||
412 | }; |
||
413 | |||
414 | // |
||
415 | // SOUND VOLUME MENU |
||
416 | // |
||
417 | enum |
||
418 | { |
||
419 | sfx_vol, |
||
420 | sfx_empty1, |
||
421 | music_vol, |
||
422 | sfx_empty2, |
||
423 | sound_end |
||
424 | } sound_e; |
||
425 | |||
426 | menuitem_t SoundMenu[]= |
||
427 | { |
||
428 | {2,"M_SFXVOL",M_SfxVol,'s'}, |
||
429 | {-1,"",0}, |
||
430 | {2,"M_MUSVOL",M_MusicVol,'m'}, |
||
431 | {-1,"",0} |
||
432 | }; |
||
433 | |||
434 | menu_t SoundDef = |
||
435 | { |
||
436 | sound_end, |
||
437 | &OptionsDef, |
||
438 | SoundMenu, |
||
439 | M_DrawSound, |
||
440 | 80,64, |
||
441 | |||
442 | }; |
||
443 | |||
444 | // |
||
445 | // LOAD GAME MENU |
||
446 | // |
||
447 | enum |
||
448 | { |
||
449 | load1, |
||
450 | load2, |
||
451 | load3, |
||
452 | load4, |
||
453 | load5, |
||
454 | load6, |
||
455 | load_end |
||
456 | } load_e; |
||
457 | |||
458 | menuitem_t LoadMenu[]= |
||
459 | { |
||
460 | {1,"", M_LoadSelect,'1'}, |
||
461 | {1,"", M_LoadSelect,'2'}, |
||
462 | {1,"", M_LoadSelect,'3'}, |
||
463 | {1,"", M_LoadSelect,'4'}, |
||
464 | {1,"", M_LoadSelect,'5'}, |
||
465 | {1,"", M_LoadSelect,'6'} |
||
466 | }; |
||
467 | |||
468 | menu_t LoadDef = |
||
469 | { |
||
470 | load_end, |
||
471 | &MainDef, |
||
472 | LoadMenu, |
||
473 | M_DrawLoad, |
||
474 | 80,54, |
||
475 | |||
476 | }; |
||
477 | |||
478 | // |
||
479 | // SAVE GAME MENU |
||
480 | // |
||
481 | menuitem_t SaveMenu[]= |
||
482 | { |
||
483 | {1,"", M_SaveSelect,'1'}, |
||
484 | {1,"", M_SaveSelect,'2'}, |
||
485 | {1,"", M_SaveSelect,'3'}, |
||
486 | {1,"", M_SaveSelect,'4'}, |
||
487 | {1,"", M_SaveSelect,'5'}, |
||
488 | {1,"", M_SaveSelect,'6'} |
||
489 | }; |
||
490 | |||
491 | menu_t SaveDef = |
||
492 | { |
||
493 | load_end, |
||
494 | &MainDef, |
||
495 | SaveMenu, |
||
496 | M_DrawSave, |
||
497 | 80,54, |
||
498 | |||
499 | }; |
||
500 | |||
501 | |||
502 | // |
||
503 | // M_ReadSaveStrings |
||
504 | // read the strings from the savegame files |
||
505 | // |
||
506 | void M_ReadSaveStrings(void) |
||
507 | { |
||
508 | FILE *handle; |
||
509 | int count; |
||
510 | int i; |
||
511 | char name[256]; |
||
550 | serge | 512 | |
298 | serge | 513 | for (i = 0;i < load_end;i++) |
514 | { |
||
550 | serge | 515 | sprintf(name,"doomsav%d.dsg",i); |
298 | serge | 516 | |
550 | serge | 517 | handle = fopen (name, "r"); |
518 | if (handle == NULL) |
||
519 | { |
||
520 | strcpy(&savegamestrings[i][0],EMPTYSTRING); |
||
521 | LoadMenu[i].status = 0; |
||
522 | continue; |
||
523 | } |
||
524 | count = fread (&savegamestrings[i], 1, SAVESTRINGSIZE, handle); |
||
525 | fclose (handle); |
||
526 | LoadMenu[i].status = 1; |
||
298 | serge | 527 | } |
528 | } |
||
529 | |||
530 | |||
531 | // |
||
532 | // M_LoadGame & Cie. |
||
533 | // |
||
534 | void M_DrawLoad(void) |
||
535 | { |
||
536 | int i; |
||
550 | serge | 537 | |
298 | serge | 538 | V_DrawPatchDirect (72,28,0,W_CacheLumpName("M_LOADG",PU_CACHE)); |
539 | for (i = 0;i < load_end; i++) |
||
540 | { |
||
550 | serge | 541 | M_DrawSaveLoadBorder(LoadDef.x,LoadDef.y+LINEHEIGHT*i); |
542 | M_WriteText(LoadDef.x,LoadDef.y+LINEHEIGHT*i,savegamestrings[i]); |
||
298 | serge | 543 | } |
544 | } |
||
545 | |||
546 | |||
547 | |||
548 | // |
||
549 | // Draw border for the savegame description |
||
550 | // |
||
551 | void M_DrawSaveLoadBorder(int x,int y) |
||
552 | { |
||
553 | int i; |
||
550 | serge | 554 | |
298 | serge | 555 | V_DrawPatchDirect (x-8,y+7,0,W_CacheLumpName("M_LSLEFT",PU_CACHE)); |
550 | serge | 556 | |
298 | serge | 557 | for (i = 0;i < 24;i++) |
558 | { |
||
550 | serge | 559 | V_DrawPatchDirect (x,y+7,0,W_CacheLumpName("M_LSCNTR",PU_CACHE)); |
560 | x += 8; |
||
298 | serge | 561 | } |
562 | |||
563 | V_DrawPatchDirect (x,y+7,0,W_CacheLumpName("M_LSRGHT",PU_CACHE)); |
||
564 | } |
||
565 | |||
566 | |||
567 | |||
568 | // |
||
569 | // User wants to load this game |
||
570 | // |
||
571 | void M_LoadSelect(int choice) |
||
572 | { |
||
573 | char name[256]; |
||
550 | serge | 574 | |
575 | // if (M_CheckParm("-cdrom")) |
||
576 | // sprintf(name,"c:\\doomdata\\doomsav%d.dsg",choice); |
||
577 | // else |
||
578 | sprintf(name,"doomsav%d.dsg",choice); |
||
579 | |||
298 | serge | 580 | G_LoadGame (name); |
581 | M_ClearMenus (); |
||
582 | } |
||
583 | |||
584 | // |
||
585 | // Selected from DOOM menu |
||
586 | // |
||
587 | void M_LoadGame (int choice) |
||
588 | { |
||
589 | if (netgame) |
||
590 | { |
||
550 | serge | 591 | M_StartMessage(LOADNET,NULL,false); |
592 | return; |
||
298 | serge | 593 | } |
550 | serge | 594 | |
298 | serge | 595 | M_SetupNextMenu(&LoadDef); |
596 | M_ReadSaveStrings(); |
||
597 | } |
||
598 | |||
599 | |||
600 | // |
||
601 | // M_SaveGame & Cie. |
||
602 | // |
||
603 | void M_DrawSave(void) |
||
604 | { |
||
605 | int i; |
||
550 | serge | 606 | |
298 | serge | 607 | V_DrawPatchDirect (72,28,0,W_CacheLumpName("M_SAVEG",PU_CACHE)); |
608 | for (i = 0;i < load_end; i++) |
||
609 | { |
||
550 | serge | 610 | M_DrawSaveLoadBorder(LoadDef.x,LoadDef.y+LINEHEIGHT*i); |
611 | M_WriteText(LoadDef.x,LoadDef.y+LINEHEIGHT*i,savegamestrings[i]); |
||
298 | serge | 612 | } |
550 | serge | 613 | |
298 | serge | 614 | if (saveStringEnter) |
615 | { |
||
550 | serge | 616 | i = M_StringWidth(savegamestrings[saveSlot]); |
617 | M_WriteText(LoadDef.x + i,LoadDef.y+LINEHEIGHT*saveSlot,"_"); |
||
298 | serge | 618 | } |
619 | } |
||
620 | |||
621 | // |
||
622 | // M_Responder calls this when user is finished |
||
623 | // |
||
624 | void M_DoSave(int slot) |
||
625 | { |
||
550 | serge | 626 | |
298 | serge | 627 | G_SaveGame (slot,savegamestrings[slot]); |
628 | M_ClearMenus (); |
||
629 | |||
630 | // PICK QUICKSAVE SLOT YET? |
||
631 | if (quickSaveSlot == -2) |
||
550 | serge | 632 | quickSaveSlot = slot; |
298 | serge | 633 | } |
634 | |||
635 | // |
||
636 | // User wants to save. Start string input for M_Responder |
||
637 | // |
||
638 | void M_SaveSelect(int choice) |
||
639 | { |
||
640 | // we are going to be intercepting all chars |
||
641 | saveStringEnter = 1; |
||
642 | |||
643 | saveSlot = choice; |
||
644 | strcpy(saveOldString,savegamestrings[choice]); |
||
645 | if (!strcmp(savegamestrings[choice],EMPTYSTRING)) |
||
550 | serge | 646 | savegamestrings[choice][0] = 0; |
298 | serge | 647 | saveCharIndex = strlen(savegamestrings[choice]); |
648 | } |
||
649 | |||
650 | // |
||
651 | // Selected from DOOM menu |
||
652 | // |
||
653 | void M_SaveGame (int choice) |
||
654 | { |
||
655 | if (!usergame) |
||
656 | { |
||
550 | serge | 657 | M_StartMessage(SAVEDEAD,NULL,false); |
658 | return; |
||
298 | serge | 659 | } |
550 | serge | 660 | |
298 | serge | 661 | if (gamestate != GS_LEVEL) |
550 | serge | 662 | return; |
663 | |||
298 | serge | 664 | M_SetupNextMenu(&SaveDef); |
665 | M_ReadSaveStrings(); |
||
666 | } |
||
667 | |||
668 | |||
669 | |||
670 | // |
||
671 | // M_QuickSave |
||
672 | // |
||
673 | char tempstring[80]; |
||
674 | |||
675 | void M_QuickSaveResponse(int ch) |
||
676 | { |
||
677 | if (ch == 'y') |
||
678 | { |
||
550 | serge | 679 | M_DoSave(quickSaveSlot); |
680 | S_StartSound(NULL,sfx_swtchx); |
||
298 | serge | 681 | } |
682 | } |
||
683 | |||
684 | void M_QuickSave(void) |
||
685 | { |
||
686 | if (!usergame) |
||
687 | { |
||
550 | serge | 688 | S_StartSound(NULL,sfx_oof); |
689 | return; |
||
298 | serge | 690 | } |
691 | |||
692 | if (gamestate != GS_LEVEL) |
||
550 | serge | 693 | return; |
694 | |||
298 | serge | 695 | if (quickSaveSlot < 0) |
696 | { |
||
550 | serge | 697 | M_StartControlPanel(); |
698 | M_ReadSaveStrings(); |
||
699 | M_SetupNextMenu(&SaveDef); |
||
700 | quickSaveSlot = -2; // means to pick a slot now |
||
701 | return; |
||
298 | serge | 702 | } |
703 | sprintf(tempstring,QSPROMPT,savegamestrings[quickSaveSlot]); |
||
704 | M_StartMessage(tempstring,M_QuickSaveResponse,true); |
||
705 | } |
||
706 | |||
707 | |||
708 | |||
709 | // |
||
710 | // M_QuickLoad |
||
711 | // |
||
712 | void M_QuickLoadResponse(int ch) |
||
713 | { |
||
714 | if (ch == 'y') |
||
715 | { |
||
550 | serge | 716 | M_LoadSelect(quickSaveSlot); |
717 | S_StartSound(NULL,sfx_swtchx); |
||
298 | serge | 718 | } |
719 | } |
||
720 | |||
721 | |||
722 | void M_QuickLoad(void) |
||
723 | { |
||
724 | if (netgame) |
||
725 | { |
||
550 | serge | 726 | M_StartMessage(QLOADNET,NULL,false); |
727 | return; |
||
298 | serge | 728 | } |
550 | serge | 729 | |
298 | serge | 730 | if (quickSaveSlot < 0) |
731 | { |
||
550 | serge | 732 | M_StartMessage(QSAVESPOT,NULL,false); |
733 | return; |
||
298 | serge | 734 | } |
735 | sprintf(tempstring,QLPROMPT,savegamestrings[quickSaveSlot]); |
||
736 | M_StartMessage(tempstring,M_QuickLoadResponse,true); |
||
737 | } |
||
738 | |||
739 | |||
740 | |||
741 | |||
742 | // |
||
743 | // Read This Menus |
||
744 | // Had a "quick hack to fix romero bug" |
||
745 | // |
||
746 | void M_DrawReadThis1(void) |
||
747 | { |
||
748 | inhelpscreens = true; |
||
749 | switch ( gamemode ) |
||
750 | { |
||
751 | case commercial: |
||
550 | serge | 752 | V_DrawPatchDirect (0,0,0,W_CacheLumpName("HELP",PU_CACHE)); |
753 | break; |
||
298 | serge | 754 | case shareware: |
755 | case registered: |
||
756 | case retail: |
||
550 | serge | 757 | V_DrawPatchDirect (0,0,0,W_CacheLumpName("HELP1",PU_CACHE)); |
758 | break; |
||
298 | serge | 759 | default: |
550 | serge | 760 | break; |
298 | serge | 761 | } |
762 | return; |
||
763 | } |
||
764 | |||
765 | |||
766 | |||
767 | // |
||
768 | // Read This Menus - optional second page. |
||
769 | // |
||
770 | void M_DrawReadThis2(void) |
||
771 | { |
||
772 | inhelpscreens = true; |
||
773 | switch ( gamemode ) |
||
774 | { |
||
775 | case retail: |
||
776 | case commercial: |
||
550 | serge | 777 | // This hack keeps us from having to change menus. |
778 | V_DrawPatchDirect (0,0,0,W_CacheLumpName("CREDIT",PU_CACHE)); |
||
779 | break; |
||
298 | serge | 780 | case shareware: |
781 | case registered: |
||
550 | serge | 782 | V_DrawPatchDirect (0,0,0,W_CacheLumpName("HELP2",PU_CACHE)); |
783 | break; |
||
298 | serge | 784 | default: |
550 | serge | 785 | break; |
298 | serge | 786 | } |
787 | return; |
||
788 | } |
||
789 | |||
790 | |||
791 | // |
||
792 | // Change Sfx & Music volumes |
||
793 | // |
||
794 | void M_DrawSound(void) |
||
795 | { |
||
796 | V_DrawPatchDirect (60,38,0,W_CacheLumpName("M_SVOL",PU_CACHE)); |
||
797 | |||
798 | M_DrawThermo(SoundDef.x,SoundDef.y+LINEHEIGHT*(sfx_vol+1), |
||
550 | serge | 799 | 16,snd_SfxVolume); |
298 | serge | 800 | |
801 | M_DrawThermo(SoundDef.x,SoundDef.y+LINEHEIGHT*(music_vol+1), |
||
550 | serge | 802 | 16,snd_MusicVolume); |
298 | serge | 803 | } |
804 | |||
805 | void M_Sound(int choice) |
||
806 | { |
||
807 | M_SetupNextMenu(&SoundDef); |
||
808 | } |
||
809 | |||
810 | void M_SfxVol(int choice) |
||
811 | { |
||
812 | switch(choice) |
||
813 | { |
||
814 | case 0: |
||
550 | serge | 815 | if (snd_SfxVolume) |
816 | snd_SfxVolume--; |
||
817 | break; |
||
298 | serge | 818 | case 1: |
550 | serge | 819 | if (snd_SfxVolume < 15) |
820 | snd_SfxVolume++; |
||
821 | break; |
||
298 | serge | 822 | } |
550 | serge | 823 | |
298 | serge | 824 | S_SetSfxVolume(snd_SfxVolume /* *8 */); |
825 | } |
||
826 | |||
827 | void M_MusicVol(int choice) |
||
828 | { |
||
829 | switch(choice) |
||
830 | { |
||
831 | case 0: |
||
550 | serge | 832 | if (snd_MusicVolume) |
833 | snd_MusicVolume--; |
||
834 | break; |
||
298 | serge | 835 | case 1: |
550 | serge | 836 | if (snd_MusicVolume < 15) |
837 | snd_MusicVolume++; |
||
838 | break; |
||
298 | serge | 839 | } |
550 | serge | 840 | |
298 | serge | 841 | S_SetMusicVolume(snd_MusicVolume /* *8 */); |
842 | } |
||
843 | |||
844 | |||
845 | |||
846 | |||
847 | // |
||
848 | // M_DrawMainMenu |
||
849 | // |
||
850 | void M_DrawMainMenu(void) |
||
851 | { |
||
852 | V_DrawPatchDirect (94,2,0,W_CacheLumpName("M_DOOM",PU_CACHE)); |
||
853 | } |
||
854 | |||
855 | |||
856 | |||
857 | |||
858 | // |
||
859 | // M_NewGame |
||
860 | // |
||
861 | void M_DrawNewGame(void) |
||
862 | { |
||
863 | V_DrawPatchDirect (96,14,0,W_CacheLumpName("M_NEWG",PU_CACHE)); |
||
864 | V_DrawPatchDirect (54,38,0,W_CacheLumpName("M_SKILL",PU_CACHE)); |
||
865 | } |
||
866 | |||
867 | void M_NewGame(int choice) |
||
868 | { |
||
869 | if (netgame && !demoplayback) |
||
870 | { |
||
550 | serge | 871 | M_StartMessage(NEWGAME,NULL,false); |
872 | return; |
||
298 | serge | 873 | } |
550 | serge | 874 | |
298 | serge | 875 | if ( gamemode == commercial ) |
550 | serge | 876 | M_SetupNextMenu(&NewDef); |
298 | serge | 877 | else |
550 | serge | 878 | M_SetupNextMenu(&EpiDef); |
298 | serge | 879 | } |
880 | |||
881 | |||
882 | // |
||
883 | // M_Episode |
||
884 | // |
||
885 | int epi; |
||
886 | |||
887 | void M_DrawEpisode(void) |
||
888 | { |
||
889 | V_DrawPatchDirect (54,38,0,W_CacheLumpName("M_EPISOD",PU_CACHE)); |
||
890 | } |
||
891 | |||
892 | void M_VerifyNightmare(int ch) |
||
893 | { |
||
894 | if (ch != 'y') |
||
550 | serge | 895 | return; |
896 | |||
298 | serge | 897 | G_DeferedInitNew(nightmare,epi+1,1); |
898 | M_ClearMenus (); |
||
899 | } |
||
900 | |||
901 | void M_ChooseSkill(int choice) |
||
902 | { |
||
903 | if (choice == nightmare) |
||
904 | { |
||
550 | serge | 905 | M_StartMessage(NIGHTMARE,M_VerifyNightmare,true); |
906 | return; |
||
298 | serge | 907 | } |
550 | serge | 908 | |
298 | serge | 909 | G_DeferedInitNew(choice,epi+1,1); |
910 | M_ClearMenus (); |
||
911 | } |
||
912 | |||
913 | void M_Episode(int choice) |
||
914 | { |
||
915 | if ( (gamemode == shareware) |
||
550 | serge | 916 | && choice) |
298 | serge | 917 | { |
550 | serge | 918 | M_StartMessage(SWSTRING,NULL,false); |
919 | M_SetupNextMenu(&ReadDef1); |
||
920 | return; |
||
298 | serge | 921 | } |
922 | |||
923 | // Yet another hack... |
||
924 | if ( (gamemode == registered) |
||
550 | serge | 925 | && (choice > 2)) |
298 | serge | 926 | { |
927 | // __libclog_printf("M_Episode: 4th episode requires UltimateDOOM\n"); |
||
928 | choice = 0; |
||
929 | } |
||
550 | serge | 930 | |
298 | serge | 931 | epi = choice; |
932 | M_SetupNextMenu(&NewDef); |
||
933 | } |
||
934 | |||
935 | |||
936 | |||
937 | // |
||
938 | // M_Options |
||
939 | // |
||
550 | serge | 940 | char detailNames[2][9] = {"M_GDHIGH","M_GDLOW"}; |
941 | char msgNames[2][9] = {"M_MSGOFF","M_MSGON"}; |
||
298 | serge | 942 | |
943 | |||
944 | void M_DrawOptions(void) |
||
945 | { |
||
946 | V_DrawPatchDirect (108,15,0,W_CacheLumpName("M_OPTTTL",PU_CACHE)); |
||
550 | serge | 947 | |
298 | serge | 948 | V_DrawPatchDirect (OptionsDef.x + 175,OptionsDef.y+LINEHEIGHT*detail,0, |
550 | serge | 949 | W_CacheLumpName(detailNames[detailLevel],PU_CACHE)); |
298 | serge | 950 | |
951 | V_DrawPatchDirect (OptionsDef.x + 120,OptionsDef.y+LINEHEIGHT*messages,0, |
||
550 | serge | 952 | W_CacheLumpName(msgNames[showMessages],PU_CACHE)); |
298 | serge | 953 | |
954 | M_DrawThermo(OptionsDef.x,OptionsDef.y+LINEHEIGHT*(mousesens+1), |
||
550 | serge | 955 | 10,mouseSensitivity); |
956 | |||
298 | serge | 957 | M_DrawThermo(OptionsDef.x,OptionsDef.y+LINEHEIGHT*(scrnsize+1), |
550 | serge | 958 | 9,screenSize); |
298 | serge | 959 | } |
960 | |||
961 | void M_Options(int choice) |
||
962 | { |
||
963 | M_SetupNextMenu(&OptionsDef); |
||
964 | } |
||
965 | |||
966 | |||
967 | |||
968 | // |
||
969 | // Toggle messages on/off |
||
970 | // |
||
971 | void M_ChangeMessages(int choice) |
||
972 | { |
||
973 | // warning: unused parameter `int choice' |
||
974 | choice = 0; |
||
975 | showMessages = 1 - showMessages; |
||
550 | serge | 976 | |
298 | serge | 977 | if (!showMessages) |
550 | serge | 978 | players[consoleplayer].message = MSGOFF; |
298 | serge | 979 | else |
550 | serge | 980 | players[consoleplayer].message = MSGON ; |
298 | serge | 981 | |
982 | message_dontfuckwithme = true; |
||
983 | } |
||
984 | |||
985 | |||
986 | // |
||
987 | // M_EndGame |
||
988 | // |
||
989 | void M_EndGameResponse(int ch) |
||
990 | { |
||
991 | if (ch != 'y') |
||
550 | serge | 992 | return; |
993 | |||
298 | serge | 994 | currentMenu->lastOn = itemOn; |
995 | M_ClearMenus (); |
||
996 | D_StartTitle (); |
||
997 | } |
||
998 | |||
999 | void M_EndGame(int choice) |
||
1000 | { |
||
1001 | choice = 0; |
||
1002 | if (!usergame) |
||
1003 | { |
||
550 | serge | 1004 | S_StartSound(NULL,sfx_oof); |
1005 | return; |
||
298 | serge | 1006 | } |
550 | serge | 1007 | |
298 | serge | 1008 | if (netgame) |
1009 | { |
||
550 | serge | 1010 | M_StartMessage(NETEND,NULL,false); |
1011 | return; |
||
298 | serge | 1012 | } |
550 | serge | 1013 | |
298 | serge | 1014 | M_StartMessage(ENDGAME,M_EndGameResponse,true); |
1015 | } |
||
1016 | |||
1017 | |||
1018 | |||
1019 | |||
1020 | // |
||
1021 | // M_ReadThis |
||
1022 | // |
||
1023 | void M_ReadThis(int choice) |
||
1024 | { |
||
1025 | choice = 0; |
||
1026 | M_SetupNextMenu(&ReadDef1); |
||
1027 | } |
||
1028 | |||
1029 | void M_ReadThis2(int choice) |
||
1030 | { |
||
1031 | choice = 0; |
||
1032 | M_SetupNextMenu(&ReadDef2); |
||
1033 | } |
||
1034 | |||
1035 | void M_FinishReadThis(int choice) |
||
1036 | { |
||
1037 | choice = 0; |
||
1038 | M_SetupNextMenu(&MainDef); |
||
1039 | } |
||
1040 | |||
1041 | |||
1042 | |||
1043 | |||
1044 | // |
||
1045 | // M_QuitDOOM |
||
1046 | // |
||
1047 | int quitsounds[8] = |
||
1048 | { |
||
1049 | sfx_pldeth, |
||
1050 | sfx_dmpain, |
||
1051 | sfx_popain, |
||
1052 | sfx_slop, |
||
1053 | sfx_telept, |
||
1054 | sfx_posit1, |
||
1055 | sfx_posit3, |
||
1056 | sfx_sgtatk |
||
1057 | }; |
||
1058 | |||
1059 | int quitsounds2[8] = |
||
1060 | { |
||
1061 | sfx_vilact, |
||
1062 | sfx_getpow, |
||
1063 | sfx_boscub, |
||
1064 | sfx_slop, |
||
1065 | sfx_skeswg, |
||
1066 | sfx_kntdth, |
||
1067 | sfx_bspact, |
||
1068 | sfx_sgtatk |
||
1069 | }; |
||
1070 | |||
1071 | |||
1072 | |||
1073 | void M_QuitResponse(int ch) |
||
1074 | { |
||
1075 | if (ch != 'y') |
||
550 | serge | 1076 | return; |
298 | serge | 1077 | if (!netgame) |
1078 | { |
||
550 | serge | 1079 | if (gamemode == commercial) |
1080 | S_StartSound(NULL,quitsounds2[(gametic>>2)&7]); |
||
1081 | else |
||
1082 | S_StartSound(NULL,quitsounds[(gametic>>2)&7]); |
||
1083 | I_WaitVBL(105); |
||
298 | serge | 1084 | } |
1085 | I_Quit (); |
||
1086 | } |
||
1087 | |||
1088 | |||
1089 | |||
1090 | |||
1091 | void M_QuitDOOM(int choice) |
||
1092 | { |
||
1093 | // We pick index 0 which is language sensitive, |
||
1094 | // or one at random, between 1 and maximum number. |
||
1095 | if (language != english ) |
||
1096 | sprintf(endstring,"%s\n\n"DOSY, endmsg[0] ); |
||
1097 | else |
||
1098 | sprintf(endstring,"%s\n\n"DOSY, endmsg[ (gametic%(NUM_QUITMESSAGES-2))+1 ]); |
||
1099 | |||
1100 | M_StartMessage(endstring,M_QuitResponse,true); |
||
1101 | } |
||
1102 | |||
1103 | |||
1104 | |||
1105 | void M_ChangeSensitivity(int choice) |
||
1106 | { |
||
1107 | switch(choice) |
||
1108 | { |
||
1109 | case 0: |
||
550 | serge | 1110 | if (mouseSensitivity) |
1111 | mouseSensitivity--; |
||
1112 | break; |
||
298 | serge | 1113 | case 1: |
550 | serge | 1114 | if (mouseSensitivity < 9) |
1115 | mouseSensitivity++; |
||
1116 | break; |
||
298 | serge | 1117 | } |
1118 | } |
||
1119 | |||
1120 | |||
1121 | |||
1122 | |||
1123 | void M_ChangeDetail(int choice) |
||
1124 | { |
||
1125 | choice = 0; |
||
1126 | detailLevel = 1 - detailLevel; |
||
1127 | |||
1128 | // FIXME - does not work. Remove anyway? |
||
1129 | // __libclog_printf("M_ChangeDetail: low detail mode n.a.\n"); |
||
1130 | |||
1131 | return; |
||
1132 | |||
1133 | /*R_SetViewSize (screenblocks, detailLevel); |
||
1134 | |||
1135 | if (!detailLevel) |
||
550 | serge | 1136 | players[consoleplayer].message = DETAILHI; |
298 | serge | 1137 | else |
550 | serge | 1138 | players[consoleplayer].message = DETAILLO;*/ |
298 | serge | 1139 | } |
1140 | |||
1141 | |||
1142 | |||
1143 | |||
1144 | void M_SizeDisplay(int choice) |
||
1145 | { |
||
1146 | switch(choice) |
||
1147 | { |
||
1148 | case 0: |
||
550 | serge | 1149 | if (screenSize > 0) |
1150 | { |
||
1151 | screenblocks--; |
||
1152 | screenSize--; |
||
1153 | } |
||
1154 | break; |
||
298 | serge | 1155 | case 1: |
550 | serge | 1156 | if (screenSize < 8) |
1157 | { |
||
1158 | screenblocks++; |
||
1159 | screenSize++; |
||
1160 | } |
||
1161 | break; |
||
298 | serge | 1162 | } |
550 | serge | 1163 | |
298 | serge | 1164 | |
1165 | R_SetViewSize (screenblocks, detailLevel); |
||
1166 | } |
||
1167 | |||
1168 | |||
1169 | |||
1170 | |||
1171 | // |
||
1172 | // Menu Functions |
||
1173 | // |
||
1174 | void |
||
1175 | M_DrawThermo |
||
550 | serge | 1176 | ( int x, |
1177 | int y, |
||
1178 | int thermWidth, |
||
1179 | int thermDot ) |
||
298 | serge | 1180 | { |
550 | serge | 1181 | int xx; |
1182 | int i; |
||
298 | serge | 1183 | |
1184 | xx = x; |
||
1185 | V_DrawPatchDirect (xx,y,0,W_CacheLumpName("M_THERML",PU_CACHE)); |
||
1186 | xx += 8; |
||
1187 | for (i=0;i |
||
1188 | { |
||
550 | serge | 1189 | V_DrawPatchDirect (xx,y,0,W_CacheLumpName("M_THERMM",PU_CACHE)); |
1190 | xx += 8; |
||
298 | serge | 1191 | } |
1192 | V_DrawPatchDirect (xx,y,0,W_CacheLumpName("M_THERMR",PU_CACHE)); |
||
1193 | |||
1194 | V_DrawPatchDirect ((x+8) + thermDot*8,y, |
||
550 | serge | 1195 | 0,W_CacheLumpName("M_THERMO",PU_CACHE)); |
298 | serge | 1196 | } |
1197 | |||
1198 | |||
1199 | |||
1200 | void |
||
1201 | M_DrawEmptyCell |
||
550 | serge | 1202 | ( menu_t* menu, |
1203 | int item ) |
||
298 | serge | 1204 | { |
1205 | V_DrawPatchDirect (menu->x - 10, menu->y+item*LINEHEIGHT - 1, 0, |
||
550 | serge | 1206 | W_CacheLumpName("M_CELL1",PU_CACHE)); |
298 | serge | 1207 | } |
1208 | |||
1209 | void |
||
1210 | M_DrawSelCell |
||
550 | serge | 1211 | ( menu_t* menu, |
1212 | int item ) |
||
298 | serge | 1213 | { |
1214 | V_DrawPatchDirect (menu->x - 10, menu->y+item*LINEHEIGHT - 1, 0, |
||
550 | serge | 1215 | W_CacheLumpName("M_CELL2",PU_CACHE)); |
298 | serge | 1216 | } |
1217 | |||
1218 | |||
1219 | void |
||
1220 | M_StartMessage |
||
550 | serge | 1221 | ( char* string, |
1222 | void* routine, |
||
1223 | boolean input ) |
||
298 | serge | 1224 | { |
1225 | messageLastMenuActive = menuactive; |
||
1226 | messageToPrint = 1; |
||
1227 | messageString = string; |
||
1228 | messageRoutine = routine; |
||
1229 | messageNeedsInput = input; |
||
1230 | menuactive = true; |
||
1231 | return; |
||
1232 | } |
||
1233 | |||
1234 | |||
1235 | |||
1236 | void M_StopMessage(void) |
||
1237 | { |
||
1238 | menuactive = messageLastMenuActive; |
||
1239 | messageToPrint = 0; |
||
1240 | } |
||
1241 | |||
1242 | |||
1243 | |||
1244 | // |
||
1245 | // Find string width from hu_font chars |
||
1246 | // |
||
1247 | int M_StringWidth(char* string) |
||
1248 | { |
||
1249 | int i; |
||
1250 | int w = 0; |
||
1251 | int c; |
||
550 | serge | 1252 | |
298 | serge | 1253 | for (i = 0;i < strlen(string);i++) |
1254 | { |
||
550 | serge | 1255 | c = toupper(string[i]) - HU_FONTSTART; |
1256 | if (c < 0 || c >= HU_FONTSIZE) |
||
1257 | w += 4; |
||
1258 | else |
||
1259 | w += SHORT (hu_font[c]->width); |
||
298 | serge | 1260 | } |
550 | serge | 1261 | |
298 | serge | 1262 | return w; |
1263 | } |
||
1264 | |||
1265 | |||
1266 | |||
1267 | // |
||
1268 | // Find string height from hu_font chars |
||
1269 | // |
||
1270 | int M_StringHeight(char* string) |
||
1271 | { |
||
1272 | int i; |
||
1273 | int h; |
||
1274 | int height = SHORT(hu_font[0]->height); |
||
550 | serge | 1275 | |
298 | serge | 1276 | h = height; |
1277 | for (i = 0;i < strlen(string);i++) |
||
550 | serge | 1278 | if (string[i] == '\n') |
1279 | h += height; |
||
1280 | |||
298 | serge | 1281 | return h; |
1282 | } |
||
1283 | |||
1284 | |||
1285 | // |
||
1286 | // Write a string using the hu_font |
||
1287 | // |
||
1288 | void |
||
1289 | M_WriteText |
||
550 | serge | 1290 | ( int x, |
1291 | int y, |
||
1292 | char* string) |
||
298 | serge | 1293 | { |
550 | serge | 1294 | int w; |
1295 | char* ch; |
||
1296 | int c; |
||
1297 | int cx; |
||
1298 | int cy; |
||
1299 | |||
298 | serge | 1300 | |
1301 | ch = string; |
||
1302 | cx = x; |
||
1303 | cy = y; |
||
550 | serge | 1304 | |
298 | serge | 1305 | while(1) |
1306 | { |
||
550 | serge | 1307 | c = *ch++; |
1308 | if (!c) |
||
1309 | break; |
||
1310 | if (c == '\n') |
||
1311 | { |
||
1312 | cx = x; |
||
1313 | cy += 12; |
||
1314 | continue; |
||
1315 | } |
||
1316 | |||
1317 | c = toupper(c) - HU_FONTSTART; |
||
1318 | if (c < 0 || c>= HU_FONTSIZE) |
||
1319 | { |
||
1320 | cx += 4; |
||
1321 | continue; |
||
1322 | } |
||
1323 | |||
1324 | w = SHORT (hu_font[c]->width); |
||
1325 | if (cx+w > SCREENWIDTH) |
||
1326 | break; |
||
1327 | V_DrawPatchDirect(cx, cy, 0, hu_font[c]); |
||
1328 | cx+=w; |
||
298 | serge | 1329 | } |
1330 | } |
||
1331 | |||
1332 | |||
1333 | |||
1334 | // |
||
1335 | // CONTROL PANEL |
||
1336 | // |
||
1337 | |||
1338 | // |
||
1339 | // M_Responder |
||
1340 | // |
||
1341 | boolean M_Responder (event_t* ev) |
||
1342 | { |
||
1343 | int ch; |
||
1344 | int i; |
||
1345 | static int joywait = 0; |
||
1346 | static int mousewait = 0; |
||
1347 | static int mousey = 0; |
||
1348 | static int lasty = 0; |
||
1349 | static int mousex = 0; |
||
1350 | static int lastx = 0; |
||
550 | serge | 1351 | |
298 | serge | 1352 | ch = -1; |
550 | serge | 1353 | |
298 | serge | 1354 | if (ev->type == ev_joystick && joywait < I_GetTime()) |
1355 | { |
||
550 | serge | 1356 | if (ev->data3 == -1) |
1357 | { |
||
1358 | ch = KEY_UPARROW; |
||
1359 | joywait = I_GetTime() + 5; |
||
1360 | } |
||
1361 | else if (ev->data3 == 1) |
||
1362 | { |
||
1363 | ch = KEY_DOWNARROW; |
||
1364 | joywait = I_GetTime() + 5; |
||
1365 | } |
||
1366 | |||
1367 | if (ev->data2 == -1) |
||
1368 | { |
||
1369 | ch = KEY_LEFTARROW; |
||
1370 | joywait = I_GetTime() + 2; |
||
1371 | } |
||
1372 | else if (ev->data2 == 1) |
||
1373 | { |
||
1374 | ch = KEY_RIGHTARROW; |
||
1375 | joywait = I_GetTime() + 2; |
||
1376 | } |
||
1377 | |||
1378 | if (ev->data1&1) |
||
1379 | { |
||
1380 | ch = KEY_ENTER; |
||
1381 | joywait = I_GetTime() + 5; |
||
1382 | } |
||
1383 | if (ev->data1&2) |
||
1384 | { |
||
1385 | ch = KEY_BACKSPACE; |
||
1386 | joywait = I_GetTime() + 5; |
||
1387 | } |
||
298 | serge | 1388 | } |
1389 | else |
||
1390 | { |
||
550 | serge | 1391 | if (ev->type == ev_mouse && mousewait < I_GetTime()) |
1392 | { |
||
1393 | mousey += ev->data3; |
||
1394 | if (mousey < lasty-30) |
||
1395 | { |
||
1396 | ch = KEY_DOWNARROW; |
||
1397 | mousewait = I_GetTime() + 5; |
||
1398 | mousey = lasty -= 30; |
||
1399 | } |
||
1400 | else if (mousey > lasty+30) |
||
1401 | { |
||
1402 | ch = KEY_UPARROW; |
||
1403 | mousewait = I_GetTime() + 5; |
||
1404 | mousey = lasty += 30; |
||
1405 | } |
||
1406 | |||
1407 | mousex += ev->data2; |
||
1408 | if (mousex < lastx-30) |
||
1409 | { |
||
1410 | ch = KEY_LEFTARROW; |
||
1411 | mousewait = I_GetTime() + 5; |
||
1412 | mousex = lastx -= 30; |
||
1413 | } |
||
1414 | else if (mousex > lastx+30) |
||
1415 | { |
||
1416 | ch = KEY_RIGHTARROW; |
||
1417 | mousewait = I_GetTime() + 5; |
||
1418 | mousex = lastx += 30; |
||
1419 | } |
||
1420 | |||
1421 | if (ev->data1&1) |
||
1422 | { |
||
1423 | ch = KEY_ENTER; |
||
1424 | mousewait = I_GetTime() + 15; |
||
1425 | } |
||
1426 | |||
1427 | if (ev->data1&2) |
||
1428 | { |
||
1429 | ch = KEY_BACKSPACE; |
||
1430 | mousewait = I_GetTime() + 15; |
||
1431 | } |
||
1432 | } |
||
1433 | else |
||
1434 | if (ev->type == ev_keydown) |
||
1435 | { |
||
1436 | ch = ev->data1; |
||
1437 | } |
||
298 | serge | 1438 | } |
1439 | |||
1440 | if (ch == -1) |
||
550 | serge | 1441 | return false; |
298 | serge | 1442 | |
1443 | |||
1444 | // Save Game string input |
||
1445 | if (saveStringEnter) |
||
1446 | { |
||
550 | serge | 1447 | switch(ch) |
1448 | { |
||
1449 | case KEY_BACKSPACE: |
||
1450 | if (saveCharIndex > 0) |
||
1451 | { |
||
1452 | saveCharIndex--; |
||
1453 | savegamestrings[saveSlot][saveCharIndex] = 0; |
||
1454 | } |
||
1455 | break; |
||
1456 | |||
1457 | case KEY_ESCAPE: |
||
1458 | saveStringEnter = 0; |
||
1459 | strcpy(&savegamestrings[saveSlot][0],saveOldString); |
||
1460 | break; |
||
1461 | |||
1462 | case KEY_ENTER: |
||
1463 | saveStringEnter = 0; |
||
1464 | if (savegamestrings[saveSlot][0]) |
||
1465 | M_DoSave(saveSlot); |
||
1466 | break; |
||
1467 | |||
1468 | default: |
||
1469 | ch = toupper(ch); |
||
1470 | if (ch != 32) |
||
1471 | if (ch-HU_FONTSTART < 0 || ch-HU_FONTSTART >= HU_FONTSIZE) |
||
1472 | break; |
||
1473 | if (ch >= 32 && ch <= 127 && |
||
1474 | saveCharIndex < SAVESTRINGSIZE-1 && |
||
1475 | M_StringWidth(savegamestrings[saveSlot]) < |
||
1476 | (SAVESTRINGSIZE-2)*8) |
||
1477 | { |
||
1478 | savegamestrings[saveSlot][saveCharIndex++] = ch; |
||
1479 | savegamestrings[saveSlot][saveCharIndex] = 0; |
||
1480 | } |
||
1481 | break; |
||
1482 | } |
||
1483 | return true; |
||
298 | serge | 1484 | } |
1485 | |||
1486 | // Take care of any messages that need input |
||
1487 | if (messageToPrint) |
||
1488 | { |
||
550 | serge | 1489 | if (messageNeedsInput == true && |
1490 | !(ch == ' ' || ch == 'n' || ch == 'y' || ch == KEY_ESCAPE)) |
||
1491 | return false; |
||
1492 | |||
1493 | menuactive = messageLastMenuActive; |
||
1494 | messageToPrint = 0; |
||
1495 | if (messageRoutine) |
||
1496 | messageRoutine(ch); |
||
1497 | |||
1498 | menuactive = false; |
||
1499 | S_StartSound(NULL,sfx_swtchx); |
||
1500 | return true; |
||
298 | serge | 1501 | } |
550 | serge | 1502 | |
298 | serge | 1503 | if (devparm && ch == KEY_F1) |
1504 | { |
||
550 | serge | 1505 | G_ScreenShot (); |
1506 | return true; |
||
298 | serge | 1507 | } |
550 | serge | 1508 | |
298 | serge | 1509 | |
1510 | // F-Keys |
||
1511 | if (!menuactive) |
||
550 | serge | 1512 | switch(ch) |
1513 | { |
||
1514 | case KEY_MINUS: // Screen size down |
||
1515 | if (automapactive || chat_on) |
||
1516 | return false; |
||
1517 | M_SizeDisplay(0); |
||
1518 | S_StartSound(NULL,sfx_stnmov); |
||
1519 | return true; |
||
1520 | |||
1521 | case KEY_EQUALS: // Screen size up |
||
1522 | if (automapactive || chat_on) |
||
1523 | return false; |
||
1524 | M_SizeDisplay(1); |
||
1525 | S_StartSound(NULL,sfx_stnmov); |
||
1526 | return true; |
||
1527 | |||
1528 | case KEY_F1: // Help key |
||
1529 | M_StartControlPanel (); |
||
298 | serge | 1530 | |
550 | serge | 1531 | if ( gamemode == retail ) |
1532 | currentMenu = &ReadDef2; |
||
1533 | else |
||
1534 | currentMenu = &ReadDef1; |
||
1535 | |||
1536 | itemOn = 0; |
||
1537 | S_StartSound(NULL,sfx_swtchn); |
||
1538 | return true; |
||
1539 | |||
1540 | case KEY_F2: // Save |
||
1541 | M_StartControlPanel(); |
||
1542 | S_StartSound(NULL,sfx_swtchn); |
||
1543 | M_SaveGame(0); |
||
1544 | return true; |
||
1545 | |||
1546 | case KEY_F3: // Load |
||
1547 | M_StartControlPanel(); |
||
1548 | S_StartSound(NULL,sfx_swtchn); |
||
1549 | M_LoadGame(0); |
||
1550 | return true; |
||
1551 | |||
1552 | case KEY_F4: // Sound Volume |
||
1553 | M_StartControlPanel (); |
||
1554 | currentMenu = &SoundDef; |
||
1555 | itemOn = sfx_vol; |
||
1556 | S_StartSound(NULL,sfx_swtchn); |
||
1557 | return true; |
||
1558 | |||
1559 | case KEY_F5: // Detail toggle |
||
1560 | M_ChangeDetail(0); |
||
1561 | S_StartSound(NULL,sfx_swtchn); |
||
1562 | return true; |
||
1563 | |||
1564 | case KEY_F6: // Quicksave |
||
1565 | S_StartSound(NULL,sfx_swtchn); |
||
1566 | M_QuickSave(); |
||
1567 | return true; |
||
1568 | |||
1569 | case KEY_F7: // End game |
||
1570 | S_StartSound(NULL,sfx_swtchn); |
||
1571 | M_EndGame(0); |
||
1572 | return true; |
||
1573 | |||
1574 | case KEY_F8: // Toggle messages |
||
1575 | M_ChangeMessages(0); |
||
1576 | S_StartSound(NULL,sfx_swtchn); |
||
1577 | return true; |
||
1578 | |||
1579 | case KEY_F9: // Quickload |
||
1580 | S_StartSound(NULL,sfx_swtchn); |
||
1581 | M_QuickLoad(); |
||
1582 | return true; |
||
1583 | |||
1584 | case KEY_F10: // Quit DOOM |
||
1585 | S_StartSound(NULL,sfx_swtchn); |
||
1586 | M_QuitDOOM(0); |
||
1587 | return true; |
||
1588 | |||
1589 | case KEY_F11: // gamma toggle |
||
1590 | usegamma++; |
||
1591 | if (usegamma > 4) |
||
1592 | usegamma = 0; |
||
1593 | players[consoleplayer].message = gammamsg[usegamma]; |
||
1594 | I_SetPalette (W_CacheLumpName ("PLAYPAL",PU_CACHE)); |
||
1595 | return true; |
||
1596 | |||
1597 | } |
||
298 | serge | 1598 | |
1599 | |||
1600 | // Pop-up menu? |
||
1601 | if (!menuactive) |
||
1602 | { |
||
550 | serge | 1603 | if (ch == KEY_ESCAPE) |
1604 | { |
||
1605 | M_StartControlPanel (); |
||
1606 | S_StartSound(NULL,sfx_swtchn); |
||
1607 | return true; |
||
1608 | } |
||
1609 | return false; |
||
298 | serge | 1610 | } |
1611 | |||
1612 | |||
1613 | // Keys usable within menu |
||
1614 | switch (ch) |
||
1615 | { |
||
1616 | case KEY_DOWNARROW: |
||
550 | serge | 1617 | do |
1618 | { |
||
1619 | if (itemOn+1 > currentMenu->numitems-1) |
||
1620 | itemOn = 0; |
||
1621 | else itemOn++; |
||
1622 | S_StartSound(NULL,sfx_pstop); |
||
1623 | } while(currentMenu->menuitems[itemOn].status==-1); |
||
1624 | return true; |
||
1625 | |||
298 | serge | 1626 | case KEY_UPARROW: |
550 | serge | 1627 | do |
1628 | { |
||
1629 | if (!itemOn) |
||
1630 | itemOn = currentMenu->numitems-1; |
||
1631 | else itemOn--; |
||
1632 | S_StartSound(NULL,sfx_pstop); |
||
1633 | } while(currentMenu->menuitems[itemOn].status==-1); |
||
1634 | return true; |
||
298 | serge | 1635 | |
1636 | case KEY_LEFTARROW: |
||
550 | serge | 1637 | if (currentMenu->menuitems[itemOn].routine && |
1638 | currentMenu->menuitems[itemOn].status == 2) |
||
1639 | { |
||
1640 | S_StartSound(NULL,sfx_stnmov); |
||
1641 | currentMenu->menuitems[itemOn].routine(0); |
||
1642 | } |
||
1643 | return true; |
||
1644 | |||
298 | serge | 1645 | case KEY_RIGHTARROW: |
550 | serge | 1646 | if (currentMenu->menuitems[itemOn].routine && |
1647 | currentMenu->menuitems[itemOn].status == 2) |
||
1648 | { |
||
1649 | S_StartSound(NULL,sfx_stnmov); |
||
1650 | currentMenu->menuitems[itemOn].routine(1); |
||
1651 | } |
||
1652 | return true; |
||
298 | serge | 1653 | |
1654 | case KEY_ENTER: |
||
550 | serge | 1655 | if (currentMenu->menuitems[itemOn].routine && |
1656 | currentMenu->menuitems[itemOn].status) |
||
1657 | { |
||
1658 | currentMenu->lastOn = itemOn; |
||
1659 | if (currentMenu->menuitems[itemOn].status == 2) |
||
1660 | { |
||
1661 | currentMenu->menuitems[itemOn].routine(1); // right arrow |
||
1662 | S_StartSound(NULL,sfx_stnmov); |
||
1663 | } |
||
1664 | else |
||
1665 | { |
||
1666 | currentMenu->menuitems[itemOn].routine(itemOn); |
||
1667 | S_StartSound(NULL,sfx_pistol); |
||
1668 | } |
||
1669 | } |
||
1670 | return true; |
||
1671 | |||
298 | serge | 1672 | case KEY_ESCAPE: |
550 | serge | 1673 | currentMenu->lastOn = itemOn; |
1674 | M_ClearMenus (); |
||
1675 | S_StartSound(NULL,sfx_swtchx); |
||
1676 | return true; |
||
1677 | |||
298 | serge | 1678 | case KEY_BACKSPACE: |
550 | serge | 1679 | currentMenu->lastOn = itemOn; |
1680 | if (currentMenu->prevMenu) |
||
1681 | { |
||
1682 | currentMenu = currentMenu->prevMenu; |
||
1683 | itemOn = currentMenu->lastOn; |
||
1684 | S_StartSound(NULL,sfx_swtchn); |
||
1685 | } |
||
1686 | return true; |
||
1687 | |||
298 | serge | 1688 | default: |
550 | serge | 1689 | for (i = itemOn+1;i < currentMenu->numitems;i++) |
1690 | if (currentMenu->menuitems[i].alphaKey == ch) |
||
1691 | { |
||
1692 | itemOn = i; |
||
1693 | S_StartSound(NULL,sfx_pstop); |
||
1694 | return true; |
||
1695 | } |
||
1696 | for (i = 0;i <= itemOn;i++) |
||
1697 | if (currentMenu->menuitems[i].alphaKey == ch) |
||
1698 | { |
||
1699 | itemOn = i; |
||
1700 | S_StartSound(NULL,sfx_pstop); |
||
1701 | return true; |
||
1702 | } |
||
1703 | break; |
||
1704 | |||
298 | serge | 1705 | } |
1706 | |||
1707 | return false; |
||
1708 | } |
||
1709 | |||
1710 | |||
1711 | |||
1712 | // |
||
1713 | // M_StartControlPanel |
||
1714 | // |
||
1715 | void M_StartControlPanel (void) |
||
1716 | { |
||
1717 | // intro might call this repeatedly |
||
1718 | if (menuactive) |
||
550 | serge | 1719 | return; |
298 | serge | 1720 | |
1721 | menuactive = 1; |
||
1722 | currentMenu = &MainDef; // JDC |
||
1723 | itemOn = currentMenu->lastOn; // JDC |
||
1724 | } |
||
1725 | |||
1726 | |||
1727 | // |
||
1728 | // M_Drawer |
||
1729 | // Called after the view has been rendered, |
||
1730 | // but before it has been blitted. |
||
1731 | // |
||
1732 | void M_Drawer (void) |
||
1733 | { |
||
550 | serge | 1734 | static short x; |
1735 | static short y; |
||
1736 | short i; |
||
1737 | short max; |
||
300 | serge | 1738 | char *p; |
1739 | int len; |
||
550 | serge | 1740 | char string[40]; |
1741 | int start; |
||
298 | serge | 1742 | |
1743 | inhelpscreens = false; |
||
1744 | |||
1745 | // Horiz. & Vertically center string and print it. |
||
1746 | if (messageToPrint) |
||
1747 | { |
||
550 | serge | 1748 | y = 100 - M_StringHeight(messageString)/2; |
1749 | p = messageString; |
||
1750 | len = strlen(p); |
||
1751 | while(*p) |
||
1752 | { |
||
300 | serge | 1753 | for (i = 0;len;i++,len--) |
1754 | { |
||
550 | serge | 1755 | if (*(p+i) == '\n') |
1756 | { memset(string,0,40); |
||
1757 | strncpy(string,p,i); |
||
1758 | p+= i+1; |
||
1759 | len-= 1; |
||
1760 | break; |
||
1761 | }; |
||
1762 | }; |
||
1763 | |||
300 | serge | 1764 | if (len == 0) |
1765 | { strncpy(string,p,i); |
||
1766 | p+=i; |
||
1767 | }; |
||
1768 | x = 160 - M_StringWidth(string)/2; |
||
1769 | M_WriteText(x,y,string); |
||
1770 | y += SHORT(hu_font[0]->height); |
||
550 | serge | 1771 | }; |
1772 | return; |
||
300 | serge | 1773 | }; |
298 | serge | 1774 | |
1775 | if (!menuactive) |
||
550 | serge | 1776 | return; |
298 | serge | 1777 | |
1778 | if (currentMenu->routine) |
||
550 | serge | 1779 | currentMenu->routine(); // call Draw routine |
298 | serge | 1780 | |
1781 | // DRAW MENU |
||
1782 | x = currentMenu->x; |
||
1783 | y = currentMenu->y; |
||
1784 | max = currentMenu->numitems; |
||
1785 | |||
1786 | for (i=0;i |
||
1787 | { |
||
550 | serge | 1788 | if (currentMenu->menuitems[i].name[0]) |
1789 | V_DrawPatchDirect (x,y,0, |
||
1790 | W_CacheLumpName(currentMenu->menuitems[i].name ,PU_CACHE)); |
||
1791 | y += LINEHEIGHT; |
||
298 | serge | 1792 | } |
1793 | |||
1794 | |||
1795 | // DRAW SKULL |
||
1796 | V_DrawPatchDirect(x + SKULLXOFF,currentMenu->y - 5 + itemOn*LINEHEIGHT, 0, |
||
550 | serge | 1797 | W_CacheLumpName(skullName[whichSkull],PU_CACHE)); |
298 | serge | 1798 | |
1799 | } |
||
1800 | |||
1801 | |||
1802 | // |
||
1803 | // M_ClearMenus |
||
1804 | // |
||
1805 | void M_ClearMenus (void) |
||
1806 | { |
||
1807 | menuactive = 0; |
||
1808 | // if (!netgame && usergame && paused) |
||
1809 | // sendpause = true; |
||
1810 | } |
||
1811 | |||
1812 | |||
1813 | |||
1814 | |||
1815 | // |
||
1816 | // M_SetupNextMenu |
||
1817 | // |
||
1818 | void M_SetupNextMenu(menu_t *menudef) |
||
1819 | { |
||
1820 | currentMenu = menudef; |
||
1821 | itemOn = currentMenu->lastOn; |
||
1822 | } |
||
1823 | |||
1824 | |||
1825 | // |
||
1826 | // M_Ticker |
||
1827 | // |
||
1828 | void M_Ticker (void) |
||
1829 | { |
||
1830 | if (--skullAnimCounter <= 0) |
||
1831 | { |
||
550 | serge | 1832 | whichSkull ^= 1; |
1833 | skullAnimCounter = 8; |
||
298 | serge | 1834 | } |
1835 | } |
||
1836 | |||
1837 | |||
1838 | // |
||
1839 | // M_Init |
||
1840 | // |
||
1841 | void M_Init (void) |
||
1842 | { |
||
1843 | currentMenu = &MainDef; |
||
1844 | menuactive = 0; |
||
1845 | itemOn = currentMenu->lastOn; |
||
1846 | whichSkull = 0; |
||
1847 | skullAnimCounter = 10; |
||
1848 | screenSize = screenblocks - 3; |
||
1849 | messageToPrint = 0; |
||
1850 | messageString = NULL; |
||
1851 | messageLastMenuActive = menuactive; |
||
1852 | quickSaveSlot = -1; |
||
1853 | |||
1854 | // Here we could catch other version dependencies, |
||
1855 | // like HELP1/2, and four episodes. |
||
1856 | |||
1857 | |||
1858 | switch ( gamemode ) |
||
1859 | { |
||
1860 | case commercial: |
||
550 | serge | 1861 | // This is used because DOOM 2 had only one HELP |
298 | serge | 1862 | // page. I use CREDIT as second page now, but |
550 | serge | 1863 | // kept this hack for educational purposes. |
1864 | MainMenu[readthis] = MainMenu[quitdoom]; |
||
1865 | MainDef.numitems--; |
||
1866 | MainDef.y += 8; |
||
1867 | NewDef.prevMenu = &MainDef; |
||
1868 | ReadDef1.routine = M_DrawReadThis1; |
||
1869 | ReadDef1.x = 330; |
||
1870 | ReadDef1.y = 165; |
||
1871 | ReadMenu1[0].routine = M_FinishReadThis; |
||
1872 | break; |
||
298 | serge | 1873 | case shareware: |
550 | serge | 1874 | // Episode 2 and 3 are handled, |
1875 | // branching to an ad screen. |
||
298 | serge | 1876 | case registered: |
550 | serge | 1877 | // We need to remove the fourth episode. |
1878 | EpiDef.numitems--; |
||
1879 | break; |
||
298 | serge | 1880 | case retail: |
550 | serge | 1881 | // We are fine. |
298 | serge | 1882 | default: |
550 | serge | 1883 | break; |
298 | serge | 1884 | } |
1885 | |||
1886 | }=> |
||
1887 |