- completely disconnected the old menu from the rest of the game to allow rebuilding the new one.

Sadly this uncovered a few more places where script events are allowed too broad access to the game state.
This commit is contained in:
Christoph Oelckers 2019-11-23 23:05:24 +01:00
parent 326d0f5f76
commit 52cfb7fb92
46 changed files with 697 additions and 538 deletions

View file

@ -939,9 +939,6 @@ void LocalKeys(void)
break;
case sc_F11:
break;
case sc_F12:
videoCaptureScreen();
break;
}
}
}

View file

@ -475,8 +475,6 @@ void Menu_AnimateChange(int32_t cm, MenuAnimationType_t animtype);
int32_t Menu_IsTextInput(Menu_t *cm);
int G_CheckPlayerColor(int color);
void Menu_Init(void);
void Menu_Open(uint8_t playerID);
void Menu_Close(uint8_t playerID);
void M_DisplayMenus(void);
extern MenuFont_t MF_Redfont, MF_Bluefont, MF_Minifont;

View file

@ -429,12 +429,6 @@ static int osdcmd_quickload(osdcmdptr_t UNUSED(parm))
return OSDCMD_OK;
}
static int osdcmd_screenshot(osdcmdptr_t parm)
{
videoCaptureScreen();
return OSDCMD_OK;
}
#if 0
static int osdcmd_savestate(osdcmdptr_t UNUSED(parm))
@ -485,7 +479,6 @@ int32_t registerosdcommands(void)
OSD_RegisterFunction("quicksave","quicksave: performs a quick save", osdcmd_quicksave);
OSD_RegisterFunction("quickload","quickload: performs a quick load", osdcmd_quickload);
OSD_RegisterFunction("restartsound","restartsound: reinitializes the sound system",osdcmd_restartsound);
OSD_RegisterFunction("screenshot","screenshot [format]: takes a screenshot.", osdcmd_screenshot);
OSD_RegisterFunction("vidmode","vidmode <xdim> <ydim> <bpp> <fullscreen>: change the video mode",osdcmd_vidmode);

View file

@ -188,6 +188,11 @@ struct GameInterface
virtual FString statFPS() { return "FPS display not available"; }
virtual GameStats getStats() { return {}; }
virtual void DrawNativeMenuText(int fontnum, int state, int xpos, int ypos, float fontscale, const char* text, int orientation = TOR_Default) {}
virtual void MainMenuOpened() {}
virtual void MenuOpened() {}
virtual void MenuSelectSound() {}
virtual void MenuChooseSound() {}
virtual bool CanSave() { return true; }
};
extern GameInterface* gi;

View file

@ -8,6 +8,7 @@
#include "cmdlib.h"
#include "gamecontrol.h"
#include "printf.h"
#include "c_dispatch.h"
#include "../../glbackend/glbackend.h"
@ -156,5 +157,10 @@ int videoCaptureScreen()
return 0;
}
CCMD(screenshot)
{
videoCaptureScreen();
}
#undef HICOLOR

View file

@ -98,6 +98,7 @@ unsigned char syncstate;
// fix for mousewheel
int32_t inputchecked = 0;
bool screenshot_requested;
char quitevent=0, appactive=1, novideo=0;
@ -2090,3 +2091,4 @@ void debugprintf(const char* f, ...)
OutputDebugStringA(buf);
}

View file

@ -65,7 +65,7 @@ bool G_Responder (event_t *ev)
stricmp (cmd, "screenshot")))
{
M_StartControlPanel(true);
M_SetMenu(NAME_Mainmenu, -1);
M_SetMenu(NAME_MainMenu, -1);
return true;
}
else

View file

@ -64,6 +64,7 @@ void DListMenu::Init(DMenu *parent, FListMenuDescriptor *desc)
{
mParentMenu = parent;
mDesc = desc;
if (mDesc->mScriptId) scriptID = mDesc->mScriptId;
if (desc->mCenter)
{
int center = 160;
@ -126,7 +127,7 @@ bool DListMenu::Responder (event_t *ev)
if (mDesc->mItems[i]->CheckHotkey(ch))
{
mDesc->mSelectedItem = i;
//S_Sound(CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
gi->MenuSelectSound();
return true;
}
}
@ -135,7 +136,7 @@ bool DListMenu::Responder (event_t *ev)
if (mDesc->mItems[i]->CheckHotkey(ch))
{
mDesc->mSelectedItem = i;
//S_Sound(CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
gi->MenuSelectSound();
return true;
}
}
@ -162,7 +163,7 @@ bool DListMenu::MenuEvent (int mkey, bool fromcontroller)
if (--mDesc->mSelectedItem < 0) mDesc->mSelectedItem = mDesc->mItems.Size()-1;
}
while (!mDesc->mItems[mDesc->mSelectedItem]->Selectable() && mDesc->mSelectedItem != startedAt);
//S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
gi->MenuSelectSound();
return true;
case MKEY_Down:
@ -171,13 +172,13 @@ bool DListMenu::MenuEvent (int mkey, bool fromcontroller)
if (++mDesc->mSelectedItem >= (int)mDesc->mItems.Size()) mDesc->mSelectedItem = 0;
}
while (!mDesc->mItems[mDesc->mSelectedItem]->Selectable() && mDesc->mSelectedItem != startedAt);
//S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
gi->MenuSelectSound();
return true;
case MKEY_Enter:
if (mDesc->mSelectedItem >= 0 && mDesc->mItems[mDesc->mSelectedItem]->Activate())
{
//S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE);
gi->MenuChooseSound();
}
return true;
@ -192,13 +193,18 @@ bool DListMenu::MenuEvent (int mkey, bool fromcontroller)
//
//=============================================================================
bool DListMenu::MouseEvent(int type, int x, int y)
bool DListMenu::MouseEvent(int type, int xx, int yy)
{
int sel = -1;
// convert x/y from screen to virtual coordinates, according to CleanX/Yfac use in DrawTexture
x = ((x - (screen->GetWidth() / 2)) / CleanXfac) + 160;
y = ((y - (screen->GetHeight() / 2)) / CleanYfac) + 100;
//x = ((x - (screen->GetWidth() / 2)) / CleanXfac) + 160;
//y = ((y - (screen->GetHeight() / 2)) / CleanYfac) + 100;
int width43 = (screen->GetHeight() * 4 / 3);
int x = (xx - (screen->GetWidth() - width43) / 2) * 320 / width43;
int y = yy * 200 / screen->GetHeight();
if (mFocusControl != NULL)
{
@ -216,7 +222,7 @@ bool DListMenu::MouseEvent(int type, int x, int y)
{
if ((int)i != mDesc->mSelectedItem)
{
//S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
// no sound. This is too noisy.
}
mDesc->mSelectedItem = i;
mDesc->mItems[i]->MouseEvent(type, x, y);

View file

@ -48,9 +48,13 @@
#include "printf.h"
#include "v_draw.h"
#include "gamecontrol.h"
#include "fx_man.h"
void RegisterDukeMenus();
extern bool rotatesprite_2doverride;
bool help_disabled, credits_disabled;
int g_currentMenu; // accessible by CON scripts - contains the current menu's script ID if defined or INT_MAX if none given.
int DrawBackground;
//
// Todo: Move these elsewhere
@ -148,12 +152,15 @@ bool DMenu::MenuEvent (int mkey, bool fromcontroller)
switch (mkey)
{
case MKEY_Back:
{
if (scriptID != 1)
{
Close();
//S_Sound (CHAN_VOICE | CHAN_UI, DMenu::CurrentMenu != NULL? "menu/backup" : "menu/clear", snd_menuvolume, ATTN_NONE);
return true;
}
}
}
return false;
}
@ -171,7 +178,11 @@ void DMenu::Close ()
delete this;
if (DMenu::CurrentMenu == NULL)
{
M_ClearMenus ();
M_ClearMenus();
}
else
{
g_currentMenu = DMenu::CurrentMenu->scriptID;
}
}
@ -307,16 +318,18 @@ void M_StartControlPanel (bool makeSound)
// That way, it won't be paused.
//P_CheckTickerPaused ();
if (makeSound)
{
//S_Sound (CHAN_VOICE | CHAN_UI, "menu/activate", snd_menuvolume, ATTN_NONE);
}
BackbuttonTime = 0;
BackbuttonAlpha = 0;
DrawBackground = -1;
DMenu::MenuTime = -1;
M_Ticker(); // This needs to be called once here to make sure that the menu actually has ticked before it gets drawn for the first time.
}
void Menu_Open(int playerid)
{
M_StartControlPanel(DMenu::CurrentMenu == nullptr);
}
//=============================================================================
//
//
@ -325,6 +338,7 @@ void M_StartControlPanel (bool makeSound)
void M_ActivateMenu(DMenu *menu)
{
g_currentMenu = menu->scriptID;
if (menuactive == MENU_Off) menuactive = MENU_On;
if (DMenu::CurrentMenu != NULL) DMenu::CurrentMenu->ReleaseCapture();
DMenu::CurrentMenu = menu;
@ -338,6 +352,11 @@ void M_ActivateMenu(DMenu *menu)
void M_SetMenu(FName menu, int param)
{
if (DrawBackground == -1)
{
if (menu == NAME_MainMenu) DrawBackground = 1;
else DrawBackground = 0;
}
// some menus need some special treatment (needs to be adjusted for the various frontends.
#if 0
switch (menu)
@ -648,7 +667,7 @@ bool M_Responder (event_t *ev)
if (ev->data1 == KEY_ESCAPE)
{
M_StartControlPanel(true);
M_SetMenu(NAME_Mainmenu, -1);
M_SetMenu(NAME_IngameMenu, -1);
return true;
}
return false;
@ -657,7 +676,7 @@ bool M_Responder (event_t *ev)
ConsoleState != c_down && m_use_mouse)
{
M_StartControlPanel(true);
M_SetMenu(NAME_Mainmenu, -1);
M_SetMenu(NAME_MainMenu, -1);
return true;
}
}
@ -730,7 +749,8 @@ void M_Drawer (void)
if (DMenu::CurrentMenu != NULL && menuactive != MENU_Off)
{
DMenu::CurrentMenu->origin = { 0,0 };
if (DMenu::CurrentMenu->DimAllowed() && fade) twod.AddColorOnlyQuad(0, 0, screen->GetWidth(), screen->GetHeight(), fade);
if (DMenu::CurrentMenu->DimAllowed() && fade && !DrawBackground) twod.AddColorOnlyQuad(0, 0, screen->GetWidth(), screen->GetHeight(), fade);
// else if (DrawBackground) Menu_DrawBackground(origin);
DMenu::CurrentMenu->Drawer();
}
rotatesprite_2doverride = false;
@ -755,6 +775,10 @@ void M_ClearMenus ()
GUICapture &= ~1;
}
void Menu_Close(int playerid)
{
M_ClearMenus();
}
//=============================================================================
//
//
@ -842,3 +866,39 @@ CCMD(reset2saved)
GameConfig->DoGlobalSetup ();
GameConfig->DoGameSetup (currentGame);
}
CCMD(openmainmenu)
{
FX_StopAllSounds();
//gi->ClearSoundLocks();
//gi->MenuSound();
M_StartControlPanel(false);
M_SetMenu(NAME_IngameMenu);
}
CCMD(openhelpmenu)
{
if (!help_disabled)
{
gi->MenuOpened();
M_StartControlPanel(false);
M_SetMenu(NAME_HelpMenu);
}
}
CCMD(opensavemenu)
{
if (gi->CanSave())
{
gi->MenuOpened();
M_StartControlPanel(false);
M_SetMenu(NAME_SaveMenu);
}
}
CCMD(openloadmenu)
{
gi->MenuOpened();
M_StartControlPanel(false);
M_SetMenu(NAME_LoadMenu);
}

