Files
Doom2DosOriginal/M_MENU.C
T

1 line
35 KiB
C++

// 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 1
char 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."
};
#else
char 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!"
};
#endif
char 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;
}
}