-- more work on the menu - episode and skill menus are working in DN3D.

This commit is contained in:
Christoph Oelckers 2019-11-25 23:21:51 +01:00
parent d73f915c66
commit a74a670c99
20 changed files with 309 additions and 682 deletions

View file

@ -1780,7 +1780,7 @@ int32_t handleevents_sdlcommon(SDL_Event *ev)
break;
case SDL_QUIT:
quitevent = 1;
throw ExitEvent(0); // completely bypass the hackery in the games to block Alt-F4.
return -1;
}

View file

@ -178,7 +178,7 @@ bool DListMenu::MenuEvent (int mkey, bool fromcontroller)
return true;
case MKEY_Enter:
if (mDesc->mSelectedItem >= 0 && mDesc->mItems[mDesc->mSelectedItem]->Activate())
if (mDesc->mSelectedItem >= 0 && mDesc->mItems[mDesc->mSelectedItem]->Activate(mDesc->mMenuName))
{
gi->MenuChooseSound();
}
@ -320,7 +320,7 @@ void FListMenuItem::DrawSelector(int xofs, int yofs, FTexture *tex)
}
}
bool FListMenuItem::Activate()
bool FListMenuItem::Activate(FName)
{
return false; // cannot be activated
}
@ -476,10 +476,9 @@ bool FListMenuItemSelectable::Selectable()
return mEnabled && !mHidden;
}
bool FListMenuItemSelectable::Activate()
bool FListMenuItemSelectable::Activate(FName caller)
{
M_SetMenu(mAction, mParam);
return true;
return M_SetMenu(mAction, mParam, caller);
}
FName FListMenuItemSelectable::GetAction(int *pparam)

View file