View file

@ -14,6 +14,8 @@ EXTERN_CVAR(Int, m_use_mouse);
const int MENU_TICRATE = 30;
extern bool help_disabled, credits_disabled;
extern int g_currentMenu;
enum EMenuState : int
@ -265,6 +267,7 @@ public:
DMenu *mParentMenu;
vec2_t origin;
int scriptID = INT_MAX;
DMenu(DMenu *parent = NULL);
virtual bool Responder (event_t *ev);
@ -301,7 +304,7 @@ protected:
FName mAction;
public:
bool mEnabled;
bool mEnabled, mHidden;
FListMenuItem(int xpos = 0, int ypos = 0, FName action = NAME_None)
{
@ -309,6 +312,7 @@ public:
mYpos = ypos;
mAction = action;
mEnabled = true;
mHidden = false;
}
virtual ~FListMenuItem();

View file

@ -1,4 +1,10 @@
// 'None' must always be the first name.
// Windows.h is just dangerous!
#ifdef LoadMenu
#undef LoadMenu
#endif
xx(None)
xx(Null)
xx(_)
@ -8,5 +14,13 @@ xx(SEQ)
xx(SFX)
xx(RAW)
xx(MAP)
xx(Mainmenu)
xx(Controlmessage)
xx(MainMenu)
xx(IngameMenu)
xx(HelpMenu)
xx(CreditsMenu)
xx(SaveMenu)
xx(LoadMenu)
xx(SoundMenu)
xx(ConfirmPlayerReset)

View file

@ -7988,13 +7988,13 @@ next_sprite:
static void G_DoEffectorLights(void) // STATNUM 14
{
#ifdef POLYMER
int32_t i;
for (SPRITES_OF(STAT_LIGHT, i))
{
switch (sprite[i].lotag)
{
#ifdef POLYMER
case SE_49_POINT_LIGHT:
{
if (!A_CheckSpriteFlags(i, SFLAG_NOLIGHT) && videoGetRenderMode() == REND_POLYMER &&
@ -8156,9 +8156,9 @@ static void G_DoEffectorLights(void) // STATNUM 14
break;
}
}
}
#endif // POLYMER
}
}
}
#ifdef POLYMER

View file

