From 6cb373da1a5724b40c96e3382af1ff3c27732c39 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Tue, 19 Mar 2024 19:28:47 -0400 Subject: [PATCH] Makes the Own Dungeon, Any Dungeon, and Overworld options work. --- .../Enhancements/randomizer/3drando/fill.cpp | 13 +++ soh/soh/Enhancements/randomizer/dungeon.cpp | 88 +++++++++++++++---- soh/soh/Enhancements/randomizer/dungeon.h | 14 ++- 3 files changed, 94 insertions(+), 21 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/fill.cpp b/soh/soh/Enhancements/randomizer/3drando/fill.cpp index 7f424f758..b49609a5c 100644 --- a/soh/soh/Enhancements/randomizer/3drando/fill.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/fill.cpp @@ -863,6 +863,11 @@ static void RandomizeOwnDungeon(const Rando::DungeonInfo* dungeon) { AddElementsToPool(dungeonItems, dungeonBossKey); } + if ((ctx->GetOption(RSK_SHUFFLE_SILVER_RUPEES).Is(RO_SILVER_SHUFFLE_OWN_DUNGEON) && dungeon->HasSilverRupees())) { + auto silverRupees = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i){ return dungeon->ContainsSilverRupee(i); }); + AddElementsToPool(dungeonItems, silverRupees); + } + //randomize boss key and small keys together for even distribution AssumedFill(dungeonItems, dungeonLocations); @@ -916,6 +921,14 @@ static void RandomizeDungeonItems() { auto ganonBossKey = FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == RG_GANONS_CASTLE_BOSS_KEY; }); AddElementsToPool(overworldItems, ganonBossKey); } + + if (ctx->GetOption(RSK_SHUFFLE_SILVER_RUPEES).Is(RO_SILVER_SHUFFLE_ANY_DUNGEON)) { + auto silverRupees = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i) { return dungeon->ContainsSilverRupee(i); }); + AddElementsToPool(anyDungeonItems, silverRupees); + } else if (ctx->GetOption(RSK_SHUFFLE_SILVER_RUPEES).Is(RO_SILVER_SHUFFLE_OVERWORLD)) { + auto silverRupees = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i){ return dungeon->ContainsSilverRupee(i); }); + AddElementsToPool(overworldItems, silverRupees); + } } if (ctx->GetOption(RSK_GERUDO_KEYS).Is(RO_GERUDO_KEYS_ANY_DUNGEON)) { diff --git a/soh/soh/Enhancements/randomizer/dungeon.cpp b/soh/soh/Enhancements/randomizer/dungeon.cpp index c15c3d2e7..5ed2fce19 100644 --- a/soh/soh/Enhancements/randomizer/dungeon.cpp +++ b/soh/soh/Enhancements/randomizer/dungeon.cpp @@ -6,12 +6,15 @@ namespace Rando { DungeonInfo::DungeonInfo(std::string name_, const RandomizerHintTextKey hintKey_, const RandomizerGet map_, - const RandomizerGet compass_, const RandomizerGet smallKey_, const RandomizerGet keyRing_, - const RandomizerGet bossKey_, RandomizerArea area_, const uint8_t vanillaKeyCount_, const uint8_t mqKeyCount_, - std::vector vanillaLocations_, std::vector mqLocations_, - std::vector sharedLocations_, std::vector bossRoomLocations_) + const RandomizerGet compass_, const RandomizerGet smallKey_, const RandomizerGet keyRing_, + const RandomizerGet bossKey_, std::unordered_set vanillaSilverRupees_, + std::unordered_set mqSilverRupees_, RandomizerArea area_, + const uint8_t vanillaKeyCount_, const uint8_t mqKeyCount_, + std::vector vanillaLocations_, std::vector mqLocations_, + std::vector sharedLocations_, std::vector bossRoomLocations_) : name(std::move(name_)), hintKey(hintKey_), map(map_), compass(compass_), smallKey(smallKey_), keyRing(keyRing_), - bossKey(bossKey_), area(area_), vanillaKeyCount(vanillaKeyCount_), mqKeyCount(mqKeyCount_), + bossKey(bossKey_), vanillaSilverRupees(std::move(vanillaSilverRupees_)), mqSilverRupees(std::move(mqSilverRupees_)), + area(area_), vanillaKeyCount(vanillaKeyCount_), mqKeyCount(mqKeyCount_), vanillaLocations(std::move(vanillaLocations_)), mqLocations(std::move(mqLocations_)), sharedLocations(std::move(sharedLocations_)), bossRoomLocations(std::move(bossRoomLocations_)) { } @@ -51,6 +54,20 @@ bool DungeonInfo::IsVanilla() const { return !masterQuest; } +bool DungeonInfo::ContainsSilverRupee(RandomizerGet rg) const { + if (masterQuest) { + return mqSilverRupees.contains(rg); + } + return vanillaSilverRupees.contains(rg); +} + +bool DungeonInfo::HasSilverRupees() const { + if (masterQuest) { + return !mqSilverRupees.empty(); + } + return !vanillaSilverRupees.empty(); +} + uint8_t DungeonInfo::GetSmallKeyCount() const { return masterQuest ? mqKeyCount : vanillaKeyCount; } @@ -152,7 +169,7 @@ std::vector DungeonInfo::GetEveryLocation() const { Dungeons::Dungeons() { dungeonList[DEKU_TREE] = - DungeonInfo("Deku Tree", RHT_DEKU_TREE, RG_DEKU_TREE_MAP, RG_DEKU_TREE_COMPASS, RG_NONE, RG_NONE, RG_NONE, RA_DEKU_TREE, 0, 0, + DungeonInfo("Deku Tree", RHT_DEKU_TREE, RG_DEKU_TREE_MAP, RG_DEKU_TREE_COMPASS, RG_NONE, RG_NONE, RG_NONE, {}, {}, RA_DEKU_TREE, 0, 0, { // Vanilla Locations RC_DEKU_TREE_MAP_CHEST, @@ -188,7 +205,7 @@ Dungeons::Dungeons() { RC_QUEEN_GOHMA, }); dungeonList[DODONGOS_CAVERN] = DungeonInfo("Dodongo's Cavern", RHT_DODONGOS_CAVERN, RG_DODONGOS_CAVERN_MAP, - RG_DODONGOS_CAVERN_COMPASS, RG_NONE, RG_NONE, RG_NONE, RA_DODONGOS_CAVERN, 0, 0, + RG_DODONGOS_CAVERN_COMPASS, RG_NONE, RG_NONE, RG_NONE, {}, {RG_DODONGOS_CAVERN_MQ_SILVER_RUPEE}, RA_DODONGOS_CAVERN, 0, 0, { // Vanilla Locations RC_DODONGOS_CAVERN_MAP_CHEST, @@ -237,7 +254,7 @@ Dungeons::Dungeons() { RC_KING_DODONGO, }); dungeonList[JABU_JABUS_BELLY] = DungeonInfo("Jabu Jabu's Belly", RHT_JABU_JABUS_BELLY, RG_JABU_JABUS_BELLY_MAP, - RG_JABU_JABUS_BELLY_COMPASS, RG_NONE, RG_NONE, RG_NONE, RA_JABU_JABUS_BELLY, 0, 0, + RG_JABU_JABUS_BELLY_COMPASS, RG_NONE, RG_NONE, RG_NONE, {}, {}, RA_JABU_JABUS_BELLY, 0, 0, { // Vanilla Locations RC_JABU_JABUS_BELLY_MAP_CHEST, @@ -276,7 +293,7 @@ Dungeons::Dungeons() { }); dungeonList[FOREST_TEMPLE] = DungeonInfo("Forest Temple", RHT_FOREST_TEMPLE, RG_FOREST_TEMPLE_MAP, RG_FOREST_TEMPLE_COMPASS, - RG_FOREST_TEMPLE_SMALL_KEY, RG_FOREST_TEMPLE_KEY_RING, RG_FOREST_TEMPLE_BOSS_KEY, RA_FOREST_TEMPLE, 5, 6, + RG_FOREST_TEMPLE_SMALL_KEY, RG_FOREST_TEMPLE_KEY_RING, RG_FOREST_TEMPLE_BOSS_KEY, {}, {}, RA_FOREST_TEMPLE, 5, 6, { // Vanilla Locations RC_FOREST_TEMPLE_FIRST_ROOM_CHEST, @@ -326,7 +343,7 @@ Dungeons::Dungeons() { }); dungeonList[FIRE_TEMPLE] = DungeonInfo("Fire Temple", RHT_FIRE_TEMPLE, RG_FIRE_TEMPLE_MAP, RG_FIRE_TEMPLE_COMPASS, - RG_FIRE_TEMPLE_SMALL_KEY, RG_FIRE_TEMPLE_KEY_RING, RG_FIRE_TEMPLE_BOSS_KEY, RA_FIRE_TEMPLE, 8, 5, + RG_FIRE_TEMPLE_SMALL_KEY, RG_FIRE_TEMPLE_KEY_RING, RG_FIRE_TEMPLE_BOSS_KEY, {}, {}, RA_FIRE_TEMPLE, 8, 5, { // Vanilla Locations RC_FIRE_TEMPLE_NEAR_BOSS_CHEST, @@ -377,7 +394,7 @@ Dungeons::Dungeons() { }); dungeonList[WATER_TEMPLE] = DungeonInfo("Water Temple", RHT_WATER_TEMPLE, RG_WATER_TEMPLE_MAP, RG_WATER_TEMPLE_COMPASS, - RG_WATER_TEMPLE_SMALL_KEY, RG_WATER_TEMPLE_KEY_RING, RG_WATER_TEMPLE_BOSS_KEY, RA_WATER_TEMPLE, 6, 2, + RG_WATER_TEMPLE_SMALL_KEY, RG_WATER_TEMPLE_KEY_RING, RG_WATER_TEMPLE_BOSS_KEY, {}, {}, RA_WATER_TEMPLE, 6, 2, { // Vanilla Locations RC_WATER_TEMPLE_MAP_CHEST, @@ -418,7 +435,13 @@ Dungeons::Dungeons() { }); dungeonList[SPIRIT_TEMPLE] = DungeonInfo("Spirit Temple", RHT_SPIRIT_TEMPLE, RG_SPIRIT_TEMPLE_MAP, RG_SPIRIT_TEMPLE_COMPASS, - RG_SPIRIT_TEMPLE_SMALL_KEY, RG_SPIRIT_TEMPLE_KEY_RING, RG_SPIRIT_TEMPLE_BOSS_KEY, RA_SPIRIT_TEMPLE, 5, 7, + RG_SPIRIT_TEMPLE_SMALL_KEY, RG_SPIRIT_TEMPLE_KEY_RING, RG_SPIRIT_TEMPLE_BOSS_KEY, { + RG_SPIRIT_CHILD_BLOCK_PUSH_SILVER_RUPEE, + RG_SPIRIT_BOULDER_SILVER_RUPEE, + RG_SPIRIT_CHILD_GATE_SILVER_RUPEE, + }, { + RG_SPIRIT_MQ_LOBBY_SILVER_RUPEE, + }, RA_SPIRIT_TEMPLE, 5, 7, { // Vanilla Locations RC_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, @@ -504,7 +527,16 @@ Dungeons::Dungeons() { }); dungeonList[SHADOW_TEMPLE] = DungeonInfo("Shadow Temple", RHT_SHADOW_TEMPLE, RG_SHADOW_TEMPLE_MAP, RG_SHADOW_TEMPLE_COMPASS, - RG_SHADOW_TEMPLE_SMALL_KEY, RG_SHADOW_TEMPLE_KEY_RING, RG_SHADOW_TEMPLE_BOSS_KEY, RA_SHADOW_TEMPLE, 5, 6, + RG_SHADOW_TEMPLE_SMALL_KEY, RG_SHADOW_TEMPLE_KEY_RING, RG_SHADOW_TEMPLE_BOSS_KEY, { + RG_SHADOW_SCYTHE_SILVER_RUPEE, + RG_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE, + RG_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE, + }, { + RG_SHADOW_MQ_SCYTHE_SILVER_RUPEE, + RG_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE, + RG_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE, + RG_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE, + }, RA_SHADOW_TEMPLE, 5, 6, { // Vanilla Locations RC_SHADOW_TEMPLE_MAP_CHEST, @@ -611,7 +643,9 @@ Dungeons::Dungeons() { }); dungeonList[BOTTOM_OF_THE_WELL] = DungeonInfo( "Bottom of the Well", RHT_BOTTOM_OF_THE_WELL, RG_BOTTOM_OF_THE_WELL_MAP, RG_BOTTOM_OF_THE_WELL_COMPASS, - RG_BOTTOM_OF_THE_WELL_SMALL_KEY, RG_BOTTOM_OF_THE_WELL_KEY_RING, RG_NONE, RA_BOTTOM_OF_THE_WELL, 3, 2, + RG_BOTTOM_OF_THE_WELL_SMALL_KEY, RG_BOTTOM_OF_THE_WELL_KEY_RING, RG_NONE, { + RG_BOTTOM_OF_THE_WELL_SILVER_RUPEE, + }, {}, RA_BOTTOM_OF_THE_WELL, 3, 2, { // Vanilla Locations RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, @@ -650,7 +684,10 @@ Dungeons::Dungeons() { }, {}, {}); dungeonList[ICE_CAVERN] = DungeonInfo("Ice Cavern", RHT_ICE_CAVERN, RG_ICE_CAVERN_MAP, RG_ICE_CAVERN_COMPASS, - RG_NONE, RG_NONE, RG_NONE, RA_ICE_CAVERN, 0, 0, + RG_NONE, RG_NONE, RG_NONE,{ + RG_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE, + RG_ICE_CAVERN_SLIDING_SILVER_RUPEE, + }, {}, RA_ICE_CAVERN, 0, 0, { // Vanilla Locations RC_ICE_CAVERN_MAP_CHEST, @@ -688,7 +725,15 @@ Dungeons::Dungeons() { {}); dungeonList[GERUDO_TRAINING_GROUNDS] = DungeonInfo("Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, RG_NONE, RG_NONE, - RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, RG_GERUDO_TRAINING_GROUNDS_KEY_RING, RG_NONE, RA_GERUDO_TRAINING_GROUND, 9, 3, + RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, RG_GERUDO_TRAINING_GROUNDS_KEY_RING, RG_NONE, { + RG_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE, + RG_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE, + RG_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE, + }, { + RG_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE, + RG_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE, + RG_GERUDO_TRAINING_GROUNDS_MQ_TOILET_SILVER_RUPEE, + }, RA_GERUDO_TRAINING_GROUND, 9, 3, { // Vanilla Locations RC_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST, @@ -766,7 +811,16 @@ Dungeons::Dungeons() { {}, {}); dungeonList[GANONS_CASTLE] = DungeonInfo("Ganon's Castle", RHT_GANONS_CASTLE, RG_NONE, RG_NONE, RG_GANONS_CASTLE_SMALL_KEY, - RG_GANONS_CASTLE_KEY_RING, RG_GANONS_CASTLE_BOSS_KEY, RA_GANONS_CASTLE, 2, 3, + RG_GANONS_CASTLE_KEY_RING, RG_GANONS_CASTLE_BOSS_KEY, { + RG_FOREST_TRIAL_SILVER_RUPEE, + RG_FIRE_TRIAL_SILVER_RUPEE, + RG_SPIRIT_TRIAL_SILVER_RUPEE, + RG_LIGHT_TRIAL_SILVER_RUPEE, + }, { + RG_FIRE_TRIAL_MQ_SILVER_RUPEE, + RG_WATER_TRIAL_MQ_SILVER_RUPEE, + RG_SHADOW_TRIAL_MQ_SILVER_RUPEE, + }, RA_GANONS_CASTLE, 2, 3, { // Vanilla Locations RC_GANONS_CASTLE_FOREST_TRIAL_CHEST, diff --git a/soh/soh/Enhancements/randomizer/dungeon.h b/soh/soh/Enhancements/randomizer/dungeon.h index a2338441d..7a470ea54 100644 --- a/soh/soh/Enhancements/randomizer/dungeon.h +++ b/soh/soh/Enhancements/randomizer/dungeon.h @@ -6,15 +6,17 @@ #include #include #include "nlohmann/json.hpp" +#include namespace Rando { class DungeonInfo { public: DungeonInfo(std::string name_, RandomizerHintTextKey hintKey_, RandomizerGet map_, RandomizerGet compass_, - RandomizerGet smallKey_, RandomizerGet keyRing_, RandomizerGet bossKey_, RandomizerArea area_, - uint8_t vanillaKeyCount_, uint8_t mqKeyCount_, std::vector vanillaLocations_, - std::vector mqLocations_, std::vector sharedLocations_, - std::vector bossRoomLocations_); + RandomizerGet smallKey_, RandomizerGet keyRing_, RandomizerGet bossKey_, + std::unordered_set vanillaSilverRupees_, std::unordered_set mqSilverRupees_, + RandomizerArea area_, uint8_t vanillaKeyCount_, uint8_t mqKeyCount_, + std::vector vanillaLocations_, std::vector mqLocations_, + std::vector sharedLocations_, std::vector bossRoomLocations_); DungeonInfo(); ~DungeonInfo(); @@ -26,6 +28,8 @@ class DungeonInfo { void ClearKeyRing(); bool HasKeyRing() const; bool IsVanilla() const; + bool ContainsSilverRupee(RandomizerGet rg) const; + bool HasSilverRupees() const; uint8_t GetSmallKeyCount() const; RandomizerHintTextKey GetHintKey() const; RandomizerArea GetArea() const; @@ -50,6 +54,8 @@ class DungeonInfo { RandomizerGet smallKey; RandomizerGet keyRing; RandomizerGet bossKey; + std::unordered_set vanillaSilverRupees; + std::unordered_set mqSilverRupees; uint8_t vanillaKeyCount{}; uint8_t mqKeyCount{}; bool masterQuest = false;