From f2947bc1c615076d7f256c2217d2d5c0c6833781 Mon Sep 17 00:00:00 2001 From: sourcehold Date: Wed, 7 Oct 2026 22:54:13 +0200 Subject: [PATCH 1/3] reimplement: OpenSHC::Game::GameCore 100% --- .../Game/GameCore/Constructor_GameCore.cpp | 54 +++ .../exitToScenarioDescriptionMenu.cpp | 10 +- src/OpenSHC/Game/GameCore/hideOrUnhideUI.cpp | 67 ++++ .../Game/GameCore/incrementMission.cpp | 45 +++ .../GameCore/incrementMissionProgress.cpp | 72 ++++ .../Game/GameCore/isGameHaltingMenuOpen.cpp | 17 +- src/OpenSHC/Game/GameCore/isInBuildingTab.cpp | 39 +++ .../Game/GameCore/processMenuViewSwitch.cpp | 99 ++++++ ...oveJesterAndLadyUnitsInCertainMissions.cpp | 53 +++ .../Game/GameCore/removeLadyAndJester.cpp | 43 +++ src/OpenSHC/Game/GameCore/setStartDateUnk.cpp | 79 +++++ .../Game/GameCore/setTabToSwitchTo.cpp | 9 +- .../Game/GameCore/setViewOnExitUnk.cpp | 7 +- .../Game/GameCore/swapBuildMenuTab.cpp | 9 +- .../Game/GameCore/switchToMenuView.cpp | 315 ++++++++++++++++++ .../switchToScenarioDescriptionMenuView.cpp | 10 +- .../GameCore/viewportAndScrollingRelated.cpp | 23 ++ status/addresses-SHC-3BB0A8C1.txt | 48 ++- 18 files changed, 940 insertions(+), 59 deletions(-) create mode 100644 src/OpenSHC/Game/GameCore/Constructor_GameCore.cpp create mode 100644 src/OpenSHC/Game/GameCore/hideOrUnhideUI.cpp create mode 100644 src/OpenSHC/Game/GameCore/incrementMission.cpp create mode 100644 src/OpenSHC/Game/GameCore/incrementMissionProgress.cpp create mode 100644 src/OpenSHC/Game/GameCore/isInBuildingTab.cpp create mode 100644 src/OpenSHC/Game/GameCore/processMenuViewSwitch.cpp create mode 100644 src/OpenSHC/Game/GameCore/removeJesterAndLadyUnitsInCertainMissions.cpp create mode 100644 src/OpenSHC/Game/GameCore/removeLadyAndJester.cpp create mode 100644 src/OpenSHC/Game/GameCore/setStartDateUnk.cpp create mode 100644 src/OpenSHC/Game/GameCore/switchToMenuView.cpp create mode 100644 src/OpenSHC/Game/GameCore/viewportAndScrollingRelated.cpp diff --git a/src/OpenSHC/Game/GameCore/Constructor_GameCore.cpp b/src/OpenSHC/Game/GameCore/Constructor_GameCore.cpp new file mode 100644 index 000000000..ed5e91006 --- /dev/null +++ b/src/OpenSHC/Game/GameCore/Constructor_GameCore.cpp @@ -0,0 +1,54 @@ +#include "../GameCore.func.hpp" + +namespace OpenSHC { +namespace Game { + + // FUNCTION: STRONGHOLDCRUSADER 0x0046B1F0 + GameCore* GameCore::Constructor_GameCore() + { + this->currentMenuViewType = UI::Enums::MVT_NO_VIEW; + this->unknownAlwaysZero01 = 0; + this->currentlyInGameUnk_0xa4 = FALSE; + this->mapTimeInTicks = 0; + this->unknownAlwaysZero02 = 0; + this->field26_0x74 = 0; + this->field24_0x6c = 0; + this->isTimeHalted2 = 0; + this->unlockAllHistoricalCampaigns = 0; + this->unused1 = 0; + this->solitaryAltUDungeon = FALSE; + this->currentTrailType = TT_FIRST_EDITION; + this->field59_0xf8 = 0; + this->specialMultiplayerState = 0; + this->cheatModeFlag = FALSE; + this->solitaryAllBuildingsAreFree = FALSE; + this->unknownAlwaysZero = 0; + this->newPlayerID = 0; + this->activeMenuTab.buildMenuTab = UI::Enums::BMTT_CASTLE; + this->gameSpeedMultiplicator = 1; + this->forty = 40; + this->menuType7_MenuItemClickHandlerUnk = NULL; + this->countdown = 1; + this->uniqueGameObjectTracker = 1; + this->gameSpeedLevel = 40; + this->settingBubbleHelp = 1; + this->twohundred = 200; + this->field62_0x104 = 1; + this->field63_0x108 = 1; + this->field52_0xdc = 1; + this->scenarioProgress.progressCallToArms = 1; + this->scenarioProgress.progressSaladinsConquest = 6; + this->scenarioProgress.progressTheKingsCrusade = 11; + this->scenarioProgress.progressCrusaderStates = 16; + this->furthestMission = 33; + this->viewportFocusBeforeBarracksHotkey = -1; + this->viewportFocusBeforeMercenaryHotkey = -1; + this->viewportFocusBeforeGranaryHotkey = -1; + this->viewportFocusBeforeMarketHotkey = -1; + this->viewportFocusBeforeKeepHotkey = -1; + this->viewportFocusBeforeArmoryHotkey = -1; + return this; + } + +} +} diff --git a/src/OpenSHC/Game/GameCore/exitToScenarioDescriptionMenu.cpp b/src/OpenSHC/Game/GameCore/exitToScenarioDescriptionMenu.cpp index 1c25e9d1d..598ac8493 100644 --- a/src/OpenSHC/Game/GameCore/exitToScenarioDescriptionMenu.cpp +++ b/src/OpenSHC/Game/GameCore/exitToScenarioDescriptionMenu.cpp @@ -1,20 +1,16 @@ -#include "OpenSHC/Game/GameCore.func.hpp" -#include "OpenSHC/UI/Enums/MenuViewType.hpp" +#include "../GameCore.func.hpp" #include "OpenSHC/Globals/DAT_GameCore.hpp" namespace OpenSHC { namespace Game { - using OpenSHC::UI::Enums::MenuViewType; - // FUNCTION: STRONGHOLDCRUSADER 0x00471A80 void GameCore::exitToScenarioDescriptionMenu() { - MACRO_CALL_MEMBER(OpenSHC::Game::GameCore_Func::removeLadyAndJester, this)(); + MACRO_CALL_MEMBER(GameCore_Func::removeLadyAndJester, this)(); DAT_GameCore::instance.field22_0x64 = 0; - MACRO_CALL_MEMBER(OpenSHC::Game::GameCore_Func::switchToMenuView, DAT_GameCore::ptr)( - OpenSHC::UI::Enums::MVT_SCENARIO_DESCRIPTION, 0); + MACRO_CALL_MEMBER(GameCore_Func::switchToMenuView, DAT_GameCore::ptr)(UI::Enums::MVT_SCENARIO_DESCRIPTION, 0); } } diff --git a/src/OpenSHC/Game/GameCore/hideOrUnhideUI.cpp b/src/OpenSHC/Game/GameCore/hideOrUnhideUI.cpp new file mode 100644 index 000000000..8205cd876 --- /dev/null +++ b/src/OpenSHC/Game/GameCore/hideOrUnhideUI.cpp @@ -0,0 +1,67 @@ +#include "../GameCore.func.hpp" + +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_MouseState.hpp" + +namespace OpenSHC { +namespace Game { + + // FUNCTION: STRONGHOLDCRUSADER 0x00471AA0 + void GameCore::hideOrUnhideUI() + { + if ((DAT_GameCore::instance.currentMenuViewType == UI::Enums::MVT_BUILD_MENU + || DAT_GameCore::instance.currentMenuViewType == UI::Enums::MVT_MAP_EDITOR_LANDSCAPING) + && DAT_MouseState::instance.selectionBoxMode == 0) { + // hide the menu + if (DAT_GameCore::instance.activeMenuTab.buildMenuTab != UI::Enums::BMTT_MENU_HIDDEN + && DAT_GameCore::instance.activeMenuTab.buildMenuTab != 62) { + if (DAT_GameCore::instance.currentMenuViewType == UI::Enums::MVT_BUILD_MENU) { + if (DAT_GameCore::instance.activeMenuTab.buildMenuTab == UI::Enums::BMTT_SOLDIERS) { + DAT_GameCore::instance.buildmenuMenuTabToSwitchTo.buildMenuTab = 62; + } else { + MACRO_CALL_MEMBER(GameCore_Func::setTabToSwitchTo, DAT_GameCore::ptr)(); + DAT_GameCore::instance.buildmenuMenuTabToSwitchTo.buildMenuTab = UI::Enums::BMTT_MENU_HIDDEN; + } + } + if (DAT_GameCore::instance.currentMenuViewType == UI::Enums::MVT_MAP_EDITOR_LANDSCAPING) { + DAT_GameCore::instance.landscapingmenuMenuTabToSwitchTo = UI::Enums::BMTT_MENU_HIDDEN; + } + MACRO_CALL_MEMBER(GameCore_Func::switchToMenuView, DAT_GameCore::ptr)( + (MenuViewType)DAT_GameCore::instance.currentMenuViewType, 0); + return; + } + + // unhide the menu + if (DAT_GameCore::instance.currentMenuViewType == UI::Enums::MVT_BUILD_MENU) { + if (DAT_GameCore::instance.activeMenuTab.buildMenuTab == 62) { + DAT_GameCore::instance.buildmenuMenuTabToSwitchTo.buildMenuTab = UI::Enums::BMTT_SOLDIERS; + } else { + MACRO_CALL_MEMBER(GameCore_Func::swapBuildMenuTab, DAT_GameCore::ptr)(); + } + } + if (DAT_GameCore::instance.currentMenuViewType == UI::Enums::MVT_MAP_EDITOR_LANDSCAPING) { + DAT_GameCore::instance.landscapingmenuMenuTabToSwitchTo + = DAT_GameCore::instance.secondaryActiveMenuTabToSwitchTo.tabType; + } + if (DAT_GameCore::instance.buildmenuMenuTabToSwitchTo.buildMenuTab == UI::Enums::BMTT_MENU_HIDDEN) { + if (DAT_GameCore::instance.currentMenuViewType == UI::Enums::MVT_BUILD_MENU) { + DAT_GameCore::instance.buildmenuMenuTabToSwitchTo.buildMenuTab = UI::Enums::BMTT_CASTLE; + } + if (DAT_GameCore::instance.currentMenuViewType == UI::Enums::MVT_MAP_EDITOR_LANDSCAPING) { + DAT_GameCore::instance.landscapingmenuMenuTabToSwitchTo = 231; + } + } + MACRO_CALL_MEMBER(GameCore_Func::switchToMenuView, DAT_GameCore::ptr)( + (MenuViewType)DAT_GameCore::instance.currentMenuViewType, 0); + return; + } + + if (DAT_GameCore::instance.currentMenuViewType == UI::Enums::MVT_BUILDING_AND_STATUS_MENU) { + this->secondaryActiveMenuTabToSwitchTo = this->buildmenuMenuTabToSwitchTo; + DAT_GameCore::instance.buildmenuMenuTabToSwitchTo.buildMenuTab = UI::Enums::BMTT_MENU_HIDDEN; + MACRO_CALL_MEMBER(GameCore_Func::switchToMenuView, DAT_GameCore::ptr)(UI::Enums::MVT_BUILD_MENU, 0); + } + } + +} +} diff --git a/src/OpenSHC/Game/GameCore/incrementMission.cpp b/src/OpenSHC/Game/GameCore/incrementMission.cpp new file mode 100644 index 000000000..f71ed25d5 --- /dev/null +++ b/src/OpenSHC/Game/GameCore/incrementMission.cpp @@ -0,0 +1,45 @@ +#include "../GameCore.func.hpp" + +#include "OpenSHC/IO/SettingsFileState.func.hpp" +#include "OpenSHC/Map/MapPropertiesState.func.hpp" + +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_MapPropertiesState.hpp" +#include "OpenSHC/Globals/DAT_SettingsFileState.hpp" + +namespace OpenSHC { +namespace Game { + + // FUNCTION: STRONGHOLDCRUSADER 0x00471A00 + void GameCore::incrementMission() + { + ++this->missionNumber1to20; + MACRO_CALL_MEMBER(GameCore_Func::removeLadyAndJester, this)(); + if (!this->unlockAllHistoricalCampaigns && this->missionNumber1to20 > (int)this->furthestMission) { + this->furthestMission = this->missionNumber1to20; + } + MACRO_CALL_MEMBER(IO::SettingsFileState_Func::writeUserConfig, DAT_SettingsFileState::ptr)(); + + if (!MACRO_CALL_MEMBER(Map::MapPropertiesState_Func::isValueInRangeOneToTwenty, DAT_MapPropertiesState::ptr)( + this->missionNumber1to20)) { + DAT_GameCore::instance.field22_0x64 = 0; + MACRO_CALL_MEMBER(GameCore_Func::switchToMenuView, DAT_GameCore::ptr)( + UI::Enums::MVT_MISSION_FINISHED_TRANSITION, 0); + } else { + DAT_GameSynchronyState::instance.currentPlayerSlotID = 1; + if (this->missionNumber1to20 != 33 && !DAT_GameCore::instance.field26_0x74) { + MACRO_CALL_MEMBER(GameCore_Func::switchToMenuView, DAT_GameCore::ptr)( + UI::Enums::MVT_MISSION_FINISHED_TRANSITION, 0); + } else { + DAT_GameCore::instance.field22_0x64 = 0; + MACRO_CALL_MEMBER(GameCore_Func::switchToMenuView, DAT_GameCore::ptr)( + UI::Enums::MVT_SCENARIO_DESCRIPTION, 0); + } + } + DAT_GameCore::instance.field26_0x74 = 0; + DAT_GameCore::instance.unknownAlwaysZero = 0; + } + +} +} diff --git a/src/OpenSHC/Game/GameCore/incrementMissionProgress.cpp b/src/OpenSHC/Game/GameCore/incrementMissionProgress.cpp new file mode 100644 index 000000000..80714bc5b --- /dev/null +++ b/src/OpenSHC/Game/GameCore/incrementMissionProgress.cpp @@ -0,0 +1,72 @@ +#include "../GameCore.func.hpp" + +#include "OpenSHC/IO/SettingsFileState.func.hpp" +#include "OpenSHC/Map/MapPropertiesState.func.hpp" + +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_MapPropertiesState.hpp" +#include "OpenSHC/Globals/DAT_SettingsFileState.hpp" + +namespace OpenSHC { +namespace Game { + + // FUNCTION: STRONGHOLDCRUSADER 0x004718F0 + void GameCore::incrementMissionProgress() + { + ++this->missionNumber1to20; + if (!this->unlockAllHistoricalCampaigns && !DAT_GameCore::instance.field26_0x74) { + if (this->missionNumber1to20 <= 6) { + if (this->missionNumber1to20 > this->scenarioProgress.progressCallToArms) { + this->scenarioProgress.progressCallToArms = this->missionNumber1to20; + } + } else if (this->missionNumber1to20 <= 11) { + if (this->missionNumber1to20 > this->scenarioProgress.progressSaladinsConquest) { + this->scenarioProgress.progressSaladinsConquest = this->missionNumber1to20; + } + } else if (this->missionNumber1to20 <= 16) { + if (this->missionNumber1to20 > this->scenarioProgress.progressTheKingsCrusade) { + this->scenarioProgress.progressTheKingsCrusade = this->missionNumber1to20; + } + } else if (this->missionNumber1to20 <= 21) { + if (this->missionNumber1to20 > this->scenarioProgress.progressCrusaderStates) { + this->scenarioProgress.progressCrusaderStates = this->missionNumber1to20; + } + } + } + MACRO_CALL_MEMBER(IO::SettingsFileState_Func::writeUserConfig, DAT_SettingsFileState::ptr)(); + + if (!MACRO_CALL_MEMBER(Map::MapPropertiesState_Func::isValueInRangeOneToTwenty, DAT_MapPropertiesState::ptr)( + this->missionNumber1to20)) { + MACRO_CALL_MEMBER(GameCore_Func::switchToMenuView, DAT_GameCore::ptr)( + UI::Enums::MVT_MISSION_FINISHED_TRANSITION, 0); + DAT_GameCore::instance.field26_0x74 = 0; + DAT_GameCore::instance.unknownAlwaysZero = 0; + return; + } + + MACRO_CALL_MEMBER(GameCore_Func::removeJesterAndLadyUnitsInCertainMissions, this)(); + DAT_GameSynchronyState::instance.currentPlayerSlotID = 1; + int const firstMissionOfCampaign = this->historicCampaignNumber * 5 - 4; + if (this->missionNumber1to20 != firstMissionOfCampaign && !DAT_GameCore::instance.field26_0x74) { + MACRO_CALL_MEMBER(GameCore_Func::switchToMenuView, DAT_GameCore::ptr)( + UI::Enums::MVT_MISSION_FINISHED_TRANSITION, 0); + DAT_GameCore::instance.field26_0x74 = 0; + DAT_GameCore::instance.unknownAlwaysZero = 0; + return; + } + + if (DAT_GameCore::instance.field26_0x74 && this->missionNumber1to20 != firstMissionOfCampaign) { + MACRO_CALL_MEMBER(GameCore_Func::switchToMenuView, DAT_GameCore::ptr)( + UI::Enums::MVT_HISTORIC_MISSION_PICTURE, 0); + } else { + MACRO_CALL_MEMBER(GameCore_Func::switchToMenuView, DAT_GameCore::ptr)( + UI::Enums::MVT_HISTORIC_CAMPAIGN_INTRO, 0); + } + DAT_GameCore::instance.field22_0x64 = 0; + DAT_GameCore::instance.field26_0x74 = 0; + DAT_GameCore::instance.unknownAlwaysZero = 0; + } + +} +} diff --git a/src/OpenSHC/Game/GameCore/isGameHaltingMenuOpen.cpp b/src/OpenSHC/Game/GameCore/isGameHaltingMenuOpen.cpp index 6c22d806a..f51d06fa8 100644 --- a/src/OpenSHC/Game/GameCore/isGameHaltingMenuOpen.cpp +++ b/src/OpenSHC/Game/GameCore/isGameHaltingMenuOpen.cpp @@ -1,7 +1,4 @@ -#include "OpenSHC/Game/GameCore.func.hpp" -#include "OpenSHC/Game/GameMode.hpp" -#include "OpenSHC/UI/Enums/MenuModalType.hpp" -#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" +#include "../GameCore.func.hpp" #include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" #include "OpenSHC/Globals/DAT_MenuModalComposition1.hpp" @@ -10,21 +7,17 @@ namespace OpenSHC { namespace Game { - using OpenSHC::Game::GameMode; - using OpenSHC::UI::Enums::MenuModalType; - using OpenSHC::WindowsHelper::Enums::BOOLEnum; - // FUNCTION: STRONGHOLDCRUSADER 0x0046BD20 BOOLEnum GameCore::isGameHaltingMenuOpen() { - if (DAT_GameSynchronyState::instance.currentGameMode != OpenSHC::Game::GM_SOLITARY - && DAT_GameSynchronyState::instance.currentGameMode != OpenSHC::Game::GM_SKIRMISH_SINGLE_PLAYER) { + if (DAT_GameSynchronyState::instance.currentGameMode != GM_SOLITARY + && DAT_GameSynchronyState::instance.currentGameMode != GM_SKIRMISH_SINGLE_PLAYER) { return FALSE; } - if (DAT_MenuTextInputState::instance.currentModalDialog != OpenSHC::UI::Enums::MMT_NO_MENU) { + if (DAT_MenuTextInputState::instance.currentModalDialog != UI::Enums::MMT_NO_MENU) { return TRUE; } - return DAT_MenuModalComposition1::instance.activeModalDialogID == OpenSHC::UI::Enums::MMT_IN_GAME_HELP_TEXT; + return DAT_MenuModalComposition1::instance.activeModalDialogID == UI::Enums::MMT_IN_GAME_HELP_TEXT; } } diff --git a/src/OpenSHC/Game/GameCore/isInBuildingTab.cpp b/src/OpenSHC/Game/GameCore/isInBuildingTab.cpp new file mode 100644 index 000000000..4455daef5 --- /dev/null +++ b/src/OpenSHC/Game/GameCore/isInBuildingTab.cpp @@ -0,0 +1,39 @@ +#include "../GameCore.func.hpp" + +#include "OpenSHC/Globals/DAT_GameCore.hpp" + +namespace OpenSHC { +namespace Game { + + // FUNCTION: STRONGHOLDCRUSADER 0x0046BB80 + BOOLEnum GameCore::isInBuildingTab() + { + if (DAT_GameCore::instance.currentMenuViewType != UI::Enums::MVT_BUILDING_AND_STATUS_MENU) { + return FALSE; + } + if (DAT_GameCore::instance.activeMenuTab.tabType == UI::Enums::BASMTT_GRANARY_OR_MPMENU_TCPIP) { + return TRUE; + } + if (DAT_GameCore::instance.activeMenuTab.tabType == UI::Enums::BASMTT_SIEGETENT_CATAPULT) { + return TRUE; + } + if (DAT_GameCore::instance.activeMenuTab.tabType == UI::Enums::BASMTT_SIEGETENT_FIREBALLISTA) { + return TRUE; + } + if (DAT_GameCore::instance.activeMenuTab.tabType == UI::Enums::BASMTT_SIEGETENT_TREBUCHET) { + return TRUE; + } + if (DAT_GameCore::instance.activeMenuTab.tabType == UI::Enums::BASMTT_SIEGETENT_SIEGETOWER) { + return TRUE; + } + if (DAT_GameCore::instance.activeMenuTab.tabType == UI::Enums::BASMTT_SIEGETENT_BATTERINGRAM) { + return TRUE; + } + if (DAT_GameCore::instance.activeMenuTab.tabType == UI::Enums::BASMTT_SIEGETENT_SHIELD) { + return TRUE; + } + return DAT_GameCore::instance.activeMenuTab.tabType == UI::Enums::BASMTT_KEEP_OR_MPMENU_IPX; + } + +} +} diff --git a/src/OpenSHC/Game/GameCore/processMenuViewSwitch.cpp b/src/OpenSHC/Game/GameCore/processMenuViewSwitch.cpp new file mode 100644 index 000000000..b532e7c22 --- /dev/null +++ b/src/OpenSHC/Game/GameCore/processMenuViewSwitch.cpp @@ -0,0 +1,99 @@ +#include "../GameCore.func.hpp" + +#include "OpenSHC/Game/GameStateStructures.func.hpp" +#include "OpenSHC/Input/MouseState.func.hpp" +#include "OpenSHC/Rendering/ViewportRenderState.func.hpp" +#include "OpenSHC/UI/BottomLeftTextDisplayState.func.hpp" +#include "OpenSHC/UI/MenuHandlerState.func.hpp" +#include "OpenSHC/UI/Rendering/TextureRenderCore.func.hpp" + +#include "OpenSHC/Globals/DAT_BottomLeftTextDisplayState.hpp" +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_MenuHandlerState.hpp" +#include "OpenSHC/Globals/DAT_MenuView_TriggerPrepare.hpp" +#include "OpenSHC/Globals/DAT_ModifierKeyState.hpp" +#include "OpenSHC/Globals/DAT_MouseState.hpp" +#include "OpenSHC/Globals/DAT_TextureRenderCoreObject.hpp" +#include "OpenSHC/Globals/DAT_UIDragDropDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" +#include "OpenSHC/Globals/DAT_WindowAndDirectDraw.hpp" + +namespace OpenSHC { +namespace Game { + + // FUNCTION: STRONGHOLDCRUSADER 0x0046B980 + void GameCore::processMenuViewSwitch() + { + if (this->menuSwitchDelay != -1) { + if (this->menuSwitchDelay != 0 && timeGetTime() - this->menuRenderMoment < (uint)this->menuSwitchDelay) { + return; + } + + DAT_BuildingsState::instance.menuSelectedBuildingID = DAT_BuildingsState::instance.newSelectedBuildingID; + DAT_BuildingsState::instance.menuSelectedUnitID = DAT_BuildingsState::instance.newSelectedUnitID; + if (this->currentMenuViewType == this->menuViewToSwitchTo + && this->activeMenuTab.tabType == this->menuTabToSwitchTo.tabType) { + DAT_UIDragDropDefinedData::instance.MenuView_TriggerInitial = TRUE; + DAT_MenuView_TriggerPrepare::instance = TRUE; + this->menuSwitchDelay = -1; + return; + } + + if (this->menuType7_MenuItemClickHandlerUnk != NULL) { + (*this->menuType7_MenuItemClickHandlerUnk)(0); + this->menuType7_MenuItemClickHandlerUnk = NULL; + } + if (this->menuViewToSwitchTo == UI::Enums::MVT_MAIN_MENU + && DAT_GameSynchronyState::instance.currentGameMode == GM_SKIRMISH_SINGLE_PLAYER) { + DAT_GameSynchronyState::instance.currentGameMode = GM_SOLITARY; + } + + // this code is executed when changing menus + this->currentMenuViewType = this->menuViewToSwitchTo; + this->activeMenuTab = this->menuTabToSwitchTo; + MACRO_CALL_MEMBER( + Rendering::ViewportRenderState_Func::resetupViewportThunk, DAT_ViewportRenderState::ptr)(); + DAT_UIDragDropDefinedData::instance.MenuView_TriggerInitial = TRUE; + DAT_MenuView_TriggerPrepare::instance = TRUE; + DAT_WindowAndDirectDraw::instance.unk_resetViewportRelated = 2; + MACRO_CALL_MEMBER(Input::MouseState_Func::resetMouseCursorState, DAT_MouseState::ptr)(); + MACRO_CALL_MEMBER(UI::MenuHandlerState_Func::setupMenuForRendering, DAT_MenuHandlerState::ptr)( + (MenuViewType)this->currentMenuViewType); + UI::Menu* const currentMenu = DAT_MenuHandlerState::instance.currentMenu; + currentMenu->xPosition = 0; + currentMenu->yPosition = 0; + DAT_MenuHandlerState::instance.x = 0; + DAT_MenuHandlerState::instance.y = 0; + + // clear the bottom left text tooltip + MACRO_CALL_MEMBER(UI::BottomLeftTextDisplayState_Func::setBottomLeftTextDisplayText, + DAT_BottomLeftTextDisplayState::ptr)(0, 0, 0, 0, 50, 0); + MACRO_CALL_MEMBER( + UI::Rendering::TextureRenderCore_Func::setActiveMenuTabIndexToZero, DAT_TextureRenderCoreObject::ptr)(); + this->menuSwitchDelay = -1; + if (this->currentMenuViewType == UI::Enums::MVT_MAP_EDITOR_LANDSCAPING) { + DAT_GameCore::instance.currentlyInGameUnk_0xa4 = TRUE; + } + } + + if (this->newPlayerID == 0) { + return; + } + + for (int i = 0; i < 9; ++i) { + DAT_GameSynchronyState::instance.currentPlayerFullIDArray[i] = -1; + } + DAT_GameSynchronyState::instance.currentPlayerFullIDArray[this->newPlayerID] = 1; + if (DAT_ModifierKeyState::instance.shift) { + MACRO_CALL_MEMBER(GameStateStructures_Func::changePlayerOwnership, DAT_GameState::ptr)( + DAT_GameSynchronyState::instance.currentPlayerSlotID, this->newPlayerID); + } + DAT_GameSynchronyState::instance.currentPlayerSlotID = this->newPlayerID; + this->newPlayerID = 0; + } + +} +} diff --git a/src/OpenSHC/Game/GameCore/removeJesterAndLadyUnitsInCertainMissions.cpp b/src/OpenSHC/Game/GameCore/removeJesterAndLadyUnitsInCertainMissions.cpp new file mode 100644 index 000000000..16f348566 --- /dev/null +++ b/src/OpenSHC/Game/GameCore/removeJesterAndLadyUnitsInCertainMissions.cpp @@ -0,0 +1,53 @@ +#include "../GameCore.func.hpp" + +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" + +namespace OpenSHC { +namespace Game { + + // FUNCTION: STRONGHOLDCRUSADER 0x0046BBD0 + void GameCore::removeJesterAndLadyUnitsInCertainMissions() + { + if (this->missionNumber1to20 < 7) { + DAT_GameState::instance.mapAndTime.unitJesterRelated = 0; + int const jesterID + = DAT_GameState::instance.playerDataArray[DAT_GameSynchronyState::instance.currentPlayerSlotID] + .jesterIDUnk; + if (jesterID != 0 + && DAT_UnitsState::instance.units[jesterID].uid + == DAT_GameState::instance.playerDataArray[DAT_GameSynchronyState::instance.currentPlayerSlotID] + .someUnitIDSelfRef_2) { + DAT_GameState::instance.playerDataArray[DAT_GameSynchronyState::instance.currentPlayerSlotID] + .jesterIDUnk = 0; + DAT_UnitsState::instance.units[jesterID].logicalState = Map::Units::ULS_REMOVE; + DAT_GameState::instance.playerDataArray[DAT_GameSynchronyState::instance.currentPlayerSlotID] + .someUnitIDSelfRef_2 = 0; + } + } else { + DAT_GameState::instance.mapAndTime.unitJesterRelated = 1; + } + + if (this->missionNumber1to20 < 11) { + DAT_GameState::instance.mapAndTime.unitLadyRelated = 0; + int const ladyID + = DAT_GameState::instance.playerDataArray[DAT_GameSynchronyState::instance.currentPlayerSlotID] + .ladyIDUnk; + if (ladyID != 0 + && DAT_UnitsState::instance.units[ladyID].uid + == DAT_GameState::instance.playerDataArray[DAT_GameSynchronyState::instance.currentPlayerSlotID] + .someUnitIDSelfRef) { + DAT_GameState::instance.playerDataArray[DAT_GameSynchronyState::instance.currentPlayerSlotID].ladyIDUnk + = 0; + DAT_GameState::instance.playerDataArray[DAT_GameSynchronyState::instance.currentPlayerSlotID] + .someUnitIDSelfRef = 0; + DAT_UnitsState::instance.units[ladyID].logicalState = Map::Units::ULS_REMOVE; + } + } else { + DAT_GameState::instance.mapAndTime.unitLadyRelated = 1; + } + } + +} +} diff --git a/src/OpenSHC/Game/GameCore/removeLadyAndJester.cpp b/src/OpenSHC/Game/GameCore/removeLadyAndJester.cpp new file mode 100644 index 000000000..49e4db32c --- /dev/null +++ b/src/OpenSHC/Game/GameCore/removeLadyAndJester.cpp @@ -0,0 +1,43 @@ +#include "../GameCore.func.hpp" + +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" + +namespace OpenSHC { +namespace Game { + + // FUNCTION: STRONGHOLDCRUSADER 0x0046BC90 + void GameCore::removeLadyAndJester() + { + DAT_GameState::instance.mapAndTime.unitJesterRelated = 0; + DAT_GameState::instance.mapAndTime.unitLadyRelated = 0; + + int const ladyID + = DAT_GameState::instance.playerDataArray[DAT_GameSynchronyState::instance.currentPlayerSlotID].ladyIDUnk; + if (ladyID != 0 + && DAT_UnitsState::instance.units[ladyID].uid + == DAT_GameState::instance.playerDataArray[DAT_GameSynchronyState::instance.currentPlayerSlotID] + .someUnitIDSelfRef) { + DAT_GameState::instance.playerDataArray[DAT_GameSynchronyState::instance.currentPlayerSlotID].ladyIDUnk = 0; + DAT_UnitsState::instance.units[ladyID].logicalState = Map::Units::ULS_REMOVE; + DAT_GameState::instance.playerDataArray[DAT_GameSynchronyState::instance.currentPlayerSlotID] + .someUnitIDSelfRef = 0; + } + + int const jesterID + = DAT_GameState::instance.playerDataArray[DAT_GameSynchronyState::instance.currentPlayerSlotID].jesterIDUnk; + if (jesterID != 0 + && DAT_UnitsState::instance.units[jesterID].uid + == DAT_GameState::instance.playerDataArray[DAT_GameSynchronyState::instance.currentPlayerSlotID] + .someUnitIDSelfRef_2) { + DAT_GameState::instance.playerDataArray[DAT_GameSynchronyState::instance.currentPlayerSlotID].jesterIDUnk + = 0; + DAT_UnitsState::instance.units[jesterID].logicalState = Map::Units::ULS_REMOVE; + DAT_GameState::instance.playerDataArray[DAT_GameSynchronyState::instance.currentPlayerSlotID] + .someUnitIDSelfRef_2 = 0; + } + } + +} +} diff --git a/src/OpenSHC/Game/GameCore/setStartDateUnk.cpp b/src/OpenSHC/Game/GameCore/setStartDateUnk.cpp new file mode 100644 index 000000000..254142180 --- /dev/null +++ b/src/OpenSHC/Game/GameCore/setStartDateUnk.cpp @@ -0,0 +1,79 @@ +#include "../GameCore.func.hpp" + +namespace OpenSHC { +namespace Game { + + // FUNCTION: STRONGHOLDCRUSADER 0x0046BD50 + void GameCore::setStartDateUnk(int trailNumber) + { + // trailNumber 0 resets all trails, otherwise 1 = skirmish, 2 = warchest, 3 = extreme + if (trailNumber == 0 || trailNumber == 1) { + this->skirmishTrailYearReached = 1100 * 12; + } + if (trailNumber == 0 || trailNumber == 2) { + this->warchestTrailYearReached = 1130 * 12; + } + if (trailNumber == 0 || trailNumber == 3) { + this->extremeTrailYearReached = 1130 * 12; + } + + if (trailNumber == 0 || trailNumber == 1) { + int mission; + for (mission = 0; mission < 50; ++mission) { + if (this->skirmishTrailMonthsTakenOrChicken[mission] == -1200) { + this->skirmishTrailStartDateInMonths[mission] = this->skirmishTrailYearReached; + this->skirmishTrailYearReached += 1200; + continue; + } + if (this->skirmishTrailMonthsTakenOrChicken[mission] < 0) { + break; + } + this->skirmishTrailStartDateInMonths[mission] = this->skirmishTrailYearReached; + this->skirmishTrailYearReached += this->skirmishTrailMonthsTakenOrChicken[mission]; + } + if (mission != 50) { + this->skirmishTrailStartDateInMonths[mission] = this->skirmishTrailYearReached; + } + } + + if (trailNumber == 0 || trailNumber == 2) { + int mission; + for (mission = 0; mission < 30; ++mission) { + if (this->warchestTrailMonthsTakenOrChicken[mission] == -1200) { + this->warchestTrailStartDatesInMonths[mission] = this->warchestTrailYearReached; + this->warchestTrailYearReached += 1200; + continue; + } + if (this->warchestTrailMonthsTakenOrChicken[mission] < 0) { + break; + } + this->warchestTrailStartDatesInMonths[mission] = this->warchestTrailYearReached; + this->warchestTrailYearReached += this->warchestTrailMonthsTakenOrChicken[mission]; + } + if (mission != 30) { + this->warchestTrailStartDatesInMonths[mission] = this->warchestTrailYearReached; + } + } + + if (trailNumber == 0 || trailNumber == 3) { + int mission; + for (mission = 0; mission < 20; ++mission) { + if (this->extremeTrailMonthsTakenOrChicken[mission] == -1200) { + this->extremeTrailStartDatesInMonths[mission] = this->extremeTrailYearReached; + this->extremeTrailYearReached += 1200; + continue; + } + if (this->extremeTrailMonthsTakenOrChicken[mission] < 0) { + break; + } + this->extremeTrailStartDatesInMonths[mission] = this->extremeTrailYearReached; + this->extremeTrailYearReached += this->extremeTrailMonthsTakenOrChicken[mission]; + } + if (mission != 20) { + this->extremeTrailStartDatesInMonths[mission] = this->extremeTrailYearReached; + } + } + } + +} +} diff --git a/src/OpenSHC/Game/GameCore/setTabToSwitchTo.cpp b/src/OpenSHC/Game/GameCore/setTabToSwitchTo.cpp index 9a93c254c..3267637b6 100644 --- a/src/OpenSHC/Game/GameCore/setTabToSwitchTo.cpp +++ b/src/OpenSHC/Game/GameCore/setTabToSwitchTo.cpp @@ -1,18 +1,15 @@ -#include "OpenSHC/Game/GameCore.func.hpp" -#include "OpenSHC/UI/Enums/MenuViewType.hpp" +#include "../GameCore.func.hpp" namespace OpenSHC { namespace Game { - using OpenSHC::UI::Enums::MenuViewType; - // FUNCTION: STRONGHOLDCRUSADER 0x0046B300 void GameCore::setTabToSwitchTo() { - if (this->currentMenuViewType == OpenSHC::UI::Enums::MVT_BUILD_MENU) { + if (this->currentMenuViewType == UI::Enums::MVT_BUILD_MENU) { this->secondaryActiveMenuTabToSwitchTo = this->buildmenuMenuTabToSwitchTo; } - if (this->currentMenuViewType == OpenSHC::UI::Enums::MVT_MAP_EDITOR_LANDSCAPING) { + if (this->currentMenuViewType == UI::Enums::MVT_MAP_EDITOR_LANDSCAPING) { this->secondaryActiveMenuTabToSwitchTo.tabType = this->landscapingmenuMenuTabToSwitchTo; } } diff --git a/src/OpenSHC/Game/GameCore/setViewOnExitUnk.cpp b/src/OpenSHC/Game/GameCore/setViewOnExitUnk.cpp index 7a5e75fbd..e06ffe25c 100644 --- a/src/OpenSHC/Game/GameCore/setViewOnExitUnk.cpp +++ b/src/OpenSHC/Game/GameCore/setViewOnExitUnk.cpp @@ -1,13 +1,10 @@ -#include "OpenSHC/Game/GameCore.func.hpp" -#include "OpenSHC/UI/Enums/MenuViewType.hpp" +#include "../GameCore.func.hpp" namespace OpenSHC { namespace Game { - using OpenSHC::UI::Enums::MenuViewType; - // FUNCTION: STRONGHOLDCRUSADER 0x0046B2F0 - void GameCore::setViewOnExitUnk() { this->currentMenuViewType = (MenuViewType)2; } + void GameCore::setViewOnExitUnk() { this->currentMenuViewType = 2; } } } diff --git a/src/OpenSHC/Game/GameCore/swapBuildMenuTab.cpp b/src/OpenSHC/Game/GameCore/swapBuildMenuTab.cpp index f3711c65c..a0eafbb33 100644 --- a/src/OpenSHC/Game/GameCore/swapBuildMenuTab.cpp +++ b/src/OpenSHC/Game/GameCore/swapBuildMenuTab.cpp @@ -1,16 +1,13 @@ -#include "OpenSHC/Game/GameCore.func.hpp" -#include "OpenSHC/UI/Enums/BuildingsAndStatusMenuTabType.hpp" +#include "../GameCore.func.hpp" namespace OpenSHC { namespace Game { - using OpenSHC::UI::Enums::BuildingsAndStatusMenuTabType; - // FUNCTION: STRONGHOLDCRUSADER 0x0046B320 void GameCore::swapBuildMenuTab() { - if (this->buildmenuMenuTabToSwitchTo.tabType == OpenSHC::UI::Enums::BASMTT_SIEGETENT_SHIELD) { - this->buildmenuMenuTabToSwitchTo.tabType = OpenSHC::UI::Enums::BASMTT_SIEGETENT_BATTERINGRAM; + if (this->buildmenuMenuTabToSwitchTo.buildMenuTab == 62) { + this->buildmenuMenuTabToSwitchTo.buildMenuTab = UI::Enums::BMTT_SOLDIERS; return; } this->buildmenuMenuTabToSwitchTo = this->secondaryActiveMenuTabToSwitchTo; diff --git a/src/OpenSHC/Game/GameCore/switchToMenuView.cpp b/src/OpenSHC/Game/GameCore/switchToMenuView.cpp new file mode 100644 index 000000000..82fdf6934 --- /dev/null +++ b/src/OpenSHC/Game/GameCore/switchToMenuView.cpp @@ -0,0 +1,315 @@ +#include "../GameCore.func.hpp" + +#include "OpenSHC/Audio/MSS/SoundSystem.func.hpp" +#include "OpenSHC/Game/GameStateStructures.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Rendering/Bink/BinkControlClass.func.hpp" +#include "OpenSHC/UI/Credits.func.hpp" +#include "OpenSHC/UI/DisplayElements.func.hpp" +#include "OpenSHC/UI/Helpers.func.hpp" +#include "OpenSHC/UI/MenuHandlerState.func.hpp" + +#include "OpenSHC/Globals/DAT_00b95954.hpp" +#include "OpenSHC/Globals/DAT_BinkControlState.hpp" +#include "OpenSHC/Globals/DAT_CurrentMenuID_3.hpp" +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_MapPropertiesState.hpp" +#include "OpenSHC/Globals/DAT_MenuHandlerState.hpp" +#include "OpenSHC/Globals/DAT_SoundSystemState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" + +namespace OpenSHC { +namespace Game { + + // FUNCTION: STRONGHOLDCRUSADER 0x0046B340 + void GameCore::switchToMenuView(MenuViewType menuID, int delay) + { + if (menuID == 23) { + menuID = UI::Enums::MVT_MAIN_MENU; + } + this->menuViewToSwitchTo = menuID; + this->menuSwitchDelay = delay; + this->menuRenderMoment = timeGetTime(); + + switch (menuID) { + case UI::Enums::MVT_MAP_EDITOR_LANDSCAPING: + this->menuTabToSwitchTo.tabType = this->landscapingmenuMenuTabToSwitchTo; + DAT_TileMapState::instance.unknownBrushRelated = (int)DAT_TileMapState::instance.editorActiveBrush >> 1; + if (this->landscapingmenuMenuTabToSwitchTo != UI::Enums::BMTT_MENU_HIDDEN + && this->activeMenuTab.buildMenuTab != UI::Enums::BMTT_MENU_HIDDEN) { + DAT_TileMapState::instance.currentMapperCommand = Commands::M_MAPPER_NULL; + } + break; + case UI::Enums::MVT_BUILD_MENU: + this->menuTabToSwitchTo = this->buildmenuMenuTabToSwitchTo; + MACRO_CALL_MEMBER(Audio::MSS::SoundSystem_Func::setSection1079_28_4_, DAT_SoundSystemState::ptr)(0); + if (this->menuTabToSwitchTo.buildMenuTab == 48) { + break; + } + if (DAT_GameCore::instance.gameMode_2 == GM_CRUSADER_TUTORIAL) { + MACRO_CALL(UI::Helpers_Func::SetTutorialBuildingActionState)(11, Map::Buildings::BT_HOVEL); + } + if (MACRO_CALL(UI::DisplayElements_Func::GetIfDisplayElementStateNotZero)( + UI::Enums::DEID_MISSION_WIN_DEFEAT_BANNER)) { + this->buildmenuMenuTabToSwitchTo.buildMenuTab = 48; + this->menuTabToSwitchTo.buildMenuTab = 48; + } else if (((DAT_GameCore::instance.gameMode_2 == GM_BUILDERUnk + || DAT_GameCore::instance.gameMode_2 == GM_CRUSADER_TUTORIAL) + && DAT_GameSynchronyState::instance.currentPlayerSlotID == 2) + || (DAT_GameSynchronyState::instance.currentPlayerSlotID == 1 + && MACRO_CALL_MEMBER( + GameStateStructures_Func::singlePlayerHasKeepAndGranaryCheck, DAT_GameState::ptr)() + == 0 + && MACRO_CALL_MEMBER(Map::Units::UnitsState_Func::getArmySize, DAT_UnitsState::ptr)( + DAT_GameSynchronyState::instance.currentPlayerSlotID) + != 0) + || (DAT_GameCore::instance.gameMode_2 == GM_BUILDERUnk + && DAT_MapPropertiesState::instance.SEC_U3_MapType2_1 == Map::MT_SIEGE) + || (DAT_GameCore::instance.gameMode_2 == GM_SKIRMISH_AND_MULTIPLAYER + && DAT_GameSynchronyState::instance.currentGameMode == GM_SKIRMISH_SINGLE_PLAYER + && DAT_GameSynchronyState::instance.currentPlayerSlotID == 0)) { + // all this is custom code for some single player modes + if (this->buildmenuMenuTabToSwitchTo.buildMenuTab != UI::Enums::BMTT_MENU_HIDDEN + && this->buildmenuMenuTabToSwitchTo.buildMenuTab != UI::Enums::BMTT_SOLDIERS + && this->buildmenuMenuTabToSwitchTo.buildMenuTab != 62) { + this->buildmenuMenuTabToSwitchTo.buildMenuTab = 48; + this->menuTabToSwitchTo.buildMenuTab = 48; + MACRO_CALL_MEMBER(Audio::MSS::SoundSystem_Func::setSection1079_28_4_, DAT_SoundSystemState::ptr)(1); + } + } else { + if (this->currentMenuViewType == UI::Enums::MVT_BUILD_MENU) { + if (this->buildmenuMenuTabToSwitchTo.buildMenuTab >= 10 + && this->buildmenuMenuTabToSwitchTo.buildMenuTab <= 49 && this->activeMenuTab.buildMenuTab >= 10 + && this->activeMenuTab.buildMenuTab <= 49) { + this->menuSwitchDelay = 150; + MACRO_CALL_MEMBER( + UI::MenuHandlerState_Func::startBuildMenuTransition, DAT_MenuHandlerState::ptr)(300); + if (this->buildmenuMenuTabToSwitchTo.buildMenuTab != 49 + && this->buildmenuMenuTabToSwitchTo.buildMenuTab != UI::Enums::BMTT_CASTLE_KEEPS) { + if (MACRO_CALL_MEMBER( + GameStateStructures_Func::singlePlayerHasKeepAndGranaryCheck, DAT_GameState::ptr)() + == 0) { + if (this->buildmenuMenuTabToSwitchTo.buildMenuTab != UI::Enums::BMTT_CASTLE_KEEPS) { + this->buildmenuMenuTabToSwitchTo.buildMenuTab = UI::Enums::BMTT_CASTLE_KEEPS; + this->menuTabToSwitchTo.buildMenuTab = UI::Enums::BMTT_CASTLE_KEEPS; + } else { + this->menuSwitchDelay = 0; + DAT_MenuHandlerState::instance.isBuildMenuTransitioning_0x18 = FALSE; + } + } else if (MACRO_CALL_MEMBER(GameStateStructures_Func::singlePlayerHasKeepAndGranaryCheck, + DAT_GameState::ptr)() + < 0) { + if (this->buildmenuMenuTabToSwitchTo.buildMenuTab != 49) { + this->buildmenuMenuTabToSwitchTo.buildMenuTab = 49; + this->menuTabToSwitchTo.buildMenuTab = 49; + } else { + this->menuSwitchDelay = 0; + DAT_MenuHandlerState::instance.isBuildMenuTransitioning_0x18 = FALSE; + } + } + } + break; + } + if (this->buildmenuMenuTabToSwitchTo.buildMenuTab < 10 + || this->buildmenuMenuTabToSwitchTo.buildMenuTab > 49) { + break; + } + } + if (this->buildmenuMenuTabToSwitchTo.buildMenuTab != 49 + && this->buildmenuMenuTabToSwitchTo.buildMenuTab != UI::Enums::BMTT_CASTLE_KEEPS) { + if (MACRO_CALL_MEMBER( + GameStateStructures_Func::singlePlayerHasKeepAndGranaryCheck, DAT_GameState::ptr)() + == 0) { + if (this->buildmenuMenuTabToSwitchTo.buildMenuTab != UI::Enums::BMTT_CASTLE_KEEPS) { + this->buildmenuMenuTabToSwitchTo.buildMenuTab = UI::Enums::BMTT_CASTLE_KEEPS; + this->menuTabToSwitchTo.buildMenuTab = UI::Enums::BMTT_CASTLE_KEEPS; + } + } else if (MACRO_CALL_MEMBER( + GameStateStructures_Func::singlePlayerHasKeepAndGranaryCheck, DAT_GameState::ptr)() + < 0) { + if (this->buildmenuMenuTabToSwitchTo.buildMenuTab != 49) { + this->buildmenuMenuTabToSwitchTo.buildMenuTab = 49; + this->menuTabToSwitchTo.buildMenuTab = 49; + } + } + } + } + break; + case UI::Enums::MVT_BUILDING_AND_STATUS_MENU: + this->menuTabToSwitchTo.tabType = this->buildingandstatusmenuMenuTabToSwitchTo; + break; + default: + MACRO_CALL_MEMBER(Rendering::Bink::BinkControlClass_Func::stopBinkPlayback, DAT_BinkControlState::ptr)(0); + MACRO_CALL_MEMBER(Rendering::Bink::BinkControlClass_Func::stopBinkPlayback, DAT_BinkControlState::ptr)(1); + break; + } + + if (menuID == this->currentMenuViewType) { + return; + } + + // handle sound + switch (menuID) { + case UI::Enums::MVT_MAP_EDITOR_LANDSCAPING: + case UI::Enums::MVT_MAP_EDITOR_PROPERTIES: + MACRO_CALL_MEMBER(Audio::MSS::SoundSystem_Func::setupVolumeAndSoundID0xF0_100, DAT_SoundSystemState::ptr)(); + return; + case UI::Enums::MVT_BUILD_MENU: + if (this->currentMenuViewType == UI::Enums::MVT_BUILDING_AND_STATUS_MENU + || this->currentMenuViewType == UI::Enums::MVT_MAP_EDITOR_LANDSCAPING + || (this->currentMenuViewType == UI::Enums::MVT_SCENARIO_DESCRIPTION + && DAT_GameCore::instance.field22_0x64 != 0)) { + return; + } + if (this->gameMode_2 == GM_CRUSADER_TUTORIAL) { + if (DAT_SoundSystemState::instance.currentSoundID_0x3278 == 9) { + return; + } + MACRO_CALL_MEMBER(Audio::MSS::SoundSystem_Func::setSomeSoundTime, DAT_SoundSystemState::ptr)(); + MACRO_CALL_MEMBER(Audio::MSS::SoundSystem_Func::setupVolumeAndSoundIDWithMultiplier, + DAT_SoundSystemState::ptr)(DE::SHCDE::MUSIC_TUNE_TUTORIAL, 70); + return; + } + MACRO_CALL_MEMBER(Audio::MSS::SoundSystem_Func::setSomeSoundTime, DAT_SoundSystemState::ptr)(); + DAT_SoundSystemState::instance.mbr_0x3288 = timeGetTime() >> 1; + DAT_SoundSystemState::instance.currentSoundID_0x3278 = -1; + return; + case UI::Enums::MVT_CRUSADE_MAP: + if (this->currentMenuViewType == UI::Enums::MVT_SELECT_CRUSADE + || this->currentMenuViewType == UI::Enums::MVT_CRUSADE_MISSION_INTRO + || this->currentMenuViewType == UI::Enums::MVT_RANKING_GAMES) { + return; + } + MACRO_CALL_MEMBER(Audio::MSS::SoundSystem_Func::setSomeSoundTime, DAT_SoundSystemState::ptr)(); + MACRO_CALL_MEMBER(Audio::MSS::SoundSystem_Func::setupVolumeAndSoundIDWithMultiplier, + DAT_SoundSystemState::ptr)(DE::SHCDE::MUSIC_TUNE_INTRO, 100); + return; + case UI::Enums::MVT_RANKING_GAMES: + if (this->currentMenuViewType == UI::Enums::MVT_LOBBY_MENU) { + MACRO_CALL(UI::Credits_Func::SetActiveCreditsSequenceIndex)(2); + DAT_CurrentMenuID_3::instance = this->currentMenuViewType; + } + if (this->currentMenuViewType == UI::Enums::MVT_CRUSADE_MAP) { + MACRO_CALL(UI::Credits_Func::SetActiveCreditsSequenceIndex)(1); + DAT_CurrentMenuID_3::instance = this->currentMenuViewType; + } + return; + case UI::Enums::MVT_HISTORIC_MISSION_PICTURE: + if (this->currentMenuViewType == UI::Enums::MVT_HISTORIC_CAMPAIGN_INTRO) { + return; + } + if (this->currentMenuViewType == UI::Enums::MVT_MISSION_FINISHED_TRANSITION) { + MACRO_CALL_MEMBER(Audio::MSS::SoundSystem_Func::stopMusicPlayback, DAT_SoundSystemState::ptr)(); + MACRO_CALL_MEMBER(Audio::MSS::SoundSystem_Func::setupVolumeAndSoundID, DAT_SoundSystemState::ptr)( + DE::SHCDE::MUSIC_TUNE_NARR1); + return; + } + if (DAT_GameCore::instance.missionNumber1to20 == 1000) { + if (DAT_SoundSystemState::instance.sec_Section1055_0x3274 != 7) { + MACRO_CALL_MEMBER(Audio::MSS::SoundSystem_Func::setSomeSoundTime, DAT_SoundSystemState::ptr)(); + } + MACRO_CALL_MEMBER(Audio::MSS::SoundSystem_Func::setupVolumeAndSoundIDWithMultiplier, + DAT_SoundSystemState::ptr)(DE::SHCDE::MUSIC_TUNE_CHOIR, 100); + return; + } + if (DAT_SoundSystemState::instance.currentSoundID_0x3278 == 4 || DAT_GameCore::instance.field22_0x64 != 0 + || DAT_GameCore::instance.currentlyInGameUnk_0xa4 == TRUE) { + return; + } + MACRO_CALL_MEMBER(Audio::MSS::SoundSystem_Func::setSomeSoundTime, DAT_SoundSystemState::ptr)(); + MACRO_CALL_MEMBER(Audio::MSS::SoundSystem_Func::setupVolumeAndSoundID, DAT_SoundSystemState::ptr)( + DE::SHCDE::MUSIC_TUNE_NARR1); + return; + case UI::Enums::MVT_HISTORIC_CAMPAIGN_INTRO: + MACRO_CALL_MEMBER(Audio::MSS::SoundSystem_Func::setSomeSoundTime, DAT_SoundSystemState::ptr)(); + MACRO_CALL_MEMBER(Audio::MSS::SoundSystem_Func::setupVolumeAndSoundID, DAT_SoundSystemState::ptr)( + (DE::SHCDE::eMusicIDs)(DAT_GameCore::instance.historicCampaignNumber * 5 + DE::SHCDE::MUSIC_TUNE_WIN1)); + return; + case UI::Enums::MVT_HISTORIC_CAMPAIGN_OUTRO: + MACRO_CALL_MEMBER(Audio::MSS::SoundSystem_Func::setSomeSoundTime, DAT_SoundSystemState::ptr)(); + MACRO_CALL_MEMBER(Audio::MSS::SoundSystem_Func::setupVolumeAndSoundID, DAT_SoundSystemState::ptr)( + (DE::SHCDE::eMusicIDs)(DAT_GameCore::instance.historicCampaignNumber + 0x42)); + return; + case UI::Enums::MVT_CREDITS: + MACRO_CALL_MEMBER(Audio::MSS::SoundSystem_Func::setSomeSoundTime, DAT_SoundSystemState::ptr)(); + if (DAT_00b95954::instance == 0) { + MACRO_CALL_MEMBER(Audio::MSS::SoundSystem_Func::setupVolumeAndSoundIDWithMultiplier, + DAT_SoundSystemState::ptr)((DE::SHCDE::eMusicIDs)15, 100); + } + if (DAT_00b95954::instance == 1) { + MACRO_CALL_MEMBER(Audio::MSS::SoundSystem_Func::setupVolumeAndSoundIDWithMultiplier, + DAT_SoundSystemState::ptr)((DE::SHCDE::eMusicIDs)38, 100); + MACRO_CALL_MEMBER(Audio::MSS::SoundSystem_Func::markMusicChangePending, DAT_SoundSystemState::ptr)(); + } + return; + case UI::Enums::MVT_MISSION_FINISHED_TRANSITION: + case UI::Enums::MVT_GAME_LOSTUnk: + if (this->currentMenuViewType == UI::Enums::MVT_RANKING_GAMES) { + return; + } + MACRO_CALL_MEMBER(Audio::MSS::SoundSystem_Func::setSomeSoundTime, DAT_SoundSystemState::ptr)(); + MACRO_CALL_MEMBER(Audio::MSS::SoundSystem_Func::setupVolumeAndSoundID, DAT_SoundSystemState::ptr)( + DE::SHCDE::MUSIC_TUNE_OFF); + return; + case UI::Enums::MVT_MP_CONNECTION: + case UI::Enums::MVT_LOBBY_MENU: + case UI::Enums::MVT_GAME_START_ENTER_NAME: + case UI::Enums::MVT_MAIN_MENU: + case UI::Enums::MVT_HISTORIC_CAMPAIGN_SELECT: + case UI::Enums::MVT_UNUSED_ECONOMIC_GAMETYPE_SELECT: + case UI::Enums::MVT_CUSTOM_SCENARIOS: + case UI::Enums::MVT_UNUSED_SELECT_RANDOM_NUMBER_OF_ENEMIES: + if (DAT_SoundSystemState::instance.currentSoundID_0x3278 == 3 + && DAT_SoundSystemState::instance.mbr_0x154 == 0) { + return; + } + MACRO_CALL_MEMBER(Audio::MSS::SoundSystem_Func::setSomeSoundTime, DAT_SoundSystemState::ptr)(); + MACRO_CALL_MEMBER(Audio::MSS::SoundSystem_Func::setupVolumeAndSoundIDWithMultiplier, + DAT_SoundSystemState::ptr)(DE::SHCDE::MUSIC_TUNE_INTRO, 100); + return; + case UI::Enums::MVT_UNUSED_EXTREME_AD: + MACRO_CALL_MEMBER(Audio::MSS::SoundSystem_Func::endSoundStreamsUnk, DAT_SoundSystemState::ptr)(); + MACRO_CALL_MEMBER(Audio::MSS::SoundSystem_Func::setSomeSoundTime, DAT_SoundSystemState::ptr)(); + MACRO_CALL_MEMBER(Audio::MSS::SoundSystem_Func::setupVolumeAndSoundIDWithMultiplier, + DAT_SoundSystemState::ptr)(DE::SHCDE::MUSIC_TUNE_TUTORIAL, 50); + return; + case UI::Enums::MVT_CRUSADE_ENDSCREEN: + MACRO_CALL_MEMBER(Audio::MSS::SoundSystem_Func::setSomeSoundTime, DAT_SoundSystemState::ptr)(); + MACRO_CALL_MEMBER(Audio::MSS::SoundSystem_Func::setupVolumeAndSoundIDWithMultiplier, + DAT_SoundSystemState::ptr)(DE::SHCDE::MUSIC_TUNE_HAPPY2, 50); + return; + case UI::Enums::MVT_BUILDING_AND_STATUS_MENU: + case UI::Enums::MVT_UNKNOWN_21: + case UI::Enums::MVT_UNUSED_HELP_TEXT_EDITOR: + case 23: + case 24: + case UI::Enums::MVT_UNKNOWN_26_CAMPAIGN_RELATEDUnk: + case UI::Enums::MVT_UNKNOWN_27_CAMPAIGNUnk: + case UI::Enums::MVT_SCENARIO_DESCRIPTION: + case UI::Enums::MVT_NEW_MAP_MAPSIZE: + case UI::Enums::MVT_UNUSED_CHOOSE_AVAILABLE_KEEPS: + case UI::Enums::MVT_UNKNOWN_33: + case UI::Enums::MVT_SINGLEPLAYER_MAP_CHOICE: + case 36: + case UI::Enums::MVT_UNUSED_CHOOSE_GAME_TYPE: + case UI::Enums::MVT_HISTORIC_MISSION_SELECT: + case UI::Enums::MVT_UNUSED_ECONOMIC_MISSION_SELECTUnk: + case UI::Enums::MVT_INTRO_VIDEO: + case UI::Enums::MVT_HISTORIC_MISSION_INTRO: + case UI::Enums::MVT_SELECT_CRUSADE: + case UI::Enums::MVT_CRUSADE_MISSION_INTRO: + case UI::Enums::MVT_EDIT_SCENARIO: + return; + default: + MACRO_CALL_MEMBER(Audio::MSS::SoundSystem_Func::setSomeSoundTime, DAT_SoundSystemState::ptr)(); + MACRO_CALL_MEMBER(Audio::MSS::SoundSystem_Func::setupVolumeAndSoundIDWithMultiplier, + DAT_SoundSystemState::ptr)(DE::SHCDE::MUSIC_TUNE_INTRO, 100); + return; + } + } + +} +} diff --git a/src/OpenSHC/Game/GameCore/switchToScenarioDescriptionMenuView.cpp b/src/OpenSHC/Game/GameCore/switchToScenarioDescriptionMenuView.cpp index a001da5b1..cade92354 100644 --- a/src/OpenSHC/Game/GameCore/switchToScenarioDescriptionMenuView.cpp +++ b/src/OpenSHC/Game/GameCore/switchToScenarioDescriptionMenuView.cpp @@ -1,19 +1,15 @@ -#include "OpenSHC/Game/GameCore.func.hpp" -#include "OpenSHC/UI/Enums/MenuViewType.hpp" +#include "../GameCore.func.hpp" #include "OpenSHC/Globals/DAT_GameCore.hpp" namespace OpenSHC { namespace Game { - using OpenSHC::UI::Enums::MenuViewType; - // FUNCTION: STRONGHOLDCRUSADER 0x004719E0 void GameCore::switchToScenarioDescriptionMenuView() { - MACRO_CALL_MEMBER(OpenSHC::Game::GameCore_Func::removeJesterAndLadyUnitsInCertainMissions, this)(); - MACRO_CALL_MEMBER(OpenSHC::Game::GameCore_Func::switchToMenuView, DAT_GameCore::ptr)( - OpenSHC::UI::Enums::MVT_SCENARIO_DESCRIPTION, 0); + MACRO_CALL_MEMBER(GameCore_Func::removeJesterAndLadyUnitsInCertainMissions, this)(); + MACRO_CALL_MEMBER(GameCore_Func::switchToMenuView, DAT_GameCore::ptr)(UI::Enums::MVT_SCENARIO_DESCRIPTION, 0); DAT_GameCore::instance.field22_0x64 = 0; } diff --git a/src/OpenSHC/Game/GameCore/viewportAndScrollingRelated.cpp b/src/OpenSHC/Game/GameCore/viewportAndScrollingRelated.cpp new file mode 100644 index 000000000..c64b388aa --- /dev/null +++ b/src/OpenSHC/Game/GameCore/viewportAndScrollingRelated.cpp @@ -0,0 +1,23 @@ +#include "../GameCore.func.hpp" + +#include "OpenSHC/Globals/DAT_ScrollingHandler.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Game { + + // FUNCTION: STRONGHOLDCRUSADER 0x0046BB20 + void GameCore::viewportAndScrollingRelated() + { + if (this->countdown > 0) { + --this->countdown; + } + if (DAT_ViewportRenderState::instance.viewportState.field0_0x0 == 0 + && !DAT_ScrollingHandler::instance.isScrolling_0x0) { + this->countdown = 1; + this->forty = 0; + } + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 1a294c2d8..713053571 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -20741,7 +20741,7 @@ SHC_3BB0A8C1_0x0046B170 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0046B1B0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0046B1F0 | 0.0% | Pending +SHC_3BB0A8C1_0x0046B1F0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0046B2F0 | 100.0% | Reimplemented @@ -20749,7 +20749,7 @@ SHC_3BB0A8C1_0x0046B300 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0046B320 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0046B340 | 0.0% | Pending +SHC_3BB0A8C1_0x0046B340 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0046B90C | 0.0% | Pending @@ -20881,21 +20881,21 @@ SHC_3BB0A8C1_0x0046B975 | 0.0% | Pending SHC_3BB0A8C1_0x0046B976 | 0.0% | Pending -SHC_3BB0A8C1_0x0046B980 | 0.0% | Pending +SHC_3BB0A8C1_0x0046B980 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0046BB20 | 0.0% | Pending +SHC_3BB0A8C1_0x0046BB20 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0046BB60 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0046BB80 | 0.0% | Pending +SHC_3BB0A8C1_0x0046BB80 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0046BBD0 | 0.0% | Pending +SHC_3BB0A8C1_0x0046BBD0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0046BC90 | 0.0% | Pending +SHC_3BB0A8C1_0x0046BC90 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0046BD20 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0046BD50 | 0.0% | Pending +SHC_3BB0A8C1_0x0046BD50 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0046BDB0 | 0.0% | Pending @@ -21325,15 +21325,15 @@ SHC_3BB0A8C1_0x00471890 | 100.0% | Reimplemented SHC_3BB0A8C1_0x004718C0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004718F0 | 0.0% | Pending +SHC_3BB0A8C1_0x004718F0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x004719E0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00471A00 | 0.0% | Pending +SHC_3BB0A8C1_0x00471A00 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00471A80 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00471AA0 | 0.0% | Pending +SHC_3BB0A8C1_0x00471AA0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00471BE0 | 100.0% | Reimplemented @@ -60107,12 +60107,8 @@ SHC_3BB0A8C1_0x0053F07C | 0.0% | Pending SHC_3BB0A8C1_0x0053F084 | 0.0% | Pending -SHC_3BB0A8C1_0x0053F088 | 0.0% | Pending - SHC_3BB0A8C1_0x0053F08F | 0.0% | Pending -SHC_3BB0A8C1_0x0053F09C | 0.0% | Pending - SHC_3BB0A8C1_0x0053F0AA | 0.0% | Pending SHC_3BB0A8C1_0x0053F0BA | 0.0% | Pending @@ -67547,7 +67543,7 @@ SHC_3BB0A8C1_0x0057B9BE | 0.0% | Pending SHC_3BB0A8C1_0x0057B9C0 | 0.0% | Pending -SHC_3BB0A8C1_0x0057BE10 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0057BE10 | 0.0% | Pending SHC_3BB0A8C1_0x0057C815 | 0.0% | Pending @@ -86289,14 +86285,34 @@ SHC_3BB0A8C1_0x00EE2350 | 0.0% | Pending SHC_3BB0A8C1_0x00EE2354 | 0.0% | Pending +SHC_3BB0A8C1_0x00EE2358 | 0.0% | Pending + +SHC_3BB0A8C1_0x00EE235C | 0.0% | Pending + +SHC_3BB0A8C1_0x00EE2360 | 0.0% | Pending + SHC_3BB0A8C1_0x00EE2364 | 0.0% | Pending SHC_3BB0A8C1_0x00EE2368 | 0.0% | Pending +SHC_3BB0A8C1_0x00EE236C | 0.0% | Pending + +SHC_3BB0A8C1_0x00EE2370 | 0.0% | Pending + SHC_3BB0A8C1_0x00EE2374 | 0.0% | Pending +SHC_3BB0A8C1_0x00EE2378 | 0.0% | Pending + +SHC_3BB0A8C1_0x00EE237C | 0.0% | Pending + SHC_3BB0A8C1_0x00EE2380 | 0.0% | Pending +SHC_3BB0A8C1_0x00EE2384 | 0.0% | Pending + +SHC_3BB0A8C1_0x00EE2388 | 0.0% | Pending + +SHC_3BB0A8C1_0x00EE238C | 0.0% | Pending + SHC_3BB0A8C1_0x00EE2390 | 0.0% | Pending SHC_3BB0A8C1_0x00EE2394 | 0.0% | Pending From d497d663957cd0279ff55d6e0b1e9567325bb206 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 11 Oct 2026 22:39:30 +0200 Subject: [PATCH 2/3] Add enums --- src/OpenSHC/Game/GameCore/setViewOnExitUnk.cpp | 2 +- src/OpenSHC/Game/GameCore/swapBuildMenuTab.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/OpenSHC/Game/GameCore/setViewOnExitUnk.cpp b/src/OpenSHC/Game/GameCore/setViewOnExitUnk.cpp index e06ffe25c..20c88f6a7 100644 --- a/src/OpenSHC/Game/GameCore/setViewOnExitUnk.cpp +++ b/src/OpenSHC/Game/GameCore/setViewOnExitUnk.cpp @@ -4,7 +4,7 @@ namespace OpenSHC { namespace Game { // FUNCTION: STRONGHOLDCRUSADER 0x0046B2F0 - void GameCore::setViewOnExitUnk() { this->currentMenuViewType = 2; } + void GameCore::setViewOnExitUnk() { this->currentMenuViewType = UI::Enums::MVT_UNKNOWN_2; } } } diff --git a/src/OpenSHC/Game/GameCore/swapBuildMenuTab.cpp b/src/OpenSHC/Game/GameCore/swapBuildMenuTab.cpp index a0eafbb33..6d04211d5 100644 --- a/src/OpenSHC/Game/GameCore/swapBuildMenuTab.cpp +++ b/src/OpenSHC/Game/GameCore/swapBuildMenuTab.cpp @@ -6,8 +6,8 @@ namespace Game { // FUNCTION: STRONGHOLDCRUSADER 0x0046B320 void GameCore::swapBuildMenuTab() { - if (this->buildmenuMenuTabToSwitchTo.buildMenuTab == 62) { - this->buildmenuMenuTabToSwitchTo.buildMenuTab = UI::Enums::BMTT_SOLDIERS; + if (this->buildmenuMenuTabToSwitchTo.tabType == OpenSHC::UI::Enums::BASMTT_SIEGETENT_SHIELD) { + this->buildmenuMenuTabToSwitchTo.tabType = OpenSHC::UI::Enums::BASMTT_SIEGETENT_BATTERINGRAM; return; } this->buildmenuMenuTabToSwitchTo = this->secondaryActiveMenuTabToSwitchTo; From 97bced4d77d6601755b08fd0c955d64c4c88a65b Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 11 Oct 2026 22:58:19 +0200 Subject: [PATCH 3/3] fix furthestMission --- src/OpenSHC/Game/GameCore/incrementMission.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OpenSHC/Game/GameCore/incrementMission.cpp b/src/OpenSHC/Game/GameCore/incrementMission.cpp index f71ed25d5..9c299cee4 100644 --- a/src/OpenSHC/Game/GameCore/incrementMission.cpp +++ b/src/OpenSHC/Game/GameCore/incrementMission.cpp @@ -16,7 +16,7 @@ namespace Game { { ++this->missionNumber1to20; MACRO_CALL_MEMBER(GameCore_Func::removeLadyAndJester, this)(); - if (!this->unlockAllHistoricalCampaigns && this->missionNumber1to20 > (int)this->furthestMission) { + if (!this->unlockAllHistoricalCampaigns && this->missionNumber1to20 > this->furthestMission) { this->furthestMission = this->missionNumber1to20; } MACRO_CALL_MEMBER(IO::SettingsFileState_Func::writeUserConfig, DAT_SettingsFileState::ptr)();