@ -153,7 +153,7 @@ bool DMenu::MenuEvent (int mkey, bool fromcontroller)
{
case MKEY_Back:
{
if (scriptID != 1)
if (scriptID != 0)
{
Close();
//S_Sound (CHAN_VOICE | CHAN_UI, DMenu::CurrentMenu != NULL? "menu/backup" : "menu/clear", snd_menuvolume, ATTN_NONE);
@ -301,10 +301,17 @@ bool DMenu::TranslateKeyboardEvents()
void M_StartControlPanel (bool makeSound)
{
static bool created = false;
// intro might call this repeatedly
if (DMenu::CurrentMenu != NULL)
return;
if (!created) // Cannot do this earlier.
{
created = true;
M_CreateMenus();
}
buttonMap.ResetButtonStates ();
for (int i = 0; i < NUM_MKEYS; ++i)
{
@ -350,7 +357,7 @@ void M_ActivateMenu(DMenu *menu)
//
//=============================================================================
void M_SetMenu(FName menu, int param)
bool M_SetMenu(FName menu, int param, FName caller)
{
if (DrawBackground == -1)
{
@ -358,32 +365,40 @@ void M_SetMenu(FName menu, int param)
else DrawBackground = 0;
}
// some menus need some special treatment (needs to be adjusted for the various frontends.
#if 0
switch (caller)
{
case NAME_EpisodeMenu:
// sent from the episode menu
GameStartupInfo.Episode = param;
GameStartupInfo.CustomLevel1 = GameStartupInfo.CustomLevel2 = -1;
GameStartupInfo.Skill = gDefaultSkill;
break;
case NAME_CustomGameMenu:
GameStartupInfo.CustomLevel1 = param;
GameStartupInfo.Episode = GameStartupInfo.CustomLevel2 = -1;
GameStartupInfo.Skill = gDefaultSkill;
// gi->CustomMenuSelection(-1, param);
break;
case NAME_CustomSubMenu1:
GameStartupInfo.CustomLevel2 = param;
// gi->CustomMenuSelection(GameStartupInfo.CustomLevel1, param);
menu = FName(ENamedName(menu + param));
break;
case NAME_SkillMenu:
GameStartupInfo.Skill = param;
break;
}
switch (menu)
{
case NAME_Episodemenu:
// sent from the player class menu
GameStartupInfo.Skill = -1;
GameStartupInfo.Episode = -1;
GameStartupInfo.PlayerClass =
param == -1000? NULL :
param == -1? "Random" : GetPrintableDisplayName(PlayerClasses[param].Type);
break;
case NAME_Skillmenu:
// sent from the episode menu
if ((gameinfo.flags & GI_SHAREWARE) && param > 0)
{
// Only Doom and Heretic have multi-episode shareware versions.
M_StartMessage(GStrings("SWSTRING"), 1);
return;
}
GameStartupInfo.Episode = param;
M_StartupSkillMenu(&GameStartupInfo); // needs player class name from class menu (later)
break;
case NAME_StartGame:
// gi->StartGame(&GameStartupInfo);
return false;
#if 0
case NAME_StartgameConfirm:
{
// sent from the skill menu for a skill that needs to be confirmed
@ -395,21 +410,6 @@ void M_SetMenu(FName menu, int param)
return;
}
case NAME_Startgame:
// sent either from skill menu or confirmation screen. Skill gets only set if sent from skill menu
// Now we can finally start the game. Ugh...
GameStartupInfo.Skill = param;
case NAME_StartgameConfirmed:
G_DeferedInitNew (&GameStartupInfo);
if (gamestate == GS_FULLCONSOLE)
{
gamestate = GS_HIDECONSOLE;
gameaction = ga_newgame;
}
M_ClearMenus ();
return;
case NAME_Savegamemenu:
if (!usergame || (players[consoleplayer].health <= 0 && !multiplayer) || gamestate != GS_LEVEL)
{
@ -417,8 +417,8 @@ void M_SetMenu(FName menu, int param)
M_StartMessage (GStrings("SAVEDEAD"), 1);
return;
}
}
#endif
}
// End of special checks
@ -439,7 +439,7 @@ void M_SetMenu(FName menu, int param)
if (ld->mAutoselect >= 0 && ld->mAutoselect < (int)ld->mItems.Size())
{
// recursively activate the autoselected item without ever creating this menu.
ld->mItems[ld->mAutoselect]->Activate();
ld->mItems[ld->mAutoselect]->Activate(ld->mMenuName);
}
else
{
@ -462,6 +462,7 @@ void M_SetMenu(FName menu, int param)
}
newmenu->Init(DMenu::CurrentMenu, ld);
M_ActivateMenu(newmenu);
return true;
}
}
else if ((*desc)->mType == MDESC_OptionsMenu)
@ -473,7 +474,7 @@ void M_SetMenu(FName menu, int param)
newmenu->Init(DMenu::CurrentMenu, ld);
M_ActivateMenu(newmenu);
}
return;
return true;
}
else
{
@ -486,12 +487,13 @@ void M_SetMenu(FName menu, int param)
DMenu *newmenu = (DMenu*)menuclass->CreateNew();
newmenu->mParentMenu = DMenu::CurrentMenu;
M_ActivateMenu(newmenu);
return;
return true;
}
}
*/
}
Printf("Attempting to open menu of unknown type '%s'\n", menu.GetChars());
return false;
}
//=============================================================================
@ -790,7 +792,6 @@ void M_Init (void)
RegisterDukeMenus();
timerSetCallback(M_Ticker);
M_ParseMenuDefs();
M_CreateMenus();
}

View file