@ -44,6 +44,11 @@ BEGIN_DUKE_NS
#define MENU_MARGIN_CENTER 160
#define MENU_HEIGHT_CENTER 100
// This is for intermediate levels in the episode selection chain. Ion Fury uses this.
MenuGameplayStemEntry g_MenuGameplayEntries[MAXMENUGAMEPLAYENTRIES];
int ME_NEWGAMECUSTOMENTRIES[MAXMENUGAMEPLAYENTRIES];
int ME_NEWGAMECUSTOMSUBENTRIES[MAXMENUGAMEPLAYENTRIES][MAXMENUGAMEPLAYENTRIES];
enum MenuTextFlags_t
{
MT_Selected = 1 << 0,
@ -72,6 +77,306 @@ MenuFont_t MF_Minifont = { { 4<<16, 5<<16 }, { 1<<16, 1<<16 },
0, 0, 16 };
/*
This function prepares data after ART and CON have been processed.
It also initializes some data in loops rather than statically at compile time.
*/
void Menu_Init(void)
{
// prepare menu fonts
// check if tilenum is -1 in case it was set in EVENT_SETDEFAULTS
if ((unsigned)MF_Redfont.tilenum >= MAXTILES) MF_Redfont.tilenum = BIGALPHANUM;
if ((unsigned)MF_Bluefont.tilenum >= MAXTILES) MF_Bluefont.tilenum = STARTALPHANUM;
if ((unsigned)MF_Minifont.tilenum >= MAXTILES) MF_Minifont.tilenum = MINIFONT;
MF_Redfont.emptychar.y = tilesiz[MF_Redfont.tilenum].y << 16;
MF_Bluefont.emptychar.y = tilesiz[MF_Bluefont.tilenum].y << 16;
MF_Minifont.emptychar.y = tilesiz[MF_Minifont.tilenum].y << 16;
if (!minitext_lowercase)
MF_Minifont.textflags |= TEXT_UPPERCASE;
#if 0
//int32_t i, j, k;
if (FURY)
{
MMF_Top_Skill.pos.x = (320 << 15);
ME_SKILL_TEMPLATE.format = &MEF_LeftMenu;
}
// prepare gamefuncs and keys
MEOSN_Gamefuncs[0] = MenuGameFuncNone;
MEOSV_Gamefuncs[0] = -1;
k = 1;
for (i = 0; i < NUMGAMEFUNCTIONS; ++i)
{
MenuGameFuncs[i] = buttonMap.GetButtonAlias(i);
MenuGameFuncs[i].Substitute('_', ' ');
if (MenuGameFuncs[i][0] != '\0')
{
MEOSN_Gamefuncs[k] = MenuGameFuncs[i];
MEOSV_Gamefuncs[k] = i;
++k;
}
}
MEOS_Gamefuncs.numOptions = k;
for (i = 0; i < NUMKEYS; ++i)
MEOSN_Keys[i] = KB_ScanCodeToString(i);
MEOSN_Keys[NUMKEYS - 1] = MenuKeyNone;
// prepare episodes
k = 0;
for (i = 0; i < g_volumeCnt; ++i)
{
if (g_volumeNames[i][0])
{
if (!(g_volumeFlags[i] & EF_HIDEFROMSP))
{
MEL_EPISODE[i] = &ME_EPISODE[i];
ME_EPISODE[i] = ME_EPISODE_TEMPLATE;
ME_EPISODE[i].name = g_volumeNames[i];
}
// if (!(EpisodeFlags[i] & EF_HIDEFROMMP))
{
MEOSN_NetEpisodes[k] = g_volumeNames[i];
MEOSV_NetEpisodes[k] = i;
k++;
}
}
// prepare levels
MEOS_NETOPTIONS_LEVEL[i] = MEOS_NETOPTIONS_LEVEL_TEMPLATE;
for (j = 0; j < MAXLEVELS; ++j)
{
MEOSN_NetLevels[i][j] = g_mapInfo[MAXLEVELS * i + j].name;
if (g_mapInfo[i * MAXLEVELS + j].filename != NULL)
MEOS_NETOPTIONS_LEVEL[i].numOptions = j + 1;
}
MEOS_NETOPTIONS_LEVEL[i].optionNames = MEOSN_NetLevels[i];
}
M_EPISODE.numEntries = g_volumeCnt + 2;
MEL_EPISODE[g_volumeCnt] = &ME_Space4_Redfont;
MEL_EPISODE[g_volumeCnt + 1] = &ME_EPISODE_USERMAP;
MEOSN_NetEpisodes[k] = MenuUserMap;
MEOSV_NetEpisodes[k] = MAXVOLUMES;
MEOS_NETOPTIONS_EPISODE.numOptions = k + 1;
NetEpisode = MEOSV_NetEpisodes[0];
MMF_Top_Episode.pos.y = (58 + (3 - k) * 6) << 16;
if (g_skillCnt == 0)
MEO_EPISODE.linkID = MENU_NULL;
M_EPISODE.currentEntry = ud.default_volume;
// prepare new game custom :O
if (g_MenuGameplayEntries[0].entry.isValid())
{
MEO_MAIN_NEWGAME.linkID = M_NEWVERIFY.linkID = MENU_NEWGAMECUSTOM;
int e = 0;
for (MenuGameplayStemEntry const& stem : g_MenuGameplayEntries)
{
MenuGameplayEntry const& entry = stem.entry;
if (!entry.isValid())
break;
MenuEntry_t& e_me = ME_NEWGAMECUSTOMENTRIES[e];
e_me = ME_EPISODE_TEMPLATE;
MenuLink_t& e_meo = MEO_NEWGAMECUSTOM[e];
e_meo = MEO_NEWGAMECUSTOM_TEMPLATE;
e_me.entry = &e_meo;
e_me.name = entry.name;
if (entry.flags & MGE_Locked)
e_me.flags |= MEF_Disabled;
if (entry.flags & MGE_Hidden)
e_me.flags |= MEF_Hidden;
int s = 0;
for (MenuGameplayEntry const& subentry : stem.subentries)
{
if (!subentry.isValid())
break;
MenuEntry_t& s_me = ME_NEWGAMECUSTOMSUBENTRIES[e][s];
s_me = ME_EPISODE_TEMPLATE;
MenuLink_t& s_meo = MEO_NEWGAMECUSTOMSUB[e][s];
s_meo = MEO_NEWGAMECUSTOMSUB_TEMPLATE;
s_me.entry = &s_meo;
s_me.name = subentry.name;
if (subentry.flags & MGE_Locked)
s_me.flags |= MEF_Disabled;
if (subentry.flags & MGE_Hidden)
s_me.flags |= MEF_Hidden;
++s;
}
if (entry.flags & MGE_UserContent)
e_meo.linkID = MENU_USERMAP;
else if (s == 0)
e_meo.linkID = MENU_SKILL;
++e;
}
Menu_PopulateNewGameCustom();
}
// prepare skills
k = -1;
for (i = 0; i < g_skillCnt && g_skillNames[i][0]; ++i)
{
MEL_SKILL[i] = &ME_SKILL[i];
ME_SKILL[i] = ME_SKILL_TEMPLATE;
ME_SKILL[i].name = g_skillNames[i];
MEOSN_NetSkills[i] = g_skillNames[i];
k = i;
}
++k;
M_SKILL.numEntries = g_skillCnt; // k;
MEOS_NETOPTIONS_MONSTERS.numOptions = g_skillCnt + 1; // k+1;
MEOSN_NetSkills[g_skillCnt] = MenuSkillNone;
MMF_Top_Skill.pos.y = (58 + (4 - g_skillCnt) * 6) << 16;
M_SKILL.currentEntry = ud.default_skill;
Menu_AdjustForCurrentEntryAssignmentBlind(&M_SKILL);
// prepare multiplayer gametypes
k = -1;
for (i = 0; i < MAXGAMETYPES; ++i)
if (g_gametypeNames[i][0])
{
MEOSN_NetGametypes[i] = g_gametypeNames[i];
k = i;
}
++k;
MEOS_NETOPTIONS_GAMETYPE.numOptions = k;
if (NAM_WW2GI)
ME_NETOPTIONS_MONSTERS.name = "Enemies";
// prepare cheats
for (i = 0; i < NUMCHEATFUNCS; ++i)
MEL_CHEATS[i + 1] = &ME_CheatCodes[i];
// prepare text chat macros
for (i = 0; i < MAXRIDECULE; ++i)
{
MEL_MACROS[i] = &ME_MACROS[i];
ME_MACROS[i] = ME_MACROS_TEMPLATE;
ME_MACROS[i].entry = &MEO_MACROS[i];
MEO_MACROS[i] = MEO_MACROS_TEMPLATE;
MEO_MACROS[i].variable = sink;// ud.ridecule[i]; temporarily disabled
}
// prepare input
for (i = 0; i < NUMGAMEFUNCTIONS; ++i)
{
if (MenuGameFuncs[i][0] == '\0')
{
MEL_KEYBOARDSETUPFUNCS[i] = NULL;
continue;
}
MEL_KEYBOARDSETUPFUNCS[i] = &ME_KEYBOARDSETUPFUNCS[i];
ME_KEYBOARDSETUPFUNCS[i] = ME_KEYBOARDSETUPFUNCS_TEMPLATE;
ME_KEYBOARDSETUPFUNCS[i].name = MenuGameFuncs[i];
ME_KEYBOARDSETUPFUNCS[i].entry = &MEO_KEYBOARDSETUPFUNCS[i];
MEO_KEYBOARDSETUPFUNCS[i] = MEO_KEYBOARDSETUPFUNCS_TEMPLATE;
}
M_KEYBOARDKEYS.numEntries = NUMGAMEFUNCTIONS;
for (i = 0; i < 2 * joystick.numButtons + 8 * joystick.numHats; ++i)
{
if (i < 2 * joystick.numButtons)
{
if (i & 1)
Bsnprintf(MenuJoystickNames[i], MAXJOYBUTTONSTRINGLENGTH, "Double %s", joyGetName(1, i >> 1));
else
Bstrncpy(MenuJoystickNames[i], joyGetName(1, i >> 1), MAXJOYBUTTONSTRINGLENGTH);
}
else
{
Bsnprintf(MenuJoystickNames[i], MAXJOYBUTTONSTRINGLENGTH, (i & 1) ? "Double Hat %d %s" : "Hat %d %s", ((i - 2 * joystick.numButtons) >> 3), MenuJoystickHatDirections[((i - 2 * joystick.numButtons) >> 1) % 4]);
}
}
for (i = 0; i < joystick.numAxes; ++i)
{
ME_JOYSTICKAXES[i] = ME_JOYSTICKAXES_TEMPLATE;
Bstrncpy(MenuJoystickAxes[i], joyGetName(0, i), MAXJOYBUTTONSTRINGLENGTH);
ME_JOYSTICKAXES[i].name = MenuJoystickAxes[i];
MEL_JOYSTICKAXES[i] = &ME_JOYSTICKAXES[i];
}
M_JOYSTICKAXES.numEntries = joystick.numAxes;
// prepare sound setup
#ifndef EDUKE32_STANDALONE
if (WW2GI)
ME_SOUND_DUKETALK.name = "GI talk:";
else if (NAM)
ME_SOUND_DUKETALK.name = "Grunt talk:";
#endif
if (FURY)
{
MF_Redfont.between.x = 2 << 16;
MF_Redfont.cursorScale = 32768;
MF_Redfont.zoom = 16384;
MF_Bluefont.zoom = 16384;
// hack; should swap out pointers
MF_Minifont = MF_Bluefont;
MMF_Top_Main.pos.x = 40 << 16;
MMF_Top_Main.pos.y = 130 << 16;
MMF_Top_Main.bottomcutoff = 190 << 16;
M_OPTIONS.format = &MMF_Top_Main;
MEF_MainMenu.width = MEF_OptionsMenu.width = -(160 << 16);
MEF_MainMenu.marginBottom = 7 << 16;
M_OPTIONS.title = NoTitle;
SELECTDIR_z = 16384;
}
// prepare shareware
if (VOLUMEONE)
{
// blue out episodes beyond the first
for (i = 1; i < g_volumeCnt; ++i)
{
if (MEL_EPISODE[i])
{
ME_EPISODE[i].entry = &MEO_EPISODE_SHAREWARE;
ME_EPISODE[i].flags |= MEF_LookDisabled;
}
}
M_EPISODE.numEntries = g_volumeCnt; // remove User Map (and spacer)
MEOS_NETOPTIONS_EPISODE.numOptions = 1;
MenuEntry_DisableOnCondition(&ME_NETOPTIONS_EPISODE, 1);
}
// prepare pre-Atomic
if (!VOLUMEALL || !PLUTOPAK)
{
// prepare credits
M_CREDITS.title = M_CREDITS2.title = M_CREDITS3.title = s_Credits;
}
MenuEntry_HideOnCondition(&ME_MAIN_HELP, G_GetLogoFlags() & LOGO_NOHELP);
#ifndef EDUKE32_SIMPLE_MENU
MenuEntry_HideOnCondition(&ME_MAIN_CREDITS, G_GetLogoFlags() & LOGO_NOCREDITS);
#endif
#endif
}
static void Menu_DrawTopBar(const vec2_t origin)
{
if ((G_GetLogoFlags() & LOGO_NOTITLEBAR) == 0)
@ -128,11 +433,11 @@ static vec2_t Menu_Text(int32_t x, int32_t y, const MenuFont_t* font, const char
else if (status & MT_Selected)
p = (status & MT_RightSide) ? font->pal_selected_right : font->pal_selected;
else
p = (status & MT_RightSide) ? font->pal_deselected_right : font->pal_deselected;
p = (status & MT_RightSide) ? font->pal_deselected_right : font->pal_deselected;
Menu_GetFmt(font, status, &s, &z);
Menu_GetFmt(font, status, &s, &z);
return G_ScreenText(font->tilenum, x, y, z, 0, 0, t, s, p, 2 | 8 | 16 | ROTATESPRITE_FULL16, 0, font->emptychar.x, font->emptychar.y, font->between.x, ybetween, f, 0, ydim_upper, xdim - 1, ydim_lower);
return G_ScreenText(font->tilenum, x, y, z, 0, 0, t, s, p, 2 | 8 | 16 | ROTATESPRITE_FULL16, 0, font->emptychar.x, font->emptychar.y, font->between.x, ybetween, f, 0, ydim_upper, xdim - 1, ydim_lower);
}
static int32_t Menu_CursorShade(void)
@ -179,7 +484,7 @@ void GameInterface::DrawNativeMenuText(int fontnum, int state, int xpos, int ypo
status |= MT_XCenter;
bool const dodraw = true;
MenuFont_t &font = fontnum == NIT_BigFont ? MF_Redfont : fontnum == NIT_SmallFont ? MF_Bluefont : MF_Minifont;
MenuFont_t& font = fontnum == NIT_BigFont ? MF_Redfont : fontnum == NIT_SmallFont ? MF_Bluefont : MF_Minifont;
int32_t const height = font.get_yline();
status |= MT_YCenter;
@ -227,6 +532,10 @@ protected:
void Ticker() override
{
auto lf = G_GetLogoFlags();
help_disabled = (lf & LOGO_NOHELP);
credits_disabled = (lf & LOGO_NOCREDITS);
// Lay out the menu. Since scripts are allowed to mess around with the font this needs to be redone each frame.
int32_t y_upper = mDesc->mYpos;
int32_t y_lower = y_upper + mDesc->mYbotton;
@ -237,8 +546,22 @@ protected:
// None of the menus still being supported will hide entries - only decactivate them if not applicable.
int32_t totalheight = 0, numvalidentries = mDesc->mItems.Size();
for (int e = 0; e < numvalidentries; ++e)
for (unsigned e = 0; e < mDesc->mItems.Size(); ++e)
{
auto entry = mDesc->mItems[e];
entry->mHidden = false;
if (entry->GetAction(nullptr) == NAME_HelpMenu && help_disabled)
{
entry->mHidden = true;
numvalidentries--;
continue;
}
else if (entry->GetAction(nullptr) == NAME_CreditsMenu && credits_disabled)
{
entry->mHidden = true;
numvalidentries--;
continue;
}
totalheight += height;
}
@ -249,13 +572,15 @@ protected:
for (int e = 0; e < numvalidentries; ++e)
{
auto entry = mDesc->mItems[e];
if (!entry->mHidden)
{
entry->SetY(y_upper + y);
y += height;
totalHeight = y;
y += calculatedentryspacing;
}
}
}
void PreDraw() override
{
@ -298,6 +623,49 @@ class MainMenu : public DukeListMenu
};
void GameInterface::MenuOpened()
{
S_PauseSounds(true);
if ((!g_netServer && ud.multimode < 2))
{
ready2send = 0;
totalclock = ototalclock;
screenpeek = myconnectindex;
}
}
void GameInterface::MenuSelectSound()
{
S_PlaySound(KICK_HIT);
}
void GameInterface::MenuChooseSound()
{
S_PlaySound(PISTOL_BODYHIT);
}
/*
void GameInterface::MenuClosed()
{
S_PlaySound(EXITMENUSOUND);
if (!ud.pause_on)
S_PauseSounds(false);
}
*/
bool GameInterface::CanSave()
{
if (ud.recstat == 2) return false;
auto &myplayer = *g_player[myconnectindex].ps;
if (sprite[myplayer.i].extra <= 0)
{
P_DoQuote(QUOTE_SAVE_DEAD, &myplayer);
return false;
}
return true;
}
END_DUKE_NS
static TMenuClassDescriptor<Duke::MainMenu> _mm("Duke.MainMenu");

View file

@ -30,6 +30,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "screens.h"
#include "i_specialpaths.h"
#include "printf.h"
#include "menu/menu.h"
BEGIN_DUKE_NS
@ -55,9 +56,9 @@ static int32_t demorec_seeds=1, demo_hasseeds;
static void Demo_RestoreModes(int32_t menu)
{
if (menu)
Menu_Open(myconnectindex);
M_StartControlPanel(false);
else
Menu_Close(myconnectindex);
M_ClearMenus();
g_player[myconnectindex].ps->gm &= ~MODE_GAME;
g_player[myconnectindex].ps->gm |= MODE_DEMO;
@ -488,7 +489,7 @@ RECHECK:
fadepal(0,0,0, 0,252,28);
P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 1); // JBF 20040308
G_DrawBackground();
M_DisplayMenus();
//M_DisplayMenus();
videoNextPage();
fadepal(0,0,0, 252,0,-28);
ud.reccnt = 0;
@ -522,7 +523,7 @@ RECHECK:
{
FX_StopAllSounds();
S_ClearSoundLocks();
Menu_Open(myconnectindex);
M_StartControlPanel(false);
}
ready2send = 0;
@ -663,7 +664,7 @@ RECHECK:
corrupt:
OSD_Printf(OSD_ERROR "Demo %d is corrupt (code %d).\n", g_whichDemo-1, corruptcode);
nextdemo:
Menu_Open(myconnectindex);
M_StartControlPanel(false);
nextdemo_nomenu:
foundemo = 0;
ud.reccnt = 0;
@ -856,16 +857,6 @@ nextdemo_nomenu:
goto RECHECK;
}
if (I_EscapeTrigger() && (g_player[myconnectindex].ps->gm&MODE_MENU) == 0 && (g_player[myconnectindex].ps->gm&MODE_TYPE) == 0)
{
I_EscapeTriggerClear();
FX_StopAllSounds();
S_ClearSoundLocks();
Menu_Open(myconnectindex);
Menu_Change(MENU_MAIN);
S_MenuSound();
}
if (Demo_IsProfiling())
{
// Do nothing: sampletimer() is reached from M_DisplayMenus() ->
@ -878,15 +869,15 @@ nextdemo_nomenu:
if ((g_player[myconnectindex].ps->gm&MODE_TYPE) != MODE_TYPE)
{
g_player[myconnectindex].ps->gm = 0;
Menu_Open(myconnectindex);
M_StartControlPanel(false);
}
}
else
{
if (ud.recstat != 2)
M_DisplayMenus();
//if (ud.recstat != 2)
// M_DisplayMenus();
if ((g_netServer || ud.multimode > 1) && !Menu_IsTextInput(m_currentMenu))
if ((g_netServer || ud.multimode > 1))// && !Menu_IsTextInput(m_currentMenu))
{
ControlInfo noshareinfo;
CONTROL_GetInput(&noshareinfo);

View file

@ -157,6 +157,10 @@ struct GameInterface : ::GameInterface
// Access to the front end specific menu code. Use is restricted to the main menu, the ingame menu and the skill/episode selection.
// Everything else is either custom screens or will use the generic option menu style.
void DrawNativeMenuText(int fontnum, int state, int xpos, int ypos, float fontscale, const char* text, int orientation = TOR_Default) override;
void MenuOpened() override;
void MenuSelectSound() override;
void MenuChooseSound() override;
bool CanSave() override;
};

View file

@ -44,8 +44,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "gameconfigfile.h"
#include "printf.h"
#include "m_argv.h"
#include "c_dispatch.h"
#include "filesystem/filesystem.h"
#include "statistics.h"
#include "menu/menu.h"
// Uncomment to prevent anything except mirrors from drawing. It is sensible to
// also uncomment ENGINE_CLEAR_SCREEN in build/src/engine_priv.h.
@ -204,13 +206,6 @@ void G_HandleSpecialKeys(void)
G_UpdateScreenArea();
}
if (inputState.UnboundKeyPressed(sc_F12))
{
inputState.ClearKeyStatus(sc_F12);
videoCaptureScreen();
P_DoQuote(QUOTE_SCREEN_SAVED, &myplayer);
}
// only dispatch commands here when not in a game
if ((myplayer.gm & MODE_GAME) != MODE_GAME)
OSD_DispatchQueued();
@ -4717,84 +4712,6 @@ void G_HandleLocalKeys(void)
typebuf[0] = 0;
}
if (inputState.UnboundKeyPressed(sc_F1) && !(G_GetLogoFlags() & LOGO_NOHELP)/* || (ud.show_help && I_AdvanceTrigger())*/)
{
inputState.ClearKeyStatus(sc_F1);
Menu_Change(MENU_STORY);
S_PauseSounds(true);
Menu_Open(myconnectindex);
if ((!g_netServer && ud.multimode < 2))
{
ready2send = 0;
totalclock = ototalclock;
screenpeek = myconnectindex;
}
}
// if((!net_server && ud.multimode < 2))
{
if (ud.recstat != 2 && inputState.UnboundKeyPressed(sc_F2))
{
inputState.ClearKeyStatus(sc_F2);
FAKE_F2:
if (sprite[myplayer.i].extra <= 0)
{
P_DoQuote(QUOTE_SAVE_DEAD, &myplayer);
return;
}
Menu_Change(MENU_SAVE);
S_PauseSounds(true);
Menu_Open(myconnectindex);
if ((!g_netServer && ud.multimode < 2))
{
ready2send = 0;
totalclock = ototalclock;
screenpeek = myconnectindex;
}
}
if (inputState.UnboundKeyPressed(sc_F3))
{
inputState.ClearKeyStatus(sc_F3);
FAKE_F3:
Menu_Change(MENU_LOAD);
S_PauseSounds(true);
Menu_Open(myconnectindex);
if ((!g_netServer && ud.multimode < 2) && ud.recstat != 2)
{
ready2send = 0;
totalclock = ototalclock;
}
screenpeek = myconnectindex;
}
}
if (inputState.GetKeyStatus(sc_F4))
if (inputState.UnboundKeyPressed(sc_F4))
{
inputState.ClearKeyStatus(sc_F4);
S_PauseSounds(true);
Menu_Open(myconnectindex);
if ((!g_netServer && ud.multimode < 2) && ud.recstat != 2)
{
ready2send = 0;
totalclock = ototalclock;
}
Menu_Change(MENU_SOUND_INGAME);
}
if (inputState.UnboundKeyPressed(sc_F5) && MusicEnabled())
{
map_t *const pMapInfo = &g_mapInfo[g_musicIndex];
@ -4817,8 +4734,10 @@ FAKE_F3:
g_doQuickSave = 0;
if (!g_lastusersave.isValid())
goto FAKE_F2;
{
C_DoCommand("opensavemenu");
return;
}
inputState.keyFlushChars();
if (sprite[myplayer.i].extra <= 0)
@ -4876,7 +4795,9 @@ FAKE_F3:
g_doQuickSave = 0;
if (g_quickload == nullptr || !g_quickload->isValid())
goto FAKE_F3;
{
C_DoCommand("openloadmenu");
}
else if (g_quickload->isValid())
{
inputState.keyFlushChars();
@ -4887,36 +4808,6 @@ FAKE_F3:
}
}
if (inputState.UnboundKeyPressed(sc_F10))
{
inputState.ClearKeyStatus(sc_F10);
Menu_Change(MENU_QUIT_INGAME);
S_PauseSounds(true);
Menu_Open(myconnectindex);
if ((!g_netServer && ud.multimode < 2) && ud.recstat != 2)
{
ready2send = 0;
totalclock = ototalclock;
}
}
if (inputState.UnboundKeyPressed(sc_F11))
{
inputState.ClearKeyStatus(sc_F11);
Menu_Change(MENU_COLCORR_INGAME);
S_PauseSounds(true);
Menu_Open(myconnectindex);
if ((!g_netServer && ud.multimode < 2) && ud.recstat != 2)
{
ready2send = 0;
totalclock = ototalclock;
}
}
if (ud.overhead_on != 0)
{
int const timerOffset = ((int) totalclock - nonsharedtimer);
@ -4963,17 +4854,6 @@ FAKE_F3:
ud.last_overhead = ud.overhead_on;
}
#ifdef __ANDROID__
if (ud.overhead_on == 1)
ud.scrollmode = 0;
else if (ud.overhead_on == 2)
{
ud.scrollmode = 1;
ud.folx = g_player[screenpeek].ps->opos.x;
ud.foly = g_player[screenpeek].ps->opos.y;
ud.fola = g_player[screenpeek].ps->oang;
}
#endif
g_restorePalette = 1;
G_UpdateScreenArea();
}
@ -6006,8 +5886,8 @@ void G_BackToMenu(void)
if (ud.recstat == 1) G_CloseDemoWrite();
ud.warp_on = 0;
g_player[myconnectindex].ps->gm = 0;
Menu_Open(myconnectindex);
Menu_Change(MENU_MAIN);
M_StartControlPanel(false);
M_SetMenu(NAME_MainMenu);
inputState.keyFlushChars();
}
@ -6050,8 +5930,8 @@ static int G_EndOfLevel(void)
G_DoOrderScreen();
#endif
p.gm = 0;
Menu_Open(myconnectindex);
Menu_Change(MENU_MAIN);
M_StartControlPanel(false);
M_SetMenu(NAME_MainMenu);
return 2;
}
else
@ -6335,8 +6215,6 @@ MAIN_LOOP_RESTART:
for (int32_t & q : user_quote_time)
q = 0;
Menu_Change(MENU_MAIN);
if(g_netClient)
{
OSD_Printf("Waiting for initial snapshot...");
@ -6380,6 +6258,9 @@ MAIN_LOOP_RESTART:
if (g_networkMode != NET_DEDICATED_SERVER)
{
M_StartControlPanel(false);
M_SetMenu(NAME_MainMenu);
if (G_PlaybackDemo())
{
FX_StopAllSounds();
@ -6390,6 +6271,7 @@ MAIN_LOOP_RESTART:
}
else G_UpdateScreenArea();
// G_GameExit(" "); ///
ud.showweapons = ud.config.ShowWeapons;

View file

@ -37,6 +37,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "files.h"
#include "base64.h"
#include "version.h"
#include "menu/menu.h"
#include "debugbreak.h"
@ -1059,7 +1060,7 @@ static void VM_Fall(int const spriteNum, spritetype * const pSprite)
static int32_t VM_ResetPlayer(int const playerNum, int32_t vmFlags, int32_t const resetFlags)
{
//AddLog("resetplayer");
// Who thought that allowing a script to do this shit is a good idea???
if (!g_netServer && ud.multimode < 2 && !(resetFlags & 2))
{
if (g_quickload && g_quickload->isValid() && ud.recstat != 2 && !(resetFlags & 8))
@ -1078,10 +1079,10 @@ static int32_t VM_ResetPlayer(int const playerNum, int32_t vmFlags, int32_t cons
}
else if (!(resetFlags & 1))
{
Menu_Open(playerNum);
inputState.ClearKeyStatus(sc_Space);
I_AdvanceTriggerClear();
Menu_Change(MENU_RESETPLAYER);
M_StartControlPanel(false);
M_SetMenu(NAME_ConfirmPlayerReset);
}
}
else
@ -4130,7 +4131,8 @@ badindex:
vInstruction(CON_CMENU):
insptr++;
Menu_Change(Gv_GetVar(*insptr++));
// Well, sorry, but - no.
//Menu_Change(Gv_GetVar(*insptr++));
dispatch();
vInstruction(CON_SOUND):

View file

@ -915,11 +915,13 @@ void __fastcall VM_SetPlayer(int const playerNum, int const labelNum, int const
break;
case PLAYER_GM:
/* WTF?!?
if (!(ps.gm & MODE_MENU) && (newValue & MODE_MENU))
Menu_Open(playerNum);
else if ((ps.gm & MODE_MENU) && !(newValue & MODE_MENU))
Menu_Close(playerNum);
ps.gm = newValue;
*/
ps.gm = newValue & ~MODE_MENU;
break;
case PLAYER_GOTWEAPON:
@ -1752,12 +1754,12 @@ void __fastcall VM_SetUserdef(int const labelNum, int const lParm2, int32_t cons
case USERDEFS_NEWGAMECUSTOMOPEN:
for (unsigned int b = 0; b < MAXMENUGAMEPLAYENTRIES; ++b)
if (iSet & (1u<<b))
ME_NEWGAMECUSTOMENTRIES[b].flags = 0;
ME_NEWGAMECUSTOMENTRIES[b] = 0;
break;
case USERDEFS_NEWGAMECUSTOMSUBOPEN:
for (unsigned int b = 0; b < MAXMENUGAMEPLAYENTRIES; ++b)
if (iSet & (1u<<b))
ME_NEWGAMECUSTOMSUBENTRIES[lParm2][b].flags = 0;
ME_NEWGAMECUSTOMSUBENTRIES[lParm2][b] = 0;
break;
}
}

View file

@ -26,6 +26,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "menus.h"
#include "savegame.h"
#include "gamecvars.h"
#include "menu/menu.h"
BEGIN_DUKE_NS

View file

@ -45,6 +45,7 @@ namespace ImGui
BEGIN_DUKE_NS
#if 0
// common positions
#define MENU_MARGIN_REGULAR 40
@ -190,8 +191,6 @@ they effectively stand in for curly braces as struct initializers.
*/
MenuGameplayStemEntry g_MenuGameplayEntries[MAXMENUGAMEPLAYENTRIES];
static MenuMenuFormat_t MMF_Top_Main = { { MENU_MARGIN_CENTER<<16, 55<<16, }, -(170<<16) };
static MenuMenuFormat_t MMF_Top_Episode = { { MENU_MARGIN_CENTER<<16, 48<<16, }, -(190<<16) };
static MenuMenuFormat_t MMF_Top_NewGameCustom = { { MENU_MARGIN_CENTER<<16, 48<<16, }, -(190<<16) };
@ -6977,4 +6976,13 @@ bool GameInterface::mouseInactiveConditional(bool condition)
return MOUSEINACTIVECONDITIONAL(condition);
}
#else
bool GameInterface::mouseInactiveConditional(bool condition)
{
return condition;
}
#endif
END_DUKE_NS

View file

@ -27,6 +27,57 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_DUKE_NS
// a subset of screentext parameters, restricted because menus require accessibility
struct MenuFont_t
{
// int32_t xspace, yline;
vec2_t emptychar, between;
int32_t zoom;
int32_t cursorLeftPosition, cursorCenterPosition, cursorScale;
int32_t textflags;
int16_t tilenum;
// selected shade glows, deselected shade is used by Blood, disabled shade is used by SW
int8_t shade_deselected, shade_disabled;
uint8_t pal;
uint8_t pal_selected, pal_deselected, pal_disabled;
uint8_t pal_selected_right, pal_deselected_right, pal_disabled_right;
int32_t get_yline() const { return mulscale16(emptychar.y, zoom); }
};
extern MenuFont_t MF_Redfont, MF_Bluefont, MF_Minifont;
#define MAXMENUGAMEPLAYENTRIES 7
enum MenuGameplayEntryFlags
{
MGE_Locked = 1u << 0u,
MGE_Hidden = 1u << 1u,
MGE_UserContent = 1u << 2u,
};
typedef struct MenuGameplayEntry
{
char name[64];
uint8_t flags;
bool isValid() const { return name[0] != '\0'; }
} MenuGameplayEntry;
typedef struct MenuGameplayStemEntry
{
MenuGameplayEntry entry;
MenuGameplayEntry subentries[MAXMENUGAMEPLAYENTRIES];
} MenuGameplayStemEntry;
extern MenuGameplayStemEntry g_MenuGameplayEntries[MAXMENUGAMEPLAYENTRIES];
extern int ME_NEWGAMECUSTOMENTRIES[MAXMENUGAMEPLAYENTRIES];
extern int ME_NEWGAMECUSTOMSUBENTRIES[MAXMENUGAMEPLAYENTRIES][MAXMENUGAMEPLAYENTRIES];
void Menu_Init(void);
#if 0
enum MenuIndex_t {
MENU_NULL = INT32_MIN, // sentinel for "do nothing"
MENU_CLOSE = -2, // sentinel for "close the menu"/"no menu"
@ -119,23 +170,6 @@ typedef enum MenuAnimationType_t
MA_Advance,
} MenuAnimationType_t;
// a subset of screentext parameters, restricted because menus require accessibility
typedef struct MenuFont_t
{
// int32_t xspace, yline;
vec2_t emptychar, between;
int32_t zoom;
int32_t cursorLeftPosition, cursorCenterPosition, cursorScale;
int32_t textflags;
int16_t tilenum;
// selected shade glows, deselected shade is used by Blood, disabled shade is used by SW
int8_t shade_deselected, shade_disabled;
uint8_t pal;
uint8_t pal_selected, pal_deselected, pal_disabled;
uint8_t pal_selected_right, pal_deselected_right, pal_disabled_right;
int32_t get_yline() const { return mulscale16(emptychar.y, zoom); }
} MenuFont_t;
@ -451,7 +485,6 @@ typedef struct MenuAnimation_t
extern MenuAnimation_t m_animation;
extern MenuID_t g_currentMenu;
extern Menu_t *m_currentMenu;
extern int32_t g_quitDeadline;
@ -460,13 +493,8 @@ int Menu_Change(MenuID_t cm);
void Menu_AnimateChange(int32_t cm, MenuAnimationType_t animtype);
int32_t Menu_IsTextInput(Menu_t *cm);
int G_CheckPlayerColor(int color);
void Menu_Init(void);
void Menu_Open(uint8_t playerID);
void Menu_Close(uint8_t playerID);
void M_DisplayMenus(void);
extern MenuFont_t MF_Redfont, MF_Bluefont, MF_Minifont;
#define M_MOUSETIMEOUT 210
extern int32_t m_mouselastactivity;
@ -488,35 +516,11 @@ extern int32_t m_mousewake_watchpoint, m_menuchange_watchpoint;
# define MOUSEWATCHPOINTCONDITIONAL(condition) ((condition) || m_mousewake_watchpoint || m_menuchange_watchpoint == 3)
#endif
#define MAXMENUGAMEPLAYENTRIES 7
enum MenuGameplayEntryFlags
{
MGE_Locked = 1u<<0u,
MGE_Hidden = 1u<<1u,
MGE_UserContent = 1u<<2u,
};
typedef struct MenuGameplayEntry
{
char name[64];
uint8_t flags;
bool isValid() const { return name[0] != '\0'; }
} MenuGameplayEntry;
typedef struct MenuGameplayStemEntry
{
MenuGameplayEntry entry;
MenuGameplayEntry subentries[MAXMENUGAMEPLAYENTRIES];
} MenuGameplayStemEntry;
extern MenuGameplayStemEntry g_MenuGameplayEntries[MAXMENUGAMEPLAYENTRIES];
extern MenuEntry_t ME_NEWGAMECUSTOMENTRIES[MAXMENUGAMEPLAYENTRIES];
extern MenuEntry_t ME_NEWGAMECUSTOMSUBENTRIES[MAXMENUGAMEPLAYENTRIES][MAXMENUGAMEPLAYENTRIES];
#endif
END_DUKE_NS
#endif

View file

@ -428,11 +428,6 @@ static int osdcmd_vidmode(osdcmdptr_t parm)
return OSDCMD_OK;
}
#ifdef LUNATIC
// Returns: INT32_MIN if no such CON label, its value else.
LUNATIC_CB int32_t (*El_GetLabelValue)(const char *label);
#endif
static int osdcmd_spawn(osdcmdptr_t parm)
{
int32_t picnum = 0;
@ -476,12 +471,6 @@ static int osdcmd_spawn(osdcmdptr_t parm)
else
{
int32_t i;
#ifdef LUNATIC
i = g_labelCnt;
picnum = El_GetLabelValue(parm->parms[0]);
if (picnum != INT32_MIN)
i = !i;
#else
int32_t j;
for (j=0; j<2; j++)
@ -499,7 +488,6 @@ static int osdcmd_spawn(osdcmdptr_t parm)
if (i < g_labelCnt)
break;
}
#endif
if (i==g_labelCnt)
{
OSD_Printf("spawn: Invalid tile label given\n");
@ -534,7 +522,6 @@ static int osdcmd_spawn(osdcmdptr_t parm)
return OSDCMD_OK;
}
#if !defined LUNATIC
static int osdcmd_setvar(osdcmdptr_t parm)
{
if (numplayers > 1)
@ -627,59 +614,6 @@ static int osdcmd_setactorvar(osdcmdptr_t parm)
return OSDCMD_OK;
}
#else
static int osdcmd_lua(osdcmdptr_t parm)
{
// Should be used like
// lua "lua code..."
// (the quotes making the whole string passed as one argument)
int32_t ret;
if (parm->numparms != 1)
return OSDCMD_SHOWHELP;
if (!L_IsInitialized(&g_ElState))
{
OSD_Printf("Lua state is not initialized.\n");
return OSDCMD_OK;
}
// TODO: "=<expr>" as shorthand for "print(<expr>)", like in the
// stand-alone Lua interpreter?
// TODO: reserve some table to explicitly store stuff on the top level, for
// debugging convenience?
// For the 'lua' OSD command, don't make errors appear on-screen:
el_addNewErrors = 0;
ret = L_RunString(&g_ElState, parm->parms[0], -1, "console");
el_addNewErrors = 1;
if (ret != 0)
OSD_Printf("Error running the Lua code (error code %d)\n", ret);
return OSDCMD_OK;
}
#endif
static int osdcmd_cmenu(osdcmdptr_t parm)
{
if (parm->numparms != 1)
return OSDCMD_SHOWHELP;
if (numplayers > 1)
{
OSD_Printf("Command not allowed in multiplayer\n");
return OSDCMD_OK;
}
if ((g_player[myconnectindex].ps->gm & MODE_MENU) != MODE_MENU)
Menu_Open(myconnectindex);
Menu_Change(Batol(parm->parms[0]));
return OSDCMD_OK;
}
@ -806,44 +740,6 @@ static int osdcmd_quickload(osdcmdptr_t UNUSED(parm))
return OSDCMD_OK;
}
static int osdcmd_screenshot(osdcmdptr_t parm)
{
videoCaptureScreen();
return OSDCMD_OK;
}
#if 0
static int osdcmd_savestate(osdcmdptr_t UNUSED(parm))
{
UNREFERENCED_PARAMETER(parm);
G_SaveMapState();
return OSDCMD_OK;
}
static int osdcmd_restorestate(osdcmdptr_t UNUSED(parm))
{
UNREFERENCED_PARAMETER(parm);
G_RestoreMapState();
return OSDCMD_OK;
}
#endif
#ifdef DEBUGGINGAIDS
static int osdcmd_inittimer(osdcmdptr_t parm)
{
if (parm->numparms != 1)
{
OSD_Printf("%dHz timer\n",g_timerTicsPerSecond);
return OSDCMD_SHOWHELP;
}
G_InitTimer(Batol(parm->parms[0]));
OSD_Printf("%s\n",parm->raw);
return OSDCMD_OK;
}
#endif
static int osdcmd_dumpmapstate(osdfuncparm_t const * const)
{
@ -1116,7 +1012,6 @@ int32_t registerosdcommands(void)
OSD_RegisterFunction("demo","demo <demofile or demonum>: starts the given demo", osdcmd_demo);
}
OSD_RegisterFunction("cmenu","cmenu <#>: jumps to menu", osdcmd_cmenu);
OSD_RegisterFunction("crosshaircolor","crosshaircolor: changes the crosshair color", osdcmd_crosshaircolor);
OSD_RegisterFunction("give","give <all|health|weapons|ammo|armor|keys|inventory>: gives requested item", osdcmd_give);
@ -1141,7 +1036,6 @@ int32_t registerosdcommands(void)
OSD_RegisterFunction("setvar","setvar <gamevar> <value>: sets the value of a gamevar", osdcmd_setvar);
OSD_RegisterFunction("setvarvar","setvarvar <gamevar1> <gamevar2>: sets the value of <gamevar1> to <gamevar2>", osdcmd_setvar);
OSD_RegisterFunction("setactorvar","setactorvar <actor#> <gamevar> <value>: sets the value of <actor#>'s <gamevar> to <value>", osdcmd_setactorvar);
OSD_RegisterFunction("screenshot","screenshot [format]: takes a screenshot.", osdcmd_screenshot);
OSD_RegisterFunction("spawn","spawn <picnum> [palnum] [cstat] [ang] [x y z]: spawns a sprite with the given properties",osdcmd_spawn);

View file

@ -29,6 +29,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "menus.h"
#include "savegame.h"
#include "statistics.h"
#include "menu/menu.h"
BEGIN_DUKE_NS
static uint8_t precachehightile[2][(MAXTILES+7)>>3];
@ -1358,7 +1359,7 @@ void G_NewGame(int volumeNum, int levelNum, int skillNum)
#endif
p0.gm = 0;
Menu_Close(0);
M_ClearMenus();
#if !defined LUNATIC
Gv_ResetVars();
@ -1911,12 +1912,12 @@ int G_EnterLevel(int gameMode)
}
}
M_ClearMenus();
if (gameMode & (MODE_GAME|MODE_EOL))
{
for (int TRAVERSE_CONNECT(i))
{
g_player[i].ps->gm = MODE_GAME;
Menu_Close(i);
}
}
else if (gameMode & MODE_RESTART)

