diff --git a/soh/include/functions.h b/soh/include/functions.h index e85259595..d5823f6f5 100644 --- a/soh/include/functions.h +++ b/soh/include/functions.h @@ -1527,6 +1527,9 @@ Gfx* Gameplay_SetFog(GlobalContext* globalCtx, Gfx* gfx); void Gameplay_Destroy(GameState* thisx); void Gameplay_Init(GameState* thisx); void Gameplay_Main(GameState* thisx); +u8 CheckStoneCount(); +u8 CheckMedallionCount(); +u8 CheckDungeonCount(); s32 Gameplay_InCsMode(GlobalContext* globalCtx); f32 func_800BFCB8(GlobalContext* globalCtx, MtxF* mf, Vec3f* vec); void* Gameplay_LoadFile(GlobalContext* globalCtx, RomFile* file); diff --git a/soh/soh/Enhancements/randomizer/3drando/settings.cpp b/soh/soh/Enhancements/randomizer/3drando/settings.cpp index 763d53f8f..546f645a1 100644 --- a/soh/soh/Enhancements/randomizer/3drando/settings.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/settings.cpp @@ -2598,6 +2598,11 @@ namespace Settings { GerudoKeys.SetSelectedIndex(cvarSettings[RSK_GERUDO_KEYS]); BossKeysanity.SetSelectedIndex(cvarSettings[RSK_BOSS_KEYSANITY]); GanonsBossKey.SetSelectedIndex(cvarSettings[RSK_GANONS_BOSS_KEY]); + LACSStoneCount.SetSelectedIndex(cvarSettings[RSK_LACS_STONE_COUNT]); + LACSMedallionCount.SetSelectedIndex(cvarSettings[RSK_LACS_MEDALLION_COUNT]); + LACSRewardCount.SetSelectedIndex(cvarSettings[RSK_LACS_REWARD_COUNT]); + LACSDungeonCount.SetSelectedIndex(cvarSettings[RSK_LACS_DUNGEON_COUNT]); + LACSTokenCount.SetSelectedIndex(cvarSettings[RSK_LACS_TOKEN_COUNT]); NumRequiredCuccos.SetSelectedIndex(cvarSettings[RSK_CUCCO_COUNT]); BigPoeTargetCount.SetSelectedIndex(cvarSettings[RSK_BIG_POE_COUNT]-1); diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index cf031f0d8..9f0092c9e 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -208,6 +208,11 @@ std::unordered_map SpoilerfileSettingNameToEn { "Shuffle Dungeon Items:Gerudo Fortress Keys", RSK_GERUDO_KEYS }, { "Shuffle Dungeon Items:Boss Keys", RSK_BOSS_KEYSANITY }, { "Shuffle Dungeon Items:Ganon's Boss Key", RSK_GANONS_BOSS_KEY }, + { "Shuffle Dungeon Items:Medallion Count", RSK_LACS_MEDALLION_COUNT }, + { "Shuffle Dungeon Items:Stone Count", RSK_LACS_STONE_COUNT }, + { "Shuffle Dungeon Items:Reward Count", RSK_LACS_REWARD_COUNT }, + { "Shuffle Dungeon Items:Dungeon Count", RSK_LACS_DUNGEON_COUNT }, + { "Shuffle Dungeon Items:Token Count", RSK_LACS_TOKEN_COUNT }, { "World Settings:Starting Age", RSK_STARTING_AGE }, { "World Settings:Ammo Drops", RSK_ENABLE_BOMBCHU_DROPS }, { "World Settings:Bombchus in Logic", RSK_BOMBCHUS_IN_LOGIC }, @@ -615,6 +620,11 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) { case RSK_RAINBOW_BRIDGE_REWARD_COUNT: case RSK_RAINBOW_BRIDGE_DUNGEON_COUNT: case RSK_RAINBOW_BRIDGE_TOKEN_COUNT: + case RSK_LACS_STONE_COUNT: + case RSK_LACS_MEDALLION_COUNT: + case RSK_LACS_REWARD_COUNT: + case RSK_LACS_DUNGEON_COUNT: + case RSK_LACS_TOKEN_COUNT: case RSK_TRIAL_COUNT: case RSK_BIG_POE_COUNT: case RSK_CUCCO_COUNT: @@ -786,6 +796,18 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) { gSaveContext.randoSettings[index].value = 4; } else if(it.value() == "Anywhere") { gSaveContext.randoSettings[index].value = 5; + } else if(it.value() == "LACS-Vanilla") { + gSaveContext.randoSettings[index].value = 6; + } else if(it.value() == "LACS-Medallions") { + gSaveContext.randoSettings[index].value = 7; + } else if(it.value() == "LACS-Stones") { + gSaveContext.randoSettings[index].value = 8; + } else if(it.value() == "LACS-Rewards") { + gSaveContext.randoSettings[index].value = 9; + } else if(it.value() == "LACS-Dungeons") { + gSaveContext.randoSettings[index].value = 10; + } else if(it.value() == "LACS-Tokens") { + gSaveContext.randoSettings[index].value = 11; } break; case RSK_SKIP_CHILD_ZELDA: @@ -3759,6 +3781,11 @@ void GenerateRandomizerImgui() { cvarSettings[RSK_GERUDO_KEYS] = CVar_GetS32("gRandomizeGerudoKeys", 0); cvarSettings[RSK_BOSS_KEYSANITY] = CVar_GetS32("gRandomizeBossKeysanity", 2); cvarSettings[RSK_GANONS_BOSS_KEY] = CVar_GetS32("gRandomizeShuffleGanonBossKey", 1); + cvarSettings[RSK_LACS_STONE_COUNT] = CVar_GetS32("gRandomizeLacsStoneCount", 3); + cvarSettings[RSK_LACS_MEDALLION_COUNT] = CVar_GetS32("gRandomizeLacsMedallionCount", 6); + cvarSettings[RSK_LACS_REWARD_COUNT] = CVar_GetS32("gRandomizeLacsRewardCount", 9); + cvarSettings[RSK_LACS_DUNGEON_COUNT] = CVar_GetS32("gRandomizeLacsDungeonCount", 8); + cvarSettings[RSK_LACS_TOKEN_COUNT] = CVar_GetS32("gRandomizeLacsTokenCount", 100); cvarSettings[RSK_STARTING_CONSUMABLES] = CVar_GetS32("gRandomizeStartingConsumables", 0); cvarSettings[RSK_FULL_WALLETS] = CVar_GetS32("gRandomizeFullWallets", 0); @@ -3869,8 +3896,10 @@ void DrawRandoEditor(bool& open) { const char* randoShuffleGerudoFortressKeys[4] = { "Vanilla", "Any Dungeon", "Overworld", "Anywhere" }; const char* randoShuffleBossKeys[6] = { "Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere" }; - const char* randoShuffleGanonsBossKey[6] = { "Vanilla", "Own dungeon", "Start with", - "Any Dungeon", "Overworld", "Anywhere" }; + const char* randoShuffleGanonsBossKey[12] = {"Vanilla", "Own dungeon", "Start with", + "Any Dungeon", "Overworld", "Anywhere", + "LACS-Vanilla", "LACS-Medallions", "LACS-Stones", + "LACS-Rewards", "LACS-Dungeons", "LACS-Tokens"}; // Misc Settings const char* randoGossipStoneHints[4] = { "No Hints", "Need Nothing", "Mask of Truth", "Stone of Agony" }; @@ -4496,9 +4525,48 @@ void DrawRandoEditor(bool& open) { "\n" "Overworld - Ganon's Boss Key Key can only appear outside of dungeons.\n" "\n" - "Anywhere - Ganon's Boss Key Key can appear anywhere in the world." + "Anywhere - Ganon's Boss Key Key can appear anywhere in the world.\n" + "\n" + "LACS - These settings put the boss key on the Light Arrow Cutscene location, from Zelda in Temple of Time as adult, with differing requirements:\n" + "- Vanilla: Obtain the Shadow Medallion and Spirit Medallion\n" + "- Medallions: Obtain the specified amount of medallions.\n" + "- Stones: Obtain the specified amount of spiritual stones.\n" + "- Dungeon rewards: Obtain the specified total sum of spiritual stones or medallions.\n" + "- Dungeons: Complete the specified amount of dungeons. Dungeons are considered complete after stepping in to the blue warp after the boss.\n" + "- Tokens: Obtain the specified amount of Skulltula tokens." ); - UIWidgets::EnhancementCombobox("gRandomizeShuffleGanonBossKey", randoShuffleGanonsBossKey, 6, 1); + UIWidgets::EnhancementCombobox("gRandomizeShuffleGanonBossKey", randoShuffleGanonsBossKey, 12, 1); + ImGui::PopItemWidth(); + switch (CVar_GetS32("gRandomizeShuffleGanonBossKey", 1)) { + case 7: + ImGui::Dummy(ImVec2(0.0f, 0.0f)); + UIWidgets::EnhancementSliderInt("Medallion Count: %d", "##RandoLacsMedallionCount", + "gRandomizeLacsMedallionCount", 1, 6, "", 6, true); + break; + case 8: + ImGui::Dummy(ImVec2(0.0f, 0.0f)); + UIWidgets::EnhancementSliderInt("Stone Count: %d", "##RandoLacsStoneCount", + "gRandomizeLacsStoneCount", 1, 3, "", 3, true); + break; + case 9: + ImGui::Dummy(ImVec2(0.0f, 0.0f)); + UIWidgets::EnhancementSliderInt("Reward Count: %d", "##RandoLacsRewardCount", + "gRandomizeLacsRewardCount", 1, 9, "", 9, true); + break; + case 10: + ImGui::Dummy(ImVec2(0.0f, 0.0f)); + UIWidgets::EnhancementSliderInt("Dungeon Count: %d", "##RandoLacsDungeonCount", + "gRandomizeLacsDungeonCount", 1, 8, "", 8, true); + break; + case 11: + ImGui::Dummy(ImVec2(0.0f, 0.0f)); + UIWidgets::EnhancementSliderInt("Token Count: %d", "##RandoLacsTokenCount", + "gRandomizeLacsTokenCount", 1, 100, "", 100, true); + break; + default: + break; + } + ImGui::PushItemWidth(-FLT_MIN); UIWidgets::PaddedSeparator(); diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index e1f8b95f6..860a8349d 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -1036,6 +1036,11 @@ typedef enum { RSK_LINKS_POCKET, RSK_RANDOM_MQ_DUNGEONS, RSK_MQ_DUNGEON_COUNT, + RSK_LACS_MEDALLION_COUNT, + RSK_LACS_STONE_COUNT, + RSK_LACS_REWARD_COUNT, + RSK_LACS_DUNGEON_COUNT, + RSK_LACS_TOKEN_COUNT, RSK_MAX } RandomizerSettingKey; diff --git a/soh/src/code/z_play.c b/soh/src/code/z_play.c index 47a6821da..6729e9f55 100644 --- a/soh/src/code/z_play.c +++ b/soh/src/code/z_play.c @@ -239,10 +239,131 @@ void GivePlayerRandoRewardRequiem(GlobalContext* globalCtx, RandomizerCheck chec } } +u8 CheckStoneCount() { + u8 stoneCount = 0; + + if (CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)) { + stoneCount++; + } + + if (CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) { + stoneCount++; + } + + if (CHECK_QUEST_ITEM(QUEST_ZORA_SAPPHIRE)) { + stoneCount++; + } + + return stoneCount; +} + +u8 CheckMedallionCount() { + u8 medallionCount = 0; + + if (CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST)) { + medallionCount++; + } + + if (CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) { + medallionCount++; + } + + if (CHECK_QUEST_ITEM(QUEST_MEDALLION_WATER)) { + medallionCount++; + } + + if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW)) { + medallionCount++; + } + + if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT)) { + medallionCount++; + } + + if (CHECK_QUEST_ITEM(QUEST_MEDALLION_LIGHT)) { + medallionCount++; + } + + return medallionCount; +} + +u8 CheckDungeonCount() { + u8 dungeonCount = 0; + + if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE)) { + dungeonCount++; + } + + if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN)) { + dungeonCount++; + } + + if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY)) { + dungeonCount++; + } + + if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FOREST_TEMPLE)) { + dungeonCount++; + } + + if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE)) { + dungeonCount++; + } + + if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE)) { + dungeonCount++; + } + + if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE)) { + dungeonCount++; + } + + if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE)) { + dungeonCount++; + } + + return dungeonCount; +} + void GivePlayerRandoRewardZeldaLightArrowsGift(GlobalContext* globalCtx, RandomizerCheck check) { Player* player = GET_PLAYER(globalCtx); - if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) && LINK_IS_ADULT && + u8 meetsRequirements = 0; + + switch (Randomizer_GetSettingValue(RSK_GANONS_BOSS_KEY)) { + case 7: + if (CheckMedallionCount() >= Randomizer_GetSettingValue(RSK_LACS_MEDALLION_COUNT)) { + meetsRequirements = true; + } + break; + case 8: + if (CheckStoneCount() >= Randomizer_GetSettingValue(RSK_LACS_STONE_COUNT)) { + meetsRequirements = true; + } + break; + case 9: + if ((CheckMedallionCount() + CheckStoneCount()) >= Randomizer_GetSettingValue(RSK_LACS_REWARD_COUNT)) { + meetsRequirements = true; + } + break; + case 10: + if (CheckDungeonCount() >= Randomizer_GetSettingValue(RSK_LACS_DUNGEON_COUNT)) { + meetsRequirements = true; + } + break; + case 11: + if (gSaveContext.inventory.gsTokens >= Randomizer_GetSettingValue(RSK_LACS_TOKEN_COUNT)) { + meetsRequirements = true; + } + break; + default: + if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW)) { + meetsRequirements = true; + } + break; + } + + if (meetsRequirements && LINK_IS_ADULT && (gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_TOKINOMA) && !Flags_GetTreasure(globalCtx, 0x1E) && player != NULL && !Player_InBlockingCsMode(globalCtx, player) && globalCtx->sceneLoadFlag == 0) { diff --git a/soh/src/overlays/actors/ovl_Bg_Gjyo_Bridge/z_bg_gjyo_bridge.c b/soh/src/overlays/actors/ovl_Bg_Gjyo_Bridge/z_bg_gjyo_bridge.c index e3539aaf7..cd8020428 100644 --- a/soh/src/overlays/actors/ovl_Bg_Gjyo_Bridge/z_bg_gjyo_bridge.c +++ b/soh/src/overlays/actors/ovl_Bg_Gjyo_Bridge/z_bg_gjyo_bridge.c @@ -81,92 +81,6 @@ u8 CheckPlayerPosition(Player* player, GlobalContext* globalCtx) { (player->actor.world.pos.z < 1662.0f) && !Gameplay_InCsMode(globalCtx); } -u8 CheckStoneCount() { - u8 stoneCount = 0; - - if (CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)) { - stoneCount++; - } - - if (CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) { - stoneCount++; - } - - if (CHECK_QUEST_ITEM(QUEST_ZORA_SAPPHIRE)) { - stoneCount++; - } - - return stoneCount; -} - -u8 CheckMedallionCount() { - u8 medallionCount = 0; - - if (CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST)) { - medallionCount++; - } - - if (CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) { - medallionCount++; - } - - if (CHECK_QUEST_ITEM(QUEST_MEDALLION_WATER)) { - medallionCount++; - } - - if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW)) { - medallionCount++; - } - - if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT)) { - medallionCount++; - } - - if (CHECK_QUEST_ITEM(QUEST_MEDALLION_LIGHT)) { - medallionCount++; - } - - return medallionCount; -} - -u8 CheckDungeonCount() { - u8 dungeonCount = 0; - - if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE)) { - dungeonCount++; - } - - if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN)) { - dungeonCount++; - } - - if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY)) { - dungeonCount++; - } - - if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FOREST_TEMPLE)) { - dungeonCount++; - } - - if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE)) { - dungeonCount++; - } - - if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE)) { - dungeonCount++; - } - - if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE)) { - dungeonCount++; - } - - if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE)) { - dungeonCount++; - } - - return dungeonCount; -} - void BgGjyoBridge_TriggerCutscene(BgGjyoBridge* this, GlobalContext* globalCtx) { Player* player = GET_PLAYER(globalCtx);