@ -17,6 +17,7 @@ enum EMax
{
MAXSKILLS = 7,
MAXVOLUMES = 7,
MAXMENUGAMEPLAYENTRIES = 7,
};
// These get filled in by the map definition parsers of the front ends.
@ -24,11 +25,40 @@ extern FString gSkillNames[MAXSKILLS];
extern FString gVolumeNames[MAXVOLUMES];
extern FString gVolumeSubtitles[MAXVOLUMES];
extern int32_t gVolumeFlags[MAXVOLUMES];
extern int gDefaultVolume, gDefaultSkill;
const int MENU_TICRATE = 30;
extern bool help_disabled, credits_disabled;
extern int g_currentMenu;
enum
{
EF_HIDEFROMSP = 1 << 0,
};
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];
enum EMenuState : int
{
@ -86,9 +116,10 @@ enum ENativeFontValues
struct FGameStartup
{
const char *PlayerClass;
int Episode;
int Skill;
int CustomLevel1;
int CustomLevel2;
};
extern FGameStartup GameStartupInfo;
@ -345,7 +376,7 @@ public:
virtual void Ticker();
virtual void Drawer(DListMenu *menu, const vec2_t& origin, bool selected);
virtual bool Selectable();
virtual bool Activate();
virtual bool Activate(FName caller);
virtual FName GetAction(int *pparam);
virtual bool SetString(int i, const char *s);
virtual bool GetString(int i, char *s, int len);
@ -363,6 +394,7 @@ public:
void SetX(int x) { mXpos = x; }
void SetY(int x) { mYpos = x; }
void SetHeight(int x) { mHeight = x; }
void SetAction(FName action) { mAction = action; }
};
class FListMenuItemStaticPatch : public FListMenuItem
@ -407,7 +439,7 @@ public:
bool CheckCoordinate(int x, int y) override;
bool Selectable() override;
bool CheckHotkey(int c) override;
bool Activate() override;
bool Activate(FName caller) override;
bool MouseEvent(int type, int x, int y) override;
FName GetAction(int *pparam) override;
};
@ -636,9 +668,11 @@ void M_ParseMenuDefs();
void M_StartupSkillMenu(FGameStartup *gs);
int M_GetDefaultSkill();
void M_StartControlPanel (bool makeSound);
void M_SetMenu(FName menu, int param = -1);
bool M_SetMenu(FName menu, int param = -1, FName callingMenu = NAME_None);
void M_NotifyNewSave (const char *file, const char *title, bool okForQuicksave);
void M_StartMessage(const char *message, int messagemode, FName action = NAME_None);
void M_UnhideCustomMenu(int menu, int itemmask);
void I_SetMouseCapture();
void I_ReleaseMouseCapture();

View file

