1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
6 // Copyright (C) 1993-1996 by id Software, Inc.
8 // This program is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU General Public License
10 // as published by the Free Software Foundation; either version 2
11 // of the License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
19 // Revision 1.7 2006/12/13 04:44:17 kkurbjun
20 // Dehacked and BEX support for Doom - currently only supports a DEHACKED file in a WAD (not as a standalone file yet).
22 // Revision 1.6 2006-04-16 23:14:04 kkurbjun
23 // Fix run so that it stays enabled across level loads. Removed some unused code and added some back in for hopeful future use.
25 // Revision 1.5 2006-04-04 23:58:37 kkurbjun
26 // Make savegame strings more informative
28 // Revision 1.4 2006-04-04 23:13:50 kkurbjun
29 // Fix up configurable keys, edit exit string, more work needs to be done on menu keys
31 // Revision 1.3 2006-04-03 20:03:02 kkurbjun
32 // Updates doom menu w/ new graphics, now requires rockdoom.wad: http://alamode.mines.edu/~kkurbjun/rockdoom.wad
34 // Revision 1.2 2006-04-03 00:28:13 kkurbjun
35 // Fixes graphic errors in scaling code, note sure about the fix in hu_lib.c though. I havn't seen any corrupted text but it may still need a proper fix.
37 // Revision 1.1 2006-03-28 15:44:01 dave
38 // Patch #2969 - Doom! Currently only working on the H300.
42 // DOOM selection menu, options, episode etc.
43 // Sliders and icons. Kinda widget stuff.
45 //-----------------------------------------------------------------------------
74 #include "rockmacros.h"
77 extern patchnum_t hu_font
[HU_FONTSIZE
];
78 extern boolean message_dontfuckwithme
;
80 extern boolean chat_on
; // in heads-up code
85 int mouseSensitivity
; // has default
87 // Show messages has default, 0 = off, 1 = on
90 // Blocky mode, has default, 0 = high, 1 = normal
91 int screenblocks
; // has default
93 // temp for screenblocks (0-9)
96 // -1 = no quicksave slot picked!
99 // 1 = message to be printed
101 // ...and here is the message string!
102 const char* messageString
;
107 int messageLastMenuActive
;
109 // timed message = no input from user
110 boolean messageNeedsInput
;
112 void (*messageRoutine
)(int response
);
114 #define SAVESTRINGSIZE 24
116 // we are going to be entering a savegame string
118 int saveSlot
; // which slot to save in
119 int saveCharIndex
; // which char we're editing
120 // old save description before edit
121 char saveOldString
[SAVESTRINGSIZE
];
123 boolean inhelpscreens
;
126 #define SKULLXOFF -32
127 #define LINEHEIGHT 16
129 extern boolean sendpause
;
130 char savegamestrings
[10][SAVESTRINGSIZE
];
140 // 0 = no cursor here, 1 = ok, 2 = arrows ok
145 // choice = menu item #.
147 // choice=0:leftarrow,1:rightarrow
148 void (*routine
)(int choice
);
157 typedef struct menu_s
159 short numitems
; // # of menu items
160 struct menu_s
* prevMenu
; // previous menu
161 menuitem_t
* menuitems
; // menu items
162 void (*routine
)(void); // draw routine ROCKBOX
164 short y
; // x,y of menu
165 short lastOn
; // last item user was on in menu
169 short itemOn
; // menu item skull is on
170 short skullAnimCounter
; // skull animation counter
171 short whichSkull
; // which skull to draw
174 // graphic name of skulls
175 // warning: initializer-string for array of chars is too long
176 char skullName
[2][/*8*/9] = {"M_SKULL1","M_SKULL2"};
184 void M_NewGame(int choice
);
185 void M_Episode(int choice
);
186 void M_ChooseSkill(int choice
);
187 void M_LoadGame(int choice
);
188 void M_SaveGame(int choice
);
189 void M_Options(int choice
);
190 void M_EndGame(int choice
);
191 void M_ReadThis(int choice
);
192 void M_ReadThis2(int choice
);
193 void M_QuitDOOM(int choice
);
195 void M_ChangeMessages(int choice
);
196 void M_ChangeGamma(int choice
);
197 void M_SfxVol(int choice
);
198 void M_MusicVol(int choice
);
199 void M_SystemVol(int choice
);
200 void M_SizeDisplay(int choice
);
201 void M_StartGame(int choice
);
202 void M_Sound(int choice
);
204 void M_FinishReadThis(int choice
);
205 void M_LoadSelect(int choice
);
206 void M_SaveSelect(int choice
);
207 void M_ReadSaveStrings(void);
208 void M_QuickSave(void);
209 void M_QuickLoad(void);
211 void M_DrawMainMenu(void);
212 void M_DrawReadThis1(void);
213 void M_DrawReadThis2(void);
214 void M_DrawNewGame(void);
215 void M_DrawEpisode(void);
216 void M_DrawOptions(void);
217 void M_DrawSound(void);
218 void M_DrawLoad(void);
219 void M_DrawSave(void);
221 void M_DrawSaveLoadBorder(int x
,int y
);
222 void M_SetupNextMenu(menu_t
*menudef
);
223 void M_DrawThermo(int x
,int y
,int thermWidth
,int thermDot
);
224 void M_DrawEmptyCell(menu_t
*menu
,int item
);
225 void M_DrawSelCell(menu_t
*menu
,int item
);
226 void M_WriteText(int x
, int y
, char *string
);
227 int M_StringWidth(const char* string
);
228 int M_StringHeight(const char* string
);
229 void M_StartControlPanel(void);
230 void M_StartMessage(const char *string
,void *routine
,boolean input
);
231 void M_StopMessage(void);
232 void M_ClearMenus (void);
251 menuitem_t MainMenu
[]=
253 {1,"M_NGAME",M_NewGame
,'n'},
254 {1,"M_OPTION",M_Options
,'o'},
255 {1,"M_LOADG",M_LoadGame
,'l'},
256 {1,"M_SAVEG",M_SaveGame
,'s'},
257 // Another hickup with Special edition.
258 {1,"M_RDTHIS",M_ReadThis
,'r'},
259 {1,"M_QUITG",M_QuitDOOM
,'q'}
285 menuitem_t EpisodeMenu
[]=
287 {1,"M_EPI1", M_Episode
,'k'},
288 {1,"M_EPI2", M_Episode
,'t'},
289 {1,"M_EPI3", M_Episode
,'i'},
290 {1,"M_EPI4", M_Episode
,'t'}
295 ep_end
, // # of menu items
296 &MainDef
, // previous menu
297 EpisodeMenu
, // menuitem_t ->
298 M_DrawEpisode
, // drawing routine ->
316 menuitem_t NewGameMenu
[]=
318 {1,"M_JKILL", M_ChooseSkill
, 'i'},
319 {1,"M_ROUGH", M_ChooseSkill
, 'h'},
320 {1,"M_HURT", M_ChooseSkill
, 'h'},
321 {1,"M_ULTRA", M_ChooseSkill
, 'u'},
322 {1,"M_NMARE", M_ChooseSkill
, 'n'}
327 newg_end
, // # of menu items
328 &EpiDef
, // previous menu
329 NewGameMenu
, // menuitem_t ->
330 M_DrawNewGame
, // drawing routine ->
352 menuitem_t OptionsMenu
[]=
354 {1,"M_ENDGAM", M_EndGame
,'e'},
355 {1,"M_MESSG", M_ChangeMessages
,'m'},
356 {2,"M_SCRNSZ", M_SizeDisplay
,'s'},
358 {2,"M_GAMMA", M_ChangeGamma
,'m'},
360 {1,"M_SVOL", M_Sound
,'s'}
374 // Read This! MENU 1 & 2
382 menuitem_t ReadMenu1
[] =
403 menuitem_t ReadMenu2
[]=
405 {1,"",M_FinishReadThis
,0}
432 menuitem_t SoundMenu
[]=
434 {2,"M_SFXVOL",M_SfxVol
,'s'},
435 {-1,"",0,0}, //ROCKBOX
436 {2,"M_MUSVOL",M_MusicVol
,'m'},
437 {-1,"",0,0}, //ROCKBOX
438 {2,"M_SYSVOL",M_SystemVol
,'z'},
439 {-1,"",0,0} //ROCKBOX
466 menuitem_t LoadMenu
[]=
468 {1,"", M_LoadSelect
,'1'},
469 {1,"", M_LoadSelect
,'2'},
470 {1,"", M_LoadSelect
,'3'},
471 {1,"", M_LoadSelect
,'4'},
472 {1,"", M_LoadSelect
,'5'},
473 {1,"", M_LoadSelect
,'6'}
489 menuitem_t SaveMenu
[]=
491 {1,"", M_SaveSelect
,'1'},
492 {1,"", M_SaveSelect
,'2'},
493 {1,"", M_SaveSelect
,'3'},
494 {1,"", M_SaveSelect
,'4'},
495 {1,"", M_SaveSelect
,'5'},
496 {1,"", M_SaveSelect
,'6'}
512 // read the strings from the savegame files
514 void M_ReadSaveStrings(void)
521 for (i
= 0;i
< load_end
;i
++)
523 if (M_CheckParm("-cdrom"))
524 snprintf(name
,sizeof(name
),"c:\\doomdata\\"SAVEGAMENAME
"%d.dsg",i
);
526 snprintf(name
,sizeof(name
),SAVEGAMENAME
"%d.dsg",i
);
528 handle
= open (name
, O_RDONLY
| 0);
531 strcpy(&savegamestrings
[i
][0],EMPTYSTRING
);
532 LoadMenu
[i
].status
= 0;
535 count
= read (handle
, &savegamestrings
[i
], SAVESTRINGSIZE
);
537 LoadMenu
[i
].status
= 1;
541 #define LOADGRAPHIC_Y 8
545 void M_DrawLoad(void)
549 V_DrawNamePatch(72 ,LOADGRAPHIC_Y
, 0, "M_LOADG", CR_DEFAULT
, VPT_STRETCH
);
550 for (i
= 0;i
< load_end
; i
++)
552 M_DrawSaveLoadBorder(LoadDef
.x
,LoadDef
.y
+LINEHEIGHT
*i
);
553 M_WriteText(LoadDef
.x
,LoadDef
.y
+LINEHEIGHT
*i
,savegamestrings
[i
]);
560 // Draw border for the savegame description
562 void M_DrawSaveLoadBorder(int x
,int y
)
566 V_DrawNamePatch(x
-8, y
+7, 0, "M_LSLEFT", CR_DEFAULT
, VPT_STRETCH
);
567 for (i
= 0;i
< 24;i
++)
569 V_DrawNamePatch(x
, y
+7, 0, "M_LSCNTR", CR_DEFAULT
, VPT_STRETCH
);
572 V_DrawNamePatch(x
, y
+7, 0, "M_LSRGHT", CR_DEFAULT
, VPT_STRETCH
);
578 // User wants to load this game
580 void M_LoadSelect(int choice
)
584 if (M_CheckParm("-cdrom"))
585 snprintf(name
,sizeof(name
),"c:\\doomdata\\"SAVEGAMENAME
"%d.dsg",choice
);
587 snprintf(name
,sizeof(name
),SAVEGAMENAME
"%d.dsg",choice
);
588 G_LoadGame (choice
, false);
593 // Selected from DOOM menu
595 void M_LoadGame (int choice
)
600 M_StartMessage(LOADNET
,NULL
,false);
604 M_SetupNextMenu(&LoadDef
);
612 void M_DrawSave(void)
616 V_DrawNamePatch(72, LOADGRAPHIC_Y
, 0, "M_SAVEG", CR_DEFAULT
, VPT_STRETCH
);
617 for (i
= 0;i
< load_end
; i
++)
619 M_DrawSaveLoadBorder(LoadDef
.x
,LoadDef
.y
+LINEHEIGHT
*i
);
620 M_WriteText(LoadDef
.x
,LoadDef
.y
+LINEHEIGHT
*i
,savegamestrings
[i
]);
625 i
= M_StringWidth(savegamestrings
[saveSlot
]);
626 M_WriteText(LoadDef
.x
+ i
,LoadDef
.y
+LINEHEIGHT
*saveSlot
,"_");
631 // M_Responder calls this when user is finished
633 void M_DoSave(int slot
)
635 G_SaveGame (slot
,savegamestrings
[slot
]);
638 // PICK QUICKSAVE SLOT YET?
639 if (quickSaveSlot
== -2)
640 quickSaveSlot
= slot
;
644 // User wants to save. Start string input for M_Responder
646 void M_SaveSelect(int choice
)
648 // we are going to be intercepting all chars
652 snprintf(savegamestrings
[choice
], sizeof(savegamestrings
[choice
]),
653 (gamemode
==shareware
||gamemode
==registered
||gamemode
==retail
) ?
654 *mapnames
[(gameepisode
-1)*9+gamemap
-1] : (gamemission
==doom2
) ?
655 *mapnames2
[gamemap
-1] : (gamemission
==pack_plut
) ?
656 *mapnamesp
[gamemap
-1] : (gamemission
==pack_tnt
) ?
657 *mapnamest
[gamemap
-1] : "Unknown Location", choice
);
658 if (!strcmp(savegamestrings
[choice
],s_EMPTYSTRING
))
659 savegamestrings
[choice
][0] = 0;
660 saveCharIndex
= strlen(savegamestrings
[choice
]);
664 // Selected from DOOM menu
666 void M_SaveGame (int choice
)
671 M_StartMessage(s_SAVEDEAD
,NULL
,false);
675 if (gamestate
!= GS_LEVEL
)
678 M_SetupNextMenu(&SaveDef
);
689 void M_QuickSaveResponse(int ch
)
693 M_DoSave(quickSaveSlot
);
695 S_StartSound(NULL
,sfx_swtchx
);
700 void M_QuickSave(void)
704 S_StartSound(NULL
,sfx_oof
);
708 if (gamestate
!= GS_LEVEL
)
711 if (quickSaveSlot
< 0)
713 M_StartControlPanel();
715 M_SetupNextMenu(&SaveDef
);
716 quickSaveSlot
= -2; // means to pick a slot now
719 snprintf(tempstring
,sizeof(tempstring
),s_QSPROMPT
,savegamestrings
[quickSaveSlot
]);
720 M_StartMessage(tempstring
,M_QuickSaveResponse
,true);
728 void M_QuickLoadResponse(int ch
)
732 M_LoadSelect(quickSaveSlot
);
733 S_StartSound(NULL
,sfx_swtchx
);
738 void M_QuickLoad(void)
742 M_StartMessage(QLOADNET
,NULL
,false);
746 if (quickSaveSlot
< 0)
748 M_StartMessage(QSAVESPOT
,NULL
,false);
751 snprintf(tempstring
, sizeof(tempstring
), QLPROMPT
,savegamestrings
[quickSaveSlot
]);
752 M_StartMessage(tempstring
,M_QuickLoadResponse
,true);
760 // Had a "quick hack to fix romero bug"
762 void M_DrawReadThis1(void)
764 inhelpscreens
= true;
768 V_DrawNamePatch(0, 0, 0, "HELP", CR_DEFAULT
, VPT_STRETCH
);
773 V_DrawNamePatch(0, 0, 0, "HELP1", CR_DEFAULT
, VPT_STRETCH
);
784 // Read This Menus - optional second page.
786 void M_DrawReadThis2(void)
788 inhelpscreens
= true;
793 // This hack keeps us from having to change menus.
794 V_DrawNamePatch(0, 0, 0, "CREDIT", CR_DEFAULT
, VPT_STRETCH
);
798 V_DrawNamePatch(0, 0, 0, "HELP2", CR_DEFAULT
, VPT_STRETCH
);
808 // Change Sfx & Music volumes
810 void M_DrawSound(void)
812 int sysmax
=(rb
->sound_max(SOUND_VOLUME
)-rb
->sound_min(SOUND_VOLUME
));
813 V_DrawNamePatch(60, 38, 0, "M_SVOL", CR_DEFAULT
, VPT_STRETCH
);
815 M_DrawThermo(SoundDef
.x
,SoundDef
.y
+LINEHEIGHT
*(sfx_vol
+1),
818 M_DrawThermo(SoundDef
.x
,SoundDef
.y
+LINEHEIGHT
*(music_vol
+1),
821 M_DrawThermo(SoundDef
.x
,SoundDef
.y
+LINEHEIGHT
*(system_vol
+1),
822 16,(sysmax
+systemvol
)/5);
825 void M_Sound(int choice
)
828 M_SetupNextMenu(&SoundDef
);
831 void M_SfxVol(int choice
)
840 if (snd_SfxVolume
< 15)
845 S_SetSfxVolume(snd_SfxVolume
/* *8 */);
848 void M_MusicVol(int choice
)
857 if (snd_MusicVolume
< 15)
862 S_SetMusicVolume(snd_MusicVolume
/* *8 */);
865 void M_SystemVol(int choice
)
870 if (systemvol
-5>rb
->sound_min(SOUND_VOLUME
))
873 rb
->sound_set(SOUND_VOLUME
, systemvol
);
874 rb
->global_settings
->volume
= systemvol
;
878 if (systemvol
+5<rb
->sound_max(SOUND_VOLUME
))
881 rb
->sound_set(SOUND_VOLUME
, systemvol
);
882 rb
->global_settings
->volume
= systemvol
;
891 void M_DrawMainMenu(void)
893 V_DrawNamePatch(94, 2, 0, "M_DOOM", CR_DEFAULT
, VPT_STRETCH
);
902 void M_DrawNewGame(void)
904 // CPhipps - patch drawing updated
905 V_DrawNamePatch(96, 14, 0, "M_NEWG", CR_DEFAULT
, VPT_STRETCH
);
906 V_DrawNamePatch(54, 38, 0, "M_SKILL",CR_DEFAULT
, VPT_STRETCH
);
909 void M_NewGame(int choice
)
912 if (netgame
&& !demoplayback
)
914 M_StartMessage(s_NEWGAME
,NULL
,false);
918 if ( gamemode
== commercial
)
919 M_SetupNextMenu(&NewDef
);
921 M_SetupNextMenu(&EpiDef
);
930 void M_DrawEpisode(void)
932 // CPhipps - patch drawing updated
933 V_DrawNamePatch(54, 38, 0, "M_EPISOD", CR_DEFAULT
, VPT_STRETCH
);
936 void M_VerifyNightmare(int ch
)
938 if (ch
!= key_menu_enter
)
941 G_DeferedInitNew(nightmare
,epi
+1,1);
945 void M_ChooseSkill(int choice
)
947 if (choice
== nightmare
)
949 M_StartMessage(s_NIGHTMARE
,M_VerifyNightmare
,true);
953 //jff 3/24/98 remember last skill selected
954 // killough 10/98 moved to here
955 defaultskill
= choice
+1;
957 G_DeferedInitNew(choice
,epi
+1,1);
961 void M_Episode(int choice
)
963 if ( (gamemode
== shareware
)
966 M_StartMessage(s_SWSTRING
,NULL
,false); // Ty 03/27/98 - externalized
967 M_SetupNextMenu(&ReadDef1
);
971 // Yet another hack...
972 if ( (gamemode
== registered
)
977 // "M_Episode: 4th episode requires UltimateDOOM\n");
982 M_SetupNextMenu(&NewDef
);
990 char detailNames
[2][9] = {"M_GDHIGH","M_GDLOW"};
991 char msgNames
[2][9] = {"M_MSGOFF","M_MSGON"};
994 void M_DrawOptions(void)
996 // CPhipps - patch drawing updated
997 V_DrawNamePatch(108, 15, 0, "M_OPTTTL", CR_DEFAULT
, VPT_STRETCH
);
999 V_DrawNamePatch(OptionsDef
.x
+ 120, OptionsDef
.y
+LINEHEIGHT
*messages
, 0,
1000 msgNames
[showMessages
], CR_DEFAULT
, VPT_STRETCH
);
1002 M_DrawThermo(OptionsDef
.x
,OptionsDef
.y
+LINEHEIGHT
*(gamasens
+1),
1005 M_DrawThermo(OptionsDef
.x
,OptionsDef
.y
+LINEHEIGHT
*(scrnsize
+1),
1009 void M_Options(int choice
)
1012 M_SetupNextMenu(&OptionsDef
);
1018 // Toggle messages on/off
1020 void M_ChangeMessages(int choice
)
1022 // warning: unused parameter `int choice'
1024 showMessages
= 1 - showMessages
;
1027 players
[consoleplayer
].message
= s_MSGOFF
;
1029 players
[consoleplayer
].message
= s_MSGON
;
1031 message_dontfuckwithme
= true;
1038 void M_EndGameResponse(int ch
)
1040 if (ch
!= key_menu_enter
)
1043 // killough 5/26/98: make endgame quit if recording or playing back demo
1044 if (demorecording
|| singledemo
)
1045 G_CheckDemoStatus();
1047 currentMenu
->lastOn
= itemOn
;
1052 void M_EndGame(int choice
)
1057 S_StartSound(NULL
,sfx_oof
);
1063 M_StartMessage(s_NETEND
,NULL
,false);
1067 M_StartMessage(s_ENDGAME
,M_EndGameResponse
,true);
1076 void M_ReadThis(int choice
)
1079 M_SetupNextMenu(&ReadDef1
);
1082 void M_ReadThis2(int choice
)
1085 M_SetupNextMenu(&ReadDef2
);
1088 void M_FinishReadThis(int choice
)
1091 M_SetupNextMenu(&MainDef
);
1112 int quitsounds2
[8] =
1126 void M_QuitResponse(int ch
)
1128 if (ch
!= key_menu_enter
)
1132 if (gamemode
== commercial
)
1133 S_StartSound(NULL
,quitsounds2
[(gametic
>>2)&7]);
1135 S_StartSound(NULL
,quitsounds
[(gametic
>>2)&7]);
1144 void M_QuitDOOM(int choice
)
1147 // We pick index 0 which is language sensitive,
1148 // or one at random, between 1 and maximum number.
1149 if (language
!= english
)
1150 snprintf(endstring
,sizeof(endstring
),"%s\n\n%s",s_DOSY
, endmsg
[0] );
1152 snprintf(endstring
,sizeof(endstring
),"%s\n\n%s", endmsg
[gametic
%(NUM_QUITMESSAGES
-1)+1], s_DOSY
);
1154 M_StartMessage(endstring
,M_QuitResponse
,true);
1160 void M_ChangeGamma(int choice
)
1176 void M_SizeDisplay(int choice
)
1197 R_SetViewSize (screenblocks
);
1217 V_DrawNamePatch(xx
, y
, 0, "M_THERML", CR_DEFAULT
, VPT_STRETCH
);
1219 for (i
=0;i
<thermWidth
;i
++)
1221 V_DrawNamePatch(xx
, y
, 0, "M_THERMM", CR_DEFAULT
, VPT_STRETCH
);
1224 V_DrawNamePatch(xx
, y
, 0, "M_THERMR", CR_DEFAULT
, VPT_STRETCH
);
1225 V_DrawNamePatch((x
+8)+thermDot
*8,y
,0,"M_THERMO",CR_DEFAULT
,VPT_STRETCH
);
1235 // CPhipps - patch drawing updated
1236 V_DrawNamePatch(menu
->x
- 10, menu
->y
+item
*LINEHEIGHT
- 1, 0,
1237 "M_CELL1", CR_DEFAULT
, VPT_STRETCH
);
1245 // CPhipps - patch drawing updated
1246 V_DrawNamePatch(menu
->x
- 10, menu
->y
+item
*LINEHEIGHT
- 1, 0,
1247 "M_CELL2", CR_DEFAULT
, VPT_STRETCH
);
1253 ( const char* string
,
1257 messageLastMenuActive
= menuactive
;
1259 messageString
= string
;
1260 messageRoutine
= routine
;
1261 messageNeedsInput
= input
;
1268 void M_StopMessage(void)
1270 menuactive
= messageLastMenuActive
;
1277 // Find string width from hu_font chars
1279 int M_StringWidth(const char* string
)
1282 for (i
= 0;(size_t)i
< strlen(string
);i
++)
1283 w
+= (c
= toupper(string
[i
]) - HU_FONTSTART
) < 0 || c
>= HU_FONTSIZE
?
1284 4 : SHORT(hu_font
[c
].width
);
1289 // Find string height from hu_font chars
1292 int M_StringHeight(const char* string
)
1294 int i
, h
, height
= h
= SHORT(hu_font
[0].height
);
1295 for (i
= 0;string
[i
];i
++) // killough 1/31/98
1296 if (string
[i
] == '\n')
1303 // Write a string using the hu_font
1334 c
= toupper(c
) - HU_FONTSTART
;
1335 if (c
< 0 || c
>= HU_FONTSIZE
)
1341 w
= SHORT (hu_font
[c
].width
);
1344 // proff/nicolas 09/20/98 -- changed for hi-res
1345 // CPhipps - patch drawing updated
1346 V_DrawNumPatch(cx
, cy
, 0, hu_font
[c
].lumpnum
, CR_DEFAULT
, VPT_STRETCH
);
1360 boolean
M_Responder (event_t
* ev
)
1364 // static int joywait = 0;
1365 // static int mousewait = 0;
1366 // static int mousey = 0;
1367 // static int lasty = 0;
1368 // static int mousex = 0;
1369 // static int lastx = 0;
1373 // Process joystick input
1375 /* if (ev->type == ev_joystick && joywait < I_GetTime())
1377 if (ev->data3 == -1)
1380 joywait = I_GetTime() + 5;
1382 else if (ev->data3 == 1)
1385 joywait = I_GetTime() + 5;
1388 if (ev->data2 == -1)
1391 joywait = I_GetTime() + 2;
1393 else if (ev->data2 == 1)
1395 ch = KEY_RIGHTARROW;
1396 joywait = I_GetTime() + 2;
1401 ch = key_menu_enter;
1402 joywait = I_GetTime() + 5;
1407 joywait = I_GetTime() + 5;
1412 // Process mouse input
1413 if (ev->type == ev_mouse && mousewait < I_GetTime())
1415 mousey += ev->data3;
1416 if (mousey < lasty-30)
1419 mousewait = I_GetTime() + 5;
1420 mousey = lasty -= 30;
1422 else if (mousey > lasty+30)
1425 mousewait = I_GetTime() + 5;
1426 mousey = lasty += 30;
1429 mousex += ev->data2;
1430 if (mousex < lastx-30)
1433 mousewait = I_GetTime() + 5;
1434 mousex = lastx -= 30;
1436 else if (mousex > lastx+30)
1438 ch = KEY_RIGHTARROW;
1439 mousewait = I_GetTime() + 5;
1440 mousex = lastx += 30;
1445 ch = key_menu_enter;
1446 mousewait = I_GetTime() + 15;
1452 mousewait = I_GetTime() + 15;
1455 else */if (ev
->type
== ev_keydown
)
1465 // Save Game string input
1466 if (saveStringEnter
)
1471 if (saveCharIndex
> 0)
1474 savegamestrings
[saveSlot
][saveCharIndex
] = 0;
1479 saveStringEnter
= 0;
1480 strcpy(&savegamestrings
[saveSlot
][0],saveOldString
);
1484 saveStringEnter
= 0;
1485 if (savegamestrings
[saveSlot
][0])
1492 if (ch
-HU_FONTSTART
< 0 || ch
-HU_FONTSTART
>= HU_FONTSIZE
)
1494 if (ch
>= 32 && ch
<= 127 &&
1495 saveCharIndex
< SAVESTRINGSIZE
-1 &&
1496 M_StringWidth(savegamestrings
[saveSlot
]) <
1497 (SAVESTRINGSIZE
-2)*8)
1499 savegamestrings
[saveSlot
][saveCharIndex
++] = ch
;
1500 savegamestrings
[saveSlot
][saveCharIndex
] = 0;
1507 // Take care of any messages that need input
1510 if (messageNeedsInput
== true &&
1511 !(ch
== ' ' || ch
== 'n' || ch
== key_menu_enter
|| ch
== key_menu_escape
))
1514 menuactive
= messageLastMenuActive
;
1520 S_StartSound(NULL
,sfx_swtchx
);
1524 if (ch == KEY_F1) // devparm &&
1533 if (ch
== key_autorun
) // Autorun // V
1542 case KEY_F1: // Help key
1543 M_StartControlPanel ();
1545 if ( gamemode == retail )
1546 currentMenu = &ReadDef2;
1548 currentMenu = &ReadDef1;
1551 S_StartSound(NULL,sfx_swtchn);
1554 case KEY_F6: // Quicksave
1555 S_StartSound(NULL,sfx_swtchn);
1559 case KEY_F9: // Quickload
1560 S_StartSound(NULL,sfx_swtchn);
1571 if (ch
== key_menu_escape
)
1573 M_StartControlPanel ();
1574 S_StartSound(NULL
,sfx_swtchn
);
1581 // Keys usable within menu
1587 if (itemOn
+1 > currentMenu
->numitems
-1)
1591 S_StartSound(NULL
,sfx_pstop
);
1593 while(currentMenu
->menuitems
[itemOn
].status
==-1);
1600 itemOn
= currentMenu
->numitems
-1;
1603 S_StartSound(NULL
,sfx_pstop
);
1605 while(currentMenu
->menuitems
[itemOn
].status
==-1);
1609 if (currentMenu
->menuitems
[itemOn
].routine
&&
1610 currentMenu
->menuitems
[itemOn
].status
== 2)
1612 S_StartSound(NULL
,sfx_stnmov
);
1613 currentMenu
->menuitems
[itemOn
].routine(0);
1617 case KEY_RIGHTARROW
:
1618 if (currentMenu
->menuitems
[itemOn
].routine
&&
1619 currentMenu
->menuitems
[itemOn
].status
== 2)
1621 S_StartSound(NULL
,sfx_stnmov
);
1622 currentMenu
->menuitems
[itemOn
].routine(1);
1627 if (currentMenu
->menuitems
[itemOn
].routine
&&
1628 currentMenu
->menuitems
[itemOn
].status
)
1630 currentMenu
->lastOn
= itemOn
;
1631 if (currentMenu
->menuitems
[itemOn
].status
== 2)
1633 currentMenu
->menuitems
[itemOn
].routine(1); // right arrow
1634 S_StartSound(NULL
,sfx_stnmov
);
1638 currentMenu
->menuitems
[itemOn
].routine(itemOn
);
1639 S_StartSound(NULL
,sfx_pistol
);
1645 currentMenu
->lastOn
= itemOn
;
1647 S_StartSound(NULL
,sfx_swtchx
);
1651 currentMenu
->lastOn
= itemOn
;
1652 if (currentMenu
->prevMenu
)
1654 currentMenu
= currentMenu
->prevMenu
;
1655 itemOn
= currentMenu
->lastOn
;
1656 S_StartSound(NULL
,sfx_swtchn
);
1661 for (i
= itemOn
+1;i
< currentMenu
->numitems
;i
++)
1662 if (currentMenu
->menuitems
[i
].alphaKey
== ch
)
1665 S_StartSound(NULL
,sfx_pstop
);
1668 for (i
= 0;i
<= itemOn
;i
++)
1669 if (currentMenu
->menuitems
[i
].alphaKey
== ch
)
1672 S_StartSound(NULL
,sfx_pstop
);
1685 // M_StartControlPanel
1687 void M_StartControlPanel (void)
1689 // intro might call this repeatedly
1694 currentMenu
= &MainDef
; // JDC
1695 itemOn
= currentMenu
->lastOn
; // JDC
1701 // Called after the view has been rendered,
1702 // but before it has been blitted.
1704 void M_Drawer (void)
1713 inhelpscreens
= false;
1716 // Horiz. & Vertically center string and print it.
1720 y
= 100 - M_StringHeight(messageString
)/2;
1721 while(*(messageString
+start
))
1723 for (i
= 0;i
< strlen(messageString
+start
);i
++)
1724 if (*(messageString
+start
+i
) == '\n')
1726 memset(string
,0,40);
1727 strncpy(string
,messageString
+start
,i
);
1731 if (i
== strlen(messageString
+start
))
1733 strcpy(string
,messageString
+start
);
1737 x
= 160 - M_StringWidth(string
)/2;
1738 M_WriteText(x
,y
,string
);
1739 y
+= SHORT(hu_font
[0].height
);
1747 if (currentMenu
->routine
)
1748 currentMenu
->routine(); // call Draw routine
1753 max
= currentMenu
->numitems
;
1757 if (currentMenu
->menuitems
[i
].name
[0])
1758 V_DrawNamePatch(x
,y
,0,currentMenu
->menuitems
[i
].name
,
1759 CR_DEFAULT
, VPT_STRETCH
);
1764 // CPhipps - patch drawing updated
1765 V_DrawNamePatch(x
+ SKULLXOFF
, currentMenu
->y
- 5 + itemOn
*LINEHEIGHT
,0,
1766 skullName
[whichSkull
], CR_DEFAULT
, VPT_STRETCH
);
1774 void M_ClearMenus (void)
1777 // if (!netgame && usergame && paused)
1778 // sendpause = true;
1787 void M_SetupNextMenu(menu_t
*menudef
)
1789 currentMenu
= menudef
;
1790 itemOn
= currentMenu
->lastOn
;
1797 void M_Ticker (void)
1799 if (--skullAnimCounter
<= 0)
1802 skullAnimCounter
= 8;
1812 currentMenu
= &MainDef
;
1814 itemOn
= currentMenu
->lastOn
;
1816 skullAnimCounter
= 10;
1817 screenSize
= screenblocks
- 3;
1819 messageString
= NULL
;
1820 messageLastMenuActive
= menuactive
;
1823 // Here we could catch other version dependencies,
1824 // like HELP1/2, and four episodes.
1830 // This is used because DOOM 2 had only one HELP
1831 // page. I use CREDIT as second page now, but
1832 // kept this hack for educational purposes.
1833 MainMenu
[readthis
] = MainMenu
[quitdoom
];
1836 NewDef
.prevMenu
= &MainDef
;
1837 ReadDef1
.routine
= M_DrawReadThis1
;
1840 ReadMenu1
[0].routine
= M_FinishReadThis
;
1843 // Episode 2 and 3 are handled,
1844 // branching to an ad screen.
1846 // We need to remove the fourth episode.