-
Notifications
You must be signed in to change notification settings - Fork 2
/
M_MENU.C
1774 lines (1554 loc) · 35.3 KB
/
M_MENU.C
1
// M_menu.c #include "doomdef.h" #include "hu_stuff.h" extern patch_t *hu_font[HU_FONTSIZE]; extern boolean message_dontfuckwithme; #ifdef __NeXT__ #include <libc.h> #endif #include <sys/stat.h> #include <fcntl.h> #include <stdlib.h> #include <ctype.h> extern boolean chat_on; // in heads-up code // // defaulted values // int mouseSensitivity; // has default int showMessages; // has default 0 = off, 1 = on int sfxVolume; // has default 0 - 15 int musicVolume; // has default 0 - 15 int detailLevel; // has default, 0 = high, 1 = normal int screenblocks; // has default int screenSize; // temp for screenblocks (0-9) int quickSaveSlot; // -1 = no slot picked! int messageToPrint; // 1 = message to be printed char *messageString; // ...and here's the message string! int messx; // message x & y int messy; int messageLastMenuActive; boolean messageNeedsInput; // timed message = no input from user void (*messageRoutine)(int response); #define SAVESTRINGSIZE 24 char gammamsg[5][26] = { GAMMALVL0, GAMMALVL1, GAMMALVL2, GAMMALVL3, GAMMALVL4 }; int saveStringEnter; // we're going to be entering a savegame string int saveSlot; // which slot to save in int saveCharIndex; // which char we're editing char saveOldString[SAVESTRINGSIZE]; // old save description before edit boolean inhelpscreens; boolean menuactive; #define SKULLXOFF -32 #define LINEHEIGHT 16 extern boolean sendpause; char savegamestrings[10][SAVESTRINGSIZE]; // // QuitDOOM messages // char endmsg[8][80]= { QUITMSG, "please don't leave, there's more\ndemons to toast!", "let's beat it -- this is turning\ninto a bloodbath!", "i wouldn't leave if i were you.\ndos is much worse.", "you're trying to say you like dos\nbetter than me, right?", "don't leave yet -- there's a\ndemon around that corner!", "ya know, next time you come in here\ni'm gonna toast ya.", "go ahead and leave. see if i care." }; // // QuitDOOM II messages // #if 1char endmsg2[8][80]= { QUITMSG, "you want to quit?\nthen, thou hast lost an eighth!", "don't go now, there's a \ndimensional shambler waiting\nat the dos prompt!", "get outta here and go back\nto your boring programs.", "if i were your boss, i'd \n deathmatch ya in a minute!", "look, bud. you leave now\nand you forfeit your body count!", "just leave. when you come\nback, i'll be waiting with a bat.", "you're lucky i don't smack\nyou for thinking about leaving." }; #elsechar endmsg2[8][80]= { QUITMSG, "fuck you, pussy!\nget the fuck out!", "you quit and i'll jizz\nin your cystholes!", "if you leave, i'll make\nthe lord drink my jizz.", "hey, ron! can we say\n'fuck' in the game?", "i'd leave: this is just\nmore monsters and levels.\nwhat a load.", "suck it down, asshole!\nyou're a fucking wimp!", "don't quit now! we're \nstill spending your money!"}; #endifchar endstring[160]; // // MENU TYPEDEFS // typedef struct { short status; // 0 = no cursor here, 1 = ok,2 = arrows ok char name[10]; void (*routine)(int choice); // choice = menu item #. if status = 2, // ...choice=0:leftarrow,1:rightarrow char alphaKey; // hotkey in menu } menuitem_t; typedef struct menu_s { short numitems; // # of menu items struct menu_s *prevMenu; // previous menu menuitem_t *menuitems; // menu items void (*routine)(); // draw routine short x,y; // x,y of menu short lastOn; // last item user was on in menu } menu_t; short itemOn; // menu item skull is on short skullAnimCounter; // skull animation counter short whichSkull; // which skull to draw char skullName[2][8] = // graphic name of skulls {"M_SKULL1","M_SKULL2"}; menu_t *currentMenu; // current menudef // // PROTOTYPES // void M_NewGame(int choice); void M_Episode(int choice); void M_ChooseSkill(int choice); void M_LoadGame(int choice); void M_SaveGame(int choice); void M_Options(int choice); void M_EndGame(int choice); void M_ReadThis(int choice); void M_QuitDOOM(int choice); void M_ChangeMessages(int choice); void M_ChangeSensitivity(int choice); void M_SfxVol(int choice); void M_MusicVol(int choice); void M_ChangeDetail(int choice); void M_SizeDisplay(int choice); void M_StartGame(int choice); void M_Sound(int choice); void M_ReadThis(int choice); void M_ReadThis2(int choice); void M_FinishReadThis(int choice); void M_LoadSelect(int choice); void M_SaveSelect(int choice); void M_ReadSaveStrings(void); void M_QuickSave(void); void M_QuickLoad(void); void M_DrawMainMenu(void); void M_DrawReadThis1(void); void M_DrawReadThis2(void); void M_DrawNewGame(void); void M_DrawEpisode(void); void M_DrawOptions(void); void M_DrawSound(void); void M_DrawLoad(void); void M_DrawSave(void); void M_DrawSaveLoadBorder(int x,int y); void M_SetupNextMenu(menu_t *menudef); void M_DrawThermo(int x,int y,int thermWidth,int thermDot); void M_DrawEmptyCell(menu_t *menu,int item); void M_DrawSelCell(menu_t *menu,int item); void M_WriteText(int x, int y, char *string); int M_StringWidth(char *string); int M_StringHeight(char *string); void M_StartControlPanel(void); void M_StartMessage(char *string,void *routine,boolean input); void M_StopMessage(void); void M_ClearMenus (void); //============================================= // // DOOM MENU // //============================================= enum { newgame = 0, options, loadgame, savegame, readthis, quitdoom, main_end } main_e; menuitem_t MainMenu[]= { {1,"M_NGAME",M_NewGame,'n'}, {1,"M_OPTION",M_Options,'o'}, {1,"M_LOADG",M_LoadGame,'l'}, {1,"M_SAVEG",M_SaveGame,'s'}, {1,"M_RDTHIS",M_ReadThis,'r'}, {1,"M_QUITG",M_QuitDOOM,'q'} }; menu_t MainDef = { main_end, NULL, MainMenu, M_DrawMainMenu, 97,64, 0 }; //============================================= // // EPISODE SELECT // //============================================= enum { ep1, ep2, ep3, ep_end } episodes_e; menuitem_t EpisodeMenu[]= { {1,"M_EPI1",M_Episode,'k'}, {1,"M_EPI2", M_Episode,'t'}, {1,"M_EPI3", M_Episode,'i'} }; menu_t EpiDef = { ep_end, // # of menu items &MainDef, // previous menu EpisodeMenu, // menuitem_t -> M_DrawEpisode, // drawing routine -> 48,63, // x,y ep1 // lastOn }; //============================================= // // NEW GAME // //============================================= enum { killthings, toorough, hurtme, violence, nightmare, newg_end } newgame_e; menuitem_t NewGameMenu[]= { {1,"M_JKILL",M_ChooseSkill,'i'}, {1,"M_ROUGH", M_ChooseSkill,'h'}, {1,"M_HURT", M_ChooseSkill,'h'}, {1,"M_ULTRA", M_ChooseSkill,'u'}, {1,"M_NMARE", M_ChooseSkill,'n'} }; menu_t NewDef = { newg_end, // # of menu items &EpiDef, // previous menu NewGameMenu, // menuitem_t -> M_DrawNewGame, // drawing routine -> 48,63, // x,y hurtme // lastOn }; //============================================= // // OPTIONS MENU // //============================================= enum { endgame, messages, detail, scrnsize, option_empty1, mousesens, option_empty2, soundvol, opt_end } options_e; menuitem_t OptionsMenu[]= { {1,"M_ENDGAM",M_EndGame,'e'}, {1,"M_MESSG",M_ChangeMessages,'m'}, {1,"M_DETAIL",M_ChangeDetail,'g'}, {2,"M_SCRNSZ",M_SizeDisplay,'s'}, {-1,"",0}, {2,"M_MSENS",M_ChangeSensitivity,'m'}, {-1,"",0}, {1,"M_SVOL",M_Sound,'s'} }; menu_t OptionsDef = { opt_end, &MainDef, OptionsMenu, M_DrawOptions, 60,37, 0 }; //============================================= // // Read This! MENU 1 & 2 // //============================================= enum { rdthsempty1, read1_end } read_e; menuitem_t ReadMenu1[]= { {1,"",M_ReadThis2,0} }; menu_t ReadDef1 = { read1_end, &MainDef, ReadMenu1, M_DrawReadThis1, 280,185, 0 }; enum { rdthsempty2, read2_end } read_e2; menuitem_t ReadMenu2[]= { {1,"",M_FinishReadThis,0} }; menu_t ReadDef2 = { read2_end, &ReadDef1, ReadMenu2, M_DrawReadThis2, 330,175, 0 }; //============================================= // // SOUND VOLUME MENU // //============================================= enum { sfx_vol, sfx_empty1, music_vol, sfx_empty2, sound_end } sound_e; menuitem_t SoundMenu[]= { {2,"M_SFXVOL",M_SfxVol,'s'}, {-1,"",0}, {2,"M_MUSVOL",M_MusicVol,'m'}, {-1,"",0} }; menu_t SoundDef = { sound_end, &OptionsDef, SoundMenu, M_DrawSound, 80,64, 0 }; //============================================= // // LOAD GAME MENU // //============================================= enum { load1, load2, load3, load4, load5, load6, load_end } load_e; menuitem_t LoadMenu[]= { {1,"", M_LoadSelect,'1'}, {1,"", M_LoadSelect,'2'}, {1,"", M_LoadSelect,'3'}, {1,"", M_LoadSelect,'4'}, {1,"", M_LoadSelect,'5'}, {1,"", M_LoadSelect,'6'} }; menu_t LoadDef = { load_end, &MainDef, LoadMenu, M_DrawLoad, 80,54, 0 }; //============================================= // // SAVE GAME MENU // //============================================= menuitem_t SaveMenu[]= { {1,"", M_SaveSelect,'1'}, {1,"", M_SaveSelect,'2'}, {1,"", M_SaveSelect,'3'}, {1,"", M_SaveSelect,'4'}, {1,"", M_SaveSelect,'5'}, {1,"", M_SaveSelect,'6'} }; menu_t SaveDef = { load_end, &MainDef, SaveMenu, M_DrawSave, 80,54, 0 }; //============================================= // // M_ReadSaveStrings - read the strings from the // savegame files // //============================================= void M_ReadSaveStrings(void) { int handle; int count; int i; char name[256]; for (i = 0;i < load_end;i++) { if (M_CheckParm("-cdrom")) sprintf(name,"c:\\doomdata\\"SAVEGAMENAME"%d.dsg",i); else sprintf(name,SAVEGAMENAME"%d.dsg",i); handle = open (name, O_RDONLY | 0, 0666); if (handle == -1) { strcpy(&savegamestrings[i][0],EMPTYSTRING); LoadMenu[i].status = 0; continue; } count = read (handle, &savegamestrings[i], SAVESTRINGSIZE); close (handle); LoadMenu[i].status = 1; } } //============================================= // // M_LoadGame // //============================================= void M_DrawLoad(void) { int i; V_DrawPatchDirect (72,28,0,W_CacheLumpName("M_LOADG",PU_CACHE)); for (i = 0;i < load_end; i++) { M_DrawSaveLoadBorder(LoadDef.x,LoadDef.y+LINEHEIGHT*i); M_WriteText(LoadDef.x,LoadDef.y+LINEHEIGHT*i,savegamestrings[i]); } } // // Draw border for the savegame description // void M_DrawSaveLoadBorder(int x,int y) { int i; V_DrawPatchDirect (x-8,y+7,0,W_CacheLumpName("M_LSLEFT",PU_CACHE)); for (i = 0;i < 24;i++) { V_DrawPatchDirect (x,y+7,0,W_CacheLumpName("M_LSCNTR",PU_CACHE)); x += 8; } V_DrawPatchDirect (x,y+7,0,W_CacheLumpName("M_LSRGHT",PU_CACHE)); } // // User wants to load this game // void M_LoadSelect(int choice) { char name[256]; if (M_CheckParm("-cdrom")) sprintf(name,"c:\\doomdata\\"SAVEGAMENAME"%d.dsg",choice); else sprintf(name,SAVEGAMENAME"%d.dsg",choice); G_LoadGame (name); M_ClearMenus (); } // // Selected from DOOM menu // void M_LoadGame (int choice) { if (netgame) { M_StartMessage(LOADNET,NULL,false); return; } M_SetupNextMenu(&LoadDef); M_ReadSaveStrings(); } //============================================= // // M_SaveGame // //============================================= void M_DrawSave(void) { int i; V_DrawPatchDirect (72,28,0,W_CacheLumpName("M_SAVEG",PU_CACHE)); for (i = 0;i < load_end; i++) { M_DrawSaveLoadBorder(LoadDef.x,LoadDef.y+LINEHEIGHT*i); M_WriteText(LoadDef.x,LoadDef.y+LINEHEIGHT*i,savegamestrings[i]); } if (saveStringEnter) { i = M_StringWidth(savegamestrings[saveSlot]); M_WriteText(LoadDef.x + i,LoadDef.y+LINEHEIGHT*saveSlot,"_"); } } // // M_Responder calls this when user is finished // void M_DoSave(int slot) { G_SaveGame (slot,savegamestrings[slot]); M_ClearMenus (); // PICK QUICKSAVE SLOT YET? if (quickSaveSlot == -2) quickSaveSlot = slot; } // // User wants to save. Start string input for M_Responder // void M_SaveSelect(int choice) { saveStringEnter = 1; // we're going to be intercepting all chars saveSlot = choice; strcpy(saveOldString,savegamestrings[choice]); if (!strcmp(savegamestrings[choice],EMPTYSTRING)) savegamestrings[choice][0] = 0; saveCharIndex = strlen(savegamestrings[choice]); } // // Selected from DOOM menu // void M_SaveGame (int choice) { if (!usergame) { M_StartMessage(SAVEDEAD,NULL,false); return; } if (gamestate != GS_LEVEL) return; M_SetupNextMenu(&SaveDef); M_ReadSaveStrings(); } //============================================= // // M_QuickSave // //============================================= char tempstring[80]; void M_QuickSaveResponse(int ch) { if (ch == 'y') { M_DoSave(quickSaveSlot); S_StartSound(NULL,sfx_swtchx); } } void M_QuickSave(void) { if (!usergame) { S_StartSound(NULL,sfx_oof); return; } if (gamestate != GS_LEVEL) return; if (quickSaveSlot < 0) { M_StartControlPanel(); M_ReadSaveStrings(); M_SetupNextMenu(&SaveDef); quickSaveSlot = -2; // means to pick a slot now return; } sprintf(tempstring,QSPROMPT,savegamestrings[quickSaveSlot]); M_StartMessage(tempstring,M_QuickSaveResponse,true); } //============================================= // // M_QuickLoad // //============================================= void M_QuickLoadResponse(int ch) { if (ch == 'y') { M_LoadSelect(quickSaveSlot); S_StartSound(NULL,sfx_swtchx); } } void M_QuickLoad(void) { if (netgame) { M_StartMessage(QLOADNET,NULL,false); return; } if (quickSaveSlot < 0) { M_StartMessage(QSAVESPOT,NULL,false); return; } sprintf(tempstring,QLPROMPT,savegamestrings[quickSaveSlot]); M_StartMessage(tempstring,M_QuickLoadResponse,true); } //============================================= // // Read This Menus // //============================================= void M_DrawReadThis1(void) { inhelpscreens = true; V_DrawPatchDirect (0,0,0,W_CacheLumpName("HELP2",PU_CACHE)); } void M_DrawReadThis2(void) { inhelpscreens = true; V_DrawPatchDirect (0,0,0,W_CacheLumpName("HELP1",PU_CACHE)); } void M_DrawReadThisRetail(void){ inhelpscreens = true; V_DrawPatchDirect (0,0,0,W_CacheLumpName("HELP",PU_CACHE)); } //============================================= // // Change Sfx & Music volumes // //============================================= void M_DrawSound(void) { V_DrawPatchDirect (60,38,0,W_CacheLumpName("M_SVOL",PU_CACHE)); M_DrawThermo(SoundDef.x,SoundDef.y+LINEHEIGHT*(sfx_vol+1), 16,sfxVolume); M_DrawThermo(SoundDef.x,SoundDef.y+LINEHEIGHT*(music_vol+1), 16,musicVolume); } void M_Sound(int choice) { M_SetupNextMenu(&SoundDef); } void M_SfxVol(int choice) { switch(choice) { case 0: if (sfxVolume) sfxVolume--; break; case 1: if (sfxVolume < 15) sfxVolume++; break; } S_SetSfxVolume(sfxVolume*8); } void M_MusicVol(int choice) { switch(choice) { case 0: if (musicVolume) musicVolume--; break; case 1: if (musicVolume < 15) musicVolume++; break; } S_SetMusicVolume(musicVolume*8); } //============================================= // // M_DrawMainMenu // //============================================= void M_DrawMainMenu(void) { V_DrawPatchDirect (94,2,0,W_CacheLumpName("M_DOOM",PU_CACHE)); } //============================================= // // M_NewGame // //============================================= void M_DrawNewGame(void) { V_DrawPatchDirect (96,14,0,W_CacheLumpName("M_NEWG",PU_CACHE)); V_DrawPatchDirect (54,38,0,W_CacheLumpName("M_SKILL",PU_CACHE)); } void M_NewGame(int choice) { if (netgame && !demoplayback) { M_StartMessage(NEWGAME,NULL,false); return; } if (commercial) M_SetupNextMenu(&NewDef); else M_SetupNextMenu(&EpiDef); } //============================================= // // M_Episode // //============================================= int epi; void M_DrawEpisode(void) { V_DrawPatchDirect (54,38,0,W_CacheLumpName("M_EPISOD",PU_CACHE)); } void M_VerifyNightmare(int ch) { if (ch != 'y') return; G_DeferedInitNew(nightmare,epi+1,1); M_ClearMenus (); } void M_ChooseSkill(int choice) { if (choice == nightmare) { M_StartMessage(NIGHTMARE,M_VerifyNightmare,true); return; } G_DeferedInitNew(choice,epi+1,1); M_ClearMenus (); } void M_Episode(int choice) { if (shareware && choice) { M_StartMessage(SWSTRING,NULL,false); M_SetupNextMenu(&ReadDef1); return; } epi = choice; M_SetupNextMenu(&NewDef); } //============================================= // // M_Options // //============================================= char detailNames[2][9] = {"M_GDHIGH","M_GDLOW"}; char msgNames[2][9] = {"M_MSGOFF","M_MSGON"}; void M_DrawOptions(void) { V_DrawPatchDirect (108,15,0,W_CacheLumpName("M_OPTTTL",PU_CACHE)); V_DrawPatchDirect (OptionsDef.x + 175,OptionsDef.y+LINEHEIGHT*detail,0, W_CacheLumpName(detailNames[detailLevel],PU_CACHE)); V_DrawPatchDirect (OptionsDef.x + 120,OptionsDef.y+LINEHEIGHT*messages,0, W_CacheLumpName(msgNames[showMessages],PU_CACHE)); M_DrawThermo(OptionsDef.x,OptionsDef.y+LINEHEIGHT*(mousesens+1), 10,mouseSensitivity); M_DrawThermo(OptionsDef.x,OptionsDef.y+LINEHEIGHT*(scrnsize+1), 9,screenSize); } void M_Options(int choice) { M_SetupNextMenu(&OptionsDef); } //============================================= // // Toggle messages on/off // //============================================= void M_ChangeMessages(int choice) { showMessages = 1 - showMessages; if (!showMessages) players[consoleplayer].message = MSGOFF; else players[consoleplayer].message = MSGON ; message_dontfuckwithme = true; } //============================================= // // M_EndGame // //============================================= void M_EndGameResponse(int ch) { if (ch != 'y') return; currentMenu->lastOn = itemOn; M_ClearMenus (); D_StartTitle (); } void M_EndGame(int choice) { if (!usergame) { S_StartSound(NULL,sfx_oof); return; } if (netgame) { M_StartMessage(NETEND,NULL,false); return; } M_StartMessage(ENDGAME,M_EndGameResponse,true); } //============================================= // // M_ReadThis // //============================================= void M_ReadThis(int choice) { M_SetupNextMenu(&ReadDef1); } void M_ReadThis2(int choice) { M_SetupNextMenu(&ReadDef2); } void M_FinishReadThis(int choice) { M_SetupNextMenu(&MainDef); } //============================================= // // M_QuitDOOM // //============================================= int quitsounds[8] = { sfx_pldeth, sfx_dmpain, sfx_popain, sfx_slop, sfx_telept, sfx_posit1, sfx_posit3, sfx_sgtatk }; int quitsounds2[8] = { sfx_vilact, sfx_getpow, sfx_boscub, sfx_slop, sfx_skeswg, sfx_kntdth, sfx_bspact, sfx_sgtatk }; void M_QuitResponse(int ch) { if (ch != 'y') return; if (!netgame) { if (commercial) S_StartSound(NULL,quitsounds2[(gametic>>2)&7]); else S_StartSound(NULL,quitsounds[(gametic>>2)&7]); I_WaitVBL(105); } I_Quit (); } void M_QuitDOOM(int choice) { if (commercial) { if (french) sprintf(endstring,"%s\n\n"DOSY, endmsg2[0]); else sprintf(endstring,"%s\n\n"DOSY, endmsg2[(gametic>>2)&7]); } else sprintf(endstring,"%s\n\n"DOSY, endmsg[(gametic>>2)&7]); M_StartMessage(endstring,M_QuitResponse,true); } void M_ChangeSensitivity(int choice) { switch(choice) { case 0: if (mouseSensitivity) mouseSensitivity--; break; case 1: if (mouseSensitivity < 9) mouseSensitivity++; break; } } void M_ChangeDetail(int choice) { detailLevel = 1 - detailLevel; R_SetViewSize (screenblocks, detailLevel); if (!detailLevel) players[consoleplayer].message = DETAILHI; else players[consoleplayer].message = DETAILLO ; } void M_SizeDisplay(int choice) { switch(choice) { case 0: if (screenSize > 0) { screenblocks--; screenSize--; } break; case 1: if (screenSize < 8) { screenblocks++; screenSize++; } break; } R_SetViewSize (screenblocks, detailLevel); } //============================================= //============================================= // // Menu Functions // //============================================= //============================================= void M_DrawThermo(int x,int y,int thermWidth,int thermDot) { int xx,i; xx = x; V_DrawPatchDirect (xx,y,0,W_CacheLumpName("M_THERML",PU_CACHE)); xx += 8; for (i=0;i<thermWidth;i++) { V_DrawPatchDirect (xx,y,0,W_CacheLumpName("M_THERMM",PU_CACHE)); xx += 8; } V_DrawPatchDirect (xx,y,0,W_CacheLumpName("M_THERMR",PU_CACHE)); V_DrawPatchDirect ((x+8) + thermDot*8,y, 0,W_CacheLumpName("M_THERMO",PU_CACHE)); } void M_DrawEmptyCell(menu_t *menu,int item) { V_DrawPatchDirect (menu->x - 10, menu->y+item*LINEHEIGHT - 1, 0, W_CacheLumpName("M_CELL1",PU_CACHE)); } void M_DrawSelCell(menu_t *menu,int item) { V_DrawPatchDirect (menu->x - 10, menu->y+item*LINEHEIGHT - 1, 0, W_CacheLumpName("M_CELL2",PU_CACHE)); } void M_StartMessage(char *string,void *routine,boolean input) { messageLastMenuActive = menuactive; menuactive = 0; messageToPrint = 1; messageString = string; messageRoutine = routine; messageNeedsInput = input; menuactive = true; return; } void M_StopMessage(void) { menuactive = messageLastMenuActive; messageToPrint = 0; } //========================================================================= // // Find string width from hu_font chars // //========================================================================= int M_StringWidth(char *string) { int i; int w = 0; int c; for (i = 0;i < strlen(string);i++) { c = toupper(string[i]) - HU_FONTSTART; if (c < 0 || c >= HU_FONTSIZE) w += 4; else w += SHORT (hu_font[c]->width); } return w; } //========================================================================= // // Find string height from hu_font chars // //========================================================================= int M_StringHeight(char *string) { int i; int h; int height = SHORT(hu_font[0]->height); h = height; for (i = 0;i < strlen(string);i++) if (string[i] == '\n') h += height; return h; } //========================================================================= // // Write a string using the hu_font // //========================================================================= void M_WriteText(int x, int y, char *string) { int w; char *ch; int c; int cx; int cy; ch = string; cx = x; cy = y; while(1) { c = *ch++; if (!c) break; if (c == '\n') { cx = x; cy += 12; continue; } c = toupper(c) - HU_FONTSTART; if (c < 0 || c>= HU_FONTSIZE) { cx += 4; continue; } w = SHORT (hu_font[c]->width); if (cx+w > SCREENWIDTH) break; V_DrawPatchDirect(cx, cy, 0, hu_font[c]); cx+=w; } } /* =============================================================================== CONTROL PANEL =============================================================================== */ /* ===================== = = M_Responder = ====================== */ boolean M_Responder (event_t *ev) { int ch; int i; static int joywait = 0; static int mousewait = 0; static int mousey = 0; static int lasty = 0; static int mousex = 0; static int lastx = 0; ch = -1; if (ev->type == ev_joystick && joywait < I_GetTime()) { if (ev->data3 == -1) { ch = KEY_UPARROW; joywait = I_GetTime() + 5; } else if (ev->data3 == 1) { ch = KEY_DOWNARROW; joywait = I_GetTime() + 5; } if (ev->data2 == -1) { ch = KEY_LEFTARROW; joywait = I_GetTime() + 2; } else if (ev->data2 == 1) { ch = KEY_RIGHTARROW; joywait = I_GetTime() + 2; } if (ev->data1&1) { ch = KEY_ENTER; joywait = I_GetTime() + 5; } if (ev->data1&2) { ch = KEY_BACKSPACE; joywait = I_GetTime() + 5; } } else if (ev->type == ev_mouse && mousewait < I_GetTime()) { mousey += ev->data3; if (mousey < lasty-30) { ch = KEY_DOWNARROW; mousewait = I_GetTime() + 5; mousey = lasty -= 30; } else if (mousey > lasty+30) { ch = KEY_UPARROW; mousewait = I_GetTime() + 5; mousey = lasty += 30; } mousex += ev->data2; if (mousex < lastx-30) { ch = KEY_LEFTARROW; mousewait = I_GetTime() + 5; mousex = lastx -= 30; } else if (mousex > lastx+30) { ch = KEY_RIGHTARROW; mousewait = I_GetTime() + 5; mousex = lastx += 30; } if (ev->data1&1) { ch = KEY_ENTER; mousewait = I_GetTime() + 15; } if (ev->data1&2) { ch = KEY_BACKSPACE; mousewait = I_GetTime() + 15; } } else if (ev->type == ev_keydown) { ch = ev->data1; } if (ch == -1) return false; // // Save Game string input // if (saveStringEnter) { switch(ch) { case KEY_BACKSPACE: if (saveCharIndex > 0) { saveCharIndex--; savegamestrings[saveSlot][saveCharIndex] = 0; } break; case KEY_ESCAPE: saveStringEnter = 0; strcpy(&savegamestrings[saveSlot][0],saveOldString); break; case KEY_ENTER: saveStringEnter = 0; if (savegamestrings[saveSlot][0]) M_DoSave(saveSlot); break; default: ch = toupper(ch); if (ch != 32) if (ch-HU_FONTSTART < 0 || ch-HU_FONTSTART >= HU_FONTSIZE) break; if (ch >= 32 && ch <= 127 && saveCharIndex < SAVESTRINGSIZE-1 && M_StringWidth(savegamestrings[saveSlot]) < (SAVESTRINGSIZE-2)*8) { savegamestrings[saveSlot][saveCharIndex++] = ch; savegamestrings[saveSlot][saveCharIndex] = 0; } break; } return true; } // // Take care of any messages that need input // if (messageToPrint) { if (messageNeedsInput == true && !(ch == ' ' || ch == 'n' || ch == 'y' || ch == KEY_ESCAPE)) return false; menuactive = messageLastMenuActive; messageToPrint = 0; if (messageRoutine) messageRoutine(ch); menuactive = false; S_StartSound(NULL,sfx_swtchx); return true; } if (devparm && ch == KEY_F1) { G_ScreenShot (); return true; } // // F-Keys // if (!menuactive) switch(ch) { case KEY_MINUS: // Screen size down if (automapactive || chat_on) return false; M_SizeDisplay(0); S_StartSound(NULL,sfx_stnmov); return true; case KEY_EQUALS: // Screen size up if (automapactive || chat_on) return false; M_SizeDisplay(1); S_StartSound(NULL,sfx_stnmov); return true; case KEY_F1: // Help key M_StartControlPanel (); currentMenu = &ReadDef1; itemOn = 0; S_StartSound(NULL,sfx_swtchn); return true; case KEY_F2: // Save M_StartControlPanel(); S_StartSound(NULL,sfx_swtchn); M_SaveGame(0); return true; case KEY_F3: // Load M_StartControlPanel(); S_StartSound(NULL,sfx_swtchn); M_LoadGame(0); return true; case KEY_F4: // Sound Volume M_StartControlPanel (); currentMenu = &SoundDef; itemOn = sfx_vol; S_StartSound(NULL,sfx_swtchn); return true; case KEY_F5: // Detail toggle M_ChangeDetail(0); S_StartSound(NULL,sfx_swtchn); return true; case KEY_F6: // Quicksave S_StartSound(NULL,sfx_swtchn); M_QuickSave(); return true; case KEY_F7: // End game S_StartSound(NULL,sfx_swtchn); M_EndGame(0); return true; case KEY_F8: // Toggle messages M_ChangeMessages(0); S_StartSound(NULL,sfx_swtchn); return true; case KEY_F9: // Quickload S_StartSound(NULL,sfx_swtchn); M_QuickLoad(); return true; case KEY_F10: // Quit DOOM S_StartSound(NULL,sfx_swtchn); M_QuitDOOM(0); return true; case KEY_F11: // gamma toggle usegamma++; if (usegamma > 4) usegamma = 0; players[consoleplayer].message = gammamsg[usegamma]; I_SetPalette (W_CacheLumpName ("PLAYPAL",PU_CACHE)); return true; } // // Pop-up menu? // if (!menuactive) { if (ch == KEY_ESCAPE) { M_StartControlPanel (); S_StartSound(NULL,sfx_swtchn); return true; } return false; } // // Keys usable within menu // switch (ch) { case KEY_DOWNARROW: do { if (itemOn+1 > currentMenu->numitems-1) itemOn = 0; else itemOn++; S_StartSound(NULL,sfx_pstop); } while(currentMenu->menuitems[itemOn].status==-1); return true; case KEY_UPARROW: do { if (!itemOn) itemOn = currentMenu->numitems-1; else itemOn--; S_StartSound(NULL,sfx_pstop); } while(currentMenu->menuitems[itemOn].status==-1); return true; case KEY_LEFTARROW: if (currentMenu->menuitems[itemOn].routine && currentMenu->menuitems[itemOn].status == 2) { S_StartSound(NULL,sfx_stnmov); currentMenu->menuitems[itemOn].routine(0); } return true; case KEY_RIGHTARROW: if (currentMenu->menuitems[itemOn].routine && currentMenu->menuitems[itemOn].status == 2) { S_StartSound(NULL,sfx_stnmov); currentMenu->menuitems[itemOn].routine(1); } return true; case KEY_ENTER: if (currentMenu->menuitems[itemOn].routine && currentMenu->menuitems[itemOn].status) { currentMenu->lastOn = itemOn; if (currentMenu->menuitems[itemOn].status == 2) { currentMenu->menuitems[itemOn].routine(1); // right arrow S_StartSound(NULL,sfx_stnmov); } else { currentMenu->menuitems[itemOn].routine(itemOn); S_StartSound(NULL,sfx_pistol); } } return true; case KEY_ESCAPE: currentMenu->lastOn = itemOn; M_ClearMenus (); S_StartSound(NULL,sfx_swtchx); return true; case KEY_BACKSPACE: currentMenu->lastOn = itemOn; if (currentMenu->prevMenu) { currentMenu = currentMenu->prevMenu; itemOn = currentMenu->lastOn; S_StartSound(NULL,sfx_swtchn); } return true; default: for (i = itemOn+1;i < currentMenu->numitems;i++) if (currentMenu->menuitems[i].alphaKey == ch) { itemOn = i; S_StartSound(NULL,sfx_pstop); return true; } for (i = 0;i <= itemOn;i++) if (currentMenu->menuitems[i].alphaKey == ch) { itemOn = i; S_StartSound(NULL,sfx_pstop); return true; } break; } return false; } /* ===================== = = M_StartControlPanel = ====================== */ void M_StartControlPanel (void) { if (menuactive) return; // intro might call this repeatedly menuactive = 1; currentMenu = &MainDef; // JDC itemOn = currentMenu->lastOn; // JDC } /* ============================================================================== = = M_Drawer = = Called after the view has been rendered, but before it has been blitted. = ============================================================================== */ void M_Drawer (void) { static short x,y; short i,max; char string[40]; int start; inhelpscreens = false; // // Horiz. & Vertically center string and print it. // if (messageToPrint) { start = 0; y = 100 - M_StringHeight(messageString)/2; while(*(messageString+start)) { for (i = 0;i < strlen(messageString+start);i++) if (*(messageString+start+i) == '\n') { memset(string,0,40); strncpy(string,messageString+start,i); start += i+1; break; } if (i == strlen(messageString+start)) { strcpy(string,messageString+start); start += i; } x = 160 - M_StringWidth(string)/2; M_WriteText(x,y,string); y += SHORT(hu_font[0]->height); } return; } if (!menuactive) return; if (currentMenu->routine) currentMenu->routine(); // call Draw routine // // DRAW MENU // x = currentMenu->x; y = currentMenu->y; max = currentMenu->numitems; for (i=0;i<max;i++) { if (currentMenu->menuitems[i].name[0]) V_DrawPatchDirect (x,y,0, W_CacheLumpName(currentMenu->menuitems[i].name ,PU_CACHE)); y += LINEHEIGHT; } // // DRAW SKULL // V_DrawPatchDirect(x + SKULLXOFF,currentMenu->y - 5 + itemOn*LINEHEIGHT, 0, W_CacheLumpName(skullName[whichSkull],PU_CACHE)); } /* ===================== = = M_ClearMenus = ====================== */ void M_ClearMenus (void) { menuactive = 0; // if (!netgame && usergame && paused) // sendpause = true; } //============================================= // // M_SetupNextMenu // //============================================= void M_SetupNextMenu(menu_t *menudef) { currentMenu = menudef; itemOn = currentMenu->lastOn; } /* ===================== = = M_Ticker = ====================== */ void M_Ticker (void) { if (--skullAnimCounter <= 0) { whichSkull ^= 1; skullAnimCounter = 8; } } /* ===================== = = M_Init = ====================== */ void M_Init (void) { currentMenu = &MainDef; menuactive = 0; itemOn = currentMenu->lastOn; whichSkull = 0; skullAnimCounter = 10; screenSize = screenblocks - 3; messageToPrint = 0; messageString = NULL; messageLastMenuActive = menuactive; quickSaveSlot = -1; if (commercial) { MainMenu[readthis] = MainMenu[quitdoom]; MainDef.numitems--; MainDef.y += 8; NewDef.prevMenu = &MainDef; ReadDef1.routine = M_DrawReadThisRetail; ReadDef1.x = 330; ReadDef1.y = 165; ReadMenu1[0].routine = M_FinishReadThis; }}