@ -49,10 +49,13 @@
void ClearSaveGames();
// Menu-relevant content that gets filled in by scripts. This will get processed after the game has loaded.
FString gSkillNames[MAXSKILLS];
FString gVolumeNames[MAXVOLUMES];
FString gVolumeSubtitles[MAXVOLUMES];
int32_t gVolumeFlags[MAXVOLUMES];
int gDefaultVolume = 0, gDefaultSkill = 1;
MenuGameplayStemEntry g_MenuGameplayEntries[MAXMENUGAMEPLAYENTRIES];
MenuDescriptorList MenuDescriptors;
static FListMenuDescriptor DefaultListMenuSettings; // contains common settings for all list menus
@ -982,10 +985,34 @@ void M_ParseMenuDefs()
}
//=============================================================================
//
// Unlocks a custom menu from a script
//
//=============================================================================
void M_UnhideCustomMenu(int menu, int iSet)
{
FName menuname = FName(ENamedName(NAME_CustomSubMenu1 + menu));
auto desc = MenuDescriptors.CheckKey(menuname);
if (desc != NULL && (*desc)->mType == MDESC_ListMenu)
{
FListMenuDescriptor* ld = static_cast<FListMenuDescriptor*>(*desc);
for (unsigned int b = 0; b < MAXMENUGAMEPLAYENTRIES; ++b)
{
if (b >= ld->mItems.Size()) return;
if (iSet & (1u << b))
{
ld->mItems[b]->mHidden = false;
ld->mItems[b]->mEnabled = true;
}
}
}
}
//=============================================================================
//
// Creates the episode menu
// Falls back on an option menu if there's not enough screen space to show all episodes
//
//=============================================================================
@ -994,68 +1021,130 @@ static void BuildEpisodeMenu()
// Build episode menu
int addedVolumes = 0;
FMenuDescriptor **desc = MenuDescriptors.CheckKey(NAME_EpisodeMenu);
if (desc != NULL)
if (desc != NULL && (*desc)->mType == MDESC_ListMenu)
{
if ((*desc)->mType == MDESC_ListMenu)
FListMenuDescriptor *ld = static_cast<FListMenuDescriptor*>(*desc);
ld->mSelectedItem = gDefaultVolume;
for (int i = 0; i < MAXVOLUMES; i++)
{
FListMenuDescriptor *ld = static_cast<FListMenuDescriptor*>(*desc);
ld->mSelectedItem = 1;
if (gVolumeNames[i].IsNotEmpty() && !(gVolumeFlags[i] & EF_HIDEFROMSP))
for (int i = 0; i < MAXVOLUMES; i++)
{
if (gVolumeNames[i].IsNotEmpty())
auto it = new FListMenuItemNativeText(ld->mXpos, 0, 0, gVolumeNames[i][0], gVolumeNames[i], NIT_BigFont, NIT_ActiveState, 1, NAME_SkillMenu, i + 1);
ld->mItems.Push(it);
addedVolumes++;
if (gVolumeSubtitles[i].IsNotEmpty())
{
auto it = new FListMenuItemNativeText(ld->mXpos, 0, 0, gVolumeNames[i][0], gVolumeNames[i], NIT_BigFont, NIT_ActiveState, 1, NAME_SkillMenu, i + 1);
ld->mItems.Push(it);
addedVolumes++;
if (gVolumeSubtitles[i].IsNotEmpty())
{
//auto it = new FListMenuItemNativeStaticText(ld->mXpos, gVolumeSubtitles[i], NIT_SmallFont);
//ld->mItems.Push(it);
}
}
if (1 /*CheckUserMaps()*/)
{
//auto it = new FListMenuItemNativeStaticText(ld->mXpos, "", NIT_SmallFont); // empty entry as spacer.
//auto it = new FListMenuItemNativeStaticText(ld->mXpos, gVolumeSubtitles[i], NIT_SmallFont);
//ld->mItems.Push(it);
}
}
}
if (1 /*CheckUserMaps()*/)
{
//auto it = new FListMenuItemNativeStaticText(ld->mXpos, "", NIT_SmallFont); // empty entry as spacer.
//ld->mItems.Push(it);
auto it = new FListMenuItemNativeText(ld->mXpos, 0, 0, 0, "$MNU_USERMAP", NIT_BigFont, NIT_ActiveState, 1, NAME_SkillMenu, i + 1);
ld->mItems.Push(it);
addedVolumes++;
if (g_gameType & GAMEFLAG_SW) // fixme: make this game independent.
auto it = new FListMenuItemNativeText(ld->mXpos, 0, 0, 0, "$MNU_USERMAP", NIT_BigFont, NIT_ActiveState, 1, NAME_UsermapMenu);
ld->mItems.Push(it);
addedVolumes++;
if (g_gameType & GAMEFLAG_SW) // fixme: make this game independent.
{
//auto it = new FListMenuItemNativeStaticText(ld->mXpos, "$MNU_SELECTUSERMAP", NIT_SmallFont);
//ld->mItems.Push(it);
}
}
if (addedVolumes == 1)
{
ld->mAutoselect = 0;
}
}
// Build skill menu
int addedSkills = 0;
desc = MenuDescriptors.CheckKey(NAME_SkillMenu);
if (desc != NULL && (*desc)->mType == MDESC_ListMenu)
{
FListMenuDescriptor* ld = static_cast<FListMenuDescriptor*>(*desc);
ld->mSelectedItem = gDefaultSkill;
for (int i = 0; i < MAXSKILLS; i++)
{
if (gSkillNames[i].IsNotEmpty())
{
auto it = new FListMenuItemNativeText(ld->mXpos, 0, 0, gSkillNames[i][0], gSkillNames[i], NIT_BigFont, NIT_ActiveState, 1, NAME_StartGame, i);
ld->mItems.Push(it);
addedSkills++;
}
}
if (addedSkills == 0)
{
// Need to add one item with the default skill so that the menu does not break.
auto it = new FListMenuItemNativeText(ld->mXpos, 0, 0, 0, "", NIT_BigFont, NIT_ActiveState, 1, NAME_StartGame, gDefaultSkill);
ld->mItems.Push(it);
}
if (addedSkills == 1)
{
ld->mAutoselect = 0;
}
}
if (g_MenuGameplayEntries[0].entry.isValid())
{
int e = 0;
FMenuDescriptor** desc = MenuDescriptors.CheckKey(NAME_CustomGameMenu);
if (desc != NULL && (*desc)->mType == MDESC_ListMenu)
{
FListMenuDescriptor* ld = static_cast<FListMenuDescriptor*>(*desc);
for (MenuGameplayStemEntry const& stem : g_MenuGameplayEntries)
{
MenuGameplayEntry const& entry = stem.entry;
if (!entry.isValid())
break;
int s = 0;
FMenuDescriptor** sdesc = MenuDescriptors.CheckKey(FName(ENamedName(NAME_CustomSubMenu1 + e)));
if (sdesc != NULL && (*sdesc)->mType == MDESC_ListMenu)
{
FListMenuDescriptor* ld = static_cast<FListMenuDescriptor*>(*desc);
for (MenuGameplayEntry const& subentry : stem.subentries)
{
//auto it = new FListMenuItemNativeStaticText(ld->mXpos, "$MNU_SELECTUSERMAP", NIT_SmallFont);
//ld->mItems.Push(it);
if (!subentry.isValid())
break;
auto li = new FListMenuItemNativeText(ld->mXpos, 0, 0, 0, subentry.name, NIT_BigFont, NIT_ActiveColor, 1.f, subentry.flags & MGE_UserContent ? NAME_UsermapMenu : NAME_SkillMenu);
if (subentry.flags & MGE_Locked) li->mEnabled = false;
if (subentry.flags & MGE_Hidden) li->mHidden = true;
++s;
}
}
if (addedVolumes == 1)
FName link = entry.flags & MGE_UserContent ? NAME_UsermapMenu : s == 0 ? NAME_SkillMenu : NAME_CustomSubMenu1;
auto li = new FListMenuItemNativeText(ld->mXpos, 0, 0, 0, entry.name, NIT_BigFont, NIT_ActiveColor, 1.f, link, link == NAME_CustomSubMenu1 ? e : -1);
if (entry.flags & MGE_Locked) li->mEnabled = false;
if (entry.flags & MGE_Hidden) li->mHidden = true;
e++;
}
}
if (e > 0)
{
FMenuDescriptor** desc = MenuDescriptors.CheckKey(NAME_MainMenu);
if (desc != NULL && (*desc)->mType == MDESC_ListMenu)
{
FListMenuDescriptor* ld = static_cast<FListMenuDescriptor*>(*desc);
auto li = ld->mItems[0];
if (li->GetAction(nullptr) == NAME_EpisodeMenu)
{
ld->mAutoselect = 0;
li->SetAction(NAME_CustomGameMenu);
}
}
}
}
#if 0
if (gVolumeNames[i].IsNotEmpty())
{
if (!(gVolumeFlags[i] & EF_HIDEFROMSP))
{
MEL_EPISODE[i] = &ME_EPISODE[i];
ME_EPISODE[i] = ME_EPISODE_TEMPLATE;
ME_EPISODE[i].name = gVolumeNames[i];
}
// if (!(EpisodeFlags[i] & EF_HIDEFROMMP))
{
MEOSN_NetEpisodes[k] = gVolumeNames[i];
MEOSV_NetEpisodes[k] = i;
k++;
}
}
M_EPISODE.numEntries = g_volumeCnt + 2;
#endif
}
//=============================================================================
@ -1141,181 +1230,6 @@ void M_CreateMenus()
#endif
}
//=============================================================================
//
// The skill menu must be refeshed each time it starts up
//
//=============================================================================
extern int restart;
void M_StartupSkillMenu(FGameStartup *gs)
{
#if 0
static int done = -1;
bool success = false;
FMenuDescriptor **desc = MenuDescriptors.CheckKey(NAME_Skillmenu);
if (desc != NULL)
{
if ((*desc)->mType == MDESC_ListMenu)
{
FListMenuDescriptor *ld = static_cast<FListMenuDescriptor*>(*desc);
int x = ld->mXpos;
int y = ld->mYpos;
// Delete previous contents
for(unsigned i=0; i<ld->mItems.Size(); i++)
{
FName n = ld->mItems[i]->GetAction(NULL);
if (n == NAME_Startgame || n == NAME_StartgameConfirm)
{
for(unsigned j=i; j<ld->mItems.Size(); j++)
{
delete ld->mItems[j];
}
ld->mItems.Resize(i);
break;
}
}
if (done != restart)
{
done = restart;
int defskill = DefaultSkill;
if ((unsigned int)defskill >= AllSkills.Size())
{
defskill = (AllSkills.Size() - 1) / 2;
}
ld->mSelectedItem = ld->mItems.Size() + defskill;
int posy = y;
int topy = posy;
// Get lowest y coordinate of any static item in the menu
for(unsigned i = 0; i < ld->mItems.Size(); i++)
{
int y = ld->mItems[i]->GetY();
if (y < topy) topy = y;
}
// center the menu on the screen if the top space is larger than the bottom space
int totalheight = posy + AllSkills.Size() * ld->mLinespacing - topy;
if (totalheight < 190 || AllSkills.Size() == 1)
{
int newtop = (200 - totalheight + topy) / 2;
int topdelta = newtop - topy;
if (topdelta < 0)
{
for(unsigned i = 0; i < ld->mItems.Size(); i++)
{
ld->mItems[i]->OffsetPositionY(topdelta);
}
y = ld->mYpos = posy - topdelta;
}
}
else
{
// too large
delete ld;
desc = NULL;
done = false;
goto fail;
}
}
unsigned firstitem = ld->mItems.Size();
for(unsigned int i = 0; i < AllSkills.Size(); i++)
{
FSkillInfo &skill = AllSkills[i];
FListMenuItem *li;
// Using a different name for skills that must be confirmed makes handling this easier.
FName action = (skill.MustConfirm && !AllEpisodes[gs->Episode].mNoSkill) ?
NAME_StartgameConfirm : NAME_Startgame;
FString *pItemText = NULL;
if (gs->PlayerClass != NULL)
{
pItemText = skill.MenuNamesForPlayerClass.CheckKey(gs->PlayerClass);
}
if (skill.PicName.Len() != 0 && pItemText == NULL)
{
FTextureID tex = GetMenuTexture(skill.PicName);
li = new FListMenuItemPatch(ld->mXpos, y, ld->mLinespacing, skill.Shortcut, tex, action, i);
}
else
{
EColorRange color = (EColorRange)skill.GetTextColor();
if (color == CR_UNTRANSLATED) color = ld->mFontColor;
li = new FListMenuItemText(x, y, ld->mLinespacing, skill.Shortcut,
pItemText? *pItemText : skill.MenuName, ld->mFont, color,ld->mFontColor2, action, i);
}
ld->mItems.Push(li);
y += ld->mLinespacing;
}
if (AllEpisodes[gs->Episode].mNoSkill || AllSkills.Size() == 1)
{
ld->mAutoselect = firstitem + M_GetDefaultSkill();
}
else
{
ld->mAutoselect = -1;
}
success = true;
}
}
if (success) return;
fail:
// Option menu fallback for overlong skill lists
FOptionMenuDescriptor *od;
if (desc == NULL)
{
od = new FOptionMenuDescriptor;
if (desc != NULL) delete *desc;
MenuDescriptors[NAME_Skillmenu] = od;
od->mType = MDESC_OptionsMenu;
od->mMenuName = NAME_Skillmenu;
od->mTitle = "$MNU_CHOOSESKILL";
od->mSelectedItem = 0;
od->mScrollPos = 0;
od->mClass = NULL;
od->mPosition = -15;
od->mScrollTop = 0;
od->mIndent = 160;
od->mDontDim = false;
}
else
{
od = static_cast<FOptionMenuDescriptor*>(*desc);
for(unsigned i=0;i<od->mItems.Size(); i++)
{
delete od->mItems[i];
}
od->mItems.Clear();
}
for(unsigned int i = 0; i < AllSkills.Size(); i++)
{
FSkillInfo &skill = AllSkills[i];
FOptionMenuItem *li;
// Using a different name for skills that must be confirmed makes handling this easier.
const char *action = (skill.MustConfirm && !AllEpisodes[gs->Episode].mNoSkill) ?
"StartgameConfirm" : "Startgame";
FString *pItemText = NULL;
if (gs->PlayerClass != NULL)
{
pItemText = skill.MenuNamesForPlayerClass.CheckKey(gs->PlayerClass);
}
li = new FOptionMenuItemSubmenu(pItemText? *pItemText : skill.MenuName, action, i);
od->mItems.Push(li);
if (!done)
{
done = true;
od->mSelectedItem = M_GetDefaultSkill();
}
}
#endif
}
//=============================================================================
//
// Returns the default skill level.
@ -1324,14 +1238,5 @@ fail:
int M_GetDefaultSkill()
{
#if 0
int defskill = DefaultSkill;
if ((unsigned int)defskill >= AllSkills.Size())
{
defskill = (AllSkills.Size() - 1) / 2;
}
return defskill;
#else
return 1;
#endif
return gDefaultSkill;
}