View file

@ -33,6 +33,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "statistics.h"
#include "secrets.h"
#include "savegamehelp.h"
#include "menu/menu.h"
BEGIN_DUKE_NS
@ -502,7 +503,7 @@ int32_t G_LoadPlayer(savebrief_t & sv)
#endif
p0.gm = 0;
Menu_Close(0);
M_ClearMenus();
#if !defined LUNATIC
Gv_ResetVars();

View file

@ -1003,19 +1003,12 @@ void G_DisplayRest(int32_t smoothratio)
}
}
#if 0
if (I_EscapeTrigger() && ud.overhead_on == 0
&& ud.show_help == 0
&& g_player[myconnectindex].ps->newowner == -1)
{
if ((g_player[myconnectindex].ps->gm&MODE_MENU) == MODE_MENU && g_currentMenu <= MENU_MAIN_INGAME)
{
I_EscapeTriggerClear();
S_PlaySound(EXITMENUSOUND);
Menu_Change(MENU_CLOSE);
if (!ud.pause_on)
S_PauseSounds(false);
}
else if ((g_player[myconnectindex].ps->gm&MODE_MENU) != MODE_MENU &&
if ((g_player[myconnectindex].ps->gm&MODE_MENU) != MODE_MENU &&
g_player[myconnectindex].ps->newowner == -1 &&
(g_player[myconnectindex].ps->gm&MODE_TYPE) != MODE_TYPE)
{
@ -1033,6 +1026,7 @@ void G_DisplayRest(int32_t smoothratio)
S_MenuSound();
}
}
#endif
if (g_player[myconnectindex].ps->newowner == -1 && ud.overhead_on == 0 && cl_crosshair && ud.camerasprite == -1)
{
@ -1157,8 +1151,8 @@ void G_DisplayRest(int32_t smoothratio)
{
if (g_player[myconnectindex].ps->gm&MODE_TYPE)
Net_SendMessage();
else
M_DisplayMenus();
//else
//M_DisplayMenus();
}
{
@ -1182,7 +1176,6 @@ void G_DisplayRest(int32_t smoothratio)
GameStats GameInterface::getStats()
{
GameStats stats;
DukePlayer_t* p = g_player[myconnectindex].ps;
return { p->actors_killed, p->max_actors_killed, p->secret_rooms, p->max_secret_rooms, p->player_par / REALGAMETICSPERSEC };
}

View file

@ -183,13 +183,6 @@ void G_HandleSpecialKeys(void)
G_UpdateScreenArea();
}
if (inputState.UnboundKeyPressed(sc_F12))
{
inputState.ClearKeyStatus(sc_F12);
videoCaptureScreen();
P_DoQuote(QUOTE_SCREEN_SAVED, g_player[myconnectindex].ps);
}
// only dispatch commands here when not in a game
if (!(g_player[myconnectindex].ps->gm & MODE_GAME))
OSD_DispatchQueued();
@ -6338,21 +6331,6 @@ FAKE_F3:
Menu_Change(MENU_SOUND_INGAME);
}
if (inputState.UnboundKeyPressed(sc_F5) && MusicEnabled())
{
map_t *const pMapInfo = &g_mapInfo[g_musicIndex];
char *const musicString = apStrings[QUOTE_MUSIC];
inputState.ClearKeyStatus(sc_F5);
if (pMapInfo->musicfn != NULL)
Bsnprintf(musicString, MAXQUOTELEN, "%s. Use SHIFT-F5 to change.", pMapInfo->musicfn);
else
musicString[0] = '\0';
P_DoQuote(QUOTE_MUSIC, g_player[myconnectindex].ps);
}
if ((buttonMap.ButtonDown(gamefunc_Quick_Save) || g_doQuickSave == 1) && (!RRRA || ud.player_skill != 4) && (!RR || RRRA || ud.player_skill != 5) && (g_player[myconnectindex].ps->gm&MODE_GAME))
{
buttonMap.ClearButton(gamefunc_Quick_Save);

View file

@ -519,27 +519,6 @@ static int osdcmd_spawn(osdcmdptr_t parm)
return OSDCMD_OK;
}
static int osdcmd_cmenu(osdcmdptr_t parm)
{
if (parm->numparms != 1)
return OSDCMD_SHOWHELP;
if (numplayers > 1)
{
OSD_Printf("Command not allowed in multiplayer\n");
return OSDCMD_OK;
}
if ((g_player[myconnectindex].ps->gm & MODE_MENU) != MODE_MENU)
Menu_Open(myconnectindex);
Menu_Change(Batol(parm->parms[0]));
return OSDCMD_OK;
}
static int osdcmd_crosshaircolor(osdcmdptr_t parm)
{
@ -664,45 +643,6 @@ static int osdcmd_quickload(osdcmdptr_t UNUSED(parm))
return OSDCMD_OK;
}
static int osdcmd_screenshot(osdcmdptr_t parm)
{
videoCaptureScreen();
return OSDCMD_OK;
}
#if 0
static int osdcmd_savestate(osdcmdptr_t UNUSED(parm))
{
UNREFERENCED_PARAMETER(parm);
G_SaveMapState();
return OSDCMD_OK;
}
static int osdcmd_restorestate(osdcmdptr_t UNUSED(parm))
{
UNREFERENCED_PARAMETER(parm);
G_RestoreMapState();
return OSDCMD_OK;
}
#endif
#ifdef DEBUGGINGAIDS
static int osdcmd_inittimer(osdcmdptr_t parm)
{
if (parm->numparms != 1)
{
OSD_Printf("%dHz timer\n",g_timerTicsPerSecond);
return OSDCMD_SHOWHELP;
}
G_InitTimer(Batol(parm->parms[0]));
OSD_Printf("%s\n",parm->raw);
return OSDCMD_OK;
}
#endif
#if !defined NETCODE_DISABLE
static int osdcmd_disconnect(osdcmdptr_t UNUSED(parm))
{
@ -911,7 +851,6 @@ int32_t registerosdcommands(void)
OSD_RegisterFunction("demo","demo <demofile or demonum>: starts the given demo", osdcmd_demo);
}
OSD_RegisterFunction("cmenu","cmenu <#>: jumps to menu", osdcmd_cmenu);
OSD_RegisterFunction("crosshaircolor","crosshaircolor: changes the crosshair color", osdcmd_crosshaircolor);
#if !defined NETCODE_DISABLE
@ -950,8 +889,6 @@ int32_t registerosdcommands(void)
OSD_RegisterFunction("restartmap", "restartmap: restarts the current map", osdcmd_restartmap);
OSD_RegisterFunction("restartsound","restartsound: reinitializes the sound system",osdcmd_restartsound);
OSD_RegisterFunction("screenshot","screenshot [format]: takes a screenshot.", osdcmd_screenshot);
OSD_RegisterFunction("spawn","spawn <picnum> [palnum] [cstat] [ang] [x y z]: spawns a sprite with the given properties",osdcmd_spawn);
OSD_RegisterFunction("vidmode","vidmode <xdim> <ydim> <bpp> <fullscreen>: change the video mode",osdcmd_vidmode);

View file

@ -1665,22 +1665,6 @@ void ResChange(void)
}
#endif
void ScreenCaptureKeys(void)
{
if (ConPanel)
return;
// screen capture
if (inputState.GetKeyStatus(KEYSC_F12))
{
inputState.ClearKeyStatus(KEYSC_F12);
PauseAction();
videoCaptureScreen();
ResumeAction();
PutStringInfo(Player + myconnectindex, "Screen Captured");
}
}
void DrawCheckKeys(PLAYERp pp)
{
extern SWBOOL ResCheat;
@ -1696,8 +1680,6 @@ void DrawCheckKeys(PLAYERp pp)
if (!InputMode)
ResizeView(pp);
ScreenCaptureKeys();
}
#if 0

