summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Dubé <serprex@users.noreply.github.com>2025-01-01 20:26:41 +0000
committerGitHub <noreply@github.com>2025-01-01 13:26:41 -0700
commit4c6a2a4b64622ccbdb46e4476ea50d67957cc525 (patch)
tree6fd1df34b94c7ff4f56976e43b0e659e0f4d4000
parent21e55563b47e637ac2c5aa2ec2c258cc9e09e529 (diff)
fix potsanity looking at deku tree MQness when dealing with pots between quests (#4773)
* fix potsanity looking at deku tree MQness when dealing with pots between dungeons also don't need a loop for a range check * share logic between placing freestanding & pots * fix settings typo * fix all freestanding items still being shuffled this reinstates original freestanding method of filling in unused locations, but also extend logic so that when only dungeons have freestanding shuffled we don't render overworld freestanding as 3d versions until collected * lift optimization check
-rw-r--r--soh/soh/Enhancements/randomizer/3drando/item_pool.cpp92
-rw-r--r--soh/soh/Enhancements/randomizer/hook_handlers.cpp17
-rw-r--r--soh/soh/Enhancements/randomizer/settings.cpp2
3 files changed, 57 insertions, 54 deletions
diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp
index a2562c99e..1a931b47a 100644
--- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp
@@ -624,25 +624,37 @@ static void PlaceVanillaOverworldFish() {
}
}
-static void PlaceFreestandingItems() {
- auto ctx = Rando::Context::GetInstance();
- auto option = ctx->GetOption(RSK_SHUFFLE_FREESTANDING);
- for (RandomizerCheck loc : ctx->GetLocations(ctx->allLocations, RCTYPE_FREESTANDING)) {
- RandomizerGet vanillaItem = Rando::StaticData::GetLocation(loc)->GetVanillaItem();
- if (option.Is(RO_FREESTANDING_OVERWORLD) || option.Is(RO_FREESTANDING_ALL)) {
- AddItemToMainPool(vanillaItem);
+static void PlaceItemsForType(RandomizerCheckType rctype, bool overworldActive, bool dungeonActive, bool placeVanilla) {
+ for (RandomizerCheck rc : ctx->GetLocations(ctx->allLocations, rctype)) {
+ auto loc = Rando::StaticData::GetLocation(rc);
+
+ // If item is in the overworld and shuffled, add its item to the pool
+ if (loc->IsOverworld()) {
+ if (overworldActive) {
+ AddItemToMainPool(loc->GetVanillaItem());
+ } else if (placeVanilla) {
+ ctx->PlaceItemInLocation(rc, loc->GetVanillaItem(), false, true);
+ }
} else {
- ctx->PlaceItemInLocation(loc, vanillaItem, false, true);
- }
- }
+ if (dungeonActive) {
+ // If the same in MQ and vanilla, add.
+ RandomizerCheckQuest currentQuest = loc->GetQuest();
+ if (currentQuest == RCQUEST_BOTH) {
+ AddItemToMainPool(loc->GetVanillaItem());
+ } else {
+ // Check if current item's dungeon is vanilla or MQ, and only add if quest corresponds to it.
+ SceneID itemScene = loc->GetScene();
- for (auto dungeon : ctx->GetDungeons()->GetDungeonList()) {
- for (RandomizerCheck loc : ctx->GetLocations(dungeon->GetDungeonLocations(), RCTYPE_FREESTANDING)) {
- RandomizerGet vanillaItem = Rando::StaticData::GetLocation(loc)->GetVanillaItem();
- if (option.Is(RO_FREESTANDING_DUNGEONS) || option.Is(RO_FREESTANDING_ALL)) {
- AddItemToMainPool(vanillaItem);
- } else {
- ctx->PlaceItemInLocation(loc, vanillaItem, false, true);
+ if (itemScene >= SCENE_DEKU_TREE && itemScene <= SCENE_GERUDO_TRAINING_GROUND) {
+ bool isMQ = ctx->GetDungeon(itemScene)->IsMQ();
+
+ if ((isMQ && currentQuest == RCQUEST_MQ) || (!isMQ && currentQuest == RCQUEST_VANILLA)) {
+ AddItemToMainPool(loc->GetVanillaItem());
+ }
+ }
+ }
+ } else if (placeVanilla) {
+ ctx->PlaceItemInLocation(rc, loc->GetVanillaItem(), false, true);
}
}
}
@@ -841,40 +853,12 @@ void GenerateItemPool() {
}
// Shuffle Pots
- if (ctx->GetOption(RSK_SHUFFLE_POTS).IsNot(RO_SHUFFLE_POTS_OFF)) {
- bool overworldPotsActive = ctx->GetOption(RSK_SHUFFLE_POTS).Is(RO_SHUFFLE_POTS_OVERWORLD) ||
- ctx->GetOption(RSK_SHUFFLE_POTS).Is(RO_SHUFFLE_POTS_ALL);
- bool dungeonPotsActive = ctx->GetOption(RSK_SHUFFLE_POTS).Is(RO_SHUFFLE_POTS_DUNGEONS) ||
+ bool overworldPotsActive = ctx->GetOption(RSK_SHUFFLE_POTS).Is(RO_SHUFFLE_POTS_OVERWORLD) ||
ctx->GetOption(RSK_SHUFFLE_POTS).Is(RO_SHUFFLE_POTS_ALL);
-
- for (RandomizerCheck loc : ctx->GetLocations(ctx->allLocations, RCTYPE_POT)) {
- bool overworldPot = Rando::StaticData::GetLocation(loc)->IsOverworld();
- bool dungeonPot = !overworldPot;
-
- // If pot is in the overworld and shuffled, add its item to the pool
- if (overworldPotsActive && overworldPot) {
- AddItemToMainPool(Rando::StaticData::GetLocation(loc)->GetVanillaItem());
- } else if (dungeonPotsActive && dungeonPot) {
- // If pot is the same in MQ and vanilla, add.
- RandomizerCheckQuest currentQuest = Rando::StaticData::GetLocation(loc)->GetQuest();
- if (currentQuest == RCQUEST_BOTH) {
- AddItemToMainPool(Rando::StaticData::GetLocation(loc)->GetVanillaItem());
- } else {
- // Check if current pot's dungeon is vanilla or MQ, and only add if quest corresponds to it.
- SceneID potScene = Rando::StaticData::GetLocation(loc)->GetScene();
-
- for (uint8_t i = SCENE_DEKU_TREE; i <= SCENE_GERUDO_TRAINING_GROUND; i++) {
- if (i == potScene) {
- bool isMQ = ctx->GetDungeon(SCENE_DEKU_TREE)->IsMQ();
-
- if ((isMQ && currentQuest == RCQUEST_MQ) || (!isMQ && currentQuest == RCQUEST_VANILLA)) {
- AddItemToMainPool(Rando::StaticData::GetLocation(loc)->GetVanillaItem());
- }
- }
- }
- }
- }
- }
+ bool dungeonPotsActive = ctx->GetOption(RSK_SHUFFLE_POTS).Is(RO_SHUFFLE_POTS_DUNGEONS) ||
+ ctx->GetOption(RSK_SHUFFLE_POTS).Is(RO_SHUFFLE_POTS_ALL);
+ if (overworldPotsActive || dungeonPotsActive) {
+ PlaceItemsForType(RCTYPE_POT, overworldPotsActive, dungeonPotsActive, false);
}
auto fsMode = ctx->GetOption(RSK_FISHSANITY);
@@ -1279,7 +1263,13 @@ void GenerateItemPool() {
PlaceVanillaDekuScrubItems(ctx->GetOption(RSK_SHUFFLE_SCRUBS).Is(RO_SCRUBS_OFF));
}
- PlaceFreestandingItems();
+ bool overworldFreeStandingActive = ctx->GetOption(RSK_SHUFFLE_FREESTANDING).Is(RO_FREESTANDING_OVERWORLD) ||
+ ctx->GetOption(RSK_SHUFFLE_FREESTANDING).Is(RO_FREESTANDING_ALL);
+ bool dungeonFreeStandingActive = ctx->GetOption(RSK_SHUFFLE_FREESTANDING).Is(RO_FREESTANDING_DUNGEONS) ||
+ ctx->GetOption(RSK_SHUFFLE_FREESTANDING).Is(RO_FREESTANDING_ALL);
+ if (overworldFreeStandingActive || dungeonFreeStandingActive) {
+ PlaceItemsForType(RCTYPE_FREESTANDING, overworldFreeStandingActive, dungeonFreeStandingActive, true);
+ }
AddItemsToPool(ItemPool, alwaysItems);
AddItemsToPool(ItemPool, dungeonRewards);
diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp
index c94ea2776..af2056dcc 100644
--- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp
+++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp
@@ -883,9 +883,22 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l
uint32_t params = item00->actor.params == ITEM00_HEART_PIECE || item00->actor.params == ITEM00_SMALL_KEY ? item00->ogParams : TWO_ACTOR_PARAMS((int32_t)pos.x, (int32_t)pos.z);
Rando::Location* loc = OTRGlobals::Instance->gRandomizer->GetCheckObjectFromActor(item00->actor.id, gPlayState->sceneNum, params);
- if (loc && loc->GetRandomizerCheck() != RC_UNKNOWN_CHECK && (RAND_GET_OPTION(RSK_SHUFFLE_FREESTANDING) || item00->actor.params == ITEM00_HEART_PIECE || item00->actor.params == ITEM00_SMALL_KEY)) {
+ if (loc && loc->GetRandomizerCheck() != RC_UNKNOWN_CHECK) {
+ auto ctx = Rando::Context::GetInstance();
+ bool freestanding_mode = ctx->GetOption(RSK_SHUFFLE_FREESTANDING).Is(RO_FREESTANDING_ALL);
+ if (!freestanding_mode) {
+ if (loc->IsOverworld()) {
+ freestanding_mode = ctx->GetOption(RSK_SHUFFLE_FREESTANDING).Is(RO_FREESTANDING_OVERWORLD);
+ } else {
+ freestanding_mode = ctx->GetOption(RSK_SHUFFLE_FREESTANDING).Is(RO_FREESTANDING_DUNGEONS);
+ }
+ }
+
// Spawn vanilla item if collected and renewable
- if (loc->GetCollectionCheck().type != SPOILER_CHK_RANDOMIZER_INF || !Rando::Context::GetInstance()->GetItemLocation(loc->GetRandomizerCheck())->HasObtained()) {
+ if (
+ (freestanding_mode || item00->actor.params == ITEM00_HEART_PIECE || item00->actor.params == ITEM00_SMALL_KEY) &&
+ (loc->GetCollectionCheck().type != SPOILER_CHK_RANDOMIZER_INF || !Rando::Context::GetInstance()->GetItemLocation(loc->GetRandomizerCheck())->HasObtained())
+ ) {
item00->randoCheck = loc->GetRandomizerCheck();
item00->itemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(loc->GetRandomizerCheck(), true);
item00->actor.params = ITEM00_SOH_DUMMY;
diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp
index 68245757b..cb0540f36 100644
--- a/soh/soh/Enhancements/randomizer/settings.cpp
+++ b/soh/soh/Enhancements/randomizer/settings.cpp
@@ -221,7 +221,7 @@ void Settings::CreateOptions() {
mOptions[RSK_SHUFFLE_BOSS_SOULS] = Option::U8("Shuffle Boss Souls", {"Off", "On", "On + Ganon"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleBossSouls"), mOptionDescriptions[RSK_SHUFFLE_BOSS_SOULS], WidgetType::Combobox);
mOptions[RSK_SHUFFLE_DEKU_STICK_BAG] = Option::Bool("Shuffle Deku Stick Bag", CVAR_RANDOMIZER_SETTING("ShuffleDekuStickBag"), mOptionDescriptions[RSK_SHUFFLE_DEKU_STICK_BAG], IMFLAG_SEPARATOR_BOTTOM, WidgetType::Checkbox, RO_GENERIC_OFF);
mOptions[RSK_SHUFFLE_DEKU_NUT_BAG] = Option::Bool("Shuffle Deku Nut Bag", CVAR_RANDOMIZER_SETTING("ShuffleDekuNutBag"), mOptionDescriptions[RSK_SHUFFLE_DEKU_NUT_BAG], IMFLAG_SEPARATOR_BOTTOM, WidgetType::Checkbox, RO_GENERIC_OFF);
- mOptions[RSK_SHUFFLE_FREESTANDING] = Option::U8("Shuffle Freestanding Items", {"Off", "Dungeons", "Overworld", "All Items"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleFreestanding"), mOptionDescriptions[RSK_SHUFFLE_FREESTANDING], WidgetType::Combobox, RO_TOKENSANITY_OFF);
+ mOptions[RSK_SHUFFLE_FREESTANDING] = Option::U8("Shuffle Freestanding Items", {"Off", "Dungeons", "Overworld", "All Items"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleFreestanding"), mOptionDescriptions[RSK_SHUFFLE_FREESTANDING], WidgetType::Combobox, RO_FREESTANDING_OFF);
mOptions[RSK_FISHSANITY] = Option::U8("Fishsanity", {"Off", "Shuffle only Hyrule Loach", "Shuffle Fishing Pond", "Shuffle Overworld Fish", "Shuffle Both"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("Fishsanity"), mOptionDescriptions[RSK_FISHSANITY], WidgetType::Combobox, RO_FISHSANITY_OFF);
mOptions[RSK_FISHSANITY_POND_COUNT] = Option::U8("Pond Fish Count", {NumOpts(0,17,1)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("FishsanityPondCount"), mOptionDescriptions[RSK_FISHSANITY_POND_COUNT], WidgetType::Slider, 0, true, IMFLAG_NONE);
mOptions[RSK_FISHSANITY_AGE_SPLIT] = Option::Bool("Pond Age Split", CVAR_RANDOMIZER_SETTING("FishsanityAgeSplit"), mOptionDescriptions[RSK_FISHSANITY_AGE_SPLIT]);