View file

@ -310,7 +310,7 @@ bool DOptionMenu::MenuEvent (int mkey, bool fromcontroller)
break;
case MKEY_Enter:
if (mDesc->mSelectedItem >= 0 && mDesc->mItems[mDesc->mSelectedItem]->Activate())
if (mDesc->mSelectedItem >= 0 && mDesc->mItems[mDesc->mSelectedItem]->Activate(mDesc->mMenuName))
{
return true;
}

View file

@ -34,3 +34,5 @@ xx(CustomSubMenu4)
xx(CustomSubMenu5)
xx(CustomSubMenu6)
xx(CustomSubMenu7)
xx(UsermapMenu)
xx(StartGame)

View file

@ -74,7 +74,6 @@ void CONFIG_SetDefaults(void)
ud.angleinterpolation = 0;
ud.camerasprite = -1;
ud.config.ShowWeapons = 0;
ud.default_skill = 1;
ud.display_bonus_screen = 1;
hud_position = 0;

View file

@ -35,6 +35,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "gamecontrol.h"
#include "c_bind.h"
#include "menu/menu.h"
#include "gstrings.h"
#include "../../glbackend/glbackend.h"
BEGIN_DUKE_NS
@ -44,10 +45,6 @@ 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
{
@ -96,212 +93,6 @@ void Menu_Init(void)
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;
if (gVolumeNames[i].IsNotEmpty())
{
if (!(gVolumeFlags[i] & EF_HIDEFROMSP))
{
MEL_EPISODE[i] = &ME_EPISODE[i];
ME_EPISODE[i] = ME_EPISODE_TEMPLATE;
ME_EPISODE[i].name = gVolumeNames[i];
}
// if (!(EpisodeFlags[i] & EF_HIDEFROMMP))
{
MEOSN_NetEpisodes[k] = gVolumeNames[i];
MEOSV_NetEpisodes[k] = i;
k++;
}
}
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
@ -311,28 +102,6 @@ void Menu_Init(void)
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)
@ -358,10 +127,7 @@ void Menu_Init(void)
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
}
@ -374,6 +140,7 @@ static void Menu_DrawTopBar(const vec2_t origin)
static void Menu_DrawTopBarCaption(const char *caption, const vec2_t origin)
{
static char t[64];
if (*caption == '$') caption = GStrings(caption + 1);
size_t const srclen = strlen(caption);
size_t const dstlen = min(srclen, ARRAY_SIZE(t)-1);
memcpy(t, caption, dstlen);
@ -572,6 +339,11 @@ protected:
void PreDraw() override
{
CallScript(CurrentMenu == this ? EVENT_DISPLAYMENU : EVENT_DISPLAYMENUREST, true);
if (mDesc->mCaption.IsNotEmpty())
{
Menu_DrawTopBar(origin);
Menu_DrawTopBarCaption(mDesc->mCaption, origin);
}
}
void PostDraw() override
@ -601,11 +373,6 @@ class MainMenu : public DukeListMenu
if (PLUTOPAK) // JBF 20030804
rotatesprite_fs((origin.y << 16) + ((MENU_MARGIN_CENTER+100)<<16), (origin.y << 16) + (36<<16), 65536L,0,PLUTOPAKSPRITE+2,(sintable[((int32_t) totalclock<<4)&2047]>>11),0,2+8);
}
else if (mDesc->mCaption.IsNotEmpty())
{
Menu_DrawTopBar(origin);
Menu_DrawTopBarCaption(mDesc->mCaption, origin);
}
}
};