View file

@ -2368,7 +2368,6 @@ void BonusScreen(PLAYERp pp)
MNU_DrawString(TEXT_TEST_COL(w), 185, ds,1,19);
videoNextPage();
ScreenCaptureKeys();
if (State == State->NextState)
BonusDone = TRUE;
@ -2590,8 +2589,6 @@ void StatScreen(PLAYERp mpp)
while (!inputState.GetKeyStatus(KEYSC_SPACE) && !inputState.GetKeyStatus(KEYSC_ENTER))
{
handleevents();
ScreenCaptureKeys();
}
StopSound();

View file

@ -0,0 +1,15 @@
// These bindings are valid for all configurationas
F1 "openhelpmenu"
F2 "opensavemenu"
F3 "openloadmenu"
F4 "openmenu SoundOptions"
F5 "openmeun OptionMenu" //this key performs some fuckery with the music in Duke Nukem,so the default here is Blood's.
F6 "+Quick_Save"
F7 "+Third_Person_View"
//F8 "toggle hud_messages" // this one needs a means to print the status to the quote display.
F9 "+Quick_Load"
F10 "openmenu QuitIngame"
F11 "openmenu ColorCorrection"
F12 "screenshot"

View file

@ -6,6 +6,7 @@
LISTMENU "MainMenu"
{
ScriptId 1
ifgame(Duke, Nam, WW2GI, Fury)
{
ifgame(fury)
@ -68,3 +69,61 @@ LISTMENU "MainMenu"
}
}
LISTMENU "IngameMenu"
{
ifgame(Duke, Nam, WW2GI, Fury)
{
ifgame(fury)
{
position 40, 130, 60, -160
}
else
{
position 160, 55, 115, 0
centermenu
}
linespacing 15
class "Duke.MainMenu"
NativeTextItem "$MNU_NEWGAME", "n", "PlayerclassMenu"
NativeTextItem "$MNU_SAVEGAME", "s", "SaveGameMenu"
NativeTextItem "$MNU_LOADGAME", "l", "LoadGameMenu"
NativeTextItem "$MNU_OPTIONS", "o", "OptionsMenu"
NativeTextItem "$MNU_HELP", "h", "HelpMenu"
NativeTextItem "$MNU_ENDGAME", "e", "QuitToMenu"
NativeTextItem "$MNU_QUITGAME", "q", "QuitMenu"
}
ifgame(Redneck, RedneckRides)
{
linespacing 15
NativeTextItem "$MNU_NEWGAME", "n", "PlayerclassMenu"
NativeTextItem "$MNU_SAVEGAME", "s", "SaveGameMenu"
NativeTextItem "$MNU_LOADGAME", "l", "LoadGameMenu"
NativeTextItem "$MNU_OPTIONS", "o", "OptionsMenu"
NativeTextItem "$MNU_HELP", "h", "HelpMenu"
NativeTextItem "$MNU_ENDGAME", "e", "QuitToMenu"
NativeTextItem "$MNU_QUITGAME", "q", "QuitMenu"
}
ifgame(Blood)
{
linespacing 15
NativeTextItem "$MNU_NEWGAME", "n", "PlayerclassMenu"
NativeTextItem "$MNU_MULTIPLAYER", "m", "MultiMenu"
NativeTextItem "$MNU_OPTIONS", "o", "OptionsMenu"
NativeTextItem "$MNU_LOADGAME", "l", "LoadGameMenu"
NativeTextItem "$MNU_HELP", "h", "HelpMenu"
NativeTextItem "$MNU_CREDITS", "c", "CreditsMenu"
NativeTextItem "$MNU_QUITGAME", "q", "QuitMenu"
}
ifgame(ShadowWarrior)
{
linespacing 15
NativeTextItem "$MNU_NEWGAME", "n", "PlayerclassMenu"
NativeTextItem "$MNU_LOADGAME", "l", "LoadGameMenu"
NativeTextItem "$MNU_SAVEGAME", "s", "SaveGameMenu"
NativeTextItem "$MNU_OPTIONS", "o", "OptionsMenu"
NativeTextItem "$MNU_COOLSTUFF", "h", "HelpMenu"
NativeTextItem "$MNU_QUITGAME", "q", "QuitMenu"
}
}

