diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index c7665115f..a4ac50831 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -603,6 +603,16 @@ void SaveManager::InitFileNormal() { void SaveManager::InitFileDebug() { InitFileNormal(); + //don't apply gDebugSaveFileMode on the title screen + if (gSaveContext.fileNum != 0xFF) { + if (CVarGetInteger("gDebugSaveFileMode", 1) == 2) { + InitFileMaxed(); + return; + } else if (CVarGetInteger("gDebugSaveFileMode", 1) == 0) { + return; + } + } + gSaveContext.totalDays = 0; gSaveContext.bgsDayCount = 0; @@ -705,6 +715,148 @@ void SaveManager::InitFileDebug() { gSaveContext.sceneFlags[5].swch = 0x40000000; } +void SaveManager::InitFileMaxed() { + gSaveContext.totalDays = 0; + gSaveContext.bgsDayCount = 0; + + gSaveContext.deaths = 0; + static std::array sPlayerName = { 0x15, 0x12, 0x17, 0x14, 0x3E, 0x3E, 0x3E, 0x3E }; + for (int i = 0; i < ARRAY_COUNT(gSaveContext.playerName); i++) { + gSaveContext.playerName[i] = sPlayerName[i]; + } + gSaveContext.n64ddFlag = 0; + gSaveContext.healthCapacity = 0x140; + gSaveContext.health = 0x140; + gSaveContext.magicLevel = 2; + gSaveContext.magic = 0x60; + gSaveContext.rupees = 500; + gSaveContext.swordHealth = 8; + gSaveContext.naviTimer = 0; + gSaveContext.isMagicAcquired = 1; + gSaveContext.isDoubleMagicAcquired = 1; + gSaveContext.isDoubleDefenseAcquired = 1; + gSaveContext.bgsFlag = 1; + gSaveContext.ocarinaGameRoundNum = 0; + for (int button = 0; button < ARRAY_COUNT(gSaveContext.childEquips.buttonItems); button++) { + gSaveContext.childEquips.buttonItems[button] = ITEM_NONE; + } + for (int button = 0; button < ARRAY_COUNT(gSaveContext.childEquips.cButtonSlots); button++) { + gSaveContext.childEquips.cButtonSlots[button] = SLOT_NONE; + } + gSaveContext.childEquips.equipment = 0; + for (int button = 0; button < ARRAY_COUNT(gSaveContext.adultEquips.buttonItems); button++) { + gSaveContext.adultEquips.buttonItems[button] = ITEM_NONE; + } + for (int button = 0; button < ARRAY_COUNT(gSaveContext.adultEquips.cButtonSlots); button++) { + gSaveContext.adultEquips.cButtonSlots[button] = SLOT_NONE; + } + gSaveContext.adultEquips.equipment = 0; + gSaveContext.unk_54 = 0; + gSaveContext.savedSceneNum = 0x51; + + // Equipment + static std::array sButtonItems = { ITEM_SWORD_MASTER, ITEM_BOW, ITEM_BOMB, ITEM_OCARINA_TIME, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE }; + for (int button = 0; button < ARRAY_COUNT(gSaveContext.equips.buttonItems); button++) { + gSaveContext.equips.buttonItems[button] = sButtonItems[button]; + } + static std::array sCButtonSlots = { SLOT_BOW, SLOT_BOMB, SLOT_OCARINA, SLOT_NONE, SLOT_NONE, SLOT_NONE, SLOT_NONE }; + for (int button = 0; button < ARRAY_COUNT(gSaveContext.equips.cButtonSlots); button++) { + gSaveContext.equips.cButtonSlots[button] = sCButtonSlots[button]; + } + gSaveContext.equips.equipment = 0x1122; + + // Inventory + static std::array sItems = { + ITEM_STICK, ITEM_NUT, ITEM_BOMB, ITEM_BOW, ITEM_ARROW_FIRE, ITEM_DINS_FIRE, + ITEM_SLINGSHOT, ITEM_OCARINA_TIME, ITEM_BOMBCHU, ITEM_LONGSHOT, ITEM_ARROW_ICE, ITEM_FARORES_WIND, + ITEM_BOOMERANG, ITEM_LENS, ITEM_BEAN, ITEM_HAMMER, ITEM_ARROW_LIGHT, ITEM_NAYRUS_LOVE, + ITEM_FAIRY, ITEM_FAIRY, ITEM_BUG, ITEM_FISH, ITEM_CLAIM_CHECK, ITEM_MASK_BUNNY, + }; + for (int item = 0; item < ARRAY_COUNT(gSaveContext.inventory.items); item++) { + gSaveContext.inventory.items[item] = sItems[item]; + } + static std::array sAmmo = { 30, 40, 40, 50, 0, 0, 50, 0, 50, 0, 0, 0, 0, 0, 15, 0 }; + for (int ammo = 0; ammo < ARRAY_COUNT(gSaveContext.inventory.ammo); ammo++) { + gSaveContext.inventory.ammo[ammo] = sAmmo[ammo]; + } + gSaveContext.inventory.equipment = 0x7777; + gSaveContext.inventory.upgrades = 3597531; + gSaveContext.inventory.questItems = 33554431; + static std::array sDungeonItems = { 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 }; + for (int dungeon = 0; dungeon < ARRAY_COUNT(gSaveContext.inventory.dungeonItems); dungeon++) { + gSaveContext.inventory.dungeonItems[dungeon] = sDungeonItems[dungeon]; + } + for (int dungeon = 0; dungeon < ARRAY_COUNT(gSaveContext.inventory.dungeonKeys); dungeon++) { + gSaveContext.inventory.dungeonKeys[dungeon] = 9; + } + gSaveContext.inventory.defenseHearts = 20; + gSaveContext.inventory.gsTokens = 100; + + gSaveContext.horseData.scene = SCENE_HYRULE_FIELD; + gSaveContext.horseData.pos.x = -1840; + gSaveContext.horseData.pos.y = 72; + gSaveContext.horseData.pos.z = 5497; + gSaveContext.horseData.angle = -0x6AD9; + gSaveContext.infTable[0] |= 0x5009; + gSaveContext.infTable[29] = 0; // unset flag from normal file setup + gSaveContext.eventChkInf[0] |= 0x123F; + gSaveContext.eventChkInf[8] |= 1; + gSaveContext.eventChkInf[12] |= 0x10; + + //set all the "Entered *" flags for dungeons + for (int i = 0; i < 0xF; i += 1) { + Flags_SetInfTable(0x1A0 + i); + } + Flags_SetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE); + + Flags_SetEventChkInf(EVENTCHKINF_OPENED_THE_DOOR_OF_TIME); + Flags_SetEventChkInf(EVENTCHKINF_EPONA_OBTAINED); + Flags_SetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED); + Flags_SetEventChkInf(EVENTCHKINF_BEGAN_NABOORU_BATTLE); + Flags_SetEventChkInf(EVENTCHKINF_BEGAN_GOHMA_BATTLE); + Flags_SetEventChkInf(EVENTCHKINF_BEGAN_KING_DODONGO_BATTLE); + Flags_SetEventChkInf(EVENTCHKINF_BEGAN_PHANTOM_GANON_BATTLE); + Flags_SetEventChkInf(EVENTCHKINF_BEGAN_VOLVAGIA_BATTLE); + Flags_SetEventChkInf(EVENTCHKINF_BEGAN_MORPHA_BATTLE); + Flags_SetEventChkInf(EVENTCHKINF_BEGAN_TWINROVA_BATTLE); + Flags_SetEventChkInf(EVENTCHKINF_BEGAN_BARINA_BATTLE); + Flags_SetEventChkInf(EVENTCHKINF_BEGAN_BONGO_BONGO_BATTLE); + Flags_SetEventChkInf(EVENTCHKINF_BEGAN_GANONDORF_BATTLE); + Flags_SetEventChkInf(EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER); + Flags_SetEventChkInf(EVENTCHKINF_ENTERED_HYRULE_FIELD); + Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DEATH_MOUNTAIN_TRAIL); + Flags_SetEventChkInf(EVENTCHKINF_ENTERED_KAKARIKO_VILLAGE); + Flags_SetEventChkInf(EVENTCHKINF_ENTERED_ZORAS_DOMAIN); + Flags_SetEventChkInf(EVENTCHKINF_ENTERED_HYRULE_CASTLE); + Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GORON_CITY); + Flags_SetEventChkInf(EVENTCHKINF_ENTERED_TEMPLE_OF_TIME); + Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DEKU_TREE); + Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DODONGOS_CAVERN); + Flags_SetEventChkInf(EVENTCHKINF_ENTERED_LAKE_HYLIA); + Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GERUDO_VALLEY); + Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GERUDOS_FORTRESS); + Flags_SetEventChkInf(EVENTCHKINF_ENTERED_LON_LON_RANCH); + Flags_SetEventChkInf(EVENTCHKINF_ENTERED_JABU_JABUS_BELLY); + Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GRAVEYARD); + Flags_SetEventChkInf(EVENTCHKINF_ENTERED_ZORAS_FOUNTAIN); + Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DESERT_COLOSSUS); + Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DEATH_MOUNTAIN_CRATER); + Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GANONS_CASTLE_EXTERIOR); + + if (LINK_AGE_IN_YEARS == YEARS_CHILD) { + gSaveContext.equips.buttonItems[0] = ITEM_SWORD_KOKIRI; + Inventory_ChangeEquipment(EQUIP_SWORD, 1); + if (gSaveContext.fileNum == 0xFF) { + gSaveContext.equips.buttonItems[1] = ITEM_SLINGSHOT; + gSaveContext.equips.cButtonSlots[0] = SLOT_SLINGSHOT; + Inventory_ChangeEquipment(EQUIP_SHIELD, 1); + } + } + + gSaveContext.entranceIndex = 0xCD; + gSaveContext.sceneFlags[5].swch = 0x40000000; +} + // Threaded SaveFile takes copy of gSaveContext for local unmodified storage void SaveManager::SaveFileThreaded(int fileNum, SaveContext* saveContext, int sectionID) { diff --git a/soh/soh/SaveManager.h b/soh/soh/SaveManager.h index f5f91c5bd..62eed98b2 100644 --- a/soh/soh/SaveManager.h +++ b/soh/soh/SaveManager.h @@ -151,6 +151,7 @@ class SaveManager { static void InitFileImpl(bool isDebug); static void InitFileNormal(); static void InitFileDebug(); + static void InitFileMaxed(); static void LoadRandomizerVersion1(); static void LoadRandomizerVersion2(); diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 2a49d752a..60370736c 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -81,6 +81,7 @@ std::string GetWindowButtonText(const char* text, bool menuOpen) { static const char* subSubPowers[7] = { allPowers[0], allPowers[1], allPowers[2], allPowers[3], allPowers[4], allPowers[5], allPowers[6] }; static const char* zFightingOptions[3] = { "Disabled", "Consistent Vanish", "No Vanish" }; static const char* autosaveLabels[6] = { "Off", "New Location + Major Item", "New Location + Any Item", "New Location", "Major Item", "Any Item" }; + static const char* DebugSaveFileModes[3] = { "Off", "Vanilla", "Maxed" }; static const char* FastFileSelect[5] = { "File N.1", "File N.2", "File N.3", "Zelda Map Select (require OoT Debug Mode)", "File select" }; static const char* bonkDamageValues[8] = { "No Damage", @@ -1356,16 +1357,25 @@ extern std::shared_ptr mActorViewerWindow; extern std::shared_ptr mDLViewerWindow; void DrawDeveloperToolsMenu() { - if (ImGui::BeginMenu("Developer Tools")) - { + if (ImGui::BeginMenu("Developer Tools")) { UIWidgets::EnhancementCheckbox("OoT Debug Mode", "gDebugEnabled"); UIWidgets::Tooltip("Enables Debug Mode, allowing you to select maps with L + R + Z, noclip with L + D-pad Right, and open the debug menu with L on the pause screen"); + if (CVarGetInteger("gDebugEnabled", 0)) { + ImGui::Text("Debug Save File Mode:"); + UIWidgets::EnhancementCombobox("gDebugSaveFileMode", DebugSaveFileModes, 1); + UIWidgets::Tooltip( + "Changes the behaviour of debug file select creation (creating a save file on slot 1 with debug mode on)\n" + "- Off: The debug save file will be a normal savefile\n" + "- Vanilla: The debug save file will be the debug save file from the original game\n" + "- Maxed: The debug save file will be a save file with all of the items & upgrades" + ); + } UIWidgets::PaddedEnhancementCheckbox("OoT Skulltula Debug", "gSkulltulaDebugEnabled", true, false); UIWidgets::Tooltip("Enables Skulltula Debug, when moving the cursor in the menu above various map icons (boss key, compass, map screen locations, etc) will set the GS bits in that area.\nUSE WITH CAUTION AS IT DOES NOT UPDATE THE GS COUNT."); UIWidgets::PaddedEnhancementCheckbox("Fast File Select", "gSkipLogoTitle", true, false); UIWidgets::Tooltip("Load the game to the selected menu or file\n\"Zelda Map Select\" require debug mode else you will fallback to File choose menu\nUsing a file number that don't have save will create a save file only if you toggle on \"Create a new save if none ?\" else it will bring you to the File choose menu"); if (CVarGetInteger("gSkipLogoTitle", 0)) { - ImGui::Text("Loading :"); + ImGui::Text("Loading:"); UIWidgets::EnhancementCombobox("gSaveFileID", FastFileSelect, 0); }; UIWidgets::PaddedEnhancementCheckbox("Better Debug Warp Screen", "gBetterDebugWarpScreen", true, false);