From 3b7aa74c27531adb205014c5d1f47e53f65067bf Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 26 Nov 2019 23:20:54 +0100 Subject: [PATCH] - connecting the dots in the menu. Duke Nukem can now start a level. --- source/build/include/baselayer.h | 21 +- source/common/menu/listmenu.cpp | 10 +- source/common/menu/menu.cpp | 13 +- source/common/menu/menu.h | 10 +- source/common/menu/menudef.cpp | 2 +- source/duke3d/src/d_menu.cpp | 61 +++++- source/duke3d/src/duke3d.h | 6 +- source/duke3d/src/gamestructures.cpp | 4 +- source/duke3d/src/menus.cpp | 297 +-------------------------- 9 files changed, 95 insertions(+), 329 deletions(-) diff --git a/source/build/include/baselayer.h b/source/build/include/baselayer.h index 36c406492..4bc2bac9f 100644 --- a/source/build/include/baselayer.h +++ b/source/build/include/baselayer.h @@ -168,8 +168,23 @@ struct GameStats int timesecnd; }; +struct FGameStartup +{ + int Episode; + int Level; + int Skill; + int CustomLevel1; + int CustomLevel2; +}; + struct GameInterface { + enum EMenuSounds + { + SelectSound, + ChooseSound + }; + virtual ~GameInterface() {} virtual void faketimerhandler() {} // This is a remnant of older versions, but Blood backend has not updated yet. virtual int app_main() = 0; @@ -182,9 +197,11 @@ struct GameInterface virtual void DrawNativeMenuText(int fontnum, int state, int xpos, int ypos, float fontscale, const char* text, int flags) {} virtual void MainMenuOpened() {} virtual void MenuOpened() {} - virtual void MenuSelectSound() {} - virtual void MenuChooseSound() {} + virtual void MenuClosed() {} + virtual void MenuSound(EMenuSounds snd) {} virtual bool CanSave() { return true; } + virtual void CustomMenuSelection(int menu, int item) {} + virtual void StartGame(FGameStartup& gs) {} }; extern GameInterface* gi; diff --git a/source/common/menu/listmenu.cpp b/source/common/menu/listmenu.cpp index bff609e2e..9138a840a 100644 --- a/source/common/menu/listmenu.cpp +++ b/source/common/menu/listmenu.cpp @@ -130,7 +130,7 @@ bool DListMenu::Responder (event_t *ev) if (mDesc->mItems[i]->CheckHotkey(ch)) { mDesc->mSelectedItem = i; - gi->MenuSelectSound(); + gi->MenuSound(GameInterface::SelectSound); return true; } } @@ -139,7 +139,7 @@ bool DListMenu::Responder (event_t *ev) if (mDesc->mItems[i]->CheckHotkey(ch)) { mDesc->mSelectedItem = i; - gi->MenuSelectSound(); + gi->MenuSound(GameInterface::SelectSound); return true; } } @@ -166,7 +166,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); - gi->MenuSelectSound(); + gi->MenuSound(GameInterface::SelectSound); return true; case MKEY_Down: @@ -175,13 +175,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); - gi->MenuSelectSound(); + gi->MenuSound(GameInterface::SelectSound); return true; case MKEY_Enter: if (mDesc->mSelectedItem >= 0 && mDesc->mItems[mDesc->mSelectedItem]->Activate(mDesc->mMenuName)) { - gi->MenuChooseSound(); + gi->MenuSound(GameInterface::ChooseSound); } return true; diff --git a/source/common/menu/menu.cpp b/source/common/menu/menu.cpp index 7e7b6d7d8..c3823d631 100644 --- a/source/common/menu/menu.cpp +++ b/source/common/menu/menu.cpp @@ -437,20 +437,23 @@ bool M_SetMenu(FName menu, int param, FName caller) case NAME_EpisodeMenu: // sent from the episode menu GameStartupInfo.Episode = param; + GameStartupInfo.Level = 0; GameStartupInfo.CustomLevel1 = GameStartupInfo.CustomLevel2 = -1; GameStartupInfo.Skill = gDefaultSkill; break; case NAME_CustomGameMenu: GameStartupInfo.CustomLevel1 = param; - GameStartupInfo.Episode = GameStartupInfo.CustomLevel2 = -1; + GameStartupInfo.CustomLevel2 = -1; + GameStartupInfo.Episode = -1; + GameStartupInfo.Level = -1; GameStartupInfo.Skill = gDefaultSkill; - // gi->CustomMenuSelection(-1, param); + gi->CustomMenuSelection(param, -1); break; case NAME_CustomSubMenu1: GameStartupInfo.CustomLevel2 = param; - // gi->CustomMenuSelection(GameStartupInfo.CustomLevel1, param); + gi->CustomMenuSelection(GameStartupInfo.CustomLevel1, param); menu = FName(ENamedName(menu + param)); break; @@ -462,7 +465,8 @@ bool M_SetMenu(FName menu, int param, FName caller) switch (menu) { case NAME_StartGame: - // gi->StartGame(&GameStartupInfo); + M_ClearMenus(); // must be done before starting the level. + gi->StartGame(GameStartupInfo); return false; #if 0 @@ -844,6 +848,7 @@ void M_ClearMenus () } menuactive = MENU_Off; GUICapture &= ~1; + gi->MenuClosed(); } void Menu_Close(int playerid) diff --git a/source/common/menu/menu.h b/source/common/menu/menu.h index b13dbe08f..545de2b20 100644 --- a/source/common/menu/menu.h +++ b/source/common/menu/menu.h @@ -9,6 +9,7 @@ #include "version.h" #include "textures.h" #include "zstring.h" +#include "baselayer.h" EXTERN_CVAR(Float, snd_menuvolume) EXTERN_CVAR(Int, m_use_mouse); @@ -113,15 +114,6 @@ enum ENativeFontValues // positive values for color are direct palswap indices. }; - -struct FGameStartup -{ - int Episode; - int Skill; - int CustomLevel1; - int CustomLevel2; -}; - extern FGameStartup GameStartupInfo; struct FSaveGameNode diff --git a/source/common/menu/menudef.cpp b/source/common/menu/menudef.cpp index c1ba3ea16..fdda98779 100644 --- a/source/common/menu/menudef.cpp +++ b/source/common/menu/menudef.cpp @@ -1035,7 +1035,7 @@ static void BuildEpisodeMenu() if (gVolumeNames[i].IsNotEmpty() && !(gVolumeFlags[i] & EF_HIDEFROMSP)) { - auto it = new FListMenuItemNativeText(ld->mXpos, 0, 0, gVolumeNames[i][0], gVolumeNames[i], NIT_BigFont, NIT_ActiveState, 1, NAME_SkillMenu, i + 1); + auto it = new FListMenuItemNativeText(ld->mXpos, 0, 0, gVolumeNames[i][0], gVolumeNames[i], NIT_BigFont, NIT_ActiveState, 1, NAME_SkillMenu, i); ld->mItems.Push(it); addedVolumes++; if (gVolumeSubtitles[i].IsNotEmpty()) diff --git a/source/duke3d/src/d_menu.cpp b/source/duke3d/src/d_menu.cpp index 3c1d69f7d..40fbc6a04 100644 --- a/source/duke3d/src/d_menu.cpp +++ b/source/duke3d/src/d_menu.cpp @@ -388,25 +388,30 @@ void GameInterface::MenuOpened() } } -void GameInterface::MenuSelectSound() +void GameInterface::MenuSound(::GameInterface::EMenuSounds snd) { - S_PlaySound(KICK_HIT); -} + switch (snd) + { + case SelectSound: + S_PlaySound(KICK_HIT); + break; -void GameInterface::MenuChooseSound() -{ - S_PlaySound(PISTOL_BODYHIT); + case ChooseSound: + S_PlaySound(PISTOL_BODYHIT); + break; + + default: + return; + } } -/* void GameInterface::MenuClosed() { S_PlaySound(EXITMENUSOUND); if (!ud.pause_on) S_PauseSounds(false); } -*/ bool GameInterface::CanSave() { @@ -420,6 +425,46 @@ bool GameInterface::CanSave() return true; } +void GameInterface::CustomMenuSelection(int menu, int item) +{ + ud.returnvar[0] = item; + ud.returnvar[1] = -1; + VM_OnEventWithReturn(EVENT_NEWGAMECUSTOM, -1, myconnectindex, menu); +} + +void GameInterface::StartGame(FGameStartup& gs) +{ + int32_t skillsound = PISTOL_BODYHIT; + + switch (gs.Skill) + { + case 0: + skillsound = JIBBED_ACTOR6; + break; + case 1: + skillsound = BONUS_SPEECH1; + break; + case 2: + skillsound = DUKE_GETWEAPON2; + break; + case 3: + skillsound = JIBBED_ACTOR5; + break; + } + + ud.m_player_skill = gs.Skill + 1; + ud.skill_voice = S_PlaySound(skillsound); + ud.m_respawn_monsters = (gs.Skill == 3); + ud.m_monsters_off = ud.monsters_off = 0; + ud.m_respawn_items = 0; + ud.m_respawn_inventory = 0; + ud.multimode = 1; + ud.m_volume_number = gs.Episode; + ud.m_level_number = gs.Level; + G_NewGame_EnterLevel(); + +} + END_DUKE_NS static TMenuClassDescriptor _mm("Duke.MainMenu"); diff --git a/source/duke3d/src/duke3d.h b/source/duke3d/src/duke3d.h index 53686b96a..d1e864766 100644 --- a/source/duke3d/src/duke3d.h +++ b/source/duke3d/src/duke3d.h @@ -158,9 +158,11 @@ struct GameInterface : ::GameInterface // 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) override; void MenuOpened() override; - void MenuSelectSound() override; - void MenuChooseSound() override; + void MenuClosed() override; + void MenuSound(EMenuSounds snd) override; bool CanSave() override; + void CustomMenuSelection(int menu, int item) override; + void StartGame(FGameStartup& gs) override; }; diff --git a/source/duke3d/src/gamestructures.cpp b/source/duke3d/src/gamestructures.cpp index a171b205f..40727c8fe 100644 --- a/source/duke3d/src/gamestructures.cpp +++ b/source/duke3d/src/gamestructures.cpp @@ -1632,8 +1632,8 @@ void __fastcall VM_SetUserdef(int const labelNum, int const lParm2, int32_t cons case USERDEFS_M_FFIRE: m_ffire = iSet; break; case USERDEFS_FFIRE: ud.ffire = iSet; break; case USERDEFS_M_PLAYER_SKILL: ud.m_player_skill = iSet; break; - case USERDEFS_M_LEVEL_NUMBER: m_level_number = iSet; break; - case USERDEFS_M_VOLUME_NUMBER: ud.m_volume_number = iSet; break; + case USERDEFS_M_LEVEL_NUMBER: GameStartupInfo.Level = m_level_number = iSet; break; + case USERDEFS_M_VOLUME_NUMBER: GameStartupInfo.Episode = ud.m_volume_number = iSet; break; case USERDEFS_MULTIMODE: ud.multimode = iSet; break; case USERDEFS_PLAYER_SKILL: ud.player_skill = iSet; break; case USERDEFS_LEVEL_NUMBER: ud.level_number = iSet; break; diff --git a/source/duke3d/src/menus.cpp b/source/duke3d/src/menus.cpp index edb88a201..b2a17664c 100644 --- a/source/duke3d/src/menus.cpp +++ b/source/duke3d/src/menus.cpp @@ -2763,63 +2763,6 @@ static void Menu_EntryLinkActivate(MenuEntry_t *entry) { switch (g_currentMenu) { - case MENU_EPISODE: - if (entry != &ME_EPISODE_USERMAP) - { - ud.m_volume_number = M_EPISODE.currentEntry; - m_level_number = 0; - - if (g_skillCnt == 0) - Menu_StartGameWithoutSkill(); - } - break; - - case MENU_NEWGAMECUSTOM: - ud.returnvar[0] = -1; - VM_OnEventWithReturn(EVENT_NEWGAMECUSTOM, -1, myconnectindex, M_NEWGAMECUSTOM.currentEntry); - break; - - case MENU_NEWGAMECUSTOMSUB: - ud.returnvar[0] = M_NEWGAMECUSTOMSUB.currentEntry; - ud.returnvar[1] = -1; - VM_OnEventWithReturn(EVENT_NEWGAMECUSTOM, -1, myconnectindex, M_NEWGAMECUSTOM.currentEntry); - break; - - case MENU_SKILL: - { - int32_t skillsound = PISTOL_BODYHIT; - - switch (M_SKILL.currentEntry) - { - case 0: - skillsound = JIBBED_ACTOR6; - break; - case 1: - skillsound = BONUS_SPEECH1; - break; - case 2: - skillsound = DUKE_GETWEAPON2; - break; - case 3: - skillsound = JIBBED_ACTOR5; - break; - } - - ud.m_player_skill = M_SKILL.currentEntry+1; - - ud.skill_voice = S_PlaySound(skillsound); - - if (M_SKILL.currentEntry == 3) ud.m_respawn_monsters = 1; - else ud.m_respawn_monsters = 0; - - ud.m_monsters_off = ud.monsters_off = 0; - - ud.m_respawn_items = 0; - ud.m_respawn_inventory = 0; - - ud.multimode = 1; - - G_NewGame_EnterLevel(); break; } @@ -3563,163 +3506,6 @@ static void Menu_FileSelect(int32_t input) } - - - -static Menu_t* Menu_BinarySearch(MenuID_t query, uint16_t searchstart, uint16_t searchend) -{ - const uint16_t thissearch = (searchstart + searchend) / 2; - const MenuID_t difference = query - Menus[thissearch].menuID; - - if (difference == 0) - return &Menus[thissearch]; - else if (searchstart == searchend) - return NULL; - else if (difference > 0) - { - if (thissearch == searchend) - return NULL; - searchstart = thissearch + 1; - } - else if (difference < 0) - { - if (thissearch == searchstart) - return NULL; - searchend = thissearch - 1; - } - - return Menu_BinarySearch(query, searchstart, searchend); -} - -static Menu_t* Menu_Find(MenuID_t query) -{ - if ((unsigned) query > (unsigned) Menus[numMenus-1].menuID) - return NULL; - - return Menu_BinarySearch(query, 0, numMenus-1); -} - -static Menu_t* Menu_FindFiltered(MenuID_t query) -{ - if ((g_player[myconnectindex].ps->gm&MODE_GAME) && query == MENU_MAIN) - query = MENU_MAIN_INGAME; - - return Menu_Find(query); -} - -MenuAnimation_t m_animation; - -int32_t Menu_Anim_SinOutRight(MenuAnimation_t *animdata) -{ - return sintable[divscale10((int32_t) totalclock - animdata->start, animdata->length) + 512] - 16384; -} -int32_t Menu_Anim_SinInRight(MenuAnimation_t *animdata) -{ - return sintable[divscale10((int32_t) totalclock - animdata->start, animdata->length) + 512] + 16384; -} -int32_t Menu_Anim_SinOutLeft(MenuAnimation_t *animdata) -{ - return -sintable[divscale10((int32_t) totalclock - animdata->start, animdata->length) + 512] + 16384; -} -int32_t Menu_Anim_SinInLeft(MenuAnimation_t *animdata) -{ - return -sintable[divscale10((int32_t) totalclock - animdata->start, animdata->length) + 512] - 16384; -} - -void Menu_AnimateChange(int32_t cm, MenuAnimationType_t animtype) -{ - if (cm == MENU_KEYBOARDKEYS) - { - GUICapture |= 2; - return; - } - - if (FURY) - { - m_animation.start = 0; - m_animation.length = 0; - Menu_Change(cm); - return; - } - - switch (animtype) - { - case MA_Advance: - { - Menu_t * const previousMenu = m_currentMenu; - - if (!Menu_Change(cm)) - { - m_animation.out = Menu_Anim_SinOutRight; - m_animation.in = Menu_Anim_SinInRight; - m_animation.start = (int32_t) totalclock; - m_animation.length = 30; - - m_animation.previous = previousMenu; - m_animation.current = m_currentMenu; - } - - break; - } - case MA_Return: - { - Menu_t * const previousMenu = m_currentMenu; - - if (!Menu_Change(cm)) - { - m_animation.out = Menu_Anim_SinOutLeft; - m_animation.in = Menu_Anim_SinInLeft; - m_animation.start = (int32_t) totalclock; - m_animation.length = 30; - - m_animation.previous = previousMenu; - m_animation.current = m_currentMenu; - } - - break; - } - default: - m_animation.start = 0; - m_animation.length = 0; - Menu_Change(cm); - break; - } -} - -static void Menu_MaybeSetSelectionToChild(Menu_t * m, MenuID_t id) -{ - if (m->type == Menu) - { - auto menu = (MenuMenu_t *)m->object; - - if (menu->currentEntry < menu->numEntries) - { - MenuEntry_t const * currentEntry = menu->entrylist[menu->currentEntry]; - if (currentEntry != NULL && currentEntry->type == Link) - { - auto const * link = (MenuLink_t const *)currentEntry->entry; - if (link->linkID == id) - return; // already good to go - } - } - - for (int i = 0, i_end = menu->numEntries; i < i_end; ++i) - { - MenuEntry_t const * entry = menu->entrylist[i]; - if (entry != NULL && entry->type == Link && !(entry->flags & MEF_Hidden)) - { - auto const * link = (MenuLink_t const *)entry->entry; - if (link->linkID == id) - { - menu->currentEntry = i; - Menu_AdjustForCurrentEntryAssignmentBlind(menu); - break; - } - } - } - } -} - static void Menu_ReadSaveGameHeaders() { ReadSaveGameHeaders(); @@ -3761,16 +3547,6 @@ static void Menu_AboutToStartDisplaying(Menu_t * m) { switch (m->menuID) { - case MENU_MAIN: - if (FURY) - ME_MAIN_LOADGAME.name = s_Continue; - break; - - case MENU_MAIN_INGAME: - if (FURY) - ME_MAIN_LOADGAME.name = s_LoadGame; - break; - case MENU_NEWGAMECUSTOMSUB: Menu_PopulateNewGameCustomSub(M_NEWGAMECUSTOM.currentEntry); break; @@ -3888,10 +3664,7 @@ static void Menu_AboutToStartDisplaying(Menu_t * m) static void Menu_ChangingTo(Menu_t * m) { -#ifdef __ANDROID__ - if (m->menuID == MENU_TOUCHBUTTONS) - AndroidToggleButtonEditor(); -#endif + switch (m->type) { @@ -3903,74 +3676,6 @@ static void Menu_ChangingTo(Menu_t * m) } } -int Menu_Change(MenuID_t cm) -{ - Menu_t * beginMenu = m_currentMenu; - - cm = VM_OnEventWithReturn(EVENT_CHANGEMENU, g_player[screenpeek].ps->i, screenpeek, cm); - - if (cm == MENU_PREVIOUS) - { - m_currentMenu = m_previousMenu; - g_currentMenu = g_previousMenu; - } - else if (cm == MENU_CLOSE) - Menu_Close(myconnectindex); - else if (cm >= 0) - { - Menu_t * search = Menu_FindFiltered(cm); - - if (search == NULL) - return 0; // intentional, so that users don't use any random value as "don't change" - - // security - if (search->type == Verify && - search->parentID != MENU_PREVIOUS && - search->parentID != MENU_CLOSE && - search->parentID != g_currentMenu) - return 1; - - m_previousMenu = m_currentMenu; - g_previousMenu = g_currentMenu; - m_currentMenu = search; - g_currentMenu = search->menuID; - } - else - return 1; - - if (FURY) - { - Menu_t * parent = m_currentMenu, * result = NULL; - - while (parent != NULL && parent->menuID != MENU_OPTIONS && parent->menuID != MENU_MAIN && parent->menuID != MENU_MAIN_INGAME) - { - result = parent = Menu_FindFiltered(parent->parentID); - } - - m_parentMenu = result; - - if (result) - { - Menu_MaybeSetSelectionToChild(result, m_currentMenu->menuID); - Menu_AboutToStartDisplaying(result); - } - } - - Menu_MaybeSetSelectionToChild(m_currentMenu, beginMenu->menuID); - Menu_AboutToStartDisplaying(m_currentMenu); - Menu_ChangingTo(m_currentMenu); - -#if !defined EDUKE32_TOUCH_DEVICES - m_menuchange_watchpoint = 1; -#endif - - return 0; -} - - - - -