View file

@ -66,9 +66,6 @@ Q "+Quick_Kick"
` "toggleconsole"
Capslock "+AutoRun"
X "+Last_Used_Weapon"
F6 "+Quick_Save"
F9 "+Quick_Load"
F7 "+Third_Person_View"
C "+Toggle_Crouch"
Mouse1 "+Fire"
Mouse2 "+Jetpack"

View file

@ -61,9 +61,6 @@ Q "+Quick_Kick"
; "+Previous_Weapon"
` "toggleconsole"
Capslock "+AutoRun"
F6 "+Quick_Save"
F9 "+Quick_Load"
F7 "+Third_Person_View"
Mouse1 "+Fire"
Mouse2 "+Open"
Mouse3 "+Run"

View file

@ -68,9 +68,6 @@ R "+Steroids"
; "+Previous_Weapon"
C "toggleconsole"
Capslock "+AutoRun"
F6 "+Quick_Save"
F9 "+Quick_Load"
F7 "+Third_Person_View"
Mouse1 "+Fire"
Mouse2 "+Jetpack"
Mouse3 "+MediKit"

View file

@ -60,9 +60,6 @@ K "+See_Coop_View"
` "toggleconsole"
Capslock "+AutoRun"
X "+Last_Used_Weapon"
F6 "+Quick_Save"
F9 "+Quick_Load"
F7 "+Third_Person_View"
C "+Toggle_Crouch"
Mouse1 "+Fire"
Mouse2 "+Jetpack"

View file

@ -59,9 +59,6 @@ I "+Toggle_Crosshair"
; "+Previous_Weapon"
` "toggleconsole"
Capslock "+AutoRun"
F6 "+Quick_Save"
F9 "+Quick_Load"
F7 "+Third_Person_View"
Mouse1 "+Fire"
Mouse2 "+Open"
Mouse3 "+Run"

