From 7b998d1f8b2346fcf7fd90b0196b2831dc6ad652 Mon Sep 17 00:00:00 2001 From: Demur Rumed Date: Sun, 29 Jun 2025 04:05:01 +0000 Subject: [PATCH] Ganon's Boss Soul Instead --- .../Enhancements/randomizer/3drando/fill.cpp | 30 +++++++++---------- .../randomizer/3drando/item_pool.cpp | 9 +++--- .../randomizer/3drando/starting_inventory.cpp | 2 +- soh/soh/Enhancements/randomizer/entrance.cpp | 21 +++++++++++-- soh/soh/Enhancements/randomizer/entrance.h | 1 + .../Enhancements/randomizer/hook_handlers.cpp | 11 ++++--- soh/soh/Enhancements/randomizer/item.cpp | 22 ++++++++------ .../dungeons/ganons_castle.cpp | 2 ++ .../randomizer/option_descriptions.cpp | 3 ++ .../Enhancements/randomizer/randomizerTypes.h | 1 + .../randomizer_entrance_tracker.cpp | 5 +++- soh/soh/Enhancements/randomizer/settings.cpp | 3 ++ 12 files changed, 74 insertions(+), 36 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/fill.cpp b/soh/soh/Enhancements/randomizer/3drando/fill.cpp index 2ac5a3592..978411731 100644 --- a/soh/soh/Enhancements/randomizer/3drando/fill.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/fill.cpp @@ -9,7 +9,6 @@ #include "hints.hpp" #include "shops.hpp" #include "pool_functions.hpp" -//#include "debug.hpp" #include "soh/Enhancements/randomizer/static_data.h" #include "soh/Enhancements/debugger/performanceTimer.h" @@ -1058,10 +1057,9 @@ static void RandomizeOwnDungeon(const Rando::DungeonInfo* dungeon) { AddElementsToPool(dungeonItems, dungeonSmallKeys); } - if ((ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) && - dungeon->GetBossKey() != RG_GANONS_CASTLE_BOSS_KEY) || - (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_OWN_DUNGEON) && - dungeon->GetBossKey() == RG_GANONS_CASTLE_BOSS_KEY)) { + if (ctx->GetOption(RSK_GANONS_SOUL) || dungeon->GetBossKey() != RG_GANONS_CASTLE_BOSS_KEY + ? ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) + : ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_OWN_DUNGEON)) { auto dungeonBossKey = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i) { return i == dungeon->GetBossKey(); }); AddElementsToPool(dungeonItems, dungeonBossKey); @@ -1112,25 +1110,27 @@ static void RandomizeDungeonItems() { } if (ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON) && - dungeon->GetBossKey() != RG_GANONS_CASTLE_BOSS_KEY) { + (ctx->GetOption(RSK_GANONS_SOUL) || dungeon->GetBossKey() != RG_GANONS_CASTLE_BOSS_KEY)) { auto bossKey = FilterAndEraseFromPool( ItemPool, [dungeon](const RandomizerGet i) { return i == dungeon->GetBossKey(); }); AddElementsToPool(anyDungeonItems, bossKey); } else if (ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OVERWORLD) && - dungeon->GetBossKey() != RG_GANONS_CASTLE_BOSS_KEY) { + (ctx->GetOption(RSK_GANONS_SOUL) || dungeon->GetBossKey() != RG_GANONS_CASTLE_BOSS_KEY)) { auto bossKey = FilterAndEraseFromPool( ItemPool, [dungeon](const RandomizerGet i) { return i == dungeon->GetBossKey(); }); AddElementsToPool(overworldItems, bossKey); } - if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_ANY_DUNGEON)) { - auto ganonBossKey = - FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == RG_GANONS_CASTLE_BOSS_KEY; }); - AddElementsToPool(anyDungeonItems, ganonBossKey); - } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_OVERWORLD)) { - auto ganonBossKey = - FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == RG_GANONS_CASTLE_BOSS_KEY; }); - AddElementsToPool(overworldItems, ganonBossKey); + if (!ctx->GetOption(RSK_GANONS_SOUL)) { + if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_ANY_DUNGEON)) { + auto ganonBossKey = + FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == RG_GANONS_CASTLE_BOSS_KEY; }); + AddElementsToPool(anyDungeonItems, ganonBossKey); + } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_OVERWORLD)) { + auto ganonBossKey = + FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == RG_GANONS_CASTLE_BOSS_KEY; }); + AddElementsToPool(overworldItems, ganonBossKey); + } } } diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp index c97ae35ce..fb3b0ede3 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -1199,14 +1199,15 @@ void GenerateItemPool() { } if (!ctx->GetOption(RSK_TRIFORCE_HUNT)) { // Don't add GBK to the pool at all for Triforce Hunt. + auto rg = ctx->GetOption(RSK_GANONS_SOUL) ? RG_GANON_SOUL : RG_GANONS_CASTLE_BOSS_KEY; if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_KAK_TOKENS)) { - ctx->PlaceItemInLocation(RC_KAK_100_GOLD_SKULLTULA_REWARD, RG_GANONS_CASTLE_BOSS_KEY); + ctx->PlaceItemInLocation(RC_KAK_100_GOLD_SKULLTULA_REWARD, rg); } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Get() >= RO_GANON_BOSS_KEY_LACS_VANILLA) { - ctx->PlaceItemInLocation(RC_TOT_LIGHT_ARROWS_CUTSCENE, RG_GANONS_CASTLE_BOSS_KEY); + ctx->PlaceItemInLocation(RC_TOT_LIGHT_ARROWS_CUTSCENE, rg); } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_VANILLA)) { - ctx->PlaceItemInLocation(RC_GANONS_TOWER_BOSS_KEY_CHEST, RG_GANONS_CASTLE_BOSS_KEY); + ctx->PlaceItemInLocation(RC_GANONS_TOWER_BOSS_KEY_CHEST, rg); } else { - AddItemToMainPool(RG_GANONS_CASTLE_BOSS_KEY); + AddItemToMainPool(rg); } } diff --git a/soh/soh/Enhancements/randomizer/3drando/starting_inventory.cpp b/soh/soh/Enhancements/randomizer/3drando/starting_inventory.cpp index dda37b18a..fd154abfb 100644 --- a/soh/soh/Enhancements/randomizer/3drando/starting_inventory.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/starting_inventory.cpp @@ -57,7 +57,7 @@ void GenerateStartingInventory() { // Add Ganon's Boss key with Triforce Hunt so the game thinks it's obtainable from the start. // During save init, the boss key isn't actually given and it's instead given when completing the triforce. if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_STARTWITH) || ctx->GetOption(RSK_TRIFORCE_HUNT)) { - AddItemToInventory(RG_GANONS_CASTLE_BOSS_KEY); + AddItemToInventory(ctx->GetOption(RSK_GANONS_SOUL) ? RG_GANON_SOUL : RG_GANONS_CASTLE_BOSS_KEY); } if (ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE) && diff --git a/soh/soh/Enhancements/randomizer/entrance.cpp b/soh/soh/Enhancements/randomizer/entrance.cpp index 00a7a5adb..406a1ad27 100644 --- a/soh/soh/Enhancements/randomizer/entrance.cpp +++ b/soh/soh/Enhancements/randomizer/entrance.cpp @@ -543,6 +543,9 @@ void SetAllEntrancesData() { { EntranceType::AdultBoss, RR_SPIRIT_TEMPLE_BOSS_ROOM, RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, ENTR_SPIRIT_TEMPLE_BOSS_DOOR } }, { { EntranceType::AdultBoss, RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, RR_SHADOW_TEMPLE_BOSS_ROOM, ENTR_SHADOW_TEMPLE_BOSS_ENTRANCE }, { EntranceType::AdultBoss, RR_SHADOW_TEMPLE_BOSS_ROOM, RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, ENTR_SHADOW_TEMPLE_BOSS_DOOR } }, + + { { EntranceType::GanonBoss, RR_GANONS_TOWER_BEFORE_GANONDORF_LAIR, RR_GANONS_TOWER_GANONDORF_LAIR, ENTR_GANONDORF_BOSS_0 }, + { EntranceType::GanonBoss, RR_GANONS_TOWER_GANONDORF_LAIR, RR_GANONS_TOWER_BEFORE_GANONDORF_LAIR, ENTR_GANONS_TOWER_2 } }, { { EntranceType::BlueWarp, RR_DEKU_TREE_BOSS_ROOM, RR_KF_OUTSIDE_DEKU_TREE, ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP }, NO_RETURN_ENTRANCE }, @@ -560,6 +563,8 @@ void SetAllEntrancesData() { NO_RETURN_ENTRANCE }, { { EntranceType::BlueWarp, RR_SHADOW_TEMPLE_BOSS_ROOM, RR_GRAVEYARD_WARP_PAD_REGION, ENTR_GRAVEYARD_SHADOW_TEMPLE_BLUE_WARP }, NO_RETURN_ENTRANCE }, + { { EntranceType::BlueWarp, RR_GANONS_TOWER_GANONDORF_LAIR, RR_GANONS_TOWER_FLOOR_1, ENTR_GANONS_TOWER_0 }, + NO_RETURN_ENTRANCE }, // clang-format on }; @@ -760,7 +765,7 @@ static bool EntranceUnreachableAs(Entrance* entrance, uint8_t age, std::vectorGetOption(RSK_SHUFFLE_BOSS_ENTRANCES).Is(RO_BOSS_ROOM_ENTRANCE_SHUFFLE_FULL)) { entrancePools[EntranceType::Boss] = GetShuffleableEntrances(EntranceType::ChildBoss); AddElementsToPool(entrancePools[EntranceType::Boss], GetShuffleableEntrances(EntranceType::AdultBoss)); + if (ctx->GetOption(RSK_GANONS_SOUL)) { + AddElementsToPool(entrancePools[EntranceType::Boss], GetShuffleableEntrances(EntranceType::GanonBoss)); + } // If forest is closed, ensure Ghoma is inside the Deku tree // Deku tree being in its vanilla location is handled below if (ctx->GetOption(RSK_FOREST).Is(RO_CLOSED_FOREST_ON) && @@ -1231,6 +1239,10 @@ int EntranceShuffler::ShuffleAllEntrances() { } else { entrancePools[EntranceType::ChildBoss] = GetShuffleableEntrances(EntranceType::ChildBoss); entrancePools[EntranceType::AdultBoss] = GetShuffleableEntrances(EntranceType::AdultBoss); + if (ctx->GetOption(RSK_GANONS_SOUL)) { + AddElementsToPool(entrancePools[EntranceType::AdultBoss], + GetShuffleableEntrances(EntranceType::GanonBoss)); + } // If forest is closed, ensure Ghoma is inside the Deku tree if (ctx->GetOption(RSK_FOREST).Is(RO_CLOSED_FOREST_ON) && !(ctx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES) || ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES))) { @@ -1506,6 +1518,8 @@ int EntranceShuffler::ShuffleAllEntrances() { GetEntrance(RR_SPIRIT_TEMPLE_ENTRYWAY, RR_DESERT_COLOSSUS_OUTSIDE_TEMPLE) }, { EntranceNameByRegions(RR_SHADOW_TEMPLE_BOSS_ROOM, RR_SHADOW_TEMPLE_BOSS_ENTRYWAY), GetEntrance(RR_SHADOW_TEMPLE_ENTRYWAY, RR_GRAVEYARD_WARP_PAD_REGION) }, + { EntranceNameByRegions(RR_GANONS_TOWER_GANONDORF_LAIR, RR_GANONS_TOWER_BEFORE_GANONDORF_LAIR), + GetEntrance(RR_GANONS_TOWER_ENTRYWAY, RR_GANONS_TOWER_FLOOR_1) }, }; // If a boss room is inside a dungeon entrance (or inside a dungeon which is inside a dungeon entrance), make @@ -1527,6 +1541,8 @@ int EntranceShuffler::ShuffleAllEntrances() { GetEntrance(RR_SPIRIT_TEMPLE_BOSS_ROOM, RR_DESERT_COLOSSUS) }, { EntranceNameByRegions(RR_SHADOW_TEMPLE_ENTRYWAY, RR_GRAVEYARD_WARP_PAD_REGION), GetEntrance(RR_SHADOW_TEMPLE_BOSS_ROOM, RR_GRAVEYARD_WARP_PAD_REGION) }, + { EntranceNameByRegions(RR_GANONS_TOWER_ENTRYWAY, RR_GANONS_TOWER_FLOOR_1), + GetEntrance(RR_GANONS_TOWER_GANONDORF_LAIR, RR_GANONS_TOWER_FLOOR_1) }, }; // Pair @@ -1547,6 +1563,8 @@ int EntranceShuffler::ShuffleAllEntrances() { GetEntrance(RR_SPIRIT_TEMPLE_BOSS_ROOM, RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY) }, { GetEntrance(RR_SHADOW_TEMPLE_BOSS_ROOM, RR_GRAVEYARD_WARP_PAD_REGION), GetEntrance(RR_SHADOW_TEMPLE_BOSS_ROOM, RR_SHADOW_TEMPLE_BOSS_ENTRYWAY) }, + { GetEntrance(RR_GANONS_TOWER_GANONDORF_LAIR, RR_GANONS_TOWER_FLOOR_1), + GetEntrance(RR_GANONS_TOWER_GANONDORF_LAIR, RR_GANONS_TOWER_BEFORE_GANONDORF_LAIR) }, }; for (EntrancePair pair : bossRoomExitPairs) { @@ -1587,7 +1605,6 @@ void EntranceShuffler::CreateEntranceOverrides() { int i = 0; for (Entrance* entrance : allShuffleableEntrances) { - // Include blue warps when dungeons or bosses are shuffled bool includeBluewarps = entrance->GetType() == Rando::EntranceType::BlueWarp && diff --git a/soh/soh/Enhancements/randomizer/entrance.h b/soh/soh/Enhancements/randomizer/entrance.h index 5b14611fe..88706e46b 100644 --- a/soh/soh/Enhancements/randomizer/entrance.h +++ b/soh/soh/Enhancements/randomizer/entrance.h @@ -25,6 +25,7 @@ enum class EntranceType { ChildBossReverse, AdultBoss, AdultBossReverse, + GanonBoss, Interior, InteriorReverse, SpecialInterior, diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 92d210300..dd02d2bba 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -2008,7 +2008,9 @@ void RandomizerOnActorInitHandler(void* actorRef) { Actor_Kill(actor); } - if (RAND_GET_OPTION(RSK_SHUFFLE_BOSS_SOULS)) { + if (RAND_GET_OPTION(RSK_SHUFFLE_BOSS_SOULS) || + (RAND_GET_OPTION(RSK_GANONS_SOUL) && gPlayState->sceneNum == SCENE_GANONDORF_BOSS || + gPlayState->sceneNum == SCENE_GANON_BOSS)) { // Boss souls require an additional item (represented by a RAND_INF) to spawn a boss in a particular lair RandomizerInf currentBossSoulRandInf = RAND_INF_MAX; switch (gPlayState->sceneNum) { @@ -2038,7 +2040,8 @@ void RandomizerOnActorInitHandler(void* actorRef) { break; case SCENE_GANONDORF_BOSS: case SCENE_GANON_BOSS: - if (RAND_GET_OPTION(RSK_SHUFFLE_BOSS_SOULS) == RO_BOSS_SOULS_ON_PLUS_GANON) { + if (RAND_GET_OPTION(RSK_GANONS_SOUL) || + RAND_GET_OPTION(RSK_SHUFFLE_BOSS_SOULS) == RO_BOSS_SOULS_ON_PLUS_GANON) { currentBossSoulRandInf = RAND_INF_GANON_SOUL; } break; @@ -2218,8 +2221,8 @@ void RandomizerOnPlayerUpdateHandler() { if (!GameInteractor::IsGameplayPaused() && Flags_GetRandomizerInf(RAND_INF_GRANT_GANONS_BOSSKEY) && gPlayState->transitionTrigger != TRANS_TRIGGER_START && (1 << 0 & gSaveContext.inventory.dungeonItems[SCENE_GANONS_TOWER]) == 0) { - GiveItemEntryWithoutActor(gPlayState, - *Rando::StaticData::GetItemTable().at(RG_GANONS_CASTLE_BOSS_KEY).GetGIEntry()); + auto rg = RAND_GET_OPTION(RSK_GANONS_SOUL) ? RG_GANON_SOUL : RG_GANONS_CASTLE_BOSS_KEY; + GiveItemEntryWithoutActor(gPlayState, *Rando::StaticData::GetItemTable().at(rg).GetGIEntry()); } if (!GameInteractor::IsGameplayPaused() && RAND_GET_OPTION(RSK_TRIFORCE_HUNT)) { diff --git a/soh/soh/Enhancements/randomizer/item.cpp b/soh/soh/Enhancements/randomizer/item.cpp index 3b75a0c95..05830d640 100644 --- a/soh/soh/Enhancements/randomizer/item.cpp +++ b/soh/soh/Enhancements/randomizer/item.cpp @@ -430,15 +430,19 @@ bool Item::IsMajorItem() const { return false; } - if (type == ITEMTYPE_BOSSKEY && getItemId != 0xAD && - (ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_VANILLA) || - ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON))) { - return false; - } - // Ganons Castle Boss Key - if (getItemId == 0xAD && (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_VANILLA) || - ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_OWN_DUNGEON))) { - return false; + if (type == ITEMTYPE_BOSSKEY) { + if (getItemId == 0xAD && !ctx->GetOption(RSK_GANONS_SOUL)) { + // Ganons Castle Boss Key handled specially unless Ganon's Soul is wincon reward + if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_VANILLA) || + ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_OWN_DUNGEON)) { + return false; + } + } else { + if (ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_VANILLA) || + ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON)) { + return false; + } + } } if (randomizerGet == RG_GREG_RUPEE) { diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp index 8571ba384..8e1a030d4 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp @@ -487,6 +487,8 @@ void RegionTable_Init_GanonsCastle() { }, { //Exits Entrance(RR_GANONS_CASTLE_ESCAPE, []{return logic->CanKillEnemy(RE_GANONDORF);}), + Entrance(RR_GANONS_TOWER_BEFORE_GANONDORF_LAIR, []{return false;}), + Entrance(RR_GANONS_TOWER_FLOOR_1, []{return false;}), }); areaTable[RR_GANONS_CASTLE_ESCAPE] = Region("Ganon's Castle Escape", SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR, {}, { diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index 16c89a1c4..e6f82247c 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -595,6 +595,9 @@ void Settings::CreateOptionDescriptions() { "\n" "Greg as Wildcard - Greg does not change logic, Greg helps obtain GBK, max number of " "rewards on slider does not change."; + mOptionDescriptions[RSK_GANONS_SOUL] = "Ganon's Boss Key reward replaced with Ganon's Soul.\n" + "GBK will be shuffled like a regular boss key.\n" + "Ganon's Tower's boss entrance may be shuffled."; mOptionDescriptions[RSK_BIG_POE_COUNT] = "The Poe collector will give a reward for turning in this many Big Poes."; mOptionDescriptions[RSK_SKIP_CHILD_STEALTH] = "The crawlspace into Hyrule Castle goes straight to Zelda, skipping the guards."; diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 8295eb6cd..e864e4395 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -5851,6 +5851,7 @@ typedef enum { RSK_GERUDO_KEYS, RSK_BOSS_KEYSANITY, RSK_GANONS_BOSS_KEY, + RSK_GANONS_SOUL, RSK_SKIP_CHILD_STEALTH, RSK_SKIP_CHILD_ZELDA, RSK_STARTING_STICKS, diff --git a/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.cpp index 1a635f58e..32dd81644 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.cpp @@ -380,7 +380,10 @@ const EntranceData entranceData[] = { { ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_OGC_DD, ENTR_POTION_SHOP_KAKARIKO_1, SINGLE_SCENE_INFO(SCENE_OUTSIDE_GANONS_CASTLE), "OGC Behind Pillar", "OGC Great Fairy Fountain", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_INTERIOR, "outside ganon's castle", 1}, { ENTR_INSIDE_GANONS_CASTLE_ENTRANCE, ENTR_CASTLE_GROUNDS_RAINBOW_BRIDGE_EXIT, SINGLE_SCENE_INFO(SCENE_OUTSIDE_GANONS_CASTLE), "OGC Rainbow Bridge Exit", "Inside Ganon's Castle Entrance", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_DUNGEON, "outside ganon's castle,gc", 1}, { ENTR_POTION_SHOP_KAKARIKO_1, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_OGC_DD, {{ SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 0x02 }}, "OGC Great Fairy Fountain", "OGC Behind Pillar", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_INTERIOR, "outside ganon's castle"}, - { ENTR_CASTLE_GROUNDS_RAINBOW_BRIDGE_EXIT, ENTR_INSIDE_GANONS_CASTLE_ENTRANCE, SINGLE_SCENE_INFO(SCENE_INSIDE_GANONS_CASTLE), "Inside Ganon's Castle Entrance", "OGC Rainbow Bridge Exit", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_DUNGEON, "outside ganon's castle,gc"} + { ENTR_CASTLE_GROUNDS_RAINBOW_BRIDGE_EXIT, ENTR_INSIDE_GANONS_CASTLE_ENTRANCE, SINGLE_SCENE_INFO(SCENE_INSIDE_GANONS_CASTLE), "Inside Ganon's Castle Entrance", "OGC Rainbow Bridge Exit", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_DUNGEON, "outside ganon's castle,gc"}, + { ENTR_GANONDORF_BOSS_0, ENTR_GANONS_TOWER_2, SINGLE_SCENE_INFO(SCENE_GANONS_TOWER), "Ganon's Tower Boss Door", "Ganondorf", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_DUNGEON, "", 1}, + { ENTR_GANONS_TOWER_2, ENTR_GANONDORF_BOSS_0, SINGLE_SCENE_INFO(SCENE_GANONDORF_BOSS), "Ganondorf", "Ganon's Tower Boss Door", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_DUNGEON, "", 1}, + { ENTR_GANONS_TOWER_0, -1, SINGLE_SCENE_INFO(SCENE_GANONDORF_BOSS), "Ganondorf Blue Warp", "Ganon's Tower Blue Warp", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_ONE_WAY, "bw", 1}, // clang-format on }; diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index 52add036e..8d30a4857 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -251,6 +251,7 @@ void Settings::CreateOptions() { OPT_U8(RSK_LACS_DUNGEON_COUNT, "GCBK Dungeon Count", {NumOpts(0, 9)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsDungeonCount"), "", WidgetType::Slider, 8, true); OPT_U8(RSK_LACS_TOKEN_COUNT, "GCBK Token Count", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsTokenCount"), "", WidgetType::Slider, 100, true); OPT_U8(RSK_LACS_OPTIONS, "GCBK LACS Reward Options", {"Standard Reward", "Greg as Reward", "Greg as Wildcard"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsRewardOptions"), mOptionDescriptions[RSK_LACS_OPTIONS], WidgetType::Combobox, RO_LACS_STANDARD_REWARD); + OPT_BOOL(RSK_GANONS_SOUL, "Ganon's Soul Instead", CVAR_RANDOMIZER_SETTING("ShuffleGanonSoul"), mOptionDescriptions[RSK_GANONS_SOUL]); OPT_U8(RSK_KEYRINGS, "Key Rings", {"Off", "Random", "Count", "Selection"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRings"), mOptionDescriptions[RSK_KEYRINGS], WidgetType::Combobox, RO_KEYRINGS_OFF); OPT_U8(RSK_KEYRINGS_RANDOM_COUNT, "Keyring Dungeon Count", {NumOpts(0, 9)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsRandomCount"), "", WidgetType::Slider, 8); OPT_U8(RSK_KEYRINGS_GERUDO_FORTRESS, "Gerudo Fortress Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGerudoFortress"), "", WidgetType::Combobox, 0); @@ -1305,6 +1306,7 @@ void Settings::CreateOptions() { &mOptions[RSK_GERUDO_KEYS], &mOptions[RSK_BOSS_KEYSANITY], &mOptions[RSK_GANONS_BOSS_KEY], + &mOptions[RSK_GANONS_SOUL], &mOptions[RSK_LACS_STONE_COUNT], &mOptions[RSK_LACS_MEDALLION_COUNT], &mOptions[RSK_LACS_DUNGEON_COUNT], @@ -1543,6 +1545,7 @@ void Settings::CreateOptions() { &mOptions[RSK_GERUDO_KEYS], &mOptions[RSK_BOSS_KEYSANITY], &mOptions[RSK_GANONS_BOSS_KEY], + &mOptions[RSK_GANONS_SOUL], &mOptions[RSK_LACS_STONE_COUNT], &mOptions[RSK_LACS_MEDALLION_COUNT], &mOptions[RSK_LACS_DUNGEON_COUNT],