View file

@ -161,8 +161,6 @@ typedef struct {
int32_t playerbest;
int32_t default_volume, default_skill;
int32_t returnvar[MAX_RETURN_VALUES-1];
uint32_t userbytever;

View file

@ -1508,8 +1508,8 @@ int32_t __fastcall VM_GetUserdef(int32_t labelNum, int const lParm2)
case USERDEFS_GLOBAL_R: labelNum = globalr; break;
case USERDEFS_GLOBAL_G: labelNum = globalg; break;
case USERDEFS_GLOBAL_B: labelNum = globalb; break;
case USERDEFS_DEFAULT_VOLUME: labelNum = ud.default_volume; break;
case USERDEFS_DEFAULT_SKILL: labelNum = ud.default_skill; break;
case USERDEFS_DEFAULT_VOLUME: labelNum = gDefaultVolume; break;
case USERDEFS_DEFAULT_SKILL: labelNum = gDefaultSkill; break;
case USERDEFS_MENU_SHADEDESELECTED: labelNum = MF_Redfont.shade_deselected; break;
case USERDEFS_MENU_SHADEDISABLED: labelNum = MF_Redfont.shade_disabled; break;
case USERDEFS_MENUTEXT_ZOOM: labelNum = MF_Redfont.zoom; break;
@ -1701,8 +1701,8 @@ void __fastcall VM_SetUserdef(int const labelNum, int const lParm2, int32_t cons
case USERDEFS_GLOBAL_R: globalr = iSet; break;
case USERDEFS_GLOBAL_G: globalg = iSet; break;
case USERDEFS_GLOBAL_B: globalb = iSet; break;
case USERDEFS_DEFAULT_VOLUME: ud.default_volume = iSet; break;
case USERDEFS_DEFAULT_SKILL: ud.default_skill = iSet; break;
case USERDEFS_DEFAULT_VOLUME: gDefaultVolume = iSet; break;
case USERDEFS_DEFAULT_SKILL: gDefaultSkill = iSet; break;
case USERDEFS_MENU_SHADEDESELECTED: MF_Redfont.shade_deselected = MF_Bluefont.shade_deselected = MF_Minifont.shade_deselected = iSet; break;
case USERDEFS_MENU_SHADEDISABLED: MF_Redfont.shade_disabled = MF_Bluefont.shade_disabled = MF_Minifont.shade_disabled = iSet; break;
case USERDEFS_MENUTEXT_ZOOM: MF_Redfont.zoom = iSet; break;
@ -1751,16 +1751,8 @@ void __fastcall VM_SetUserdef(int const labelNum, int const lParm2, int32_t cons
case USERDEFS_DRAW_Y: rotatesprite_y_offset = iSet; break;
case USERDEFS_DRAW_YXASPECT: rotatesprite_yxaspect = iSet; break;
case USERDEFS_FOV: r_fov.SetGenericRepDefault(iSet, CVAR_Int); break;
case USERDEFS_NEWGAMECUSTOMOPEN:
for (unsigned int b = 0; b < MAXMENUGAMEPLAYENTRIES; ++b)
if (iSet & (1u<<b))
ME_NEWGAMECUSTOMENTRIES[b] = 0;
break;
case USERDEFS_NEWGAMECUSTOMSUBOPEN:
for (unsigned int b = 0; b < MAXMENUGAMEPLAYENTRIES; ++b)
if (iSet & (1u<<b))
ME_NEWGAMECUSTOMSUBENTRIES[lParm2][b] = 0;
break;
case USERDEFS_NEWGAMECUSTOMOPEN: M_UnhideCustomMenu(-1, iSet); break;
case USERDEFS_NEWGAMECUSTOMSUBOPEN: M_UnhideCustomMenu(lParm2, iSet); break;
}
}

View file

@ -189,11 +189,6 @@ extern int32_t g_gametypeFlags[MAXGAMETYPES];
extern const char *s_buildDate;
#endif
enum
{
EF_HIDEFROMSP = 1<<0,
};
EXTERN_INLINE_HEADER void G_UpdateInterpolations(void);
EXTERN_INLINE_HEADER void G_RestoreInterpolations(void);

View file

@ -1564,8 +1564,6 @@ void Menu_Init(void)
}
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;
@ -1576,74 +1574,6 @@ void Menu_Init(void)
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;

View file

@ -47,32 +47,6 @@ struct MenuFont_t
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);

View file

@ -86,7 +86,6 @@ void CONFIG_SetDefaults(void)
ud.show_level_text = 1;
ud.screenfade = 1;
ud.menubackground = 1;
ud.default_skill = 1;
ud.slidebar_paldisabled = 1;
ud.shadow_pal = 4;
ud.menu_scrollbartilenum = -1;

View file

@ -163,8 +163,6 @@ typedef struct {
int32_t playerbest;
int32_t default_volume, default_skill;
//int32_t returnvar[MAX_RETURN_VALUES-1];
uint32_t userbytever;

View file

@ -1579,7 +1579,7 @@ void Menu_Init(void)
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;
M_EPISODE.currentEntry = gDefaultVolume;
// prepare skills
k = -1;
@ -1598,7 +1598,7 @@ void Menu_Init(void)
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;
M_SKILL.currentEntry = gDefaultSkill;
Menu_AdjustForCurrentEntryAssignmentBlind(&M_SKILL);
// prepare multiplayer gametypes

View file

@ -754,7 +754,6 @@ FString GameInterface::statFPS()
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 };
}