View file

@ -62,9 +62,6 @@ I "+Toggle_Crosshair"
; "+Previous_Weapon"
C "toggleconsole"
Capslock "+AutoRun"
F6 "+Quick_Save"
F9 "+Quick_Load"
F7 "+Third_Person_View"
Mouse1 "+Fire"
Mouse2 "+Jetpack"
Mouse3 "+MediKit"

View file

@ -66,9 +66,6 @@ Q "+Quick_Kick"
` "toggleconsole"
Capslock "+AutoRun"
X "+Last_Used_Weapon"
F6 "+Quick_Save"
F9 "+Quick_Load"
F7 "+Third_Person_View"
C "+Toggle_Crouch"
Mouse1 "+Fire"
Mouse2 "+Jetpack"

View file

@ -65,9 +65,6 @@ Q "+Quick_Kick"
; "+Previous_Weapon"
` "toggleconsole"
Capslock "+AutoRun"
F6 "+Quick_Save"
F9 "+Quick_Load"
F7 "+Third_Person_View"
Mouse1 "+Fire"
Mouse2 "+Open"
Mouse3 "+Run"

View file

@ -68,9 +68,6 @@ R "+Steroids"
; "+Previous_Weapon"
C "toggleconsole"
Capslock "+AutoRun"
F6 "+Quick_Save"
F9 "+Quick_Load"
F7 "+Third_Person_View"
Mouse1 "+Fire"
Mouse2 "+Jetpack"
Mouse3 "+MediKit"

View file

@ -67,9 +67,6 @@ Q "+Quick_Kick"
` "toggleconsole"
+ "+Dpad_Select"
X "+Last_Used_Weapon"
F6 "+Quick_Save"
F9 "+Quick_Load"
F7 "+Third_Person_View"
Mouse1 "+Fire"
Mouse2 "+Jetpack"
Mouse3 "+MediKit"

View file

@ -64,9 +64,6 @@ Q "+Quick_Kick"
' "+Next_Weapon"
; "+Previous_Weapon"
` "toggleconsole"
F6 "+Quick_Save"
F9 "+Quick_Load"
F7 "+Third_Person_View"
Mouse1 "+Fire"
Mouse2 "+Open"
Mouse3 "+Run"

View file

@ -69,6 +69,3 @@ M "+Steroids"
' "+Next_Weapon"
; "+Previous_Weapon"
V "toggleconsole"
F6 "+Quick_Save"
F9 "+Quick_Load"
F7 "+Third_Person_View"

View file

@ -66,9 +66,6 @@ Q "+Quick_Kick"
` "toggleconsole"
Capslock "+AutoRun"
X "+Last_Used_Weapon"
F6 "+Quick_Save"
F9 "+Quick_Load"
F7 "+Third_Person_View"
C "+Toggle_Crouch"
Mouse1 "+Fire"
Mouse2 "+Jetpack"

View file

@ -66,9 +66,6 @@ Q "+Quick_Kick"
; "+Previous_Weapon"
` "toggleconsole"
Capslock "+AutoRun"
F6 "+Quick_Save"
F9 "+Quick_Load"
F7 "+Third_Person_View"
Mouse1 "+Fire"
Mouse2 "+Open"
Mouse3 "+Run"

View file

@ -69,9 +69,6 @@ R "+Steroids"
; "+Previous_Weapon"
C "toggleconsole"
Capslock "+AutoRun"
F6 "+Quick_Save"
F9 "+Quick_Load"
F7 "+Third_Person_View"
Mouse1 "+Fire"
Mouse2 "+Jetpack"
Mouse3 "+MediKit"