From ab9af742fa730b0ea14fa4fb5651d703e34cb34a Mon Sep 17 00:00:00 2001 From: Jordan Longstaff Date: Sat, 14 Jun 2025 01:43:31 -0400 Subject: [PATCH 01/31] Finish hint translations for fish by waterfall (#5466) * Finish hint translations for fish by waterfall * Revise --- .../3drando/hint_list/hint_list_exclude_overworld.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp index b47c68646..7129a0f5f 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp @@ -313,11 +313,11 @@ void StaticData::HintTable_Init_Exclude_Overworld() { /*german*/ "Man erzählt sich, daß ein #Tauchexperiment# mit #[[1]]# belohnt würde.", /*french*/ "Selon moi, l'#expérience de plongée# donne #[[1]]#.", {QM_RED, QM_GREEN})); // /*spanish*/ Según dicen, #bucear para un experimento# se premia con #[[1]]#. - // RANDOTODO: needs translation + hintTextTable[RHT_ZD_FISH] = HintText(CustomMessage("They say that a #fish by a waterfall# hoards #[[1]]#.", /*german*/ "Man erzählt sich, daß ein #Fisch nahe eines Wasserfalls# #[[1]]# horte.", - /*french*/ "Selon moi, #[[1]]#.", {QM_RED, QM_GREEN})); - // /*spanish*/ Según dicen, #[[1]]#. + /*french*/ "Selon moi, un #poisson près d'une cascade# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #pez junto a una cascada# otorga #[[1]]#. hintTextTable[RHT_GC_ROLLING_GORON_AS_ADULT] = HintText(CustomMessage("They say that #reassuring a young Goron# is rewarded with #[[1]]#.", From eefe7729ab69a0ceabc61a46a36084f461d6d739 Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Sat, 14 Jun 2025 15:51:33 +0100 Subject: [PATCH 02/31] CanUse instead of HasItem for Hover Boots to reach jabu switch ledge (#5581) * CanUse instead of HasItem for Hover Boots to reach jabu switch * also fix a similar issue in fountain --- .../randomizer/location_access/dungeons/jabujabus_belly.cpp | 4 ++-- .../randomizer/location_access/overworld/zoras_fountain.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp index 95494212a..305ec3e0d 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp @@ -64,7 +64,7 @@ void RegionTable_Init_JabuJabusBelly() { //Exits Entrance(RR_JABU_JABUS_BELLY_MAIN, []{return true;}), //there's tricks for getting here with bunny-jumps or just side-hops - Entrance(RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_LEDGE, []{return logic->HasItem(RG_BRONZE_SCALE) || logic->HasItem(RG_HOVER_BOOTS);}), + Entrance(RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_LEDGE, []{return logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOVER_BOOTS);}), Entrance(RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_SOUTH, []{return logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE);}), }); @@ -90,7 +90,7 @@ void RegionTable_Init_JabuJabusBelly() { }, { //Exits Entrance(RR_JABU_JABUS_BELLY_B1_NORTH, []{return logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE);}), - Entrance(RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_LEDGE, []{return logic->HasItem(RG_BRONZE_SCALE) || logic->HasItem(RG_HOVER_BOOTS);}), + Entrance(RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_LEDGE, []{return logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOVER_BOOTS);}), Entrance(RR_JABU_JABUS_BELLY_MAIN, []{return logic->CanUseProjectile();}), }); diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp index 3ac0921a3..c2287f2d0 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp @@ -41,7 +41,7 @@ void RegionTable_Init_ZorasFountain() { }, { //Exits //This hover is pretty tight, come at it with momentum and aim for the small corner polygon of the big iceburg while spamming roll - Entrance(RR_ZORAS_FOUNTAIN, []{return logic->HasItem(RG_BRONZE_SCALE) || logic->HasItem(RG_HOVER_BOOTS);}), + Entrance(RR_ZORAS_FOUNTAIN, []{return logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOVER_BOOTS);}), Entrance(RR_ZF_LAKEBED, []{return logic->CanUse(RG_IRON_BOOTS);}), Entrance(RR_ZF_LEDGE, []{return true;}), }); From b600836e4f8f8cbd9970d2a2c36da6331980dd5e Mon Sep 17 00:00:00 2001 From: Jordan Longstaff Date: Sun, 15 Jun 2025 13:19:52 -0400 Subject: [PATCH 03/31] New options that affect feeding Jabu-Jabu (#5397) * New options that affect feeding Jabu-Jabu * Add hints for what Jabu-Jabu wants * Roll back "key" settings to just closed/open, finish rando logic * Revert "Add hints for what Jabu-Jabu wants" This reverts commit 2a1974a669a51f3ff0f33ce8ba251769614cfde5. * Fix vanilla enhancement disabler --- .../Enhancements/Presets/PresetEntries.cpp | 2 + .../overworld/zoras_fountain.cpp | 2 +- .../randomizer/option_descriptions.cpp | 2 + .../Enhancements/randomizer/randomizerTypes.h | 7 ++++ soh/soh/Enhancements/randomizer/settings.cpp | 3 ++ .../Enhancements/timesaver_hook_handlers.cpp | 40 +++++++++++++++++++ soh/soh/SohGui/SohMenuEnhancements.cpp | 9 +++++ 7 files changed, 64 insertions(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/Presets/PresetEntries.cpp b/soh/soh/Enhancements/Presets/PresetEntries.cpp index c9ca5c24f..cf86793e2 100644 --- a/soh/soh/Enhancements/Presets/PresetEntries.cpp +++ b/soh/soh/Enhancements/Presets/PresetEntries.cpp @@ -82,6 +82,7 @@ const std::vector enhancedPresetEntries = { PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableCritWiggle"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterOwl"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("QuitFishingAtDoor"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InstantPutaway"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeSavers.SleepingWaterfall"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeSavers.SkipJabuJabuFish"), 1), // Skips & Speed-ups PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipText"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TextSpeed"), 5), @@ -176,6 +177,7 @@ const std::vector randomizerPresetEntries = { PRESET_ENTRY_S32(CVAR_ENHANCEMENT("QuitFishingAtDoor"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InstantPutaway"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeSavers.SleepingWaterfall"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeSavers.SkipJabuJabuFish"), 1), // Skips & Speed-ups PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), 1), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp index c2287f2d0..2a5390e99 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp @@ -31,7 +31,7 @@ void RegionTable_Init_ZorasFountain() { //child can break the brown rock without lifting the silver rock and it stays gone for adult, but it's not intuitive and there's no reasonable case where it matters. Entrance(RR_ZF_HIDDEN_CAVE, []{return logic->CanUse(RG_SILVER_GAUNTLETS) && logic->BlastOrSmash();}), Entrance(RR_ZF_ROCK, []{return logic->IsAdult && logic->CanUse(RG_SCARECROW);}), - Entrance(RR_JABU_JABUS_BELLY_ENTRYWAY, []{return (logic->IsChild && logic->CanUse(RG_BOTTLE_WITH_FISH));}), + Entrance(RR_JABU_JABUS_BELLY_ENTRYWAY, []{return logic->IsChild && (ctx->GetOption(RSK_JABU_OPEN).Is(RO_JABU_OPEN) || logic->CanUse(RG_BOTTLE_WITH_FISH));}), Entrance(RR_ZF_GREAT_FAIRY_FOUNTAIN, []{return logic->HasExplosives() || (ctx->GetTrickOption(RT_ZF_GREAT_FAIRY_WITHOUT_EXPLOSIVES) && logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_SILVER_GAUNTLETS));}), }); diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index 8dc07ce7a..cc5c5fec1 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -42,6 +42,8 @@ void Settings::CreateOptionDescriptions() { "\n" "Open - Sleeping Waterfall is always open. " "Link may always enter Zora's Domain."; + mOptionDescriptions[RSK_JABU_OPEN] = "Closed - A fish is required to open Jabu-Jabu's mouth.\n\n" + "Open - Jabu-Jabu's mouth opens without the need for a fish."; mOptionDescriptions[RSK_LOCK_OVERWORLD_DOORS] = "Add locks to all wooden overworld doors, requiring specific small keys to open them"; mOptionDescriptions[RSK_STARTING_AGE] = diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 396a37b23..d19d32c99 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -5688,6 +5688,7 @@ typedef enum { RSK_DOOR_OF_TIME, RSK_ZORAS_FOUNTAIN, RSK_SLEEPING_WATERFALL, + RSK_JABU_OPEN, RSK_STARTING_AGE, RSK_SELECTED_STARTING_AGE, RSK_GERUDO_FORTRESS, @@ -5938,6 +5939,12 @@ typedef enum { RO_WATERFALL_OPEN, } RandoOptionSleepingWaterfall; +// Jabu-Jabu settings (closed, open) +typedef enum { + RO_JABU_CLOSED, + RO_JABU_OPEN, +} RandoOptionJabu; + // Starting Age settings (child, adult, random) typedef enum { RO_AGE_CHILD, diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index a2db7ee0e..a9f7b4e64 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -120,6 +120,7 @@ void Settings::CreateOptions() { OPT_U8(RSK_DOOR_OF_TIME, "Door of Time", {"Closed", "Song only", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("DoorOfTime"), mOptionDescriptions[RSK_DOOR_OF_TIME], WidgetType::Combobox); OPT_U8(RSK_ZORAS_FOUNTAIN, "Zora's Fountain", {"Closed", "Closed as child", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ZorasFountain"), mOptionDescriptions[RSK_ZORAS_FOUNTAIN]); OPT_U8(RSK_SLEEPING_WATERFALL, "Sleeping Waterfall", {"Closed", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SleepingWaterfall"), mOptionDescriptions[RSK_SLEEPING_WATERFALL]); + OPT_U8(RSK_JABU_OPEN, "Jabu-Jabu", {"Closed", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("JabuJabu"), mOptionDescriptions[RSK_JABU_OPEN]); OPT_BOOL(RSK_LOCK_OVERWORLD_DOORS, "Lock Overworld Doors", CVAR_RANDOMIZER_SETTING("LockOverworldDoors"), mOptionDescriptions[RSK_LOCK_OVERWORLD_DOORS]); OPT_U8(RSK_GERUDO_FORTRESS, "Fortress Carpenters", {"Normal", "Fast", "Free"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("FortressCarpenters"), mOptionDescriptions[RSK_GERUDO_FORTRESS]); OPT_U8(RSK_RAINBOW_BRIDGE, "Rainbow Bridge", {"Vanilla", "Always open", "Stones", "Medallions", "Dungeon rewards", "Dungeons", "Tokens", "Greg"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("RainbowBridge"), mOptionDescriptions[RSK_RAINBOW_BRIDGE], WidgetType::Combobox, RO_BRIDGE_VANILLA, false, IMFLAG_NONE); @@ -1151,6 +1152,7 @@ void Settings::CreateOptions() { &mOptions[RSK_DOOR_OF_TIME], &mOptions[RSK_ZORAS_FOUNTAIN], &mOptions[RSK_SLEEPING_WATERFALL], + &mOptions[RSK_JABU_OPEN], &mOptions[RSK_LOCK_OVERWORLD_DOORS], }, WidgetContainerType::COLUMN); @@ -1405,6 +1407,7 @@ void Settings::CreateOptions() { &mOptions[RSK_DOOR_OF_TIME], &mOptions[RSK_ZORAS_FOUNTAIN], &mOptions[RSK_SLEEPING_WATERFALL], + &mOptions[RSK_JABU_OPEN], &mOptions[RSK_LOCK_OVERWORLD_DOORS], &mOptions[RSK_GERUDO_FORTRESS], &mOptions[RSK_RAINBOW_BRIDGE], diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index 9f488efce..9a602323d 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -25,6 +25,7 @@ extern "C" { #include "src/overlays/actors/ovl_Bg_Ddan_Kd/z_bg_ddan_kd.h" #include "src/overlays/actors/ovl_En_Tk/z_en_tk.h" #include "src/overlays/actors/ovl_En_Fu/z_en_fu.h" +#include "src/overlays/actors/ovl_En_Jj/z_en_jj.h" #include "src/overlays/actors/ovl_En_Daiku/z_en_daiku.h" #include "src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.h" #include "src/overlays/actors/ovl_Bg_Spot03_Taki/z_bg_spot03_taki.h" @@ -47,6 +48,10 @@ extern void EnGo2_CurledUp(EnGo2* enGo2, PlayState* play); extern void EnRu2_SetEncounterSwitchFlag(EnRu2* enRu2, PlayState* play); extern void EnDaiku_EscapeSuccess(EnDaiku* enDaiku, PlayState* play); + +extern void EnJj_WaitToOpenMouth(EnJj* enJj, PlayState* play); +extern void EnJj_WaitForFish(EnJj* enJj, PlayState* play); +extern void EnJj_SetupAction(EnJj* enJj, EnJjActionFunc actionFunc); } #define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).Get() @@ -869,6 +874,8 @@ static uint32_t enMa1UpdateHook = 0; static uint32_t enMa1KillHook = 0; static uint32_t enFuUpdateHook = 0; static uint32_t enFuKillHook = 0; +static uint32_t enJjUpdateHook = 0; +static uint32_t enJjKillHook = 0; static uint32_t bgSpot02UpdateHook = 0; static uint32_t bgSpot02KillHook = 0; static uint32_t bgSpot03UpdateHook = 0; @@ -934,6 +941,39 @@ void TimeSaverOnActorInitHandler(void* actorRef) { }); } + if (actor->id == ACTOR_EN_JJ && !IS_RANDO) { + enJjUpdateHook = + GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) mutable { + Actor* innerActor = static_cast(innerActorRef); + + if (innerActor->id != ACTOR_EN_JJ || Flags_GetEventChkInf(EVENTCHKINF_OFFERED_FISH_TO_JABU_JABU)) { + return; + } + + bool shouldOpen = IS_RANDO ? RAND_GET_OPTION(RSK_JABU_OPEN) + : CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipJabuJabuFish"), 0); + if (!shouldOpen) { + return; + } + + EnJj* enJj = static_cast(innerActorRef); + if (enJj->actionFunc == EnJj_WaitForFish) { + EnJj_SetupAction(enJj, EnJj_WaitToOpenMouth); + GameInteractor::Instance->UnregisterGameHook(enJjUpdateHook); + GameInteractor::Instance->UnregisterGameHook(enJjKillHook); + enJjUpdateHook = 0; + enJjKillHook = 0; + } + }); + enJjKillHook = + GameInteractor::Instance->RegisterGameHook([](int16_t sceneNum) mutable { + GameInteractor::Instance->UnregisterGameHook(enJjUpdateHook); + GameInteractor::Instance->UnregisterGameHook(enJjKillHook); + enJjUpdateHook = 0; + enJjKillHook = 0; + }); + } + if (actor->id == ACTOR_EN_OWL && gPlayState->sceneNum == SCENE_ZORAS_RIVER && CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SleepingWaterfall"), 0) == 2) { Actor_Kill(actor); diff --git a/soh/soh/SohGui/SohMenuEnhancements.cpp b/soh/soh/SohGui/SohMenuEnhancements.cpp index 9305c8ec5..1ded80e74 100644 --- a/soh/soh/SohGui/SohMenuEnhancements.cpp +++ b/soh/soh/SohGui/SohMenuEnhancements.cpp @@ -262,6 +262,15 @@ void SohMenu::AddMenuEnhancements() { "open permanently.\n" "Never: Link never needs to play Zelda's Lullaby to open the waterfall. He only needs to have " "learned it and have an Ocarina.")); + AddWidget(path, "Skip Feeding Jabu-Jabu", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_ENHANCEMENT("TimeSavers.SkipJabuJabuFish")) + .PreFunc([](WidgetInfo& info) { + info.options->disabled = + IS_RANDO && OTRGlobals::Instance->gRandoContext->GetOption(RSK_JABU_OPEN).Is(RO_JABU_OPEN); + info.options->disabledTooltip = + "This setting is disabled because a randomizer savefile with \"Jabu-Jaby: Open\" is loaded."; + }) + .Options(CheckboxOptions().Tooltip("Allow Link to enter Jabu-Jabu without feeding him a fish.")); // Skips & Speed-ups path.sidebarName = "Skips & Speed-ups"; From 35361c9e8d59c92ea820edd25ead124d086d3b52 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Sun, 15 Jun 2025 10:20:09 -0700 Subject: [PATCH 04/31] Create macro to make All and None buttons for cutscene skips trigger ShipInit for each CVar changed. (#5576) --- soh/soh/SohGui/SohMenuEnhancements.cpp | 44 ++++++++++++++------------ 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/soh/soh/SohGui/SohMenuEnhancements.cpp b/soh/soh/SohGui/SohMenuEnhancements.cpp index 1ded80e74..f6f627f78 100644 --- a/soh/soh/SohGui/SohMenuEnhancements.cpp +++ b/soh/soh/SohGui/SohMenuEnhancements.cpp @@ -7,6 +7,10 @@ #include #include +#define CVAR_INT_SHIP_INIT(cvar, val) \ + CVarSetInteger(cvar, val); \ + ShipInit::Init(cvar); + static std::string comboboxTooltip = ""; static int32_t enhancementPresetSelected = ENHANCEMENT_PRESET_DEFAULT; bool isBetaQuestEnabled = false; @@ -281,16 +285,16 @@ void SohMenu::AddMenuEnhancements() { AddWidget(path, "All##Skips", WIDGET_BUTTON) .Options(ButtonOptions().Size(Sizes::Inline)) .Callback([](WidgetInfo& info) { - CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), true); - CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Entrances"), true); - CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), true); - CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.LearnSong"), true); - CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.BossIntro"), true); - CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.QuickBossDeaths"), true); - CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), true); - CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipOwlInteractions"), true); - CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), true); - CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.DisableTitleCard"), true); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), true); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Entrances"), true); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), true); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.LearnSong"), true); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.BossIntro"), true); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.QuickBossDeaths"), true); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), true); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipOwlInteractions"), true); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), true); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.DisableTitleCard"), true); Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); }); @@ -298,16 +302,16 @@ void SohMenu::AddMenuEnhancements() { .SameLine(true) .Options(ButtonOptions().Size(Sizes::Inline)) .Callback([](WidgetInfo& info) { - CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), false); - CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Entrances"), false); - CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), false); - CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.LearnSong"), false); - CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.BossIntro"), false); - CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.QuickBossDeaths"), false); - CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), false); - CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipOwlInteractions"), false); - CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), false); - CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.DisableTitleCard"), false); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), false); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Entrances"), false); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), false); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.LearnSong"), false); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.BossIntro"), false); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.QuickBossDeaths"), false); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), false); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipOwlInteractions"), false); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), false); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.DisableTitleCard"), false); Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); }); From 620d08002c33ac6b1c70c4f1726de710ba06488c Mon Sep 17 00:00:00 2001 From: xxAtrain223 Date: Sun, 15 Jun 2025 12:22:03 -0500 Subject: [PATCH 05/31] RecalculateAvailableChecks Fix - IsSaveLoaded Guard (#5587) * Added IsSaveLoaded guard clause to RecalculateAvailableChecks. * Combined RecalculateAvailableChecks guard clauses. --- soh/soh/Enhancements/debugconsole.cpp | 5 +---- .../Enhancements/randomizer/randomizer_check_tracker.cpp | 7 ++----- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/soh/soh/Enhancements/debugconsole.cpp b/soh/soh/Enhancements/debugconsole.cpp index d25c3cfff..91c0d4c1c 100644 --- a/soh/soh/Enhancements/debugconsole.cpp +++ b/soh/soh/Enhancements/debugconsole.cpp @@ -1471,10 +1471,7 @@ static bool AvailableChecksProcessUndiscoveredExitsHandler(std::shared_ptrACProcessUndiscoveredExits ? "enabled" : "disabled"); - if (GameInteractor::IsSaveLoaded(true)) { - CheckTracker::RecalculateAvailableChecks(); - } - + CheckTracker::RecalculateAvailableChecks(); return 0; } diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index 3a2c5e475..887bc3731 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -1985,7 +1985,7 @@ void ImGuiDrawTwoColorPickerSection(const char* text, const char* cvarMainName, } void RecalculateAvailableChecks(RandomizerRegion startingRegion /* = RR_ROOT */) { - if (!enableAvailableChecks) { + if (!enableAvailableChecks || !GameInteractor::IsSaveLoaded(true)) { return; } @@ -2135,10 +2135,7 @@ void CheckTrackerSettingsWindow::DrawElement() { "with your current progress.") .Color(THEME_COLOR))) { enableAvailableChecks = CVarGetInteger(CVAR_TRACKER_CHECK("EnableAvailableChecks"), 0); - - if (GameInteractor::IsSaveLoaded(true)) { - RecalculateAvailableChecks(); - } + RecalculateAvailableChecks(); } ImGui::EndDisabled(); From f2bc7cd1dce0918dacaa8bb71c2f867903006c64 Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Sun, 15 Jun 2025 18:22:36 +0100 Subject: [PATCH 06/31] Fix rare crash in randomiser generation (#5585) --- soh/soh/Enhancements/randomizer/randomizer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 7809a39c1..f0f57b353 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -3586,7 +3586,7 @@ std::thread randoThread; void GenerateRandomizerImgui(std::string seed = "") { CVarSetInteger(CVAR_GENERAL("RandoGenerating"), 1); - CVarSave(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); auto ctx = Rando::Context::GetInstance(); // RANDOTODO proper UI for selecting if a spoiler loaded should be used for settings Rando::Settings::GetInstance()->SetAllToContext(); From aa7693a10351e8221096c79b23e4d6a14a9e2cfc Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Mon, 16 Jun 2025 23:29:22 +0100 Subject: [PATCH 07/31] fix various oversights with altar hint off (#5589) --- .../custom-message/CustomMessageManager.h | 1 + .../randomizer/3drando/hint_list.cpp | 26 +++++++------- .../Enhancements/randomizer/3drando/hints.cpp | 36 ++++++++++--------- soh/soh/Enhancements/randomizer/hint.cpp | 4 +++ soh/soh/OTRGlobals.cpp | 2 +- 5 files changed, 38 insertions(+), 31 deletions(-) diff --git a/soh/soh/Enhancements/custom-message/CustomMessageManager.h b/soh/soh/Enhancements/custom-message/CustomMessageManager.h index f312d9f85..6b14c8060 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageManager.h +++ b/soh/soh/Enhancements/custom-message/CustomMessageManager.h @@ -47,6 +47,7 @@ class CustomMessage { TextBoxPosition position_ = TEXTBOX_POS_BOTTOM); CustomMessage(std::string english_, TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM); + // RANDOTODO trying to declare this with capital and type causes ambiguity with the first signature CustomMessage(std::string english_, std::vector colors_, std::vector capital_ = {}, TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM); CustomMessage(Text text, TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM); diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp index 72c90fa19..0670f9139 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp @@ -1976,27 +1976,27 @@ void StaticData::HintTable_Init() { hintTextTable[RHT_BRIDGE_OPEN_HINT] = HintText(CustomMessage("$lThe awakened ones have #already created a bridge# to the castle where the evil dwells.^", /*german*/ "$lDie Weisen haben #bereits&eine Brücke zum Portal von&Ganons Schloß gelegt#...^", /*french*/ "$lLes êtres de sagesse ont#déjà créé un pont# vers le repaire du mal.^", - {QM_LBLUE})); + {QM_LBLUE}, {}, TEXTBOX_TYPE_BLUE)); // /*spanish*/$lLos sabios #ya habrán creado un puente#&al castillo, de donde emana el mal.^ hintTextTable[RHT_BRIDGE_VANILLA_HINT] = HintText(CustomMessage("$6The awakened ones require the #Shadow and Spirit Medallions# as well as the #Light Arrows#.^", /*german*/ "$6Die Weisen werden darauf warten, daß der Held das #Amulett des Schattens, Amulett der Geister# und die #Licht-Pfeile# sammelt.^", /*french*/ "$6Les êtres de sagesse attendront le héros muni des #Médaillons de l'Ombre et l'Esprit# et des #Flèches de Lumière#.^", - {QM_RED, QM_YELLOW})); + {QM_RED, QM_YELLOW}, {}, TEXTBOX_TYPE_BLUE)); // /*spanish*/$6Los sabios aguardarán a que el héroe obtenga tanto el #Medallón de las Sombras y el del Espíritu# junto // a la #flecha de luz#.^ hintTextTable[RHT_BRIDGE_STONES_HINT] = HintText(CustomMessage("$0The awakened ones will await for the Hero to collect #[[d]] Spiritual Stone||s|#.^", /*german*/ "$0Die Weisen werden darauf warten, daß der Held #[[d]] |Heiligen Stein|Heilige Steine|# sammelt.^", /*french*/ "$0Les êtres de sagesse attendront le héros muni de #[[d]] |Pierre Ancestrale|Pierres Ancestrales|#.^", - {QM_BLUE})); + {QM_BLUE}, {}, TEXTBOX_TYPE_BLUE)); // /*spanish*/$0Los sabios aguardarán a que el héroe&obtenga #[[d]] |piedra espiritual|piedras espirituales|#.^ hintTextTable[RHT_BRIDGE_MEDALLIONS_HINT] = HintText(CustomMessage("$8The awakened ones will await for the Hero to collect #[[d]] Medallion||s|#.^", /*german*/ "$8Die Weisen werden darauf warten, daß der Held #[[d]] Amulett||e|# sammelt.^", /*french*/ "$8Les êtres de sagesse attendront le héros muni de #[[d]] Médaillon||s|#.^", - {QM_RED})); + {QM_RED}, {}, TEXTBOX_TYPE_BLUE)); // /*spanish*/$8Los sabios aguardarán a que el héroe&obtenga #[[d]] |medallón|medallones|#.^ hintTextTable[RHT_BRIDGE_REWARDS_HINT] = HintText(CustomMessage("$CThe awakened ones will await for the Hero to collect #[[d]]# |#Spiritual Stone# or #Medallion#|" @@ -2005,24 +2005,24 @@ void StaticData::HintTable_Init() { "#Heilige Steine# oder #Amulette#| sammelt.^", /*french*/ "$CLes êtres de sagesse attendront le héros muni de #[[d]]# |#Pierre Ancestrale# ou #Médaillon#" "|#Pierres Ancestrales# ou #Médaillons#|.^", - {QM_YELLOW, QM_BLUE, QM_RED})); + {QM_YELLOW, QM_BLUE, QM_RED}, {}, TEXTBOX_TYPE_BLUE)); // /*spanish*/$CLos sabios aguardarán a que el héroe obtenga #[[d]]# |#piedra espiritual# o #medallón#| //#piedras espirtuales# y #medallones#|.^ hintTextTable[RHT_BRIDGE_DUNGEONS_HINT] = HintText(CustomMessage("$mThe awakened ones will await for the Hero to conquer #[[d]] Dungeon||s|#.^", /*german*/ "$mDie Weisen werden darauf warten, daß der Held #[[d]] Labyrinth||e|# abschließt.^", /*french*/ "$mLes êtres de sagesse attendront la conquête de #[[d]] Donjon||s|#.^", - {QM_PINK})); + {QM_PINK}, {}, TEXTBOX_TYPE_BLUE)); // /*spanish*/$mLos sabios aguardarán a que el héroe complete #[[d]] mazmorra||s|#.^ hintTextTable[RHT_BRIDGE_TOKENS_HINT] = HintText(CustomMessage("$sThe awakened ones will await for the Hero to collect #[[d]] Gold Skulltula Token||s|#.^", /*german*/ "$sDie Weisen werden darauf warten, daß der Held #[[d]] Skulltula-Symbol||e|# sammelt.^", /*french*/ "$sLes êtres de sagesse attendront le héros muni de #[[d]] Symbole||s| de Skulltula d'or#.^", - {QM_YELLOW})); + {QM_YELLOW}, {}, TEXTBOX_TYPE_BLUE)); // /*spanish*/$sLos sabios aguardarán a que el héroe obtenga #[[d]] símbolo||s| de skulltula dorada#.^ - hintTextTable[RHT_BRIDGE_GREG_HINT] = HintText(CustomMessage("$gThe awakened ones will await for the Hero to find #Greg#.^", - {QM_GREEN})); + hintTextTable[RHT_BRIDGE_GREG_HINT] = HintText(CustomMessage("$gThe awakened ones will await for the Hero to find #Greg#.^", TODO_TRANSLATE, TODO_TRANSLATE, + {QM_GREEN}, {}, TEXTBOX_TYPE_BLUE)); /*-------------------------- @@ -2176,22 +2176,22 @@ void StaticData::HintTable_Init() { hintTextTable[RHT_CHILD_ALTAR_STONES] = HintText(CustomMessage("3 Spiritual Stones found in Hyrule...^$0#[[1]]#...^$1#[[2]]#...^$2#[[3]]#...^", /*german*/ "Drei Heilige Steine, zu finden in Hyrule...$0#[[1]]#...^$1#[[2]]#...^$2#[[3]]#...^", /*french*/ "Les trois Pierres Ancestrales cachées&dans Hyrule...$0#[[1]]#...^$1#[[2]]#...^$2#[[3]]#...^", - {QM_GREEN, QM_RED, QM_BLUE}, {true, true, true})); + {QM_GREEN, QM_RED, QM_BLUE}, {true, true, true}, TEXTBOX_TYPE_BLUE)); // /*spanish*/ Tres piedras espirituales halladas por Hyrule...$0#[[1]]#...^$1#[[2]]#...^$2#[[3]]#...^ hintTextTable[RHT_CHILD_ALTAR_TEXT_END_DOTOPEN] = HintText(CustomMessage("$oYe who may become a Hero...&The path to the future is open...", /*german*/ "$oJener auf dem Weg des Helden...&Der Pfad zur Zukunft sei geöffnet...", - /*french*/ "$oÀ celui qui a quête de devenir&héros...&Le futur vous accueille béant...")); + /*french*/ "$oÀ celui qui a quête de devenir&héros...&Le futur vous accueille béant...", TEXTBOX_TYPE_BLUE)); // /*spanish*/$oPara aquel que se convierta en el héroe...&La puerta al futuro está a su disposición... hintTextTable[RHT_CHILD_ALTAR_TEXT_END_DOTSONGONLY] = HintText(CustomMessage("$cYe who may become a Hero...&Stand with the Ocarina and&play the Song of Time.", /*german*/ "$cJener auf dem Weg des Helden...&Nehme er seine Okarina zur Hand und&spiele hier die Hymne der Zeit.", - /*french*/ "$cÀ celui qui a quête de devenir&héros...&Portez l'Ocarina et jouez&le chant du temps.")); + /*french*/ "$cÀ celui qui a quête de devenir&héros...&Portez l'Ocarina et jouez&le chant du temps.", TEXTBOX_TYPE_BLUE)); // /*spanish*/$cPara aquel que se convierta en el héroe...&Tome la ocarina y&entone la Canción del Tiempo. hintTextTable[RHT_CHILD_ALTAR_TEXT_END_DOTCLOSED] = HintText(CustomMessage("$iYe who may become a Hero...&Offer the spiritual stones and&play the Song of Time.", /*german*/ "$iJener mit den drei Heiligen Steinen&nehme seine Okarina zur Hand und&spiele hier die Hymne der Zeit.", - /*french*/ "$iÀ celui qui a quête de devenir&héros... Présentez les Pierres&Ancestrales et jouez&le chant du temps.")); + /*french*/ "$iÀ celui qui a quête de devenir&héros... Présentez les Pierres&Ancestrales et jouez&le chant du temps.", TEXTBOX_TYPE_BLUE)); // /*spanish*/$iPara aquel que se convierta en el héroe...&Tome las piedras espirituales y&entone la Canción del Tiempo. hintTextTable[RHT_ADULT_ALTAR_MEDALLIONS] = HintText(CustomMessage("An awakening voice from the Sacred Realm will call those destined to be Sages, who dwell in the #five temples#.^" diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.cpp b/soh/soh/Enhancements/randomizer/3drando/hints.cpp index 8e928185f..c38d57d8b 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.cpp @@ -728,20 +728,22 @@ std::vector FindItemsAndMarkHinted(std::vector i void CreateChildAltarHint() { auto ctx = Rando::Context::GetInstance(); - if (!ctx->GetHint(RH_ALTAR_CHILD)->IsEnabled() && ctx->GetOption(RSK_TOT_ALTAR_HINT)) { + if (!ctx->GetHint(RH_ALTAR_CHILD)->IsEnabled()) { std::vector stoneLocs = {}; - // force marking the rewards as hinted if they are at the end of dungeons as they can be inferred - if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON) || - ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_VANILLA)) { - stoneLocs = FindItemsAndMarkHinted({ RG_KOKIRI_EMERALD, RG_GORON_RUBY, RG_ZORA_SAPPHIRE }, {}); - } else { - stoneLocs = - FindItemsAndMarkHinted({ RG_KOKIRI_EMERALD, RG_GORON_RUBY, RG_ZORA_SAPPHIRE }, { RC_ALTAR_HINT_CHILD }); - } std::vector stoneAreas = {}; - for (auto loc : stoneLocs) { - if (loc != RC_UNKNOWN_CHECK) { - stoneAreas.push_back(ctx->GetItemLocation(loc)->GetRandomArea()); + if (ctx->GetOption(RSK_TOT_ALTAR_HINT)) { + // force marking the rewards as hinted if they are at the end of dungeons as they can be inferred + if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON) || + ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_VANILLA)) { + stoneLocs = FindItemsAndMarkHinted({ RG_KOKIRI_EMERALD, RG_GORON_RUBY, RG_ZORA_SAPPHIRE }, {}); + } else { + stoneLocs = FindItemsAndMarkHinted({ RG_KOKIRI_EMERALD, RG_GORON_RUBY, RG_ZORA_SAPPHIRE }, + { RC_ALTAR_HINT_CHILD }); + } + for (auto loc : stoneLocs) { + if (loc != RC_UNKNOWN_CHECK) { + stoneAreas.push_back(ctx->GetItemLocation(loc)->GetRandomArea()); + } } } ctx->AddHint(RH_ALTAR_CHILD, Hint(RH_ALTAR_CHILD, HINT_TYPE_ALTAR_CHILD, {}, stoneLocs, stoneAreas)); @@ -752,6 +754,7 @@ void CreateAdultAltarHint() { auto ctx = Rando::Context::GetInstance(); if (!ctx->GetHint(RH_ALTAR_ADULT)->IsEnabled()) { std::vector medallionLocs = {}; + std::vector medallionAreas = {}; if (ctx->GetOption(RSK_TOT_ALTAR_HINT)) { // force marking the rewards as hinted if they are at the end of dungeons as they can be inferred if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON) || @@ -764,11 +767,10 @@ void CreateAdultAltarHint() { RG_WATER_MEDALLION, RG_SPIRIT_MEDALLION, RG_SHADOW_MEDALLION }, { RC_ALTAR_HINT_ADULT }); } - } - std::vector medallionAreas = {}; - for (auto loc : medallionLocs) { - if (loc != RC_UNKNOWN_CHECK) { - medallionAreas.push_back(ctx->GetItemLocation(loc)->GetRandomArea()); + for (auto loc : medallionLocs) { + if (loc != RC_UNKNOWN_CHECK) { + medallionAreas.push_back(ctx->GetItemLocation(loc)->GetRandomArea()); + } } } ctx->AddHint(RH_ALTAR_ADULT, Hint(RH_ALTAR_ADULT, HINT_TYPE_ALTAR_ADULT, {}, medallionLocs, medallionAreas)); diff --git a/soh/soh/Enhancements/randomizer/hint.cpp b/soh/soh/Enhancements/randomizer/hint.cpp index d81e94f2f..c2011c101 100644 --- a/soh/soh/Enhancements/randomizer/hint.cpp +++ b/soh/soh/Enhancements/randomizer/hint.cpp @@ -299,6 +299,8 @@ const CustomMessage Hint::GetHintMessage(MessageFormat format, uint8_t id) const } else if (hintType == HINT_TYPE_ALTAR_CHILD) { if (ctx->GetOption(RSK_TOT_ALTAR_HINT)) { hintText = StaticData::hintTextTable[RHT_CHILD_ALTAR_STONES].GetHintMessage(); + } else { + hintText.SetTextBoxType(TEXTBOX_TYPE_BLUE); } if (ctx->GetOption(RSK_DOOR_OF_TIME).Is(RO_DOOROFTIME_OPEN)) { hintText += CustomMessage(StaticData::hintTextTable[RHT_CHILD_ALTAR_TEXT_END_DOTOPEN].GetHintMessage()); @@ -310,6 +312,8 @@ const CustomMessage Hint::GetHintMessage(MessageFormat format, uint8_t id) const } else if (hintType == HINT_TYPE_ALTAR_ADULT) { if (ctx->GetOption(RSK_TOT_ALTAR_HINT)) { hintText = StaticData::hintTextTable[RHT_ADULT_ALTAR_MEDALLIONS].GetHintMessage(); + } else { + hintText.SetTextBoxType(TEXTBOX_TYPE_BLUE); } hintText += GetBridgeReqsText() + GetGanonBossKeyText() + StaticData::hintTextTable[RHT_ADULT_ALTAR_TEXT_END].GetHintMessage(); diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 9bd3008f8..630ffeaaa 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2258,7 +2258,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { } } else if ((textId == TEXT_ALTAR_CHILD || textId == TEXT_ALTAR_ADULT)) { // rando hints at altar - messageEntry = (LINK_IS_ADULT) ? ctx->GetHint(RH_ALTAR_ADULT)->GetHintMessage() + messageEntry = (LINK_IS_ADULT) ? ctx->GetHint(RH_ALTAR_ADULT)->GetHintMessage(MF_AUTO_FORMAT) : ctx->GetHint(RH_ALTAR_CHILD)->GetHintMessage(MF_AUTO_FORMAT); } else if (textId == TEXT_GANONDORF) { if (ctx->GetOption(RSK_GANONDORF_HINT)) { From 19e9f39a9ab1be147a18e437728d41097fe439de Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Mon, 16 Jun 2025 23:29:46 +0100 Subject: [PATCH 08/31] Hardcode spirit hands to be dungeon checks (#5590) * Hardcode spirit hands to be dungeon checks * CLANG CLANG CLANG! --- soh/soh/Enhancements/randomizer/location.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/location.cpp b/soh/soh/Enhancements/randomizer/location.cpp index f474397aa..6c27e3aef 100644 --- a/soh/soh/Enhancements/randomizer/location.cpp +++ b/soh/soh/Enhancements/randomizer/location.cpp @@ -54,8 +54,9 @@ const std::string& Rando::Location::GetShortName() const { bool Rando::Location::IsDungeon() const { return (checkType != RCTYPE_SKULL_TOKEN && - (scene <= SCENE_GERUDO_TRAINING_GROUND || scene == SCENE_INSIDE_GANONS_CASTLE || - (scene >= SCENE_DEKU_TREE_BOSS && scene <= SCENE_GANONDORF_BOSS))) || + (scene <= SCENE_GERUDO_TRAINING_GROUND || scene == SCENE_INSIDE_GANONS_CASTLE || + (scene >= SCENE_DEKU_TREE_BOSS && scene <= SCENE_GANONDORF_BOSS)) || + (rc == RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST || rc == RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST)) || (checkType == RCTYPE_SKULL_TOKEN && scene <= SCENE_ICE_CAVERN); } From b932b8f6c9912cfd57a0bd37b8091f2047a89396 Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Wed, 18 Jun 2025 16:39:09 +0100 Subject: [PATCH 09/31] Clarify hint text for pots in interiors (#5591) * Clarify hint text for pots in interors * Make dampe's pots text less like a naming error --- .../hint_list/hint_list_exclude_overworld.cpp | 47 ++++-- .../Enhancements/randomizer/ShufflePots.cpp | 156 +++++++++--------- .../Enhancements/randomizer/randomizerTypes.h | 15 +- 3 files changed, 122 insertions(+), 96 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp index 7129a0f5f..754709f97 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp @@ -1492,9 +1492,17 @@ void StaticData::HintTable_Init_Exclude_Overworld() { /*french*/ "Selon moi, une #rucheau derrière le Roi des Zoras# cache #[[1]]#.", {QM_RED, QM_GREEN})); // /*spanish*/ Según dicen, una #colmena detrás del rey de los zoras# esconde #[[1]]#. - hintTextTable[RHT_POT_KOKIRI_FOREST] = HintText(CustomMessage("They say that a #pot in Kokiri Forest# contains #[[1]]#.", - /*german*/ "Man erzählt sich, daß eine #Vase im Kokiri-Wald# #[[1]]# enthielte.", - /*french*/ "Selon moi, une #jarre dans la Fôret Kokiri# contient #[[1]]#.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_POT_LINKS_HOUSE] = HintText(CustomMessage("They say that the #pot in the hero's house# contains #[[1]]#.", + /*german*/ "Man erzählt sich, daß eine #Vase im Kokiri-Wald# #[[1]]# enthielte.", //TODO_TRANSLATE update to match + /*french*/ "Selon moi, une #jarre dans la Fôret Kokiri# contient #[[1]]#.", {QM_RED, QM_GREEN})); //TODO_TRANSLATE update to match + + hintTextTable[RHT_POT_TWINS_HOUSE] = HintText(CustomMessage("They say that a #pot shared by twins# contains #[[1]]#.", + /*german*/ "Man erzählt sich, daß eine #Vase im Kokiri-Wald# #[[1]]# enthielte.", //TODO_TRANSLATE update to match + /*french*/ "Selon moi, une #jarre dans la Fôret Kokiri# contient #[[1]]#.", {QM_RED, QM_GREEN})); //TODO_TRANSLATE update to match + + hintTextTable[RHT_POT_KNOW_IT_ALL] = HintText(CustomMessage("They say that a #know-it-all bother's pot# contains #[[1]]#.", + /*german*/ "Man erzählt sich, daß eine #Vase im Kokiri-Wald# #[[1]]# enthielte.", //TODO_TRANSLATE update to match + /*french*/ "Selon moi, une #jarre dans la Fôret Kokiri# contient #[[1]]#.", {QM_RED, QM_GREEN})); //TODO_TRANSLATE update to match hintTextTable[RHT_POT_GERUDO_FORTRESS] = HintText(CustomMessage("They say that a #pot in Gerudo Fortress# contains #[[1]]#.", /*german*/ "Man erzählt sich, daß eine #Vase in der Gerudo-Festung# #[[1]]# enthielte.", @@ -1504,15 +1512,24 @@ void StaticData::HintTable_Init_Exclude_Overworld() { /*german*/ "Man erzählt sich, daß eine #Vase in der Gespensterwüste# #[[1]]# enthielte.", /*french*/ "Selon moi, une #jarre dans le Désert Hanté# contient #[[1]]#.", {QM_RED, QM_GREEN})); - hintTextTable[RHT_POT_MARKET] = HintText(CustomMessage("They say that a #pot in Market# contains #[[1]]#.", - /*german*/ "Man erzählt sich, daß eine #Vase auf dem Markt# #[[1]]# enthielte.", - /*french*/ "Selon moi, une #jarre dans la Place du Marché# contient #[[1]]#.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_POT_GUARD_HOUSE] = HintText(CustomMessage("They say that a #pot in the Guard House# contains #[[1]]#.", + /*german*/ "Man erzählt sich, daß eine #Vase auf dem Markt# #[[1]]# enthielte.",//TODO_TRANSLATE update to match + /*french*/ "Selon moi, une #jarre dans la Place du Marché# contient #[[1]]#.", {QM_RED, QM_GREEN}));//TODO_TRANSLATE update to match + + hintTextTable[RHT_POT_POE_SHOP] = HintText(CustomMessage("They say that a #pot in the Poe Shop# contains #[[1]]#.", + /*german*/ "Man erzählt sich, daß eine #Vase auf dem Markt# #[[1]]# enthielte.",//TODO_TRANSLATE update to match + /*french*/ "Selon moi, une #jarre dans la Place du Marché# contient #[[1]]#.", {QM_RED, QM_GREEN}));//TODO_TRANSLATE update to match + + hintTextTable[RHT_POT_ALLY_HOUSE] = HintText(CustomMessage("They say that a #bearded man's pot# contains #[[1]]#.", + /*german*/ "Man erzählt sich, daß eine #Vase auf dem Markt# #[[1]]# enthielte.",//TODO_TRANSLATE update to match + /*french*/ "Selon moi, une #jarre dans la Place du Marché# contient #[[1]]#.", {QM_RED, QM_GREEN}));//TODO_TRANSLATE update to match hintTextTable[RHT_POT_KAKARIKO] = HintText(CustomMessage("They say that a #pot in Kakariko Village# contains #[[1]]#.", /*german*/ "Man erzählt sich, daß eine #Vase in Kakariko# #[[1]]# enthielte.", /*french*/ "Selon moi, une #jarre dans le Village de Cocorico# contient #[[1]]#.", {QM_RED, QM_GREEN})); - hintTextTable[RHT_POT_GRAVEYARD] = HintText(CustomMessage("They say that a #pot in Graveyard# contains #[[1]]#.", + hintTextTable[RHT_POT_DAMPE] = HintText(CustomMessage("They say that a #pot in gravekeeper's tomb# contains #[[1]]#.", + //TODO_TRANSLATE check these to make sure they refernce dampe's tomb not the graveyard area /*german*/ "Man erzählt sich, daß eine #Vase auf dem Friedhof# #[[1]]# enthielte.", /*french*/ "Selon moi, une #jarre dans le Cimetière# contient #[[1]]#.", {QM_RED, QM_GREEN})); @@ -1536,13 +1553,17 @@ void StaticData::HintTable_Init_Exclude_Overworld() { /*german*/ "Man erzählt sich, daß eine #Vase auf der Lon Lon-Farm# #[[1]]# enthielte.", /*french*/ "Selon moi, une #jarre dans le Ranch Lon Lon# contient #[[1]]#.", {QM_RED, QM_GREEN})); - hintTextTable[RHT_POT_HYRULE_FIELD] = HintText(CustomMessage("They say that a #pot in Hyrule Field# contains #[[1]]#.", - /*german*/ "Man erzählt sich, daß eine #Vase in der Hylianischen Steppe# #[[1]]# enthielte.", - /*french*/ "Selon moi, une #jarre dans la Plaine d'Hyrule# contient #[[1]]#.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_POT_TALONS_HOUSE] = HintText(CustomMessage("They say that a #pot in Talon's Bedroom# contains #[[1]]#.", + /*german*/ "Man erzählt sich, daß eine #Vase auf der Lon Lon-Farm# #[[1]]# enthielte.",//TODO_TRANSLATE update to match + /*french*/ "Selon moi, une #jarre dans le Ranch Lon Lon# contient #[[1]]#.", {QM_RED, QM_GREEN}));//TODO_TRANSLATE update to match - hintTextTable[RHT_POT_HYRULE_CASTLE] = HintText(CustomMessage("They say that a #pot in Hyrule Castle# contains #[[1]]#.", - /*german*/ "Man erzählt sich, daß eine #Vase in Schloß Hyrule# #[[1]]# enthielte.", - /*french*/ "Selon moi, une #jarre dans le Château d'Hyrule# contient #[[1]]#.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_POT_WEB_GROTTO] = HintText(CustomMessage("They say that a #pot behind a grotto's webbing# contains #[[1]]#.", + /*german*/ "Man erzählt sich, daß eine #Vase in der Hylianischen Steppe# #[[1]]# enthielte.",//TODO_TRANSLATE update to match + /*french*/ "Selon moi, une #jarre dans la Plaine d'Hyrule# contient #[[1]]#.", {QM_RED, QM_GREEN}));//TODO_TRANSLATE update to match + + hintTextTable[RHT_POT_MUD_WALL_GROTTO] = HintText(CustomMessage("They say that a #pot walled off in a grotto# contains #[[1]]#.", + /*german*/ "Man erzählt sich, daß eine #Vase in Schloß Hyrule# #[[1]]# enthielte.",//TODO_TRANSLATE update to match + /*french*/ "Selon moi, une #jarre dans le Château d'Hyrule# contient #[[1]]#.", {QM_RED, QM_GREEN}));//TODO_TRANSLATE update to match hintTextTable[RHT_KOKIRI_FOREST_RUPEE] = HintText(CustomMessage("They say that a rupee in a #tranquil forest# hides #[[1]]#.", /*german*/ "Man erzählt sich, daß ein Rubin in einem #ruhigen Wald# #[[1]]# verstecke.", diff --git a/soh/soh/Enhancements/randomizer/ShufflePots.cpp b/soh/soh/Enhancements/randomizer/ShufflePots.cpp index 9e6f50f42..5afd9859c 100644 --- a/soh/soh/Enhancements/randomizer/ShufflePots.cpp +++ b/soh/soh/Enhancements/randomizer/ShufflePots.cpp @@ -103,11 +103,11 @@ void Rando::StaticData::RegisterPotLocations() { // clang-format off // Overworld Pots // Randomizer Check Randomizer Check Quest Area Scene ID Params Short Name Hint Text Key Vanilla Spoiler Collection Check - locationTable[RC_KF_LINKS_HOUSE_POT] = Location::Pot(RC_KF_LINKS_HOUSE_POT, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_LINKS_HOUSE, TWO_ACTOR_PARAMS(-118, 51), "Links House Pot", RHT_POT_KOKIRI_FOREST, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_LINKS_HOUSE_POT)); - locationTable[RC_KF_TWINS_HOUSE_POT_2] = Location::Pot(RC_KF_TWINS_HOUSE_POT_2, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_TWINS_HOUSE, TWO_ACTOR_PARAMS(35, 57), "Twins House Pot 2", RHT_POT_KOKIRI_FOREST, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_TWINS_HOUSE_POT_2)); - locationTable[RC_KF_TWINS_HOUSE_POT_1] = Location::Pot(RC_KF_TWINS_HOUSE_POT_1, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_TWINS_HOUSE, TWO_ACTOR_PARAMS(33, -55), "Twins House Pot 1", RHT_POT_KOKIRI_FOREST, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_TWINS_HOUSE_POT_1)); - locationTable[RC_KF_BROTHERS_HOUSE_POT_1] = Location::Pot(RC_KF_BROTHERS_HOUSE_POT_1, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KNOW_IT_ALL_BROS_HOUSE, TWO_ACTOR_PARAMS(-134, -29), "Brothers House Pot 1", RHT_POT_KOKIRI_FOREST, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_BROTHERS_HOUSE_POT_1)); - locationTable[RC_KF_BROTHERS_HOUSE_POT_2] = Location::Pot(RC_KF_BROTHERS_HOUSE_POT_2, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KNOW_IT_ALL_BROS_HOUSE, TWO_ACTOR_PARAMS(-68, 114), "Brothers House Pot 2", RHT_POT_KOKIRI_FOREST, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_BROTHERS_HOUSE_POT_2)); + locationTable[RC_KF_LINKS_HOUSE_POT] = Location::Pot(RC_KF_LINKS_HOUSE_POT, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_LINKS_HOUSE, TWO_ACTOR_PARAMS(-118, 51), "Links House Pot", RHT_POT_LINKS_HOUSE, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_LINKS_HOUSE_POT)); + locationTable[RC_KF_TWINS_HOUSE_POT_2] = Location::Pot(RC_KF_TWINS_HOUSE_POT_2, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_TWINS_HOUSE, TWO_ACTOR_PARAMS(35, 57), "Twins House Pot 2", RHT_POT_TWINS_HOUSE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_TWINS_HOUSE_POT_2)); + locationTable[RC_KF_TWINS_HOUSE_POT_1] = Location::Pot(RC_KF_TWINS_HOUSE_POT_1, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_TWINS_HOUSE, TWO_ACTOR_PARAMS(33, -55), "Twins House Pot 1", RHT_POT_TWINS_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_TWINS_HOUSE_POT_1)); + locationTable[RC_KF_BROTHERS_HOUSE_POT_1] = Location::Pot(RC_KF_BROTHERS_HOUSE_POT_1, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KNOW_IT_ALL_BROS_HOUSE, TWO_ACTOR_PARAMS(-134, -29), "Brothers House Pot 1", RHT_POT_KNOW_IT_ALL, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_BROTHERS_HOUSE_POT_1)); + locationTable[RC_KF_BROTHERS_HOUSE_POT_2] = Location::Pot(RC_KF_BROTHERS_HOUSE_POT_2, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KNOW_IT_ALL_BROS_HOUSE, TWO_ACTOR_PARAMS(-68, 114), "Brothers House Pot 2", RHT_POT_KNOW_IT_ALL, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_BROTHERS_HOUSE_POT_2)); locationTable[RC_GF_BREAK_ROOM_POT_1] = Location::Pot(RC_GF_BREAK_ROOM_POT_1, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(1438, -3629), "Break Room Pot 1", RHT_POT_GERUDO_FORTRESS, RG_ARROWS_10, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GF_BREAK_ROOM_POT_1)); locationTable[RC_GF_BREAK_ROOM_POT_2] = Location::Pot(RC_GF_BREAK_ROOM_POT_2, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(1403, -3679), "Break Room Pot 2", RHT_POT_GERUDO_FORTRESS, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GF_BREAK_ROOM_POT_2)); locationTable[RC_GF_KITCHEN_POT_1] = Location::Pot(RC_GF_KITCHEN_POT_1, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(1908, -789), "Kitchen Pot 1", RHT_POT_GERUDO_FORTRESS, RG_ARROWS_10, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GF_KITCHEN_POT_1)); @@ -128,64 +128,64 @@ void Rando::StaticData::RegisterPotLocations() { locationTable[RC_WASTELAND_NEAR_GS_POT_2] = Location::Pot(RC_WASTELAND_NEAR_GS_POT_2, RCQUEST_BOTH, RCAREA_WASTELAND, SCENE_HAUNTED_WASTELAND, TWO_ACTOR_PARAMS(485, -2463), "Near GS Pot 2", RHT_POT_GERUDO_FORTRESS, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_WASTELAND_NEAR_GS_POT_2)); locationTable[RC_WASTELAND_NEAR_GS_POT_3] = Location::Pot(RC_WASTELAND_NEAR_GS_POT_3, RCQUEST_BOTH, RCAREA_WASTELAND, SCENE_HAUNTED_WASTELAND, TWO_ACTOR_PARAMS(806, -2426), "Near GS Pot 3", RHT_POT_GERUDO_FORTRESS, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_WASTELAND_NEAR_GS_POT_3)); locationTable[RC_WASTELAND_NEAR_GS_POT_4] = Location::Pot(RC_WASTELAND_NEAR_GS_POT_4, RCQUEST_BOTH, RCAREA_WASTELAND, SCENE_HAUNTED_WASTELAND, TWO_ACTOR_PARAMS(801, -2460), "Near GS Pot 4", RHT_POT_GERUDO_FORTRESS, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_WASTELAND_NEAR_GS_POT_4)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_1] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_1, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-60, 27), "Guard House Child Pot 1", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_1)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_2] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_2, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-89, 28), "Guard House Child Pot 2", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_2)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_3] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_3, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-110, 6), "Guard House Child Pot 3", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_3)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_4] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_4, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-58, -7), "Guard House Child Pot 4", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_4)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_5] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_5, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-80, -7), "Guard House Child Pot 5", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_5)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_6] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_6, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-65, -45), "Guard House Child Pot 6", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_6)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_7] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_7, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-85, -41), "Guard House Child Pot 7", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_7)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_8] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_8, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-107, -45), "Guard House Child Pot 8", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_8)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_9] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_9, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-66, -79), "Guard House Child Pot 9", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_9)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_10] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_10, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-88, -84), "Guard House Child Pot 10", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_10)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_11] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_11, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(70, 215), "Guard House Child Pot 11", RHT_POT_MARKET, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_11)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_12] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_12, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(68, 148), "Guard House Child Pot 12", RHT_POT_MARKET, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_12)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_13] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_13, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(73, 117), "Guard House Child Pot 13", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_13)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_14] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_14, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(40, 123), "Guard House Child Pot 14", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_14)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_15] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_15, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(43, 89), "Guard House Child Pot 15", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_15)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_16] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_16, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(68, 81), "Guard House Child Pot 16", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_16)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_17] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_17, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(21, 73), "Guard House Child Pot 17", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_17)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_18] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_18, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(64, 45), "Guard House Child Pot 18", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_18)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_19] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_19, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(84, 31), "Guard House Child Pot 19", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_19)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_20] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_20, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(42, 26), "Guard House Child Pot 20", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_20)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_21] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_21, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(20, 34), "Guard House Child Pot 21", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_21)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_22] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_22, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(89, -2), "Guard House Child Pot 22", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_22)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_23] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_23, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(70, -12), "Guard House Child Pot 23", RHT_POT_MARKET, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_23)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_24] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_24, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(42, -5), "Guard House Child Pot 24", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_24)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_25] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_25, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(16, -6), "Guard House Child Pot 25", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_25)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_26] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_26, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(68, -44), "Guard House Child Pot 26", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_26)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_27] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_27, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(37, -40), "Guard House Child Pot 27", RHT_POT_MARKET, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_27)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_28] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_28, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(70, -80), "Guard House Child Pot 28", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_28)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_29] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_29, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(50, -74), "Guard House Child Pot 29", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_29)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_30] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_30, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(28, -79), "Guard House Child Pot 30", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_30)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_31] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_31, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(39, -111), "Guard House Child Pot 31", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_31)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_32] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_32, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(169, 216), "Guard House Child Pot 32", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_32)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_33] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_33, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(168, 166), "Guard House Child Pot 33", RHT_POT_MARKET, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_33)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_34] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_34, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(170, 120), "Guard House Child Pot 34", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_34)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_35] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_35, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(177, 85), "Guard House Child Pot 35", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_35)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_36] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_36, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(155, 39), "Guard House Child Pot 36", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_36)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_37] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_37, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(184, 13), "Guard House Child Pot 37", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_37)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_38] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_38, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(156, -1), "Guard House Child Pot 38", RHT_POT_MARKET, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_38)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_39] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_39, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(181, -33), "Guard House Child Pot 39", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_39)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_40] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_40, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(156, -45), "Guard House Child Pot 40", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_40)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_41] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_41, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(172, -82), "Guard House Child Pot 41", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_41)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_42] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_42, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(170, -120), "Guard House Child Pot 42", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_42)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_43] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_43, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(170, -166), "Guard House Child Pot 43", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_43)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_44] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_44, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(170, -216), "Guard House Child Pot 44", RHT_POT_MARKET, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_44)); - locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_1] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_1, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(61, 204), "Guard House Adult Pot 1", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_1)); - locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_2] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_2, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(71, 132), "Guard House Adult Pot 2", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_2)); - locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_3] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_3, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(74, 23), "Guard House Adult Pot 3", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_3)); - locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_4] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_4, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(40, 4), "Guard House Adult Pot 4", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_4)); - locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_5] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_5, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(71, -22), "Guard House Adult Pot 5", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_5)); - locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_6] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_6, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(44, -151), "Guard House Adult Pot 6", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_6)); - locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_7] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_7, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(79, -182), "Guard House Adult Pot 7", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_7)); - locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_8] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_8, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(44, -198), "Guard House Adult Pot 8", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_8)); - locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_9] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_9, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(168, 210), "Guard House Adult Pot 9", RHT_POT_MARKET, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_9)); - locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_10] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_10, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(167, -122), "Guard House Adult Pot 10", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_10)); - locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_11] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_11, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(167, -210), "Guard House Adult Pot 11", RHT_POT_MARKET, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_11)); - locationTable[RC_MK_BACK_ALLEY_HOUSE_POT_1] = Location::Pot(RC_MK_BACK_ALLEY_HOUSE_POT_1, RCQUEST_BOTH, RCAREA_MARKET, SCENE_BACK_ALLEY_HOUSE, TWO_ACTOR_PARAMS(100, 45), "Back Alley House Pot 1", RHT_POT_MARKET, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_BACK_ALLEY_HOUSE_POT_1)); - locationTable[RC_MK_BACK_ALLEY_HOUSE_POT_2] = Location::Pot(RC_MK_BACK_ALLEY_HOUSE_POT_2, RCQUEST_BOTH, RCAREA_MARKET, SCENE_BACK_ALLEY_HOUSE, TWO_ACTOR_PARAMS(12, -180), "Back Alley House Pot 2", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_BACK_ALLEY_HOUSE_POT_2)); - locationTable[RC_MK_BACK_ALLEY_HOUSE_POT_3] = Location::Pot(RC_MK_BACK_ALLEY_HOUSE_POT_3, RCQUEST_BOTH, RCAREA_MARKET, SCENE_BACK_ALLEY_HOUSE, TWO_ACTOR_PARAMS(-54, -180), "Back Alley House Pot 3", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_BACK_ALLEY_HOUSE_POT_3)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_1] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_1, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-60, 27), "Guard House Child Pot 1", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_1)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_2] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_2, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-89, 28), "Guard House Child Pot 2", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_2)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_3] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_3, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-110, 6), "Guard House Child Pot 3", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_3)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_4] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_4, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-58, -7), "Guard House Child Pot 4", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_4)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_5] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_5, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-80, -7), "Guard House Child Pot 5", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_5)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_6] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_6, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-65, -45), "Guard House Child Pot 6", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_6)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_7] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_7, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-85, -41), "Guard House Child Pot 7", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_7)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_8] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_8, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-107, -45), "Guard House Child Pot 8", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_8)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_9] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_9, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-66, -79), "Guard House Child Pot 9", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_9)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_10] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_10, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-88, -84), "Guard House Child Pot 10", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_10)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_11] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_11, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(70, 215), "Guard House Child Pot 11", RHT_POT_GUARD_HOUSE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_11)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_12] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_12, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(68, 148), "Guard House Child Pot 12", RHT_POT_GUARD_HOUSE, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_12)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_13] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_13, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(73, 117), "Guard House Child Pot 13", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_13)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_14] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_14, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(40, 123), "Guard House Child Pot 14", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_14)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_15] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_15, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(43, 89), "Guard House Child Pot 15", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_15)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_16] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_16, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(68, 81), "Guard House Child Pot 16", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_16)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_17] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_17, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(21, 73), "Guard House Child Pot 17", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_17)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_18] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_18, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(64, 45), "Guard House Child Pot 18", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_18)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_19] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_19, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(84, 31), "Guard House Child Pot 19", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_19)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_20] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_20, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(42, 26), "Guard House Child Pot 20", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_20)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_21] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_21, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(20, 34), "Guard House Child Pot 21", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_21)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_22] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_22, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(89, -2), "Guard House Child Pot 22", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_22)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_23] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_23, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(70, -12), "Guard House Child Pot 23", RHT_POT_GUARD_HOUSE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_23)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_24] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_24, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(42, -5), "Guard House Child Pot 24", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_24)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_25] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_25, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(16, -6), "Guard House Child Pot 25", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_25)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_26] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_26, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(68, -44), "Guard House Child Pot 26", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_26)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_27] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_27, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(37, -40), "Guard House Child Pot 27", RHT_POT_GUARD_HOUSE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_27)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_28] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_28, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(70, -80), "Guard House Child Pot 28", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_28)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_29] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_29, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(50, -74), "Guard House Child Pot 29", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_29)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_30] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_30, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(28, -79), "Guard House Child Pot 30", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_30)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_31] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_31, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(39, -111), "Guard House Child Pot 31", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_31)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_32] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_32, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(169, 216), "Guard House Child Pot 32", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_32)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_33] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_33, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(168, 166), "Guard House Child Pot 33", RHT_POT_GUARD_HOUSE, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_33)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_34] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_34, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(170, 120), "Guard House Child Pot 34", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_34)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_35] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_35, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(177, 85), "Guard House Child Pot 35", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_35)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_36] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_36, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(155, 39), "Guard House Child Pot 36", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_36)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_37] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_37, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(184, 13), "Guard House Child Pot 37", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_37)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_38] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_38, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(156, -1), "Guard House Child Pot 38", RHT_POT_GUARD_HOUSE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_38)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_39] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_39, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(181, -33), "Guard House Child Pot 39", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_39)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_40] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_40, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(156, -45), "Guard House Child Pot 40", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_40)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_41] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_41, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(172, -82), "Guard House Child Pot 41", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_41)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_42] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_42, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(170, -120), "Guard House Child Pot 42", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_42)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_43] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_43, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(170, -166), "Guard House Child Pot 43", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_43)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_44] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_44, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(170, -216), "Guard House Child Pot 44", RHT_POT_GUARD_HOUSE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_44)); + locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_1] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_1, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(61, 204), "Guard House Adult Pot 1", RHT_POT_POE_SHOP, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_1)); + locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_2] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_2, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(71, 132), "Guard House Adult Pot 2", RHT_POT_POE_SHOP, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_2)); + locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_3] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_3, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(74, 23), "Guard House Adult Pot 3", RHT_POT_POE_SHOP, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_3)); + locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_4] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_4, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(40, 4), "Guard House Adult Pot 4", RHT_POT_POE_SHOP, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_4)); + locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_5] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_5, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(71, -22), "Guard House Adult Pot 5", RHT_POT_POE_SHOP, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_5)); + locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_6] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_6, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(44, -151), "Guard House Adult Pot 6", RHT_POT_POE_SHOP, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_6)); + locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_7] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_7, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(79, -182), "Guard House Adult Pot 7", RHT_POT_POE_SHOP, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_7)); + locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_8] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_8, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(44, -198), "Guard House Adult Pot 8", RHT_POT_POE_SHOP, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_8)); + locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_9] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_9, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(168, 210), "Guard House Adult Pot 9", RHT_POT_POE_SHOP, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_9)); + locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_10] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_10, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(167, -122), "Guard House Adult Pot 10", RHT_POT_POE_SHOP, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_10)); + locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_11] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_11, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(167, -210), "Guard House Adult Pot 11", RHT_POT_POE_SHOP, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_11)); + locationTable[RC_MK_BACK_ALLEY_HOUSE_POT_1] = Location::Pot(RC_MK_BACK_ALLEY_HOUSE_POT_1, RCQUEST_BOTH, RCAREA_MARKET, SCENE_BACK_ALLEY_HOUSE, TWO_ACTOR_PARAMS(100, 45), "Back Alley House Pot 1", RHT_POT_ALLY_HOUSE, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_BACK_ALLEY_HOUSE_POT_1)); + locationTable[RC_MK_BACK_ALLEY_HOUSE_POT_2] = Location::Pot(RC_MK_BACK_ALLEY_HOUSE_POT_2, RCQUEST_BOTH, RCAREA_MARKET, SCENE_BACK_ALLEY_HOUSE, TWO_ACTOR_PARAMS(12, -180), "Back Alley House Pot 2", RHT_POT_ALLY_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_BACK_ALLEY_HOUSE_POT_2)); + locationTable[RC_MK_BACK_ALLEY_HOUSE_POT_3] = Location::Pot(RC_MK_BACK_ALLEY_HOUSE_POT_3, RCQUEST_BOTH, RCAREA_MARKET, SCENE_BACK_ALLEY_HOUSE, TWO_ACTOR_PARAMS(-54, -180), "Back Alley House Pot 3", RHT_POT_ALLY_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_BACK_ALLEY_HOUSE_POT_3)); locationTable[RC_KAK_NEAR_POTION_SHOP_POT_1] = Location::Pot(RC_KAK_NEAR_POTION_SHOP_POT_1, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(222, -377), "Near Potion Shop Pot 1", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_POTION_SHOP_POT_1)); locationTable[RC_KAK_NEAR_POTION_SHOP_POT_2] = Location::Pot(RC_KAK_NEAR_POTION_SHOP_POT_2, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(255, -366), "Near Potion Shop Pot 2", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_POTION_SHOP_POT_2)); locationTable[RC_KAK_NEAR_POTION_SHOP_POT_3] = Location::Pot(RC_KAK_NEAR_POTION_SHOP_POT_3, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(284, -356), "Near Potion Shop Pot 3", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_POTION_SHOP_POT_3)); @@ -197,12 +197,12 @@ void Rando::StaticData::RegisterPotLocations() { locationTable[RC_KAK_NEAR_GUARDS_HOUSE_POT_3] = Location::Pot(RC_KAK_NEAR_GUARDS_HOUSE_POT_3, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-450, -895), "Near Guards House Pot 3", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_GUARDS_HOUSE_POT_3)); locationTable[RC_KAK_NEAR_MEDICINE_SHOP_POT_1] = Location::Pot(RC_KAK_NEAR_MEDICINE_SHOP_POT_1, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(781, 89), "Near Medicine Shop Pot 1", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_MEDICINE_SHOP_POT_1)); locationTable[RC_KAK_NEAR_MEDICINE_SHOP_POT_2] = Location::Pot(RC_KAK_NEAR_MEDICINE_SHOP_POT_2, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(815, 89), "Near Medicine Shop Pot 2", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_MEDICINE_SHOP_POT_2)); - locationTable[RC_GY_DAMPES_GRAVE_POT_1] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_1, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(-319, -1542), "Dampes Grave Pot 1", RHT_POT_GRAVEYARD, RG_ARROWS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_1)); - locationTable[RC_GY_DAMPES_GRAVE_POT_2] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_2, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(-319, -1600), "Dampes Grave Pot 2", RHT_POT_GRAVEYARD, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_2)); - locationTable[RC_GY_DAMPES_GRAVE_POT_3] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_3, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(-364, -1571), "Dampes Grave Pot 3", RHT_POT_GRAVEYARD, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_3)); - locationTable[RC_GY_DAMPES_GRAVE_POT_4] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_4, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(198, -1540), "Dampes Grave Pot 4", RHT_POT_GRAVEYARD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_4)); - locationTable[RC_GY_DAMPES_GRAVE_POT_5] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_5, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(198, -1608), "Dampes Grave Pot 5", RHT_POT_GRAVEYARD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_5)); - locationTable[RC_GY_DAMPES_GRAVE_POT_6] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_6, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(239, -1577), "Dampes Grave Pot 6", RHT_POT_GRAVEYARD, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_6)); + locationTable[RC_GY_DAMPES_GRAVE_POT_1] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_1, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(-319, -1542), "Dampes Grave Pot 1", RHT_POT_DAMPE, RG_ARROWS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_1)); + locationTable[RC_GY_DAMPES_GRAVE_POT_2] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_2, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(-319, -1600), "Dampes Grave Pot 2", RHT_POT_DAMPE, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_2)); + locationTable[RC_GY_DAMPES_GRAVE_POT_3] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_3, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(-364, -1571), "Dampes Grave Pot 3", RHT_POT_DAMPE, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_3)); + locationTable[RC_GY_DAMPES_GRAVE_POT_4] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_4, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(198, -1540), "Dampes Grave Pot 4", RHT_POT_DAMPE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_4)); + locationTable[RC_GY_DAMPES_GRAVE_POT_5] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_5, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(198, -1608), "Dampes Grave Pot 5", RHT_POT_DAMPE, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_5)); + locationTable[RC_GY_DAMPES_GRAVE_POT_6] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_6, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(239, -1577), "Dampes Grave Pot 6", RHT_POT_DAMPE, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_6)); locationTable[RC_GC_LOWER_STAIRCASE_POT_1] = Location::Pot(RC_GC_LOWER_STAIRCASE_POT_1, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS(-189, 866), "Lower Staircase Pot 1", RHT_POT_GORON_CITY, RG_DEKU_STICK_1, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_LOWER_STAIRCASE_POT_1)); locationTable[RC_GC_LOWER_STAIRCASE_POT_2] = Location::Pot(RC_GC_LOWER_STAIRCASE_POT_2, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS(-271, 825), "Lower Staircase Pot 2", RHT_POT_GORON_CITY, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_LOWER_STAIRCASE_POT_2)); locationTable[RC_GC_UPPER_STAIRCASE_POT_1] = Location::Pot(RC_GC_UPPER_STAIRCASE_POT_1, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS(-1170, 60), "Upper Staircase Pot 1", RHT_POT_GORON_CITY, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_UPPER_STAIRCASE_POT_1)); @@ -235,15 +235,15 @@ void Rando::StaticData::RegisterPotLocations() { locationTable[RC_LLR_RAIN_SHED_POT_1] = Location::Pot(RC_LLR_RAIN_SHED_POT_1, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, TWO_ACTOR_PARAMS(852, 172), "Rain Shed Pot 1", RHT_POT_LON_LON_RANCH, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_RAIN_SHED_POT_1)); locationTable[RC_LLR_RAIN_SHED_POT_2] = Location::Pot(RC_LLR_RAIN_SHED_POT_2, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, TWO_ACTOR_PARAMS(840, 212), "Rain Shed Pot 2", RHT_POT_LON_LON_RANCH, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_RAIN_SHED_POT_2)); locationTable[RC_LLR_RAIN_SHED_POT_3] = Location::Pot(RC_LLR_RAIN_SHED_POT_3, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, TWO_ACTOR_PARAMS(872, 219), "Rain Shed Pot 3", RHT_POT_LON_LON_RANCH, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_RAIN_SHED_POT_3)); - locationTable[RC_LLR_TALONS_HOUSE_POT_1] = Location::Pot(RC_LLR_TALONS_HOUSE_POT_1, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_BUILDINGS, TWO_ACTOR_PARAMS(1255, 47), "Talons House Pot 1", RHT_POT_LON_LON_RANCH, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_TALONS_HOUSE_POT_1)); - locationTable[RC_LLR_TALONS_HOUSE_POT_2] = Location::Pot(RC_LLR_TALONS_HOUSE_POT_2, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_BUILDINGS, TWO_ACTOR_PARAMS(1256, -51), "Talons House Pot 2", RHT_POT_LON_LON_RANCH, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_TALONS_HOUSE_POT_2)); - locationTable[RC_LLR_TALONS_HOUSE_POT_3] = Location::Pot(RC_LLR_TALONS_HOUSE_POT_3, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_BUILDINGS, TWO_ACTOR_PARAMS(1256, -78), "Talons House Pot 3", RHT_POT_LON_LON_RANCH, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_TALONS_HOUSE_POT_3)); - locationTable[RC_HF_COW_GROTTO_POT_1] = Location::Pot(RC_HF_COW_GROTTO_POT_1, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, TWO_ACTOR_PARAMS(3410, -223), "Cow Grotto Pot 1", RHT_POT_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_COW_GROTTO_POT_1)); - locationTable[RC_HF_COW_GROTTO_POT_2] = Location::Pot(RC_HF_COW_GROTTO_POT_2, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, TWO_ACTOR_PARAMS(3390, -258), "Cow Grotto Pot 2", RHT_POT_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_COW_GROTTO_POT_2)); - locationTable[RC_HC_STORMS_GROTTO_POT_1] = Location::Pot(RC_HC_STORMS_GROTTO_POT_1, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, TWO_ACTOR_PARAMS(1843, 1014), "Storms Grotto Pot 1", RHT_POT_HYRULE_CASTLE, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_STORMS_GROTTO_POT_1)); - locationTable[RC_HC_STORMS_GROTTO_POT_2] = Location::Pot(RC_HC_STORMS_GROTTO_POT_2, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, TWO_ACTOR_PARAMS(1769, 954), "Storms Grotto Pot 2", RHT_POT_HYRULE_CASTLE, RG_ARROWS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_STORMS_GROTTO_POT_2)); - locationTable[RC_HC_STORMS_GROTTO_POT_3] = Location::Pot(RC_HC_STORMS_GROTTO_POT_3, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, TWO_ACTOR_PARAMS(1857, 897), "Storms Grotto Pot 3", RHT_POT_HYRULE_CASTLE, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_STORMS_GROTTO_POT_3)); - locationTable[RC_HC_STORMS_GROTTO_POT_4] = Location::Pot(RC_HC_STORMS_GROTTO_POT_4, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, TWO_ACTOR_PARAMS(1764, 847), "Storms Grotto Pot 4", RHT_POT_HYRULE_CASTLE, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_STORMS_GROTTO_POT_4)); + locationTable[RC_LLR_TALONS_HOUSE_POT_1] = Location::Pot(RC_LLR_TALONS_HOUSE_POT_1, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_BUILDINGS, TWO_ACTOR_PARAMS(1255, 47), "Talons House Pot 1", RHT_POT_TALONS_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_TALONS_HOUSE_POT_1)); + locationTable[RC_LLR_TALONS_HOUSE_POT_2] = Location::Pot(RC_LLR_TALONS_HOUSE_POT_2, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_BUILDINGS, TWO_ACTOR_PARAMS(1256, -51), "Talons House Pot 2", RHT_POT_TALONS_HOUSE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_TALONS_HOUSE_POT_2)); + locationTable[RC_LLR_TALONS_HOUSE_POT_3] = Location::Pot(RC_LLR_TALONS_HOUSE_POT_3, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_BUILDINGS, TWO_ACTOR_PARAMS(1256, -78), "Talons House Pot 3", RHT_POT_TALONS_HOUSE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_TALONS_HOUSE_POT_3)); + locationTable[RC_HF_COW_GROTTO_POT_1] = Location::Pot(RC_HF_COW_GROTTO_POT_1, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, TWO_ACTOR_PARAMS(3410, -223), "Cow Grotto Pot 1", RHT_POT_WEB_GROTTO, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_COW_GROTTO_POT_1)); + locationTable[RC_HF_COW_GROTTO_POT_2] = Location::Pot(RC_HF_COW_GROTTO_POT_2, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, TWO_ACTOR_PARAMS(3390, -258), "Cow Grotto Pot 2", RHT_POT_WEB_GROTTO, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_COW_GROTTO_POT_2)); + locationTable[RC_HC_STORMS_GROTTO_POT_1] = Location::Pot(RC_HC_STORMS_GROTTO_POT_1, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, TWO_ACTOR_PARAMS(1843, 1014), "Storms Grotto Pot 1", RHT_POT_MUD_WALL_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_STORMS_GROTTO_POT_1)); + locationTable[RC_HC_STORMS_GROTTO_POT_2] = Location::Pot(RC_HC_STORMS_GROTTO_POT_2, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, TWO_ACTOR_PARAMS(1769, 954), "Storms Grotto Pot 2", RHT_POT_MUD_WALL_GROTTO, RG_ARROWS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_STORMS_GROTTO_POT_2)); + locationTable[RC_HC_STORMS_GROTTO_POT_3] = Location::Pot(RC_HC_STORMS_GROTTO_POT_3, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, TWO_ACTOR_PARAMS(1857, 897), "Storms Grotto Pot 3", RHT_POT_MUD_WALL_GROTTO, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_STORMS_GROTTO_POT_3)); + locationTable[RC_HC_STORMS_GROTTO_POT_4] = Location::Pot(RC_HC_STORMS_GROTTO_POT_4, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, TWO_ACTOR_PARAMS(1764, 847), "Storms Grotto Pot 4", RHT_POT_MUD_WALL_GROTTO, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_STORMS_GROTTO_POT_4)); // Dungeon Pots // Randomizer Check Randomizer Check Quest Area Scene ID Params Short Name Spoiler Name Hint Text Key Vanilla Spoiler Collection Check diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index d19d32c99..d9eae0af8 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -5370,19 +5370,24 @@ typedef enum { RHT_SKULLS_HINT, RHT_MASK_SHOP_HINT, // Shuffle Pots - RHT_POT_KOKIRI_FOREST, + RHT_POT_LINKS_HOUSE, + RHT_POT_TWINS_HOUSE, + RHT_POT_KNOW_IT_ALL, RHT_POT_GERUDO_FORTRESS, RHT_POT_WASTELAND, - RHT_POT_MARKET, + RHT_POT_GUARD_HOUSE, + RHT_POT_POE_SHOP, + RHT_POT_ALLY_HOUSE, RHT_POT_KAKARIKO, - RHT_POT_GRAVEYARD, + RHT_POT_DAMPE, RHT_POT_GORON_CITY, RHT_POT_DEATH_MOUNTAIN_CRATER, RHT_POT_ZORAS_DOMAIN, RHT_POT_ZORAS_FOUNTAIN, RHT_POT_LON_LON_RANCH, - RHT_POT_HYRULE_FIELD, - RHT_POT_HYRULE_CASTLE, + RHT_POT_TALONS_HOUSE, + RHT_POT_WEB_GROTTO, + RHT_POT_MUD_WALL_GROTTO, RHT_POT_DODONGOS_CAVERN, RHT_POT_JABU_JABUS_BELLY, RHT_POT_FOREST_TEMPLE, From 2daf343755be6968b2b259e3f2b42f50f343ce28 Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Thu, 19 Jun 2025 21:26:30 +0100 Subject: [PATCH 10/31] Change excluded checks to have junk instead of non-advancment. (#5592) * Change excluded checks to have junk instead of non-advancment * loud frying pan noises --- .../randomizer/3drando/item_pool.cpp | 2 +- soh/soh/Enhancements/randomizer/item.cpp | 14 +++++--- soh/soh/Enhancements/randomizer/item.h | 5 ++- soh/soh/Enhancements/randomizer/item_list.cpp | 32 +++++++++---------- 4 files changed, 31 insertions(+), 22 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp index a04a7d65c..fb2ac94cc 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -354,7 +354,7 @@ void PlaceJunkInExcludedLocation(const RandomizerCheck il) { // place a non-advancement item in this location auto ctx = Rando::Context::GetInstance(); for (size_t i = 0; i < ItemPool.size(); i++) { - if (!Rando::StaticData::RetrieveItem(ItemPool[i]).IsAdvancement()) { + if (Rando::StaticData::RetrieveItem(ItemPool[i]).GetCategory() == ITEM_CATEGORY_JUNK) { ctx->PlaceItemInLocation(il, ItemPool[i]); ItemPool.erase(ItemPool.begin() + i); return; diff --git a/soh/soh/Enhancements/randomizer/item.cpp b/soh/soh/Enhancements/randomizer/item.cpp index 3b75a0c95..71f9fff38 100644 --- a/soh/soh/Enhancements/randomizer/item.cpp +++ b/soh/soh/Enhancements/randomizer/item.cpp @@ -21,7 +21,8 @@ Item::Item(const RandomizerGet randomizerGet_, Text name_, const ItemType type_, const int16_t chestAnimation_, const GetItemCategory category_, const uint16_t modIndex_, const bool progressive_, const uint16_t price_) : randomizerGet(randomizerGet_), name(std::move(name_)), type(type_), getItemId(getItemId_), - advancement(advancement_), logicVal(logicVal_), hintKey(hintKey_), progressive(progressive_), price(price_) { + advancement(advancement_), logicVal(logicVal_), hintKey(hintKey_), category(category_), progressive(progressive_), + price(price_) { if (modIndex_ == MOD_RANDOMIZER || getItemId > 0x7D) { giEntry = std::make_shared(GetItemEntry{ itemId_, field_, static_cast((chestAnimation_ != CHEST_ANIM_SHORT ? 1 : -1) * (gid_ + 1)), textId_, @@ -36,10 +37,11 @@ Item::Item(const RandomizerGet randomizerGet_, Text name_, const ItemType type_, } Item::Item(const RandomizerGet randomizerGet_, Text name_, const ItemType type_, const int16_t getItemId_, - const bool advancement_, LogicVal logicVal_, const RandomizerHintTextKey hintKey_, const bool progressive_, - const uint16_t price_) + const bool advancement_, LogicVal logicVal_, const RandomizerHintTextKey hintKey_, + const GetItemCategory category_, const bool progressive_, const uint16_t price_) : randomizerGet(randomizerGet_), name(std::move(name_)), type(type_), getItemId(getItemId_), - advancement(advancement_), logicVal(logicVal_), hintKey(hintKey_), progressive(progressive_), price(price_) { + advancement(advancement_), logicVal(logicVal_), hintKey(hintKey_), category(category_), progressive(progressive_), + price(price_) { } Item::~Item() = default; @@ -456,6 +458,10 @@ const HintText& Item::GetHint() const { return StaticData::hintTextTable[hintKey]; } +GetItemCategory Item::GetCategory() { + return category; +} + bool Item::operator==(const Item& right) const { return type == right.GetItemType() && getItemId == right.GetItemID(); } diff --git a/soh/soh/Enhancements/randomizer/item.h b/soh/soh/Enhancements/randomizer/item.h index da8632151..13a654d9c 100644 --- a/soh/soh/Enhancements/randomizer/item.h +++ b/soh/soh/Enhancements/randomizer/item.h @@ -35,7 +35,8 @@ class Item { uint16_t textId_, uint16_t field_, int16_t chestAnimation_, GetItemCategory category_, uint16_t modIndex_, bool progressive_ = false, uint16_t price_ = 0); Item(RandomizerGet randomizerGet_, Text name_, ItemType type_, int16_t getItemId_, bool advancement_, - LogicVal logicVal_, RandomizerHintTextKey hintKey_, bool progressive_ = false, uint16_t price_ = 0); + LogicVal logicVal_, RandomizerHintTextKey hintKey_, GetItemCategory category_, bool progressive_ = false, + uint16_t price_ = 0); ~Item(); void ApplyEffect() const; @@ -58,6 +59,7 @@ class Item { bool IsMajorItem() const; RandomizerHintTextKey GetHintKey() const; const HintText& GetHint() const; + GetItemCategory GetCategory(); bool operator==(const Item& right) const; bool operator!=(const Item& right) const; @@ -69,6 +71,7 @@ class Item { bool advancement; LogicVal logicVal; RandomizerHintTextKey hintKey; + GetItemCategory category; bool progressive; uint16_t price; bool playthrough = false; diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index e8198737c..f00796f31 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -59,19 +59,19 @@ void Rando::StaticData::InitItemTable() { // Skulltula Token itemTable[RG_GOLD_SKULLTULA_TOKEN] = Item(RG_GOLD_SKULLTULA_TOKEN, Text{ "Gold Skulltula Token", "Symbole de Skulltula d'Or", "Goldenes Skulltula-Symbol" }, ITEMTYPE_TOKEN, GI_SKULL_TOKEN, true, LOGIC_GOLD_SKULLTULA_TOKENS, RHT_GOLD_SKULLTULA_TOKEN, ITEM_SKULL_TOKEN, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, 0xB4, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SKULLTULA_TOKEN, MOD_NONE); // Progressive Items - itemTable[RG_PROGRESSIVE_HOOKSHOT] = Item(RG_PROGRESSIVE_HOOKSHOT, Text{ "Progressive Hookshot", "Grappin (prog.)", "Progressiver Fanghaken" }, ITEMTYPE_ITEM, 0x80, true, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_PROGRESSIVE_HOOKSHOT, true); - itemTable[RG_PROGRESSIVE_STRENGTH] = Item(RG_PROGRESSIVE_STRENGTH, Text{ "Strength Upgrade", "Amélioration de Force (prog.)", "Progressives Kraft-Upgrade" }, ITEMTYPE_ITEM, 0x81, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_PROGRESSIVE_STRENGTH, true); - itemTable[RG_PROGRESSIVE_BOMB_BAG] = Item(RG_PROGRESSIVE_BOMB_BAG, Text{ "Progressive Bomb Bag", "Sac de Bombes (prog.)", "Progressive Bombentasche" }, ITEMTYPE_ITEM, 0x82, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_PROGRESSIVE_BOMB_BAG, true); - itemTable[RG_PROGRESSIVE_BOW] = Item(RG_PROGRESSIVE_BOW, Text{ "Progressive Bow", "Arc (prog.)", "Progressiver Bogen" }, ITEMTYPE_ITEM, 0x83, true, LOGIC_PROGRESSIVE_BOW, RHT_PROGRESSIVE_BOW, true); - itemTable[RG_PROGRESSIVE_SLINGSHOT] = Item(RG_PROGRESSIVE_SLINGSHOT, Text{ "Progressive Slingshot", "Lance-Pierre (prog.)", "Progressive Steinschleuder" }, ITEMTYPE_ITEM, 0x84, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_PROGRESSIVE_SLINGSHOT, true); - itemTable[RG_PROGRESSIVE_WALLET] = Item(RG_PROGRESSIVE_WALLET, Text{ "Progressive Wallet", "Bourse (prog.)", "Progressive Geldbörse" }, ITEMTYPE_ITEM, 0x85, true, LOGIC_PROGRESSIVE_WALLET, RHT_PROGRESSIVE_WALLET, true); - itemTable[RG_PROGRESSIVE_SCALE] = Item(RG_PROGRESSIVE_SCALE, Text{ "Progressive Scale", "Écaille (prog.)", "Progressive Schuppe" }, ITEMTYPE_ITEM, 0x86, true, LOGIC_PROGRESSIVE_SCALE, RHT_PROGRESSIVE_SCALE, true); - itemTable[RG_PROGRESSIVE_NUT_UPGRADE] = Item(RG_PROGRESSIVE_NUT_UPGRADE, Text{ "Progressive Nut Capacity", "Capacité de Noix (prog.)", "Progressive Nuß-Kapazität" }, ITEMTYPE_ITEM, 0x87, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_PROGRESSIVE_NUT_UPGRADE, true); - itemTable[RG_PROGRESSIVE_STICK_UPGRADE] = Item(RG_PROGRESSIVE_STICK_UPGRADE, Text{ "Progressive Stick Capacity", "Capacité de Bâtons (prog.)", "Progressive Stab-Kapazität" }, ITEMTYPE_ITEM, 0x88, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_PROGRESSIVE_STICK_UPGRADE, true); - itemTable[RG_PROGRESSIVE_BOMBCHUS] = Item(RG_PROGRESSIVE_BOMBCHUS, Text{ "Progressive Bombchu", "Missiles (prog.)", "Progressive Krabbelminen" }, ITEMTYPE_ITEM, 0x89, true, LOGIC_BOMBCHUS, RHT_PROGRESSIVE_BOMBCHUS, true); - itemTable[RG_PROGRESSIVE_MAGIC_METER] = Item(RG_PROGRESSIVE_MAGIC_METER, Text{ "Progressive Magic Meter", "Jauge de Magie (prog.)", "Progressives Magisches Maß" }, ITEMTYPE_ITEM, 0x8A, true, LOGIC_PROGRESSIVE_MAGIC, RHT_PROGRESSIVE_MAGIC_METER, true); - itemTable[RG_PROGRESSIVE_OCARINA] = Item(RG_PROGRESSIVE_OCARINA, Text{ "Progressive Ocarina", "Ocarina (prog.)", "Progressive Okarina" }, ITEMTYPE_ITEM, 0x8B, true, LOGIC_PROGRESSIVE_OCARINA, RHT_PROGRESSIVE_OCARINA, true); - itemTable[RG_PROGRESSIVE_GORONSWORD] = Item(RG_PROGRESSIVE_GORONSWORD, Text{ "Progressive Goron Sword", "Épée Goron (prog.)", "Progressives Goronen-Schwert" }, ITEMTYPE_ITEM, 0xD4, true, LOGIC_PROGRESSIVE_GIANT_KNIFE, RHT_PROGRESSIVE_GORONSWORD, true); + itemTable[RG_PROGRESSIVE_HOOKSHOT] = Item(RG_PROGRESSIVE_HOOKSHOT, Text{ "Progressive Hookshot", "Grappin (prog.)", "Progressiver Fanghaken" }, ITEMTYPE_ITEM, 0x80, true, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_PROGRESSIVE_HOOKSHOT, ITEM_CATEGORY_MAJOR, true); + itemTable[RG_PROGRESSIVE_STRENGTH] = Item(RG_PROGRESSIVE_STRENGTH, Text{ "Strength Upgrade", "Amélioration de Force (prog.)", "Progressives Kraft-Upgrade" }, ITEMTYPE_ITEM, 0x81, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_PROGRESSIVE_STRENGTH, ITEM_CATEGORY_MAJOR, true); + itemTable[RG_PROGRESSIVE_BOMB_BAG] = Item(RG_PROGRESSIVE_BOMB_BAG, Text{ "Progressive Bomb Bag", "Sac de Bombes (prog.)", "Progressive Bombentasche" }, ITEMTYPE_ITEM, 0x82, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_PROGRESSIVE_BOMB_BAG, ITEM_CATEGORY_MAJOR, true); + itemTable[RG_PROGRESSIVE_BOW] = Item(RG_PROGRESSIVE_BOW, Text{ "Progressive Bow", "Arc (prog.)", "Progressiver Bogen" }, ITEMTYPE_ITEM, 0x83, true, LOGIC_PROGRESSIVE_BOW, RHT_PROGRESSIVE_BOW, ITEM_CATEGORY_MAJOR, true); + itemTable[RG_PROGRESSIVE_SLINGSHOT] = Item(RG_PROGRESSIVE_SLINGSHOT, Text{ "Progressive Slingshot", "Lance-Pierre (prog.)", "Progressive Steinschleuder" }, ITEMTYPE_ITEM, 0x84, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_PROGRESSIVE_SLINGSHOT, ITEM_CATEGORY_MAJOR, true); + itemTable[RG_PROGRESSIVE_WALLET] = Item(RG_PROGRESSIVE_WALLET, Text{ "Progressive Wallet", "Bourse (prog.)", "Progressive Geldbörse" }, ITEMTYPE_ITEM, 0x85, true, LOGIC_PROGRESSIVE_WALLET, RHT_PROGRESSIVE_WALLET, ITEM_CATEGORY_MAJOR, true); + itemTable[RG_PROGRESSIVE_SCALE] = Item(RG_PROGRESSIVE_SCALE, Text{ "Progressive Scale", "Écaille (prog.)", "Progressive Schuppe" }, ITEMTYPE_ITEM, 0x86, true, LOGIC_PROGRESSIVE_SCALE, RHT_PROGRESSIVE_SCALE, ITEM_CATEGORY_MAJOR, true); + itemTable[RG_PROGRESSIVE_NUT_UPGRADE] = Item(RG_PROGRESSIVE_NUT_UPGRADE, Text{ "Progressive Nut Capacity", "Capacité de Noix (prog.)", "Progressive Nuß-Kapazität" }, ITEMTYPE_ITEM, 0x87, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_PROGRESSIVE_NUT_UPGRADE, ITEM_CATEGORY_MAJOR, true); + itemTable[RG_PROGRESSIVE_STICK_UPGRADE] = Item(RG_PROGRESSIVE_STICK_UPGRADE, Text{ "Progressive Stick Capacity", "Capacité de Bâtons (prog.)", "Progressive Stab-Kapazität" }, ITEMTYPE_ITEM, 0x88, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_PROGRESSIVE_STICK_UPGRADE, ITEM_CATEGORY_MAJOR, true); + itemTable[RG_PROGRESSIVE_BOMBCHUS] = Item(RG_PROGRESSIVE_BOMBCHUS, Text{ "Progressive Bombchu", "Missiles (prog.)", "Progressive Krabbelminen" }, ITEMTYPE_ITEM, 0x89, true, LOGIC_BOMBCHUS, RHT_PROGRESSIVE_BOMBCHUS, ITEM_CATEGORY_MAJOR, true); + itemTable[RG_PROGRESSIVE_MAGIC_METER] = Item(RG_PROGRESSIVE_MAGIC_METER, Text{ "Progressive Magic Meter", "Jauge de Magie (prog.)", "Progressives Magisches Maß" }, ITEMTYPE_ITEM, 0x8A, true, LOGIC_PROGRESSIVE_MAGIC, RHT_PROGRESSIVE_MAGIC_METER, ITEM_CATEGORY_MAJOR, true); + itemTable[RG_PROGRESSIVE_OCARINA] = Item(RG_PROGRESSIVE_OCARINA, Text{ "Progressive Ocarina", "Ocarina (prog.)", "Progressive Okarina" }, ITEMTYPE_ITEM, 0x8B, true, LOGIC_PROGRESSIVE_OCARINA, RHT_PROGRESSIVE_OCARINA, ITEM_CATEGORY_MAJOR, true); + itemTable[RG_PROGRESSIVE_GORONSWORD] = Item(RG_PROGRESSIVE_GORONSWORD, Text{ "Progressive Goron Sword", "Épée Goron (prog.)", "Progressives Goronen-Schwert" }, ITEMTYPE_ITEM, 0xD4, true, LOGIC_PROGRESSIVE_GIANT_KNIFE, RHT_PROGRESSIVE_GORONSWORD, ITEM_CATEGORY_MAJOR, true); // Bottles itemTable[RG_EMPTY_BOTTLE] = Item(RG_EMPTY_BOTTLE, Text{ "Empty Bottle", "Bouteille Vide", "Leere Flasche" }, ITEMTYPE_ITEM, GI_BOTTLE, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_MILK, ITEM_BOTTLE, OBJECT_GI_BOTTLE, GID_BOTTLE, 0x42, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); itemTable[RG_BOTTLE_WITH_MILK] = Item(RG_BOTTLE_WITH_MILK, Text{ "Bottle with Milk", "Bouteille avec du Lait", "Flasche mit Milch" }, ITEMTYPE_ITEM, GI_MILK_BOTTLE, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_MILK, ITEM_MILK_BOTTLE, OBJECT_GI_MILK, GID_MILK, 0x98, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); @@ -305,7 +305,7 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_BUY_BOMBCHUS_10] = Item(RG_BUY_BOMBCHUS_10, Text{ "Buy Bombchu (10)", "Acheter: Missiles (10)", "Krabbelminen kaufen (10)" }, ITEMTYPE_SHOP, GI_BOMBCHUS_10, true, LOGIC_BUY_BOMBCHUS, RHT_BOMBCHUS_10, ITEM_BOMBCHU, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 99); itemTable[RG_BUY_BOMBCHUS_20] = Item(RG_BUY_BOMBCHUS_20, Text{ "Buy Bombchu (20)", "Acheter: Missiles (20)", "Krabbelminen kaufen (20)" }, ITEMTYPE_SHOP, GI_BOMBCHUS_20, true, LOGIC_BUY_BOMBCHUS, RHT_BOMBCHUS_20, ITEM_BOMBCHUS_20, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 180); itemTable[RG_BUY_DEKU_SEEDS_30] = Item(RG_BUY_DEKU_SEEDS_30, Text{ "Buy Deku Seeds (30)", "Acheter: Graines Mojo (30)", "Deku-Samen kaufen (30)" }, ITEMTYPE_SHOP, GI_SEEDS_30, true, LOGIC_BUY_SEED, RHT_DEKU_SEEDS_30, ITEM_SEEDS_30, OBJECT_GI_SEED, GID_SEEDS, 0xDC, 0x50, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 30); - itemTable[RG_SOLD_OUT] = Item(RG_SOLD_OUT, Text{ "Sold Out", "Rupture de stock", "Ausverkauft" }, ITEMTYPE_SHOP, RG_SOLD_OUT, false, LOGIC_NONE, RHT_NONE, false, 0); + itemTable[RG_SOLD_OUT] = Item(RG_SOLD_OUT, Text{ "Sold Out", "Rupture de stock", "Ausverkauft" }, ITEMTYPE_SHOP, RG_SOLD_OUT, false, LOGIC_NONE, RHT_NONE, ITEM_CATEGORY_JUNK, false, 0); itemTable[RG_BUY_BLUE_FIRE] = Item(RG_BUY_BLUE_FIRE, Text{ "Buy Blue Fire", "Acheter: Flamme Bleue", "Blaues Feuer kaufen" }, ITEMTYPE_SHOP, GI_BLUE_FIRE, true, LOGIC_BLUE_FIRE_ACCESS, RHT_BOTTLE_WITH_BLUE_FIRE, ITEM_BLUE_FIRE, OBJECT_GI_FIRE, GID_BLUE_FIRE, 0x5D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 300); itemTable[RG_BUY_BOTTLE_BUG] = Item(RG_BUY_BOTTLE_BUG, Text{ "Buy Bottle Bug", "Acheter: Insecte en bouteille", "Flaschenkäfer kaufen" }, ITEMTYPE_SHOP, GI_BUGS, true, LOGIC_BUGS_ACCESS, RHT_BOTTLE_WITH_BUGS, ITEM_BUG, OBJECT_GI_INSECT, GID_BUG, 0x7A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 50); itemTable[RG_BUY_POE] = Item(RG_BUY_POE, Text{ "Buy Poe", "Acheter: Esprit", "Geist kaufen" }, ITEMTYPE_SHOP, RG_BUY_POE, false, LOGIC_NONE, RHT_BOTTLE_WITH_BIG_POE, ITEM_POE, OBJECT_GI_GHOST, GID_POE, 0x97, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 30); @@ -372,8 +372,8 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_DEKU_NUT_BAG] = Item(RG_DEKU_NUT_BAG, Text{ "Deku Nut Bag", "Sac de Noix Mojo", "Deku-Nuß-Tasche" }, ITEMTYPE_ITEM, GI_NUT_UPGRADE_30, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_NONE, RG_DEKU_NUT_BAG, OBJECT_GI_NUTS, GID_NUTS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_TRIFORCE] = Item(RG_TRIFORCE, Text{ "Triforce", "Triforce", "Triforce" }, ITEMTYPE_EVENT, RG_TRIFORCE, false, LOGIC_NONE, RHT_NONE); - itemTable[RG_HINT] = Item(RG_HINT, Text{ "Hint", "Indice", "Hinweis" }, ITEMTYPE_EVENT, RG_HINT, false, LOGIC_NONE, RHT_NONE); + itemTable[RG_TRIFORCE] = Item(RG_TRIFORCE, Text{ "Triforce", "Triforce", "Triforce" }, ITEMTYPE_EVENT, RG_TRIFORCE, false, LOGIC_NONE, RHT_NONE, ITEM_CATEGORY_MAJOR); + itemTable[RG_HINT] = Item(RG_HINT, Text{ "Hint", "Indice", "Hinweis" }, ITEMTYPE_EVENT, RG_HINT, false, LOGIC_NONE, RHT_NONE, ITEM_CATEGORY_LESSER); // Individual stages of progressive items (only here for GetItemEntry purposes, not for use in seed gen) itemTable[RG_HOOKSHOT] = Item(RG_HOOKSHOT, Text{ "Hookshot", "Grappin", "Fanghaken" }, ITEMTYPE_ITEM, GI_HOOKSHOT, true, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_HOOKSHOT, ITEM_HOOKSHOT, OBJECT_GI_HOOKSHOT, GID_HOOKSHOT, 0x36, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); itemTable[RG_LONGSHOT] = Item(RG_LONGSHOT, Text{ "Longshot", "Super-Grappin", "Enterhaken" }, ITEMTYPE_ITEM, GI_LONGSHOT, true, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_LONGSHOT, ITEM_LONGSHOT, OBJECT_GI_HOOKSHOT, GID_LONGSHOT, 0x4F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); From a9a49ccbe6f963ffc84c59715e30107f08c868a2 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Thu, 19 Jun 2025 13:26:43 -0700 Subject: [PATCH 11/31] Adds saving and loading for location exclusion, and hooks the check tracker up to return false from IsVisibleInCheckTracker if a location was excluded. (#5594) --- .../Enhancements/randomizer/randomizer_check_tracker.cpp | 9 +++++---- soh/soh/SaveManager.cpp | 6 ++++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index 887bc3731..d0cad2544 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -1588,10 +1588,11 @@ bool IsCheckShuffled(RandomizerCheck rc) { bool IsVisibleInCheckTracker(RandomizerCheck rc) { auto loc = Rando::StaticData::GetLocation(rc); if (IS_RANDO) { - return IsCheckShuffled(rc) || - (alwaysShowGS && loc->GetRCType() == RCTYPE_SKULL_TOKEN && - OTRGlobals::Instance->gRandoContext->IsQuestOfLocationActive(rc)) || - (loc->GetRCType() == RCTYPE_SHOP && showShops && !hideShopUnshuffledChecks); + return !Rando::Context::GetInstance()->GetItemLocation(rc)->IsExcluded() && + (IsCheckShuffled(rc) || + (alwaysShowGS && loc->GetRCType() == RCTYPE_SKULL_TOKEN && + OTRGlobals::Instance->gRandoContext->IsQuestOfLocationActive(rc)) || + (loc->GetRCType() == RCTYPE_SHOP && showShops && !hideShopUnshuffledChecks)); } else { return loc->IsVanillaCompletion() && (!loc->IsDungeon() || (loc->IsDungeon() && loc->GetQuest() == gSaveContext.ship.quest.id)); diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index e023f9afe..43bd25b23 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -179,6 +179,9 @@ void SaveManager::LoadRandomizer() { // all ItemLocations is 0 anyway. randoContext->GetItemLocation(i)->SetCustomPrice(price); } + bool excluded = false; + SaveManager::Instance->LoadData("excluded", excluded, false); + randoContext->GetItemLocation(i)->SetExcludedOption(excluded); }); }); @@ -269,6 +272,9 @@ void SaveManager::SaveRandomizer(SaveContext* saveContext, int sectionID, bool f // TODO: German (trick names don't have german translations yet) }); } + if (randoContext->GetItemLocation(i)->IsExcluded()) { + SaveManager::Instance->SaveData("excluded", true); + } if (randoContext->GetItemLocation(i)->HasCustomPrice()) { SaveManager::Instance->SaveData("price", randoContext->GetItemLocation(i)->GetPrice()); } From b56414838078d58d240b9e964f7c9ea95a2534fa Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Thu, 19 Jun 2025 21:28:50 +0100 Subject: [PATCH 12/31] Add wallet to mask logic, clean up mask logic (#5567) --- .../location_access/overworld/graveyard.cpp | 7 ++++--- .../location_access/overworld/hyrule_field.cpp | 3 ++- .../randomizer/location_access/overworld/kakariko.cpp | 2 ++ .../location_access/overworld/lost_woods.cpp | 11 ++++++----- .../randomizer/location_access/overworld/market.cpp | 10 ++++++++-- soh/soh/Enhancements/randomizer/logic.cpp | 9 ++++++--- soh/soh/Enhancements/randomizer/logic.h | 9 ++++++--- 7 files changed, 34 insertions(+), 17 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp index 012503d9a..d04606018 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp @@ -7,9 +7,10 @@ void RegionTable_Init_Graveyard() { // clang-format off areaTable[RR_THE_GRAVEYARD] = Region("The Graveyard", "The Graveyard", {RA_THE_GRAVEYARD}, NO_DAY_NIGHT_CYCLE, { //Events - EventAccess(&logic->ButterflyFairy, []{return logic->ButterflyFairy || (logic->CanUse(RG_STICKS) && logic->AtDay);}), - EventAccess(&logic->BeanPlantFairy, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}), - EventAccess(&logic->BugRock, []{return true;}), + EventAccess(&logic->ButterflyFairy, []{return logic->ButterflyFairy || (logic->CanUse(RG_STICKS) && logic->AtDay);}), + EventAccess(&logic->BeanPlantFairy, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}), + EventAccess(&logic->BugRock, []{return true;}), + EventAccess(&logic->BorrowBunnyHood, []{return logic->IsChild && logic->AtDay && logic->BorrowSpookyMask && logic->HasItem(RG_CHILD_WALLET);}), }, { //Locations LOCATION(RC_GRAVEYARD_FREESTANDING_POH, (((logic->IsAdult && CanPlantBean(RR_THE_GRAVEYARD)) || logic->CanUse(RG_LONGSHOT)) && logic->CanBreakCrates()) || (ctx->GetTrickOption(RT_GY_POH) && logic->CanUse(RG_BOOMERANG))), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp index add3a2f86..3359089e0 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp @@ -7,7 +7,8 @@ void RegionTable_Init_HyruleField() { // clang-format off areaTable[RR_HYRULE_FIELD] = Region("Hyrule Field", "Hyrule Field", {RA_HYRULE_FIELD}, DAY_NIGHT_CYCLE, { //Events - EventAccess(&logic->BigPoeKill, []{return logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_EPONA) && logic->HasBottle();}), + EventAccess(&logic->BigPoeKill, []{return logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_EPONA) && logic->HasBottle();}), + EventAccess(&logic->BorrowRightMasks, []{return logic->IsChild && logic->BorrowBunnyHood && logic->HasItem(RG_KOKIRI_EMERALD) && logic->HasItem(RG_GORON_RUBY) && logic->HasItem(RG_ZORA_SAPPHIRE) && logic->HasItem(RG_CHILD_WALLET);}), }, { //Locations LOCATION(RC_HF_OCARINA_OF_TIME_ITEM, logic->IsChild && logic->StoneCount() == 3 && logic->HasItem(RG_BRONZE_SCALE)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp index 3e84bb72a..3247ef5f4 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp @@ -10,6 +10,8 @@ void RegionTable_Init_Kakariko() { EventAccess(&logic->BugRock, []{return true;}), //Open Gate setting is applied in RR_ROOT EventAccess(&logic->KakarikoVillageGateOpen, []{return logic->IsChild && logic->HasItem(RG_ZELDAS_LETTER);}), + //Needs wallet to be able to get another mask after selling Keaton + EventAccess(&logic->BorrowSkullMask, []{return logic->IsChild && logic->CanBorrowMasks && logic->HasItem(RG_CHILD_WALLET);}), }, { //Locations LOCATION(RC_SHEIK_IN_KAKARIKO, logic->IsAdult && logic->HasItem(RG_FOREST_MEDALLION) && logic->HasItem(RG_FIRE_MEDALLION) && logic->HasItem(RG_WATER_MEDALLION)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp index 812b33a55..a83664fd6 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp @@ -12,9 +12,10 @@ void RegionTable_Init_LostWoods() { areaTable[RR_THE_LOST_WOODS] = Region("Lost Woods", "Lost Woods", {RA_THE_LOST_WOODS}, NO_DAY_NIGHT_CYCLE, { //Events - EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairyExceptSuns();}), - EventAccess(&logic->BeanPlantFairy, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}), - EventAccess(&logic->BugShrub, []{return logic->IsChild && logic->CanCutShrubs();}), + EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairyExceptSuns();}), + EventAccess(&logic->BeanPlantFairy, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}), + EventAccess(&logic->BugShrub, []{return logic->IsChild && logic->CanCutShrubs();}), + EventAccess(&logic->BorrowSpookyMask, []{return logic->IsChild && logic->BorrowSkullMask && logic->CanUse(RG_SARIAS_SONG) && logic->HasItem(RG_CHILD_WALLET);}), }, { //Locations LOCATION(RC_LW_SKULL_KID, logic->IsChild && logic->CanUse(RG_SARIAS_SONG)), @@ -110,8 +111,8 @@ void RegionTable_Init_LostWoods() { areaTable[RR_DEKU_THEATER] = Region("Deku Theater", "Deku Theater", {}, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LOCATION(RC_DEKU_THEATER_SKULL_MASK, logic->IsChild && logic->SkullMask), - LOCATION(RC_DEKU_THEATER_MASK_OF_TRUTH, logic->IsChild && logic->MaskOfTruth), + LOCATION(RC_DEKU_THEATER_SKULL_MASK, logic->IsChild && logic->BorrowSkullMask), + LOCATION(RC_DEKU_THEATER_MASK_OF_TRUTH, logic->IsChild && logic->BorrowRightMasks), }, { //Exits Entrance(RR_LW_BEYOND_MIDO, []{return true;}), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp index 0314bfde0..b1090d361 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp @@ -138,8 +138,14 @@ void RegionTable_Init_Market() { areaTable[RR_MARKET_MASK_SHOP] = Region("Market Mask Shop", "Market Mask Shop", {}, NO_DAY_NIGHT_CYCLE, { //Events - EventAccess(&logic->SkullMask, []{return logic->SkullMask || (logic->HasItem(RG_ZELDAS_LETTER) && (ctx->GetOption(RSK_COMPLETE_MASK_QUEST) || ChildCanAccess(RR_KAKARIKO_VILLAGE)));}), //RANDOTODO Complete mask quest does not need this location, so should be tied to link's pocket - EventAccess(&logic->MaskOfTruth, []{return logic->MaskOfTruth || (logic->SkullMask && (ctx->GetOption(RSK_COMPLETE_MASK_QUEST) || (ChildCanAccess(RR_THE_LOST_WOODS) && logic->CanUse(RG_SARIAS_SONG) && RegionTable(RR_THE_GRAVEYARD)->childDay && ChildCanAccess(RR_HYRULE_FIELD) && logic->StoneCount() == 3)));}), + //Currently, mask swap in menu doesn't need access to the mask shop + //If it is forced on/a setting, a copy of these events should be added to root + //it also doesn't need you to open kak gate, but that might be best treated as a bug + EventAccess(&logic->CanBorrowMasks, []{return logic->HasItem(RG_ZELDAS_LETTER) && logic->KakarikoVillageGateOpen;}), + EventAccess(&logic->BorrowSkullMask, []{return ctx->GetOption(RSK_COMPLETE_MASK_QUEST) && logic->CanBorrowMasks;}), + EventAccess(&logic->BorrowSpookyMask, []{return ctx->GetOption(RSK_COMPLETE_MASK_QUEST) && logic->CanBorrowMasks;}), + EventAccess(&logic->BorrowBunnyHood, []{return ctx->GetOption(RSK_COMPLETE_MASK_QUEST) && logic->CanBorrowMasks;}), + EventAccess(&logic->BorrowRightMasks, []{return ctx->GetOption(RSK_COMPLETE_MASK_QUEST) && logic->CanBorrowMasks;}), }, { //Locations LOCATION(RC_MASK_SHOP_HINT, true), diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index 597feb463..710437dc6 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -2345,9 +2345,12 @@ void Logic::Reset(bool resetSaveContext /*= true*/) { // AmmoCanDrop = /*AmmoDrops.IsNot(AMMODROPS_NONE)*/ false; TODO: AmmoDrop setting - // Child item logic - SkullMask = false; - MaskOfTruth = false; + // Mask quest + CanBorrowMasks = false; + BorrowSkullMask = false; + BorrowSpookyMask = false; + BorrowBunnyHood = false; + BorrowRightMasks = false; // Adult logic FreedEpona = false; diff --git a/soh/soh/Enhancements/randomizer/logic.h b/soh/soh/Enhancements/randomizer/logic.h index 0c138a3eb..05e44b402 100644 --- a/soh/soh/Enhancements/randomizer/logic.h +++ b/soh/soh/Enhancements/randomizer/logic.h @@ -30,9 +30,12 @@ class Logic { public: bool noVariable = false; - // Child item logic - bool SkullMask = false; - bool MaskOfTruth = false; + // Mask Quest + bool CanBorrowMasks = false; + bool BorrowSkullMask = false; + bool BorrowSpookyMask = false; + bool BorrowBunnyHood = false; + bool BorrowRightMasks = false; // Adult logic bool FreedEpona = false; From 17613d1f508cf6895df9785d42e089dc8ad1f606 Mon Sep 17 00:00:00 2001 From: xxAtrain223 Date: Mon, 23 Jun 2025 17:52:17 -0500 Subject: [PATCH 13/31] Fix Available Checks On Load (#5599) * Setup call to RecalculateAvailableChecks instead of direct call. * Remove RecalculateAvailableChecks from CheckTrackerSettingsWindow::DrawElement. --- .../randomizer/randomizer_check_tracker.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index d0cad2544..1f53e4caf 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -587,7 +587,7 @@ void CheckTrackerLoadGame(int32_t fileNum) { Rando::Context::GetInstance()->GetEntranceShuffler()->ApplyEntranceOverrides(); } - RecalculateAvailableChecks(); + recalculateAvailable = true; } void CheckTrackerShopSlotChange(uint8_t cursorSlot, int16_t basePrice) { @@ -994,6 +994,11 @@ void CheckTrackerWindow::DrawElement() { return; } + if (recalculateAvailable) { + recalculateAvailable = false; + RecalculateAvailableChecks(); + } + SceneID sceneId = SCENE_ID_MAX; if (gPlayState != nullptr) { sceneId = (SceneID)gPlayState->sceneNum; @@ -1986,7 +1991,7 @@ void ImGuiDrawTwoColorPickerSection(const char* text, const char* cvarMainName, } void RecalculateAvailableChecks(RandomizerRegion startingRegion /* = RR_ROOT */) { - if (!enableAvailableChecks || !GameInteractor::IsSaveLoaded(true)) { + if (!enableAvailableChecks || !GameInteractor::IsSaveLoaded()) { return; } @@ -2052,10 +2057,6 @@ static std::unordered_map buttonStrings = { }; void CheckTrackerSettingsWindow::DrawElement() { - if (recalculateAvailable) { - recalculateAvailable = false; - RecalculateAvailableChecks(); - } ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, { 8.0f, 8.0f }); if (ImGui::BeginTable("CheckTrackerSettingsTable", 2, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV)) { ImGui::TableSetupColumn("General settings", ImGuiTableColumnFlags_WidthStretch, 200.0f); From afde504a0f0b4ef36f236437142fbe42362314dd Mon Sep 17 00:00:00 2001 From: xxAtrain223 Date: Mon, 23 Jun 2025 18:01:49 -0500 Subject: [PATCH 14/31] Updated SpoilerFileExists to cache the results. (#5606) --- .../Enhancements/randomizer/randomizer.cpp | 64 ++++++++++++++++--- 1 file changed, 55 insertions(+), 9 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index f0f57b353..581861158 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -359,26 +359,72 @@ std::unordered_map getItemIdToItemId = { #pragma GCC push_options #pragma GCC optimize("O0") bool Randomizer::SpoilerFileExists(const char* spoilerFileName) { - if (strcmp(spoilerFileName, "") != 0) { - std::ifstream spoilerFileStream(SohUtils::Sanitize(spoilerFileName)); + static std::unordered_map existsCache; + static std::unordered_map lastModifiedCache; + + if (strcmp(spoilerFileName, "") == 0) { + return false; + } + + std::string sanitizedFileName = SohUtils::Sanitize(spoilerFileName); + + try { + // Check if file exists and get last modified time + std::filesystem::path filePath(sanitizedFileName); + if (!std::filesystem::exists(filePath)) { + // Cache and return false if file doesn't exist + existsCache[sanitizedFileName] = false; + lastModifiedCache.erase(sanitizedFileName); + return false; + } + + auto currentLastModified = std::filesystem::last_write_time(filePath); + + // Check cache first + auto existsCacheIt = existsCache.find(sanitizedFileName); + auto lastModifiedCacheIt = lastModifiedCache.find(sanitizedFileName); + + // If we have a valid cache entry and the file hasn't been modified + if (existsCacheIt != existsCache.end() && lastModifiedCacheIt != lastModifiedCache.end() && + lastModifiedCacheIt->second == currentLastModified) { + return existsCacheIt->second; + } + + // Cache miss or file modified - need to check contents + std::ifstream spoilerFileStream(sanitizedFileName); if (spoilerFileStream) { nlohmann::json contents; spoilerFileStream >> contents; spoilerFileStream.close(); - if (contents.contains("version") && - strcmp(std::string(contents["version"]).c_str(), (char*)gBuildVersion) == 0) { - return true; - } else { + + bool isValid = contents.contains("version") && + strcmp(std::string(contents["version"]).c_str(), (char*)gBuildVersion) == 0; + + if (!isValid) { SohGui::RegisterPopup( "Old Spoiler Version", "The spoiler file located at\n" + std::string(spoilerFileName) + "\nwas made by a version that doesn't match the currently running version.\n" + "Loading for this file has been cancelled."); } - } - } - return false; + // Update cache + existsCache[sanitizedFileName] = isValid; + lastModifiedCache[sanitizedFileName] = currentLastModified; + return isValid; + } + + // File couldn't be opened + existsCache[sanitizedFileName] = false; + lastModifiedCache.erase(sanitizedFileName); + return false; + + } catch (const std::filesystem::filesystem_error&) { + // Handle filesystem errors by invalidating cache + existsCache[sanitizedFileName] = false; + lastModifiedCache.erase(sanitizedFileName); + return false; + } } #pragma GCC pop_options #pragma optimize("", on) From 4676242086b5066abfa625677c5985632bc93101 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Mon, 23 Jun 2025 16:02:04 -0700 Subject: [PATCH 15/31] Fix dpad navigation on Quest Status pause screen. (#5607) --- .../ovl_kaleido_scope/z_kaleido_collect.c | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_collect.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_collect.c index 17f1aa89e..78a072c6f 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_collect.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_collect.c @@ -124,7 +124,17 @@ void KaleidoScope_DrawQuestStatus(PlayState* play, GraphicsContext* gfxCtx) { s16 pad2; s16 phi_s0_2; s16 sp208[3]; - bool dpad = CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0); + if (CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0)) { + if (CHECK_BTN_ALL(input->press.button, BTN_DLEFT)) { + pauseCtx->stickRelX = -35; + } else if (CHECK_BTN_ALL(input->press.button, BTN_DRIGHT)) { + pauseCtx->stickRelX = 35; + } else if (CHECK_BTN_ALL(input->press.button, BTN_DDOWN)) { + pauseCtx->stickRelY = -35; + } else if (CHECK_BTN_ALL(input->press.button, BTN_DUP)) { + pauseCtx->stickRelY = 35; + } + } OPEN_DISPS(gfxCtx); @@ -140,7 +150,7 @@ void KaleidoScope_DrawQuestStatus(PlayState* play, GraphicsContext* gfxCtx) { } else { phi_s3 = pauseCtx->cursorPoint[PAUSE_QUEST]; - if ((pauseCtx->stickRelX < -30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DLEFT))) { + if ((pauseCtx->stickRelX < -30)) { phi_s0 = D_8082A1AC[phi_s3][2]; if (phi_s0 == -3) { KaleidoScope_MoveCursorToSpecialPos(play, PAUSE_CURSOR_PAGE_LEFT); @@ -153,7 +163,7 @@ void KaleidoScope_DrawQuestStatus(PlayState* play, GraphicsContext* gfxCtx) { phi_s0 = D_8082A1AC[phi_s0][2]; } } - } else if ((pauseCtx->stickRelX > 30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DRIGHT))) { + } else if ((pauseCtx->stickRelX > 30)) { phi_s0 = D_8082A1AC[phi_s3][3]; if (phi_s0 == -2) { KaleidoScope_MoveCursorToSpecialPos(play, PAUSE_CURSOR_PAGE_RIGHT); @@ -168,7 +178,7 @@ void KaleidoScope_DrawQuestStatus(PlayState* play, GraphicsContext* gfxCtx) { } } - if ((pauseCtx->stickRelY < -30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DDOWN))) { + if ((pauseCtx->stickRelY < -30)) { phi_s0 = D_8082A1AC[phi_s3][1]; while (phi_s0 >= 0) { if ((s16)KaleidoScope_UpdateQuestStatusPoint(pauseCtx, phi_s0) != 0) { @@ -176,7 +186,7 @@ void KaleidoScope_DrawQuestStatus(PlayState* play, GraphicsContext* gfxCtx) { } phi_s0 = D_8082A1AC[phi_s0][1]; } - } else if ((pauseCtx->stickRelY > 30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DUP))) { + } else if ((pauseCtx->stickRelY > 30)) { phi_s0 = D_8082A1AC[phi_s3][0]; while (phi_s0 >= 0) { if ((s16)KaleidoScope_UpdateQuestStatusPoint(pauseCtx, phi_s0) != 0) { @@ -267,7 +277,7 @@ void KaleidoScope_DrawQuestStatus(PlayState* play, GraphicsContext* gfxCtx) { } } } else if (pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_LEFT) { - if ((pauseCtx->stickRelX > 30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DRIGHT))) { + if ((pauseCtx->stickRelX > 30)) { pauseCtx->cursorPoint[PAUSE_QUEST] = 0x15; pauseCtx->nameDisplayTimer = 0; pauseCtx->cursorSpecialPos = 0; @@ -285,7 +295,7 @@ void KaleidoScope_DrawQuestStatus(PlayState* play, GraphicsContext* gfxCtx) { pauseCtx->cursorSlot[pauseCtx->pageIndex] = sp216; } } else { - if ((pauseCtx->stickRelX < -30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DLEFT))) { + if ((pauseCtx->stickRelX < -30)) { pauseCtx->cursorPoint[PAUSE_QUEST] = 0; pauseCtx->nameDisplayTimer = 0; pauseCtx->cursorSpecialPos = 0; From 3b82b8eeffb1694b98997fdb1adb825e32dba01a Mon Sep 17 00:00:00 2001 From: Jordan Longstaff Date: Wed, 25 Jun 2025 12:27:45 -0400 Subject: [PATCH 16/31] Ruto no longer targetable with sitting down skip (#5611) --- .../SkipMiscInteractions/SkipChildRutoInteractions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/TimeSavers/SkipMiscInteractions/SkipChildRutoInteractions.cpp b/soh/soh/Enhancements/TimeSavers/SkipMiscInteractions/SkipChildRutoInteractions.cpp index 97b65a543..42862d4d9 100644 --- a/soh/soh/Enhancements/TimeSavers/SkipMiscInteractions/SkipChildRutoInteractions.cpp +++ b/soh/soh/Enhancements/TimeSavers/SkipMiscInteractions/SkipChildRutoInteractions.cpp @@ -93,7 +93,7 @@ void SkipChildRutoInteractions_Register() { if (enRu1->action == 22) { enRu1->action = 27; enRu1->drawConfig = 1; - enRu1->actor.flags |= ACTOR_FLAG_ATTENTION_ENABLED | ACTOR_FLAG_FRIENDLY; + enRu1->actor.flags &= ~(ACTOR_FLAG_ATTENTION_ENABLED | ACTOR_FLAG_FRIENDLY); Animation_Change(&enRu1->skelAnime, (AnimationHeader*)&gRutoChildSittingAnim, 1.0f, 0.0f, Animation_GetLastFrame((void*)&gRutoChildSittingAnim), ANIMMODE_LOOP, 0.0f); } From 8b616c8709a307426017ec511c939259c78dd114 Mon Sep 17 00:00:00 2001 From: Eric Hoey <121978037+A-Green-Spoon@users.noreply.github.com> Date: Thu, 26 Jun 2025 00:54:57 -0400 Subject: [PATCH 17/31] first person to first-person (#5616) --- soh/soh/Enhancements/controls/SohInputEditorWindow.cpp | 4 ++-- soh/soh/SohGui/SohMenuEnhancements.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp b/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp index 8a8227073..f9fb48ac1 100644 --- a/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp +++ b/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp @@ -1366,10 +1366,10 @@ void SohInputEditorWindow::DrawCameraControlPanel() { .Color(THEME_COLOR) .Tooltip("Allows for aiming with the right stick in:\n-First-Person/C-Up view\n-Weapon Aiming")); if (CVarGetInteger(CVAR_SETTING("Controls.RightStickAim"), 0)) { - CVarCheckbox("Allow moving while in first person mode", CVAR_SETTING("MoveInFirstPerson"), + CVarCheckbox("Allow moving while in first-person mode", CVAR_SETTING("MoveInFirstPerson"), CheckboxOptions() .Color(THEME_COLOR) - .Tooltip("Changes the left stick to move the player while in first person mode")); + .Tooltip("Changes the left stick to move the player while in first-person mode")); } CVarCheckbox("Invert Aiming X Axis", CVAR_SETTING("Controls.InvertAimingXAxis"), CheckboxOptions() diff --git a/soh/soh/SohGui/SohMenuEnhancements.cpp b/soh/soh/SohGui/SohMenuEnhancements.cpp index f6f627f78..8e1e94c08 100644 --- a/soh/soh/SohGui/SohMenuEnhancements.cpp +++ b/soh/soh/SohGui/SohMenuEnhancements.cpp @@ -507,7 +507,7 @@ void SohMenu::AddMenuEnhancements() { .Options(CheckboxOptions().Tooltip( "Scales all of the Adult Equipment, as well as moving some a bit, to fit on Child Link better. May " "not work properly with some mods.")); - AddWidget(path, "Show Gauntlets in First Person", WIDGET_CVAR_CHECKBOX) + AddWidget(path, "Show Gauntlets in First-Person", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("FirstPersonGauntlets")) .RaceDisable(false) .Options(CheckboxOptions().Tooltip("Renders Gauntlets when using the Bow and Hookshot like in OoT3D.")); From 1161ce3546aafadec2bf0f0eff46e912b6675867 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Sat, 28 Jun 2025 07:50:06 -0700 Subject: [PATCH 18/31] Expand tooltip for Free Look to explain camera locks and scene reload. (#5624) --- soh/soh/Enhancements/controls/SohInputEditorWindow.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp b/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp index f9fb48ac1..41a31f8be 100644 --- a/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp +++ b/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp @@ -1432,7 +1432,9 @@ void SohInputEditorWindow::DrawCameraControlPanel() { CheckboxOptions() .Color(THEME_COLOR) .Tooltip("Enables free look camera control\nNote: You must remap C buttons off of the right stick in the " - "controller config menu, and map the camera stick to the right stick.")); + "controller config menu, and map the camera stick to the right stick.\n" + "Doesn't work in areas were the game locks the camera.\n" + "Scene reload may be necessary to enable.")); CVarCheckbox("Invert Camera X Axis", CVAR_SETTING("FreeLook.InvertXAxis"), CheckboxOptions().Color(THEME_COLOR).Tooltip("Inverts the Camera X Axis in:\n-Free look")); CVarCheckbox( From a9b857469ef1fae2fcec6ee706e5a53a33470c53 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Sat, 28 Jun 2025 17:48:21 -0700 Subject: [PATCH 19/31] Fix Boss Rush scene/cutscene setup after Bongo/Twinrova. (#5623) Also prevent check tracker crash loading Boss Rush. --- .../Enhancements/randomizer/randomizer_check_tracker.cpp | 3 +++ soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index 1f53e4caf..8ff302bfe 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -495,6 +495,9 @@ void SetShopSeen(uint32_t sceneNum, bool prices) { } void CheckTrackerLoadGame(int32_t fileNum) { + if (!IS_RANDO) { + return; + } LoadSettings(); TrySetAreas(); for (auto& entry : Rando::StaticData::GetLocationTable()) { diff --git a/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c b/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c index a90764717..54e9768b4 100644 --- a/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c +++ b/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c @@ -813,7 +813,8 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, PlayState* play) { gSaveContext.nextCutsceneIndex = 0; } } else if (play->sceneNum == SCENE_SPIRIT_TEMPLE_BOSS) { - if (GameInteractor_Should(VB_PLAY_BLUE_WARP_CS, !CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT), + if (GameInteractor_Should(VB_PLAY_BLUE_WARP_CS, + !Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE), RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE)) { Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE); if (GameInteractor_Should(VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_SPIRIT)) { @@ -831,7 +832,8 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, PlayState* play) { gSaveContext.nextCutsceneIndex = 0; } } else if (play->sceneNum == SCENE_SHADOW_TEMPLE_BOSS) { - if (GameInteractor_Should(VB_PLAY_BLUE_WARP_CS, !CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW), + if (GameInteractor_Should(VB_PLAY_BLUE_WARP_CS, + !Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE), RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE)) { Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE); if (GameInteractor_Should(VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_SHADOW)) { From 32683e2a748da238250de1f192d2fe36eee976d3 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Sun, 29 Jun 2025 19:12:04 -0700 Subject: [PATCH 20/31] Change early return in CheckTrackerLoadGame to check specifically for Boss Rush instead of Not Rando. (#5634) --- soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index 8ff302bfe..d1ec624ef 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -495,7 +495,7 @@ void SetShopSeen(uint32_t sceneNum, bool prices) { } void CheckTrackerLoadGame(int32_t fileNum) { - if (!IS_RANDO) { + if (IS_BOSS_RUSH) { return; } LoadSettings(); From 30d193235442a456cf2f72845a53450530532e61 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Mon, 30 Jun 2025 09:37:02 -0700 Subject: [PATCH 21/31] Re-add new preset items to new preset files. --- soh/assets/custom/presets/Main Enhanced.json | 3 ++ .../custom/presets/Main Randomizer.json | 1 + .../Enhancements/randomizer/ShufflePots.cpp | 40 +++++++++---------- 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/soh/assets/custom/presets/Main Enhanced.json b/soh/assets/custom/presets/Main Enhanced.json index 026a78de7..0f31227fb 100644 --- a/soh/assets/custom/presets/Main Enhanced.json +++ b/soh/assets/custom/presets/Main Enhanced.json @@ -44,6 +44,9 @@ "SkipText": 1, "TextSpeed": 5, "TimeFlowFileSelect": 1, + "TimeSavers": { + "SkipJabuJabuFish": 1 + }, "TwoHandedIdle": 1, "VisualAgony": 1, "WidescreenActorCulling": 1 diff --git a/soh/assets/custom/presets/Main Randomizer.json b/soh/assets/custom/presets/Main Randomizer.json index 59c24e982..a4962a5ef 100644 --- a/soh/assets/custom/presets/Main Randomizer.json +++ b/soh/assets/custom/presets/Main Randomizer.json @@ -116,6 +116,7 @@ "Story": 1 }, "SkipForcedDialog": 3, + "SkipJabuJabuFish": 1, "SkipMiscInteractions": 1, "SkipOwlInteractions": 1, "SkipTowerEscape": 1, diff --git a/soh/soh/Enhancements/randomizer/ShufflePots.cpp b/soh/soh/Enhancements/randomizer/ShufflePots.cpp index 4df32a553..5d89bdcfd 100644 --- a/soh/soh/Enhancements/randomizer/ShufflePots.cpp +++ b/soh/soh/Enhancements/randomizer/ShufflePots.cpp @@ -7,7 +7,7 @@ extern "C" { #include "variables.h" #include "overlays/actors/ovl_Obj_Tsubo/z_obj_tsubo.h" #include "overlays/actors/ovl_Door_Shutter/z_door_shutter.h" - extern PlayState* gPlayState; +extern PlayState* gPlayState; } extern void EnItem00_DrawRandomizedItem(EnItem00* enItem00, PlayState* play); @@ -19,7 +19,7 @@ extern "C" void ObjTsubo_RandomizerDraw(Actor* thisx, PlayState* play) { Gfx_SetupDL_25Opa(play->state.gfxCtx); Matrix_Scale(potSize, potSize, potSize, MTXMODE_APPLY); gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), - G_MTX_MODELVIEW | G_MTX_LOAD); + G_MTX_MODELVIEW | G_MTX_LOAD); gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gRandoPotDL); CLOSE_DISPS(play->state.gfxCtx); @@ -68,37 +68,37 @@ void RegisterShufflePots() { ObjTsubo* potActor = static_cast(actorRef); auto potIdentity = OTRGlobals::Instance->gRandomizer->IdentifyPot(gPlayState->sceneNum, (s16)actor->world.pos.x, - (s16)actor->world.pos.z); + (s16)actor->world.pos.z); ObjectExtension::GetInstance().Set(actor, std::move(potIdentity)); - }); + }); // Draw custom model for pot to indicate it holding a randomized item. COND_VB_SHOULD(VB_POT_SETUP_DRAW, shouldRegister, { ObjTsubo* potActor = va_arg(args, ObjTsubo*); - if (ObjTsubo_RandomizerHoldsItem(potActor, gPlayState)) { - potActor->actor.draw = (ActorFunc)ObjTsubo_RandomizerDraw; - *should = false; - } - }); + if (ObjTsubo_RandomizerHoldsItem(potActor, gPlayState)) { + potActor->actor.draw = (ActorFunc)ObjTsubo_RandomizerDraw; + *should = false; + } + }); // Do not spawn vanilla item from pot, instead spawn the ranomized item. COND_VB_SHOULD(VB_POT_DROP_ITEM, shouldRegister, { ObjTsubo* potActor = va_arg(args, ObjTsubo*); - if (ObjTsubo_RandomizerHoldsItem(potActor, gPlayState)) { - ObjTsubo_RandomizerSpawnCollectible(potActor, gPlayState); - *should = false; - } - }); + if (ObjTsubo_RandomizerHoldsItem(potActor, gPlayState)) { + ObjTsubo_RandomizerSpawnCollectible(potActor, gPlayState); + *should = false; + } + }); // Unlock early Ganon's Boss Key doors to allow access to the pots there when pots are shuffled in dungeon COND_VB_SHOULD(VB_LOCK_BOSS_DOOR, shouldRegister, { DoorShutter* doorActor = va_arg(args, DoorShutter*); - uint8_t shufflePotSetting = RAND_GET_OPTION(RSK_SHUFFLE_POTS); - if (gPlayState->sceneNum == SCENE_GANONS_TOWER && doorActor->dyna.actor.world.pos.y == 800 && - (shufflePotSetting == RO_SHUFFLE_POTS_DUNGEONS || shufflePotSetting == RO_SHUFFLE_POTS_ALL)) { - *should = false; - } - }); + uint8_t shufflePotSetting = RAND_GET_OPTION(RSK_SHUFFLE_POTS); + if (gPlayState->sceneNum == SCENE_GANONS_TOWER && doorActor->dyna.actor.world.pos.y == 800 && + (shufflePotSetting == RO_SHUFFLE_POTS_DUNGEONS || shufflePotSetting == RO_SHUFFLE_POTS_ALL)) { + *should = false; + } + }); } void Rando::StaticData::RegisterPotLocations() { From 015dcf2af19340544d5e9ad3606c5045bd5ae176 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Mon, 30 Jun 2025 09:38:06 -0700 Subject: [PATCH 22/31] Fix typo. --- .../3drando/hint_list/hint_list_exclude_overworld.cpp | 2 +- soh/soh/Enhancements/randomizer/ShufflePots.cpp | 6 +++--- soh/soh/Enhancements/randomizer/randomizerTypes.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp index 0826dff0f..5fcb213ff 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp @@ -1548,7 +1548,7 @@ void StaticData::HintTable_Init_Exclude_Overworld() { /*german*/ "Man erzählt sich, daß eine #Krug auf dem Markt# #[[1]]# enthielte.",//TODO_TRANSLATE update to match /*french*/ "Selon moi, une #jarre dans la Place du Marché# contient #[[1]]#.", {QM_RED, QM_GREEN}));//TODO_TRANSLATE update to match - hintTextTable[RHT_POT_ALLY_HOUSE] = HintText(CustomMessage("They say that a #bearded man's pot# contains #[[1]]#.", + hintTextTable[RHT_POT_ALLEY_HOUSE] = HintText(CustomMessage("They say that a #bearded man's pot# contains #[[1]]#.", /*german*/ "Man erzählt sich, daß eine #Krug auf dem Markt# #[[1]]# enthielte.",//TODO_TRANSLATE update to match /*french*/ "Selon moi, une #jarre dans la Place du Marché# contient #[[1]]#.", {QM_RED, QM_GREEN}));//TODO_TRANSLATE update to match diff --git a/soh/soh/Enhancements/randomizer/ShufflePots.cpp b/soh/soh/Enhancements/randomizer/ShufflePots.cpp index 5d89bdcfd..869af92e4 100644 --- a/soh/soh/Enhancements/randomizer/ShufflePots.cpp +++ b/soh/soh/Enhancements/randomizer/ShufflePots.cpp @@ -189,9 +189,9 @@ void Rando::StaticData::RegisterPotLocations() { locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_9] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_9, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(168, 210), "Guard House Adult Pot 9", RHT_POT_POE_SHOP, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_9)); locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_10] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_10, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(167, -122), "Guard House Adult Pot 10", RHT_POT_POE_SHOP, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_10)); locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_11] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_11, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(167, -210), "Guard House Adult Pot 11", RHT_POT_POE_SHOP, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_11)); - locationTable[RC_MK_BACK_ALLEY_HOUSE_POT_1] = Location::Pot(RC_MK_BACK_ALLEY_HOUSE_POT_1, RCQUEST_BOTH, RCAREA_MARKET, SCENE_BACK_ALLEY_HOUSE, TWO_ACTOR_PARAMS(100, 45), "Back Alley House Pot 1", RHT_POT_ALLY_HOUSE, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_BACK_ALLEY_HOUSE_POT_1)); - locationTable[RC_MK_BACK_ALLEY_HOUSE_POT_2] = Location::Pot(RC_MK_BACK_ALLEY_HOUSE_POT_2, RCQUEST_BOTH, RCAREA_MARKET, SCENE_BACK_ALLEY_HOUSE, TWO_ACTOR_PARAMS(12, -180), "Back Alley House Pot 2", RHT_POT_ALLY_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_BACK_ALLEY_HOUSE_POT_2)); - locationTable[RC_MK_BACK_ALLEY_HOUSE_POT_3] = Location::Pot(RC_MK_BACK_ALLEY_HOUSE_POT_3, RCQUEST_BOTH, RCAREA_MARKET, SCENE_BACK_ALLEY_HOUSE, TWO_ACTOR_PARAMS(-54, -180), "Back Alley House Pot 3", RHT_POT_ALLY_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_BACK_ALLEY_HOUSE_POT_3)); + locationTable[RC_MK_BACK_ALLEY_HOUSE_POT_1] = Location::Pot(RC_MK_BACK_ALLEY_HOUSE_POT_1, RCQUEST_BOTH, RCAREA_MARKET, SCENE_BACK_ALLEY_HOUSE, TWO_ACTOR_PARAMS(100, 45), "Back Alley House Pot 1", RHT_POT_ALLEY_HOUSE, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_BACK_ALLEY_HOUSE_POT_1)); + locationTable[RC_MK_BACK_ALLEY_HOUSE_POT_2] = Location::Pot(RC_MK_BACK_ALLEY_HOUSE_POT_2, RCQUEST_BOTH, RCAREA_MARKET, SCENE_BACK_ALLEY_HOUSE, TWO_ACTOR_PARAMS(12, -180), "Back Alley House Pot 2", RHT_POT_ALLEY_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_BACK_ALLEY_HOUSE_POT_2)); + locationTable[RC_MK_BACK_ALLEY_HOUSE_POT_3] = Location::Pot(RC_MK_BACK_ALLEY_HOUSE_POT_3, RCQUEST_BOTH, RCAREA_MARKET, SCENE_BACK_ALLEY_HOUSE, TWO_ACTOR_PARAMS(-54, -180), "Back Alley House Pot 3", RHT_POT_ALLEY_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_BACK_ALLEY_HOUSE_POT_3)); locationTable[RC_KAK_NEAR_POTION_SHOP_POT_1] = Location::Pot(RC_KAK_NEAR_POTION_SHOP_POT_1, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(222, -377), "Near Potion Shop Pot 1", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_POTION_SHOP_POT_1)); locationTable[RC_KAK_NEAR_POTION_SHOP_POT_2] = Location::Pot(RC_KAK_NEAR_POTION_SHOP_POT_2, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(255, -366), "Near Potion Shop Pot 2", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_POTION_SHOP_POT_2)); locationTable[RC_KAK_NEAR_POTION_SHOP_POT_3] = Location::Pot(RC_KAK_NEAR_POTION_SHOP_POT_3, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(284, -356), "Near Potion Shop Pot 3", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_POTION_SHOP_POT_3)); diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 8852abd96..15a2fbd37 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -5440,7 +5440,7 @@ typedef enum { RHT_POT_WASTELAND, RHT_POT_GUARD_HOUSE, RHT_POT_POE_SHOP, - RHT_POT_ALLY_HOUSE, + RHT_POT_ALLEY_HOUSE, RHT_POT_KAKARIKO, RHT_POT_DAMPE, RHT_POT_GORON_CITY, From 7f3d2adc63544946509ff75caeeb5582cbbc47a6 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Mon, 30 Jun 2025 13:04:51 -0700 Subject: [PATCH 23/31] Fix whitespacing in presets. --- soh/assets/custom/presets/Main Enhanced.json | 6 +++--- soh/assets/custom/presets/Main Randomizer.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/soh/assets/custom/presets/Main Enhanced.json b/soh/assets/custom/presets/Main Enhanced.json index 0f31227fb..5e63d651f 100644 --- a/soh/assets/custom/presets/Main Enhanced.json +++ b/soh/assets/custom/presets/Main Enhanced.json @@ -44,9 +44,9 @@ "SkipText": 1, "TextSpeed": 5, "TimeFlowFileSelect": 1, - "TimeSavers": { - "SkipJabuJabuFish": 1 - }, + "TimeSavers": { + "SkipJabuJabuFish": 1 + }, "TwoHandedIdle": 1, "VisualAgony": 1, "WidescreenActorCulling": 1 diff --git a/soh/assets/custom/presets/Main Randomizer.json b/soh/assets/custom/presets/Main Randomizer.json index a4962a5ef..7ece7315a 100644 --- a/soh/assets/custom/presets/Main Randomizer.json +++ b/soh/assets/custom/presets/Main Randomizer.json @@ -116,7 +116,7 @@ "Story": 1 }, "SkipForcedDialog": 3, - "SkipJabuJabuFish": 1, + "SkipJabuJabuFish": 1, "SkipMiscInteractions": 1, "SkipOwlInteractions": 1, "SkipTowerEscape": 1, From 928bb7767bbc2a869824acaf5b4ff23c405a4cb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20Dub=C3=A9?= Date: Mon, 30 Jun 2025 21:52:02 +0000 Subject: [PATCH 24/31] reduce logical implications of closed forest (#5626) * reduce logical implications of closed forest closed forest should only be about kokiri blocking the way, no need to try plug alternate forest escapes out * revert adult deku being unlocked in forest without showing mido sword/shield --- soh/soh/Enhancements/randomizer/entrance.cpp | 25 ------------------- .../randomizer/location_access.cpp | 10 ++++---- .../location_access/overworld/goron_city.cpp | 2 +- .../overworld/kokiri_forest.cpp | 2 +- .../location_access/overworld/lost_woods.cpp | 4 +-- soh/soh/Enhancements/randomizer/logic.cpp | 5 ---- soh/soh/Enhancements/randomizer/logic.h | 1 - soh/soh/Enhancements/randomizer/savefile.cpp | 11 -------- soh/soh/Enhancements/randomizer/settings.cpp | 17 +++---------- 9 files changed, 13 insertions(+), 64 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/entrance.cpp b/soh/soh/Enhancements/randomizer/entrance.cpp index d4a027ee5..1cd4160de 100644 --- a/soh/soh/Enhancements/randomizer/entrance.cpp +++ b/soh/soh/Enhancements/randomizer/entrance.cpp @@ -1211,15 +1211,6 @@ int EntranceShuffler::ShuffleAllEntrances() { if (ctx->GetOption(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 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) && - !(ctx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES) || ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES))) { - FilterAndEraseFromPool(entrancePools[EntranceType::Boss], [](const Entrance* entrance) { - return entrance->GetParentRegionKey() == RR_DEKU_TREE_BOSS_ENTRYWAY && - entrance->GetConnectedRegionKey() == RR_DEKU_TREE_BOSS_ROOM; - }); - } if (ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) { for (Entrance* entrance : entrancePools[EntranceType::Boss]) { entrancePools[EntranceType::BossReverse].push_back(entrance->GetReverse()); @@ -1228,14 +1219,6 @@ int EntranceShuffler::ShuffleAllEntrances() { } else { entrancePools[EntranceType::ChildBoss] = GetShuffleableEntrances(EntranceType::ChildBoss); entrancePools[EntranceType::AdultBoss] = GetShuffleableEntrances(EntranceType::AdultBoss); - // 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))) { - FilterAndEraseFromPool(entrancePools[EntranceType::ChildBoss], [](const Entrance* entrance) { - return entrance->GetParentRegionKey() == RR_DEKU_TREE_BOSS_ENTRYWAY && - entrance->GetConnectedRegionKey() == RR_DEKU_TREE_BOSS_ROOM; - }); - } if (ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) { for (Entrance* entrance : entrancePools[EntranceType::ChildBoss]) { entrancePools[EntranceType::ChildBossReverse].push_back(entrance->GetReverse()); @@ -1255,14 +1238,6 @@ int EntranceShuffler::ShuffleAllEntrances() { AddElementsToPool(entrancePools[EntranceType::Dungeon], GetShuffleableEntrances(EntranceType::GanonDungeon)); } - // If forest is closed don't allow a forest escape via spirit temple hands - if (ctx->GetOption(RSK_FOREST).Is(RO_CLOSED_FOREST_ON) && - !(ctx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES) || ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES))) { - FilterAndEraseFromPool(entrancePools[EntranceType::Dungeon], [](const Entrance* entrance) { - return entrance->GetParentRegionKey() == RR_KF_OUTSIDE_DEKU_TREE && - entrance->GetConnectedRegionKey() == RR_DEKU_TREE_ENTRYWAY; - }); - } if (ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) { for (Entrance* entrance : entrancePools[EntranceType::Dungeon]) { entrancePools[EntranceType::DungeonReverse].push_back(entrance->GetReverse()); diff --git a/soh/soh/Enhancements/randomizer/location_access.cpp b/soh/soh/Enhancements/randomizer/location_access.cpp index fceb6c08f..e261b8d49 100644 --- a/soh/soh/Enhancements/randomizer/location_access.cpp +++ b/soh/soh/Enhancements/randomizer/location_access.cpp @@ -808,11 +808,11 @@ void RegionTable_Init() { Entrance(RR_CHILD_SPAWN, []{return logic->IsChild;}), Entrance(RR_ADULT_SPAWN, []{return logic->IsAdult;}), Entrance(RR_MINUET_OF_FOREST_WARP, []{return logic->CanUse(RG_MINUET_OF_FOREST);}), - Entrance(RR_BOLERO_OF_FIRE_WARP, []{return logic->CanUse(RG_BOLERO_OF_FIRE) && logic->CanLeaveForest();}), - Entrance(RR_SERENADE_OF_WATER_WARP, []{return logic->CanUse(RG_SERENADE_OF_WATER) && logic->CanLeaveForest();}), - Entrance(RR_NOCTURNE_OF_SHADOW_WARP, []{return logic->CanUse(RG_NOCTURNE_OF_SHADOW) && logic->CanLeaveForest();}), - Entrance(RR_REQUIEM_OF_SPIRIT_WARP, []{return logic->CanUse(RG_REQUIEM_OF_SPIRIT) && logic->CanLeaveForest();}), - Entrance(RR_PRELUDE_OF_LIGHT_WARP, []{return logic->CanUse(RG_PRELUDE_OF_LIGHT) && logic->CanLeaveForest();}), + Entrance(RR_BOLERO_OF_FIRE_WARP, []{return logic->CanUse(RG_BOLERO_OF_FIRE);}), + Entrance(RR_SERENADE_OF_WATER_WARP, []{return logic->CanUse(RG_SERENADE_OF_WATER);}), + Entrance(RR_NOCTURNE_OF_SHADOW_WARP, []{return logic->CanUse(RG_NOCTURNE_OF_SHADOW);}), + Entrance(RR_REQUIEM_OF_SPIRIT_WARP, []{return logic->CanUse(RG_REQUIEM_OF_SPIRIT);}), + Entrance(RR_PRELUDE_OF_LIGHT_WARP, []{return logic->CanUse(RG_PRELUDE_OF_LIGHT);}), }); areaTable[RR_CHILD_SPAWN] = Region("Child Spawn", SCENE_ID_MAX, TIME_DOESNT_PASS, {RA_LINKS_POCKET}, {}, {}, { diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp index 7027ab6c6..9d155c3a0 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp @@ -63,7 +63,7 @@ void RegionTable_Init_GoronCity() { EventAccess(&logic->GCWoodsWarpOpen, []{return logic->BlastOrSmash() || logic->CanUse(RG_DINS_FIRE);}), }, {}, { //Exits - Entrance(RR_GORON_CITY, []{return logic->CanLeaveForest() && logic->GCWoodsWarpOpen;}), + Entrance(RR_GORON_CITY, []{return logic->GCWoodsWarpOpen;}), Entrance(RR_THE_LOST_WOODS, []{return true;}), }); diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp index 525e22200..5d8ef11ec 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp @@ -13,7 +13,7 @@ void RegionTable_Init_KokiriForest() { }, { //Locations LOCATION(RC_KF_KOKIRI_SWORD_CHEST, logic->IsChild), - LOCATION(RC_KF_GS_KNOW_IT_ALL_HOUSE, logic->IsChild && logic->CanAttack() && (/*TODO: HasNightStart ||*/ logic->CanLeaveForest() || logic->CanUse(RG_SUNS_SONG)) && logic->CanGetNightTimeGS()), + LOCATION(RC_KF_GS_KNOW_IT_ALL_HOUSE, logic->IsChild && logic->CanAttack() && logic->CanGetNightTimeGS()), LOCATION(RC_KF_GS_BEAN_PATCH, logic->CanSpawnSoilSkull() && logic->CanAttack()), LOCATION(RC_KF_GS_HOUSE_OF_TWINS, logic->IsAdult && (logic->HookshotOrBoomerang() || (ctx->GetTrickOption(RT_KF_ADULT_GS) && logic->CanUse(RG_HOVER_BOOTS))) && logic->CanGetNightTimeGS()), LOCATION(RC_KF_BEAN_SPROUT_FAIRY_1, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp index 753d7247d..6c6bdb536 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp @@ -57,8 +57,8 @@ void RegionTable_Init_LostWoods() { //Exits Entrance(RR_LW_FOREST_EXIT, []{return true;}), Entrance(RR_GC_WOODS_WARP, []{return true;}), - Entrance(RR_LW_BRIDGE, []{return logic->CanLeaveForest() && ((logic->IsAdult && (CanPlantBean(RR_THE_LOST_WOODS) || ctx->GetTrickOption(RT_LW_BRIDGE))) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_LONGSHOT));}), - Entrance(RR_ZR_FROM_SHORTCUT, []{return logic->CanLeaveForest() && (logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS) || (ctx->GetTrickOption(RT_LOST_WOOD_NAVI_DIVE) && logic->IsChild && logic->HasItem(RG_BRONZE_SCALE) && logic->CanJumpslash()));}), + Entrance(RR_LW_BRIDGE, []{return (logic->IsAdult && (CanPlantBean(RR_THE_LOST_WOODS) || ctx->GetTrickOption(RT_LW_BRIDGE))) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_LONGSHOT);}), + Entrance(RR_ZR_FROM_SHORTCUT, []{return logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS) || (ctx->GetTrickOption(RT_LOST_WOOD_NAVI_DIVE) && logic->IsChild && logic->HasItem(RG_BRONZE_SCALE) && logic->CanJumpslash());}), Entrance(RR_LW_BEYOND_MIDO, []{return logic->IsChild || logic->CanUse(RG_SARIAS_SONG) || ctx->GetTrickOption(RT_LW_MIDO_BACKFLIP);}), Entrance(RR_LW_NEAR_SHORTCUTS_GROTTO, []{return Here(RR_THE_LOST_WOODS, []{return logic->BlastOrSmash();});}), }); diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index f759ca3c6..eea79e92d 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -1177,11 +1177,6 @@ bool Logic::CanStunDeku() { return CanAttack() || CanUse(RG_NUTS) || CanReflectNuts(); } -bool Logic::CanLeaveForest() { - return ctx->GetOption(RSK_FOREST).IsNot(RO_CLOSED_FOREST_ON) || IsAdult || DekuTreeClear || - ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES) || ctx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES); -} - bool Logic::CallGossipFairyExceptSuns() { return CanUse(RG_ZELDAS_LULLABY) || CanUse(RG_EPONAS_SONG) || CanUse(RG_SONG_OF_TIME); } diff --git a/soh/soh/Enhancements/randomizer/logic.h b/soh/soh/Enhancements/randomizer/logic.h index 4355bc96d..2bfea75e9 100644 --- a/soh/soh/Enhancements/randomizer/logic.h +++ b/soh/soh/Enhancements/randomizer/logic.h @@ -231,7 +231,6 @@ class Logic { bool CanReflectNuts(); bool CanCutShrubs(); bool CanStunDeku(); - bool CanLeaveForest(); bool CallGossipFairy(); bool CallGossipFairyExceptSuns(); uint8_t EffectiveHealth(); diff --git a/soh/soh/Enhancements/randomizer/savefile.cpp b/soh/soh/Enhancements/randomizer/savefile.cpp index 05a10a2b3..51101f6fa 100644 --- a/soh/soh/Enhancements/randomizer/savefile.cpp +++ b/soh/soh/Enhancements/randomizer/savefile.cpp @@ -358,17 +358,6 @@ extern "C" void Randomizer_InitSaveFile() { gSaveContext.sceneFlags[SCENE_WATER_TEMPLE].swch |= (1 << 0x15); } - // Now handled on the fly. - // int openForest = Randomizer_GetSettingValue(RSK_FOREST); - // switch (openForest) { - // case RO_CLOSED_FOREST_OFF: - // Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD); - // // Fallthrough - // case RO_CLOSED_FOREST_DEKU_ONLY: - // Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD); - // break; - // } - int doorOfTime = Randomizer_GetSettingValue(RSK_DOOR_OF_TIME); switch (doorOfTime) { case RO_DOOROFTIME_OPEN: diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index ff683c2ef..5f8c60ac0 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -1832,10 +1832,9 @@ void Settings::UpdateOptionProperties() { } else { mOptionGroups[RSG_AREA_ACCESS_IMGUI].Enable(); // Starting Age - Disabled when Forest is set to Closed or under very specific conditions - if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ClosedForest"), RO_CLOSED_FOREST_ON) == RO_CLOSED_FOREST_ON || - (CVarGetInteger(CVAR_RANDOMIZER_SETTING("DoorOfTime"), RO_DOOROFTIME_CLOSED) == RO_DOOROFTIME_CLOSED && - CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleOcarinas"), RO_GENERIC_OFF) == - RO_GENERIC_OFF)) /* closed door of time with ocarina shuffle off */ { + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("DoorOfTime"), RO_DOOROFTIME_CLOSED) == RO_DOOROFTIME_CLOSED && + CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleOcarinas"), RO_GENERIC_OFF) == + RO_GENERIC_OFF) /* closed door of time with ocarina shuffle off */ { mOptions[RSK_STARTING_AGE].Disable( "This option is disabled due to other options making the game unbeatable."); } else { @@ -2532,8 +2531,7 @@ void Context::FinalizeSettings(const std::set& excludedLocation } // With certain access settings, the seed is only beatable if Starting Age is set to Child. - if (mOptions[RSK_FOREST].Is(RO_CLOSED_FOREST_ON) || - (mOptions[RSK_DOOR_OF_TIME].Is(RO_DOOROFTIME_CLOSED) && !mOptions[RSK_SHUFFLE_OCARINA])) { + if (mOptions[RSK_DOOR_OF_TIME].Is(RO_DOOROFTIME_CLOSED) && !mOptions[RSK_SHUFFLE_OCARINA]) { mOptions[RSK_STARTING_AGE].Set(RO_AGE_CHILD); } @@ -2847,13 +2845,6 @@ void Context::FinalizeSettings(const std::set& excludedLocation mOptions[RSK_MIX_GROTTO_ENTRANCES].Set(RO_GENERIC_OFF); } - if (mOptions[RSK_FOREST].Is(RO_CLOSED_FOREST_ON) && - (mOptions[RSK_SHUFFLE_INTERIOR_ENTRANCES].Is(RO_INTERIOR_ENTRANCE_SHUFFLE_ALL) || - mOptions[RSK_SHUFFLE_OVERWORLD_ENTRANCES] || mOptions[RSK_SHUFFLE_OVERWORLD_SPAWNS] || - mOptions[RSK_DECOUPLED_ENTRANCES] || mOptions[RSK_MIXED_ENTRANCE_POOLS])) { - mOptions[RSK_FOREST].Set(RO_CLOSED_FOREST_DEKU_ONLY); - } - if (mOptions[RSK_STARTING_AGE].Is(RO_AGE_RANDOM)) { if (const uint32_t choice = Random(0, 2); choice == 0) { mOptions[RSK_SELECTED_STARTING_AGE].Set(RO_AGE_CHILD); From f80836d8b728bb40cdfd4f37fed8f7b89f6db154 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20Dub=C3=A9?= Date: Mon, 30 Jun 2025 21:52:45 +0000 Subject: [PATCH 25/31] Enemy Randomizer: all the invis (#5621) Fire Keese, Floormaster, Ice Keese, Keese, Redead, Stalfos --- soh/soh/Enhancements/enemyrandomizer.cpp | 127 +++++++++++++++-------- soh/soh/Enhancements/enemyrandomizer.h | 2 +- 2 files changed, 87 insertions(+), 42 deletions(-) diff --git a/soh/soh/Enhancements/enemyrandomizer.cpp b/soh/soh/Enhancements/enemyrandomizer.cpp index 2e15a9ed9..11f024226 100644 --- a/soh/soh/Enhancements/enemyrandomizer.cpp +++ b/soh/soh/Enhancements/enemyrandomizer.cpp @@ -28,33 +28,66 @@ bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy); EnemyEntry GetRandomizedEnemyEntry(uint32_t seed, PlayState* play); const char* enemyCVarList[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] = { - CVAR_ENHANCEMENT("RandomizedEnemyList.Anubis"), CVAR_ENHANCEMENT("RandomizedEnemyList.Armos"), - CVAR_ENHANCEMENT("RandomizedEnemyList.Arwing"), CVAR_ENHANCEMENT("RandomizedEnemyList.BabyDodongo"), - CVAR_ENHANCEMENT("RandomizedEnemyList.Bari"), CVAR_ENHANCEMENT("RandomizedEnemyList.Beamos"), - CVAR_ENHANCEMENT("RandomizedEnemyList.BigSkulltula"), CVAR_ENHANCEMENT("RandomizedEnemyList.BigStalchild"), - CVAR_ENHANCEMENT("RandomizedEnemyList.Biri"), CVAR_ENHANCEMENT("RandomizedEnemyList.BlackKnuckle"), - CVAR_ENHANCEMENT("RandomizedEnemyList.BlueTektite"), CVAR_ENHANCEMENT("RandomizedEnemyList.Bubble"), - CVAR_ENHANCEMENT("RandomizedEnemyList.ClubMoblin"), CVAR_ENHANCEMENT("RandomizedEnemyList.DarkLink"), - CVAR_ENHANCEMENT("RandomizedEnemyList.Dinolfos"), CVAR_ENHANCEMENT("RandomizedEnemyList.Dodongo"), - CVAR_ENHANCEMENT("RandomizedEnemyList.FireKeese"), /*CVAR_ENHANCEMENT("RandomizedEnemyList.FlareDancer"),*/ - CVAR_ENHANCEMENT("RandomizedEnemyList.FloorTile"), CVAR_ENHANCEMENT("RandomizedEnemyList.Floormaster"), - CVAR_ENHANCEMENT("RandomizedEnemyList.FlyingPeahat"), CVAR_ENHANCEMENT("RandomizedEnemyList.FlyingPot"), - CVAR_ENHANCEMENT("RandomizedEnemyList.Freezard"), CVAR_ENHANCEMENT("RandomizedEnemyList.Gibdo"), - CVAR_ENHANCEMENT("RandomizedEnemyList.GohmaLarva"), CVAR_ENHANCEMENT("RandomizedEnemyList.Guay"), - CVAR_ENHANCEMENT("RandomizedEnemyList.IceKeese"), CVAR_ENHANCEMENT("RandomizedEnemyList.InvisSkulltula"), - CVAR_ENHANCEMENT("RandomizedEnemyList.Keese"), CVAR_ENHANCEMENT("RandomizedEnemyList.LargeBaba"), - CVAR_ENHANCEMENT("RandomizedEnemyList.LikeLike"), CVAR_ENHANCEMENT("RandomizedEnemyList.Lizalfos"), - CVAR_ENHANCEMENT("RandomizedEnemyList.MadScrub"), CVAR_ENHANCEMENT("RandomizedEnemyList.NormalWolfos"), - CVAR_ENHANCEMENT("RandomizedEnemyList.PeahatLarva"), /*CVAR_ENHANCEMENT("RandomizedEnemyList.Poe"),*/ - CVAR_ENHANCEMENT("RandomizedEnemyList.Redead"), CVAR_ENHANCEMENT("RandomizedEnemyList.RedTektite"), - CVAR_ENHANCEMENT("RandomizedEnemyList.Shabom"), CVAR_ENHANCEMENT("RandomizedEnemyList.ShellBlade"), - CVAR_ENHANCEMENT("RandomizedEnemyList.Skulltula"), CVAR_ENHANCEMENT("RandomizedEnemyList.SkullKid"), - CVAR_ENHANCEMENT("RandomizedEnemyList.SmallBaba"), CVAR_ENHANCEMENT("RandomizedEnemyList.SmallStalchild"), - CVAR_ENHANCEMENT("RandomizedEnemyList.SpearMoblin"), CVAR_ENHANCEMENT("RandomizedEnemyList.Spike"), - CVAR_ENHANCEMENT("RandomizedEnemyList.Stalfos"), CVAR_ENHANCEMENT("RandomizedEnemyList.Stinger"), - CVAR_ENHANCEMENT("RandomizedEnemyList.Tailparasan"), CVAR_ENHANCEMENT("RandomizedEnemyList.TorchSlug"), - CVAR_ENHANCEMENT("RandomizedEnemyList.Wallmaster"), CVAR_ENHANCEMENT("RandomizedEnemyList.WhiteKnuckle"), - CVAR_ENHANCEMENT("RandomizedEnemyList.WhiteWolfos"), CVAR_ENHANCEMENT("RandomizedEnemyList.WitheredBaba"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Anubis"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Armos"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Arwing"), + CVAR_ENHANCEMENT("RandomizedEnemyList.BabyDodongo"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Bari"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Beamos"), + CVAR_ENHANCEMENT("RandomizedEnemyList.BigSkulltula"), + CVAR_ENHANCEMENT("RandomizedEnemyList.BigStalchild"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Biri"), + CVAR_ENHANCEMENT("RandomizedEnemyList.BlackKnuckle"), + CVAR_ENHANCEMENT("RandomizedEnemyList.BlueTektite"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Bubble"), + CVAR_ENHANCEMENT("RandomizedEnemyList.ClubMoblin"), + CVAR_ENHANCEMENT("RandomizedEnemyList.DarkLink"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Dinolfos"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Dodongo"), + CVAR_ENHANCEMENT("RandomizedEnemyList.FireKeese"), + // CVAR_ENHANCEMENT("RandomizedEnemyList.FlareDancer"), + CVAR_ENHANCEMENT("RandomizedEnemyList.FloorTile"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Floormaster"), + CVAR_ENHANCEMENT("RandomizedEnemyList.FlyingPeahat"), + CVAR_ENHANCEMENT("RandomizedEnemyList.FlyingPot"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Freezard"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Gibdo"), + CVAR_ENHANCEMENT("RandomizedEnemyList.GohmaLarva"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Guay"), + CVAR_ENHANCEMENT("RandomizedEnemyList.IceKeese"), + CVAR_ENHANCEMENT("RandomizedEnemyList.InvisFireKeese"), + CVAR_ENHANCEMENT("RandomizedEnemyList.InvisFloormaster"), + CVAR_ENHANCEMENT("RandomizedEnemyList.InvisIceKeese"), + CVAR_ENHANCEMENT("RandomizedEnemyList.InvisKeese"), + CVAR_ENHANCEMENT("RandomizedEnemyList.InvisRedead"), + CVAR_ENHANCEMENT("RandomizedEnemyList.InvisSkulltula"), + CVAR_ENHANCEMENT("RandomizedEnemyList.InvisStalfos"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Keese"), + CVAR_ENHANCEMENT("RandomizedEnemyList.LargeBaba"), + CVAR_ENHANCEMENT("RandomizedEnemyList.LikeLike"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Lizalfos"), + CVAR_ENHANCEMENT("RandomizedEnemyList.MadScrub"), + CVAR_ENHANCEMENT("RandomizedEnemyList.NormalWolfos"), + CVAR_ENHANCEMENT("RandomizedEnemyList.PeahatLarva"), + // CVAR_ENHANCEMENT("RandomizedEnemyList.Poe"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Redead"), + CVAR_ENHANCEMENT("RandomizedEnemyList.RedTektite"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Shabom"), + CVAR_ENHANCEMENT("RandomizedEnemyList.ShellBlade"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Skulltula"), + CVAR_ENHANCEMENT("RandomizedEnemyList.SkullKid"), + CVAR_ENHANCEMENT("RandomizedEnemyList.SmallBaba"), + CVAR_ENHANCEMENT("RandomizedEnemyList.SmallStalchild"), + CVAR_ENHANCEMENT("RandomizedEnemyList.SpearMoblin"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Spike"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Stalfos"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Stinger"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Tailparasan"), + CVAR_ENHANCEMENT("RandomizedEnemyList.TorchSlug"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Wallmaster"), + CVAR_ENHANCEMENT("RandomizedEnemyList.WhiteKnuckle"), + CVAR_ENHANCEMENT("RandomizedEnemyList.WhiteWolfos"), + CVAR_ENHANCEMENT("RandomizedEnemyList.WitheredBaba"), }; const char* enemyNameList[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] = { @@ -85,7 +118,13 @@ const char* enemyNameList[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] = { "Gohma Larva", "Guay", "Ice Keese", + "Invisible Fire Keese", + "Invisible Floormaster", + "Invisible Ice Keese", + "Invisible Keese", + "Invisible Redead", "Invisible Skulltula", + "Invisible Stalfos", "Keese", "Large Deku Baba", "Like-Like", @@ -134,20 +173,26 @@ static EnemyEntry randomizedEnemySpawnTable[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] = { ACTOR_EN_FIREFLY, 1 }, // Fire Keese // { ACTOR_EN_FD, 0 }, // Flare Dancer (possible cause of crashes because of spawning flame actors on // sloped ground) - { ACTOR_EN_YUKABYUN, 0 }, // Flying Floor Tile - { ACTOR_EN_FLOORMAS, 0 }, // Floormaster - { ACTOR_EN_PEEHAT, -1 }, // Flying Peahat (big grounded, doesn't spawn larva) - { ACTOR_EN_TUBO_TRAP, 0 }, // Flying pot - { ACTOR_EN_FZ, 0 }, // Freezard - { ACTOR_EN_RD, 32766 }, // Gibdo (standing) - { ACTOR_EN_GOMA, 7 }, // Gohma Larva (Non-Gohma rooms) - { ACTOR_EN_CROW, 0 }, // Guay - { ACTOR_EN_FIREFLY, 4 }, // Ice Keese - { ACTOR_EN_ST, 2 }, // Skulltula (invisible) - { ACTOR_EN_FIREFLY, 2 }, // Regular Keese - { ACTOR_EN_DEKUBABA, 1 }, // Deku Baba (large) - // Doesn't work (reliant on surface and also normally used in tandem with a leever spawner, kills itself too quickly - // otherwise) { ACTOR_EN_REEBA, 0 }, // Leever + { ACTOR_EN_YUKABYUN, 0 }, // Flying Floor Tile + { ACTOR_EN_FLOORMAS, 0 }, // Floormaster + { ACTOR_EN_PEEHAT, -1 }, // Flying Peahat (big grounded, doesn't spawn larva) + { ACTOR_EN_TUBO_TRAP, 0 }, // Flying pot + { ACTOR_EN_FZ, 0 }, // Freezard + { ACTOR_EN_RD, 32766 }, // Gibdo (standing) + { ACTOR_EN_GOMA, 7 }, // Gohma Larva (Non-Gohma rooms) + { ACTOR_EN_CROW, 0 }, // Guay + { ACTOR_EN_FIREFLY, 4 }, // Ice Keese + { ACTOR_EN_FIREFLY, 0x8001 }, // Fire Keese (invisible) + { ACTOR_EN_FLOORMAS, 0x8000 }, // Floormaster (invisible) + { ACTOR_EN_FIREFLY, 0x8004 }, // Ice Keese (invisible) + { ACTOR_EN_FIREFLY, 0x8002 }, // Keese (invisible) + { ACTOR_EN_RD, 3 }, // Redead (invisible) + { ACTOR_EN_ST, 2 }, // Skulltula (invisible) + { ACTOR_EN_TEST, 0 }, // Stalfos (invisible) + { ACTOR_EN_FIREFLY, 2 }, // Regular Keese + { ACTOR_EN_DEKUBABA, 1 }, // Deku Baba (large) + // Doesn't work (reliant on surface, without a spawner it kills itself too quickly) + // { ACTOR_EN_REEBA, 0 }, // Leever { ACTOR_EN_RR, 0 }, // Like-Like { ACTOR_EN_ZF, -1 }, // Lizalfos { ACTOR_EN_DEKUNUTS, 768 }, // Mad Scrub (triple attack) (projectiles don't work) diff --git a/soh/soh/Enhancements/enemyrandomizer.h b/soh/soh/Enhancements/enemyrandomizer.h index 9220f2db0..79171246c 100644 --- a/soh/soh/Enhancements/enemyrandomizer.h +++ b/soh/soh/Enhancements/enemyrandomizer.h @@ -3,7 +3,7 @@ #include #include "item-tables/ItemTableTypes.h" -#define RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE 52 +#define RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE 58 extern const char* enemyCVarList[]; extern const char* enemyNameList[]; From db58c3a0297cf4d6861e6b044bccbfb53e8c8a28 Mon Sep 17 00:00:00 2001 From: aMannus Date: Tue, 1 Jul 2025 01:56:55 +0200 Subject: [PATCH 26/31] Fix clang-format ps1 script (#5637) * Fix clang-format ps1 script * use path variable --- run-clang-format.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run-clang-format.ps1 b/run-clang-format.ps1 index 063cec7af..3ff6998a6 100644 --- a/run-clang-format.ps1 +++ b/run-clang-format.ps1 @@ -25,7 +25,7 @@ if (-not (Test-Path $clangFormatFilePath) -or ($currentVersion -ne $requiredVers } $wc = New-Object net.webclient - $wc.Downloadfile($url, $llvmInstallerPath) + $wc.Downloadfile($url, $PSScriptRoot + $llvmInstallerPath) $sevenZipPath = "C:\Program Files\7-Zip\7z.exe" $specificFileInArchive = "bin\clang-format.exe" From 05a7f728e736836b3b6d799487c4c922ff789581 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20Dub=C3=A9?= Date: Tue, 1 Jul 2025 17:30:02 +0000 Subject: [PATCH 27/31] dev tools save editor: change dungeon drop down to current dungeon (#5635) --- soh/soh/Enhancements/debugger/debugSaveEditor.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp index 547d1907a..7b514a16c 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp @@ -1305,6 +1305,15 @@ void DrawQuestStatusTab() { ImGui::Text("Dungeon Items"); static int32_t dungeonItemsScene = SCENE_DEKU_TREE; + static int32_t lastDungeonScene = -1; + if (gPlayState != nullptr) { + int32_t sceneNum = gPlayState->sceneNum; + if (sceneNum >= SCENE_DEKU_TREE && sceneNum <= SCENE_JABU_JABU_BOSS && lastDungeonScene != sceneNum) { + dungeonItemsScene = sceneNum; + lastDungeonScene = sceneNum; + } + } + PushStyleCombobox(THEME_COLOR); if (ImGui::BeginCombo("##DungeonSelect", SohUtils::GetSceneName(dungeonItemsScene).c_str())) { for (int32_t dungeonIndex = SCENE_DEKU_TREE; dungeonIndex < SCENE_JABU_JABU_BOSS + 1; dungeonIndex++) { From 48d2193fec455a2105708b5cd692ee0c14cd31ac Mon Sep 17 00:00:00 2001 From: aMannus Date: Tue, 1 Jul 2025 19:54:26 +0200 Subject: [PATCH 28/31] CrowdControl additions & improvements (#5104) * CrowdControl additions & improvements * Update after dev merge * clang format * Revert "clang format" This reverts commit 1be5ad18f5995792971fa0a1772109b0157817b4. * clang format --- soh/soh/Enhancements/ExtraTraps.cpp | 4 +- soh/soh/Enhancements/debugconsole.cpp | 2 +- .../game-interactor/GameInteractionEffect.cpp | 31 ++-- .../game-interactor/GameInteractionEffect.h | 7 +- .../game-interactor/GameInteractor.h | 12 +- .../GameInteractor_RawAction.cpp | 164 ++++-------------- .../game-interactor/GameInteractor_State.cpp | 6 +- soh/soh/Network/CrowdControl/CrowdControl.cpp | 152 +--------------- soh/soh/Network/CrowdControl/CrowdControl.h | 1 + .../Network/CrowdControl/ShipOfHarkinian.cs | 45 ----- soh/soh/Network/Sail/Sail.cpp | 11 +- soh/soh/SohGui/SohMenuNetwork.cpp | 31 ++-- soh/src/code/z_actor.c | 12 +- .../ovl_En_Attack_Niw/z_en_attack_niw.c | 5 + .../actors/ovl_player_actor/z_player.c | 17 -- 15 files changed, 103 insertions(+), 397 deletions(-) diff --git a/soh/soh/Enhancements/ExtraTraps.cpp b/soh/soh/Enhancements/ExtraTraps.cpp index e88a8f1fe..155b1af71 100644 --- a/soh/soh/Enhancements/ExtraTraps.cpp +++ b/soh/soh/Enhancements/ExtraTraps.cpp @@ -82,7 +82,7 @@ static void RollRandomTrap(uint32_t seed) { case ADD_SPEED_TRAP: Audio_PlaySoundGeneral(NA_SE_VO_KZ_MOVE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); - GameInteractor::State::RunSpeedModifier = -2; + GameInteractor::State::MovementSpeedMultiplier = 0.5f; statusTimer = 200; Notification::Emit({ .message = "Speed Decreased!" }); break; @@ -112,7 +112,7 @@ static void RollRandomTrap(uint32_t seed) { static void OnPlayerUpdate() { Player* player = GET_PLAYER(gPlayState); if (statusTimer == 0) { - GameInteractor::State::RunSpeedModifier = 0; + GameInteractor::State::MovementSpeedMultiplier = 1.0f; } if (eventTimer == 0) { switch (roll) { diff --git a/soh/soh/Enhancements/debugconsole.cpp b/soh/soh/Enhancements/debugconsole.cpp index 91c0d4c1c..7713b48b8 100644 --- a/soh/soh/Enhancements/debugconsole.cpp +++ b/soh/soh/Enhancements/debugconsole.cpp @@ -1130,7 +1130,7 @@ static bool SpeedModifierHandler(std::shared_ptr Console, const s ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; } - GameInteractionEffectBase* effect = new GameInteractionEffect::ModifyRunSpeedModifier(); + GameInteractionEffectBase* effect = new GameInteractionEffect::ModifyMovementSpeedMultiplier(); try { dynamic_cast(effect)->parameters[0] = std::stoi(args[1], nullptr, 10); diff --git a/soh/soh/Enhancements/game-interactor/GameInteractionEffect.cpp b/soh/soh/Enhancements/game-interactor/GameInteractionEffect.cpp index 95455926b..03667dd86 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractionEffect.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractionEffect.cpp @@ -11,6 +11,7 @@ have functions to both enable and disable said effect. #include "GameInteractionEffect.h" #include "GameInteractor.h" #include +#include "soh/Enhancements/cosmetics/CosmeticsEditor.h" extern "C" { #include @@ -371,19 +372,23 @@ void ForceEquipBoots::_Remove() { GameInteractor::RawAction::ForceEquipBoots(EQUIP_VALUE_BOOTS_KOKIRI); } -// MARK: - ModifyRunSpeedModifier -GameInteractionEffectQueryResult ModifyRunSpeedModifier::CanBeApplied() { +// MARK: - ModifyMovementSpeedMultiplier +GameInteractionEffectQueryResult ModifyMovementSpeedMultiplier::CanBeApplied() { if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else { return GameInteractionEffectQueryResult::Possible; } } -void ModifyRunSpeedModifier::_Apply() { - GameInteractor::State::RunSpeedModifier = parameters[0]; +void ModifyMovementSpeedMultiplier::_Apply() { + if (parameters[0] == -2) { + GameInteractor::State::MovementSpeedMultiplier = 0.5f; + } else if (parameters[0] == 2) { + GameInteractor::State::MovementSpeedMultiplier = 2.0f; + } } -void ModifyRunSpeedModifier::_Remove() { - GameInteractor::State::RunSpeedModifier = 0; +void ModifyMovementSpeedMultiplier::_Remove() { + GameInteractor::State::MovementSpeedMultiplier = 1.0f; } // MARK: - OneHitKO @@ -485,18 +490,6 @@ void SetCollisionViewer::_Remove() { GameInteractor::RawAction::SetCollisionViewer(false); } -// MARK: - SetCosmeticsColor -GameInteractionEffectQueryResult SetCosmeticsColor::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded()) { - return GameInteractionEffectQueryResult::TemporarilyNotPossible; - } else { - return GameInteractionEffectQueryResult::Possible; - } -} -void SetCosmeticsColor::_Apply() { - GameInteractor::RawAction::SetCosmeticsColor(parameters[0], parameters[1]); -} - // MARK: - RandomizeCosmetics GameInteractionEffectQueryResult RandomizeCosmetics::CanBeApplied() { if (!GameInteractor::IsSaveLoaded()) { @@ -506,7 +499,7 @@ GameInteractionEffectQueryResult RandomizeCosmetics::CanBeApplied() { } } void RandomizeCosmetics::_Apply() { - GameInteractor::RawAction::RandomizeCosmeticsColors(true); + CosmeticsEditor_RandomizeAll(); } // MARK: - PressButton diff --git a/soh/soh/Enhancements/game-interactor/GameInteractionEffect.h b/soh/soh/Enhancements/game-interactor/GameInteractionEffect.h index 72eb101b0..9243621d1 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractionEffect.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractionEffect.h @@ -156,7 +156,7 @@ class ForceEquipBoots : public RemovableGameInteractionEffect, public Parameteri void _Remove() override; }; -class ModifyRunSpeedModifier : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect { +class ModifyMovementSpeedMultiplier : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect { GameInteractionEffectQueryResult CanBeApplied() override; void _Apply() override; void _Remove() override; @@ -200,11 +200,6 @@ class SetCollisionViewer : public RemovableGameInteractionEffect { void _Remove() override; }; -class SetCosmeticsColor : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { - GameInteractionEffectQueryResult CanBeApplied() override; - void _Apply() override; -}; - class RandomizeCosmetics : public GameInteractionEffectBase { GameInteractionEffectQueryResult CanBeApplied() override; void _Apply() override; diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index db68ad86a..8ac2d9dda 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -76,7 +76,7 @@ uint8_t GameInteractor_PacifistModeActive(); uint8_t GameInteractor_DisableZTargetingActive(); uint8_t GameInteractor_ReverseControlsActive(); int32_t GameInteractor_DefenseModifier(); -int32_t GameInteractor_RunSpeedModifier(); +float GameInteractor_MovementSpeedMultiplier(); GIGravityLevel GameInteractor_GravityLevel(); uint32_t GameInteractor_GetEmulatedButtons(); void GameInteractor_SetEmulatedButtons(uint32_t buttons); @@ -204,7 +204,7 @@ class GameInteractor { static bool DisableZTargetingActive; static bool ReverseControlsActive; static int32_t DefenseModifier; - static int32_t RunSpeedModifier; + static float MovementSpeedMultiplier; static GIGravityLevel GravityLevel; static uint32_t EmulatedButtons; static uint8_t RandomBombFuseTimerActive; @@ -566,8 +566,6 @@ class GameInteractor { static void ClearAssignedButtons(uint8_t buttonSet); static void SetTimeOfDay(uint32_t time); static void SetCollisionViewer(bool active); - static void SetCosmeticsColor(uint8_t cosmeticCategory, uint8_t colorValue); - static void RandomizeCosmeticsColors(bool excludeBiddingWarColors); static void EmulateButtonPress(int32_t button); static void AddOrTakeAmmo(int16_t amount, int16_t item); static void EmulateRandomButtonPress(uint32_t chancePercentage = 100); @@ -575,8 +573,10 @@ class GameInteractor { static void SetPlayerInvincibility(bool active); static void ClearCutscenePointer(); - static GameInteractionEffectQueryResult SpawnEnemyWithOffset(uint32_t enemyId, int32_t enemyParams); - static GameInteractionEffectQueryResult SpawnActor(uint32_t actorId, int32_t actorParams); + static GameInteractionEffectQueryResult SpawnEnemyWithOffset(uint32_t enemyId, int32_t enemyParams, + std::string nameTag = ""); + static GameInteractionEffectQueryResult SpawnActor(uint32_t actorId, int32_t actorParams, + std::string nameTag = ""); }; }; diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp index 779b37981..793466c19 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp @@ -1,9 +1,9 @@ #include "GameInteractor.h" #include -#include "soh/Enhancements/cosmetics/CosmeticsEditor.h" #include "soh/Enhancements/randomizer/3drando/random.hpp" #include #include "soh/Enhancements/debugger/colViewer.h" +#include "soh/Enhancements/nametag.h" extern "C" { #include "variables.h" @@ -405,125 +405,6 @@ void GameInteractor::RawAction::SetCollisionViewer(bool active) { } } -void GameInteractor::RawAction::SetCosmeticsColor(uint8_t cosmeticCategory, uint8_t colorValue) { - Color_RGBA8 newColor; - newColor.r = 255; - newColor.g = 255; - newColor.b = 255; - newColor.a = 255; - - switch (colorValue) { - case GI_COLOR_RED: - newColor.r = 200; - newColor.g = 30; - newColor.b = 30; - break; - case GI_COLOR_GREEN: - newColor.r = 50; - newColor.g = 200; - newColor.b = 50; - break; - case GI_COLOR_BLUE: - newColor.r = 50; - newColor.g = 50; - newColor.b = 200; - break; - case GI_COLOR_ORANGE: - newColor.r = 200; - newColor.g = 120; - newColor.b = 0; - break; - case GI_COLOR_YELLOW: - newColor.r = 234; - newColor.g = 240; - newColor.b = 33; - break; - case GI_COLOR_PURPLE: - newColor.r = 144; - newColor.g = 13; - newColor.b = 178; - break; - case GI_COLOR_PINK: - newColor.r = 215; - newColor.g = 93; - newColor.b = 246; - break; - case GI_COLOR_BROWN: - newColor.r = 108; - newColor.g = 72; - newColor.b = 15; - break; - case GI_COLOR_BLACK: - newColor.r = 0; - newColor.g = 0; - newColor.b = 0; - break; - default: - break; - } - - switch (cosmeticCategory) { - case GI_COSMETICS_TUNICS: - CVarSetColor(CVAR_COSMETIC("Link.KokiriTunic.Value"), newColor); - CVarSetInteger(CVAR_COSMETIC("Link.KokiriTunic.Changed"), 1); - CVarSetColor(CVAR_COSMETIC("Link.GoronTunic.Value"), newColor); - CVarSetInteger(CVAR_COSMETIC("Link.GoronTunic.Changed"), 1); - CVarSetColor(CVAR_COSMETIC("Link.ZoraTunic.Value"), newColor); - CVarSetInteger(CVAR_COSMETIC("Link.ZoraTunic.Changed"), 1); - break; - case GI_COSMETICS_NAVI: - CVarSetColor(CVAR_COSMETIC("Navi.EnemyPrimary.Value"), newColor); - CVarSetInteger(CVAR_COSMETIC("Navi.EnemyPrimary.Changed"), 1); - CVarSetColor(CVAR_COSMETIC("Navi.EnemySecondary.Value"), newColor); - CVarSetInteger(CVAR_COSMETIC("Navi.EnemySecondary.Changed"), 1); - CVarSetColor(CVAR_COSMETIC("Navi.IdlePrimary.Value"), newColor); - CVarSetInteger(CVAR_COSMETIC("Navi.IdlePrimary.Changed"), 1); - CVarSetColor(CVAR_COSMETIC("Navi.IdleSecondary.Value"), newColor); - CVarSetInteger(CVAR_COSMETIC("Navi.IdleSecondary.Changed"), 1); - CVarSetColor(CVAR_COSMETIC("Navi.NPCPrimary.Value"), newColor); - CVarSetInteger(CVAR_COSMETIC("Navi.NPCPrimary.Changed"), 1); - CVarSetColor(CVAR_COSMETIC("Navi.NPCSecondary.Value"), newColor); - CVarSetInteger(CVAR_COSMETIC("Navi.NPCSecondary.Changed"), 1); - CVarSetColor(CVAR_COSMETIC("Navi.PropsPrimary.Value"), newColor); - CVarSetInteger(CVAR_COSMETIC("Navi.PropsPrimary.Changed"), 1); - CVarSetColor(CVAR_COSMETIC("Navi.PropsSecondary.Value"), newColor); - CVarSetInteger(CVAR_COSMETIC("Navi.PropsSecondary.Changed"), 1); - break; - case GI_COSMETICS_HAIR: - CVarSetColor(CVAR_COSMETIC("Link.Hair.Value"), newColor); - CVarSetInteger(CVAR_COSMETIC("Link.Hair.Changed"), 1); - break; - } - - Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); - ApplyOrResetCustomGfxPatches(); -} - -void GameInteractor::RawAction::RandomizeCosmeticsColors(bool excludeBiddingWarColors) { - const char* cvarsToLock[12] = { - CVAR_COSMETIC("Link.KokiriTunic.Locked"), CVAR_COSMETIC("Link.GoronTunic.Locked"), - CVAR_COSMETIC("Link.ZoraTunic.Locked"), CVAR_COSMETIC("Navi.EnemyPrimary.Locked"), - CVAR_COSMETIC("Navi.EnemySecondary.Locked"), CVAR_COSMETIC("Navi.IdlePrimary.Locked"), - CVAR_COSMETIC("Navi.IdleSecondary.Locked"), CVAR_COSMETIC("Navi.NPCPrimary.Locked"), - CVAR_COSMETIC("Navi.NPCSecondary.Locked"), CVAR_COSMETIC("Navi.PropsPrimary.Locked"), - CVAR_COSMETIC("Navi.PropsSecondary.Locked"), CVAR_COSMETIC("Link.Hair.Locked") - }; - - if (excludeBiddingWarColors) { - for (uint8_t i = 0; i < 12; i++) { - CVarSetInteger(cvarsToLock[i], 1); - } - } - - CosmeticsEditor_RandomizeAll(); - - if (excludeBiddingWarColors) { - for (uint8_t i = 0; i < 12; i++) { - CVarSetInteger(cvarsToLock[i], 0); - } - } -} - void GameInteractor::RawAction::EmulateButtonPress(int32_t button) { GameInteractor::State::EmulatedButtons |= button; } @@ -580,8 +461,8 @@ void GameInteractor::RawAction::ClearCutscenePointer() { gPlayState->csCtx.segment = &null_cs; } -GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset(uint32_t enemyId, - int32_t enemyParams) { +GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset(uint32_t enemyId, int32_t enemyParams, + std::string nameTag) { if (!GameInteractor::CanSpawnActor()) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; @@ -651,15 +532,29 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset pos.x += 10; pos.y += 10; pos.z += 10; - if (Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, pos.x, pos.y, pos.z, 0, 0, 0, enemyParams, 0) == - NULL) { + Actor* actor = + Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, pos.x, pos.y, pos.z, 0, 0, 0, enemyParams, 0); + if (actor == NULL) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } + if (nameTag != "" && CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("EnemyNameTags"), 0)) { + NameTag_RegisterForActor(actor, nameTag.c_str()); + } + if (CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("SpawnedEnemiesIgnoredIngame"), 0)) { + Actor_ChangeCategory(gPlayState, &gPlayState->actorCtx, actor, ACTORCAT_NPC); + } } return GameInteractionEffectQueryResult::Possible; } else { - if (Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, pos.x, pos.y, pos.z, 0, 0, 0, enemyParams, 0) != - NULL) { + Actor* actor = + Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, pos.x, pos.y, pos.z, 0, 0, 0, enemyParams, 0); + if (actor != NULL) { + if (nameTag != "" && CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("EnemyNameTags"), 0)) { + NameTag_RegisterForActor(actor, nameTag.c_str()); + } + if (CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("SpawnedEnemiesIgnoredIngame"), 0)) { + Actor_ChangeCategory(gPlayState, &gPlayState->actorCtx, actor, ACTORCAT_NPC); + } return GameInteractionEffectQueryResult::Possible; } } @@ -667,7 +562,8 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset return GameInteractionEffectQueryResult::TemporarilyNotPossible; } -GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnActor(uint32_t actorId, int32_t actorParams) { +GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnActor(uint32_t actorId, int32_t actorParams, + std::string nameTag) { if (!GameInteractor::CanSpawnActor()) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; @@ -684,6 +580,9 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnActor(uint32_t return GameInteractionEffectQueryResult::TemporarilyNotPossible; } + if (nameTag != "" && CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("EnemyNameTags"), 0)) { + NameTag_RegisterForActor((Actor*)cucco, nameTag.c_str()); + } cucco->actionFunc = func_80AB70A0_nocutscene; return GameInteractionEffectQueryResult::Possible; } else if (actorId == ACTOR_EN_BOM) { @@ -703,8 +602,15 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnActor(uint32_t return GameInteractionEffectQueryResult::Possible; } else { // Generic spawn an actor at Link's position - if (Actor_Spawn(&gPlayState->actorCtx, gPlayState, actorId, player->actor.world.pos.x, - player->actor.world.pos.y, player->actor.world.pos.z, 0, 0, 0, actorParams, 0) != NULL) { + Actor* actor = Actor_Spawn(&gPlayState->actorCtx, gPlayState, actorId, player->actor.world.pos.x, + player->actor.world.pos.y, player->actor.world.pos.z, 0, 0, 0, actorParams, 0); + if (actor != NULL) { + if (nameTag != "" && CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("EnemyNameTags"), 0)) { + NameTag_RegisterForActor((Actor*)actor, nameTag.c_str()); + } + if (CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("SpawnedEnemiesIgnoredIngame"), 0)) { + Actor_ChangeCategory(gPlayState, &gPlayState->actorCtx, actor, ACTORCAT_NPC); + } return GameInteractionEffectQueryResult::Possible; } } diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_State.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_State.cpp index 21642dded..bdcb4f37a 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_State.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_State.cpp @@ -10,7 +10,7 @@ bool GameInteractor::State::PacifistModeActive = 0; bool GameInteractor::State::DisableZTargetingActive = 0; bool GameInteractor::State::ReverseControlsActive = 0; int32_t GameInteractor::State::DefenseModifier = 0; -int32_t GameInteractor::State::RunSpeedModifier = 0; +float GameInteractor::State::MovementSpeedMultiplier = 1.0f; GIGravityLevel GameInteractor::State::GravityLevel = GI_GRAVITY_LEVEL_NORMAL; uint32_t GameInteractor::State::EmulatedButtons = 0; uint8_t GameInteractor::State::RandomBombFuseTimerActive = 0; @@ -81,8 +81,8 @@ int32_t GameInteractor_DefenseModifier() { } // MARK: - GameInteractor::State::DisableCameraRotationActive -int32_t GameInteractor_RunSpeedModifier() { - return GameInteractor::State::RunSpeedModifier; +float GameInteractor_MovementSpeedMultiplier() { + return GameInteractor::State::MovementSpeedMultiplier; } // MARK: - GameInteractor::State::DisableCameraRotationActive diff --git a/soh/soh/Network/CrowdControl/CrowdControl.cpp b/soh/soh/Network/CrowdControl/CrowdControl.cpp index f706bed89..fd293d8ba 100644 --- a/soh/soh/Network/CrowdControl/CrowdControl.cpp +++ b/soh/soh/Network/CrowdControl/CrowdControl.cpp @@ -136,9 +136,11 @@ void CrowdControl::EmitMessage(uint32_t eventId, long timeRemaining, EffectResul CrowdControl::EffectResult CrowdControl::ExecuteEffect(Effect* effect) { GameInteractionEffectQueryResult giResult; if (effect->category == kEffectCatSpawnEnemy) { - giResult = GameInteractor::RawAction::SpawnEnemyWithOffset(effect->spawnParams[0], effect->spawnParams[1]); + giResult = GameInteractor::RawAction::SpawnEnemyWithOffset(effect->spawnParams[0], effect->spawnParams[1], + effect->viewerName); } else if (effect->category == kEffectCatSpawnActor) { - giResult = GameInteractor::RawAction::SpawnActor(effect->spawnParams[0], effect->spawnParams[1]); + giResult = + GameInteractor::RawAction::SpawnActor(effect->spawnParams[0], effect->spawnParams[1], effect->viewerName); } else { giResult = GameInteractor::ApplyEffect(effect->giEffect); } @@ -185,6 +187,7 @@ CrowdControl::Effect* CrowdControl::ParseMessage(nlohmann::json dataReceived) { Effect* effect = new Effect(); effect->lastExecutionResult = EffectResult::Initiate; effect->id = dataReceived["id"]; + effect->viewerName = dataReceived["viewer"]; auto parameters = dataReceived["parameters"]; uint32_t receivedParameter = 0; auto effectName = dataReceived["code"].get(); @@ -301,13 +304,13 @@ CrowdControl::Effect* CrowdControl::ParseMessage(nlohmann::json dataReceived) { case kEffectIncreaseSpeed: effect->category = kEffectCatSpeed; effect->timeRemaining = 30000; - effect->giEffect = new GameInteractionEffect::ModifyRunSpeedModifier(); + effect->giEffect = new GameInteractionEffect::ModifyMovementSpeedMultiplier(); dynamic_cast(effect->giEffect)->parameters[0] = 2; break; case kEffectDecreaseSpeed: effect->category = kEffectCatSpeed; effect->timeRemaining = 30000; - effect->giEffect = new GameInteractionEffect::ModifyRunSpeedModifier(); + effect->giEffect = new GameInteractionEffect::ModifyMovementSpeedMultiplier(); dynamic_cast(effect->giEffect)->parameters[0] = -2; break; case kEffectLowGravity: @@ -620,147 +623,6 @@ CrowdControl::Effect* CrowdControl::ParseMessage(nlohmann::json dataReceived) { dynamic_cast(effect->giEffect)->parameters[0] = GI_TP_DEST_PRELUDE; break; - // Tunic Color (Bidding War) - case kEffectTunicRed: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_RED; - break; - case kEffectTunicGreen: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_GREEN; - break; - case kEffectTunicBlue: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_BLUE; - break; - case kEffectTunicOrange: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_ORANGE; - break; - case kEffectTunicYellow: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_YELLOW; - break; - case kEffectTunicPurple: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_PURPLE; - break; - case kEffectTunicPink: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_PINK; - break; - case kEffectTunicBrown: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_BROWN; - break; - case kEffectTunicBlack: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_BLACK; - break; - - // Navi Color (Bidding War) - case kEffectNaviRed: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_RED; - break; - case kEffectNaviGreen: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_GREEN; - break; - case kEffectNaviBlue: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_BLUE; - break; - case kEffectNaviOrange: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_ORANGE; - break; - case kEffectNaviYellow: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_YELLOW; - break; - case kEffectNaviPurple: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_PURPLE; - break; - case kEffectNaviPink: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_PINK; - break; - case kEffectNaviBrown: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_BROWN; - break; - case kEffectNaviBlack: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_BLACK; - break; - - // Link's Hair Color (Bidding War) - case kEffectHairRed: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_RED; - break; - case kEffectHairGreen: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_GREEN; - break; - case kEffectHairBlue: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_BLUE; - break; - case kEffectHairOrange: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_ORANGE; - break; - case kEffectHairYellow: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_YELLOW; - break; - case kEffectHairPurple: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_PURPLE; - break; - case kEffectHairPink: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_PINK; - break; - case kEffectHairBrown: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_BROWN; - break; - case kEffectHairBlack: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_BLACK; - break; - default: break; } diff --git a/soh/soh/Network/CrowdControl/CrowdControl.h b/soh/soh/Network/CrowdControl/CrowdControl.h index 8951e6cf1..f906961c3 100644 --- a/soh/soh/Network/CrowdControl/CrowdControl.h +++ b/soh/soh/Network/CrowdControl/CrowdControl.h @@ -56,6 +56,7 @@ class CrowdControl : public Network { uint32_t category = 0; long timeRemaining; GameInteractionEffectBase* giEffect; + std::string viewerName; // Metadata used while executing (only for timed effects) bool isPaused; diff --git a/soh/soh/Network/CrowdControl/ShipOfHarkinian.cs b/soh/soh/Network/CrowdControl/ShipOfHarkinian.cs index b1617435c..554e0d56b 100644 --- a/soh/soh/Network/CrowdControl/ShipOfHarkinian.cs +++ b/soh/soh/Network/CrowdControl/ShipOfHarkinian.cs @@ -124,50 +124,5 @@ public class ShipOfHarkinian : SimpleTCPPack new("Requiem Destination", "tp_requiem") { Category = "Teleport Player", Price = 100, Description = "Teleport the player to Desert Colossus." }, new("Nocturne Destination", "tp_nocturne") { Category = "Teleport Player", Price = 100, Description = "Teleport the player to the Raveyard." }, new("Prelude Destination", "tp_prelude") { Category = "Teleport Player", Price = 100, Description = "Teleport the player to the Temple of Time." }, - - // Tunic Color (Bidding War) - new("Tunic Color", "tunic", ItemKind.BidWar) - { - Parameters = new ParameterDef("Color", "color_tunic_param", - new Parameter("Red", "red"), - new Parameter("Green", "green"), - new Parameter("Blue", "blue"), - new Parameter("Orange", "orange"), - new Parameter("Yellow", "yellow"), - new Parameter("Purple", "purple"), - new Parameter("Pink", "pink"), - new Parameter("Brown", "brown"), - new Parameter("Black", "black")) - }, - - // Navi Color (Bidding War) - new("Navi Color", "navi", ItemKind.BidWar) - { - Parameters = new ParameterDef("Color", "color_navi_param", - new Parameter("Red", "red"), - new Parameter("Green", "green"), - new Parameter("Blue", "blue"), - new Parameter("Orange", "orange"), - new Parameter("Yellow", "yellow"), - new Parameter("Purple", "purple"), - new Parameter("Pink", "pink"), - new Parameter("Brown", "brown"), - new Parameter("Black", "black")) - }, - - // Link's Hair Color (Bidding War) - new("Link's Hair Color", "hair", ItemKind.BidWar) - { - Parameters = new ParameterDef("Color", "color_hair_param", - new Parameter("Red", "red"), - new Parameter("Green", "green"), - new Parameter("Blue", "blue"), - new Parameter("Orange", "orange"), - new Parameter("Yellow", "yellow"), - new Parameter("Purple", "purple"), - new Parameter("Pink", "pink"), - new Parameter("Brown", "brown"), - new Parameter("Black", "black")) - } }; } diff --git a/soh/soh/Network/Sail/Sail.cpp b/soh/soh/Network/Sail/Sail.cpp index a5396777e..08f23fca5 100644 --- a/soh/soh/Network/Sail/Sail.cpp +++ b/soh/soh/Network/Sail/Sail.cpp @@ -242,8 +242,8 @@ GameInteractionEffectBase* Sail::EffectFromJson(nlohmann::json payload) { effect->parameters[0] = payload["parameters"][0].get(); } return effect; - } else if (name == "ModifyRunSpeedModifier") { - auto effect = new GameInteractionEffect::ModifyRunSpeedModifier(); + } else if (name == "ModifyMovementSpeedMultiplier") { + auto effect = new GameInteractionEffect::ModifyMovementSpeedMultiplier(); if (payload.contains("parameters")) { effect->parameters[0] = payload["parameters"][0].get(); } @@ -282,13 +282,6 @@ GameInteractionEffectBase* Sail::EffectFromJson(nlohmann::json payload) { return effect; } else if (name == "SetCollisionViewer") { return new GameInteractionEffect::SetCollisionViewer(); - } else if (name == "SetCosmeticsColor") { - auto effect = new GameInteractionEffect::SetCosmeticsColor(); - if (payload.contains("parameters")) { - effect->parameters[0] = payload["parameters"][0].get(); - effect->parameters[1] = payload["parameters"][1].get(); - } - return effect; } else if (name == "RandomizeCosmetics") { return new GameInteractionEffect::RandomizeCosmetics(); } else if (name == "PressButton") { diff --git a/soh/soh/SohGui/SohMenuNetwork.cpp b/soh/soh/SohGui/SohMenuNetwork.cpp index bb6004288..f2fba3ff1 100644 --- a/soh/soh/SohGui/SohMenuNetwork.cpp +++ b/soh/soh/SohGui/SohMenuNetwork.cpp @@ -96,21 +96,15 @@ void SohMenu::AddMenuNetwork() { AddSidebarEntry("Network", path.sidebarName, 3); path.column = SECTION_COLUMN_1; + AddWidget(path, "About Crowd Control", WIDGET_SEPARATOR_TEXT); AddWidget(path, "Crowd Control is a platform that allows viewers to interact " "with a streamer's game in real time.\n" "\n" - "Click the question mark to copy the link to the Crowd Control " - "website to your clipboard.", + "Please head over to www.crowdcontrol.live for more information!", WIDGET_TEXT); - AddWidget(path, ICON_FA_CLIPBOARD "##CrowdControl", WIDGET_BUTTON) - .Callback([](WidgetInfo& info) { - ImGui::SetClipboardText("https://crowdcontrol.live"); - Notification::Emit({ - .message = "Copied to clipboard", - }); - }) - .Options(ButtonOptions().Tooltip("https://crowdcontrol.live")); + + AddWidget(path, "Connect to Crowd Control", WIDGET_SEPARATOR_TEXT); AddWidget(path, "Host & Port", WIDGET_CUSTOM).CustomFunction([](WidgetInfo& info) { ImGui::BeginDisabled(CrowdControl::Instance->isEnabled || CVarGetInteger(CVAR_SETTING("DisableChanges"), 0)); ImGui::Text("%s", info.name.c_str()); @@ -155,14 +149,25 @@ void SohMenu::AddMenuNetwork() { CrowdControl::Instance->Enable(); } }); - AddWidget(path, "Connecting...##CrowdControl", WIDGET_TEXT).PreFunc([](WidgetInfo& info) { + AddWidget(path, "Connecting...", WIDGET_TEXT).PreFunc([](WidgetInfo& info) { info.isHidden = !CrowdControl::Instance->isEnabled; if (CrowdControl::Instance->isConnected) { - info.name = "Connected##CrowdControl"; + info.name = "Connected"; } else { - info.name = "Connecting...##CrowdControl"; + info.name = "Connecting..."; } }); + AddWidget(path, "Additional Settings", WIDGET_SEPARATOR_TEXT); + AddWidget(path, "Enemy Name Tags", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_REMOTE_CROWD_CONTROL("EnemyNameTags")) + .RaceDisable(true) + .Options(CheckboxOptions().Tooltip( + "When viewers spawn enemies, the enemy will have a name tag above them with the viewer's name.")); + AddWidget(path, "Spawned Enemies Ignored Ingame", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_REMOTE_CROWD_CONTROL("SpawnedEnemiesIgnoredIngame")) + .RaceDisable(true) + .Options(CheckboxOptions().Tooltip("Enemies spawned by CrowdControl won't be considered for \"clear enemy " + "rooms\", so they don't need to be killed to complete these rooms.")); } } // namespace SohGui diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index 3933f263d..620cb4959 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -1284,8 +1284,16 @@ void Actor_UpdatePos(Actor* actor) { } void Actor_UpdateVelocityXZGravity(Actor* actor) { - actor->velocity.x = Math_SinS(actor->world.rot.y) * actor->speedXZ; - actor->velocity.z = Math_CosS(actor->world.rot.y) * actor->speedXZ; + Player* player = GET_PLAYER(gPlayState); + uint8_t inCutscene = player->stateFlags1 & PLAYER_STATE1_CLIMBING_LADDER || + player->stateFlags1 & PLAYER_STATE1_IN_CUTSCENE || + player->stateFlags2 & PLAYER_STATE2_CRAWLING; + f32 speedModifier = 1.0f; + if (actor->id == ACTOR_PLAYER && !inCutscene) { + speedModifier = GameInteractor_MovementSpeedMultiplier(); + } + actor->velocity.x = Math_SinS(actor->world.rot.y) * actor->speedXZ * speedModifier; + actor->velocity.z = Math_CosS(actor->world.rot.y) * actor->speedXZ * speedModifier; actor->velocity.y += actor->gravity; if (actor->velocity.y < actor->minVelocityY) { diff --git a/soh/src/overlays/actors/ovl_En_Attack_Niw/z_en_attack_niw.c b/soh/src/overlays/actors/ovl_En_Attack_Niw/z_en_attack_niw.c index aa455739e..70bd36a6b 100644 --- a/soh/src/overlays/actors/ovl_En_Attack_Niw/z_en_attack_niw.c +++ b/soh/src/overlays/actors/ovl_En_Attack_Niw/z_en_attack_niw.c @@ -58,6 +58,11 @@ void EnAttackNiw_Init(Actor* thisx, PlayState* play) { this->actor.flags &= ~ACTOR_FLAG_ATTENTION_ENABLED; this->actor.shape.rot.y = this->actor.world.rot.y = (Rand_ZeroOne() - 0.5f) * 60000.0f; this->actionFunc = func_809B5670; + + if (CVarGetInteger("gCrowdControl", 0) && + CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("SpawnedEnemiesIgnoredIngame"), 0)) { + Actor_ChangeCategory(gPlayState, &gPlayState->actorCtx, this, ACTORCAT_NPC); + } } void EnAttackNiw_Destroy(Actor* thisx, PlayState* play) { diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 4ae6fb744..205079576 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -7124,15 +7124,6 @@ void func_8083DFE0(Player* this, f32* arg1, s16* arg2) { if (this->meleeWeaponState == 0) { float maxSpeed = R_RUN_SPEED_LIMIT / 100.0f; - int32_t giSpeedModifier = GameInteractor_RunSpeedModifier(); - if (giSpeedModifier != 0) { - if (giSpeedModifier > 0) { - maxSpeed *= giSpeedModifier; - } else { - maxSpeed /= abs(giSpeedModifier); - } - } - if (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) == BUNNY_HOOD_FAST_AND_JUMP && this->currentMask == PLAYER_MASK_BUNNY) { maxSpeed *= 1.5f; @@ -8873,14 +8864,6 @@ void Player_Action_80842180(Player* this, PlayState* play) { Player_GetMovementSpeedAndYaw(this, &sp2C, &sp2A, SPEED_MODE_CURVED, play); if (!func_8083C484(this, &sp2C, &sp2A)) { - int32_t giSpeedModifier = GameInteractor_RunSpeedModifier(); - if (giSpeedModifier != 0) { - if (giSpeedModifier > 0) { - sp2C *= giSpeedModifier; - } else { - sp2C /= abs(giSpeedModifier); - } - } if (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA && this->currentMask == PLAYER_MASK_BUNNY) { From cddc7353af5c9cf5eb60ab2ff99112822dee14f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20Dub=C3=A9?= Date: Tue, 1 Jul 2025 17:54:39 +0000 Subject: [PATCH 29/31] tts: replace rupee count with key count in dungeons (except first 3 child dungeons) (#5642) --- .../accessibility/texts/kaleidoscope_eng.json | 1 + .../accessibility/texts/kaleidoscope_fra.json | 1 + .../accessibility/texts/kaleidoscope_ger.json | 1 + soh/soh/Enhancements/tts/tts.cpp | 13 ++++++++++--- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/soh/assets/custom/accessibility/texts/kaleidoscope_eng.json b/soh/assets/custom/accessibility/texts/kaleidoscope_eng.json index a89c12889..04fc1f8f2 100644 --- a/soh/assets/custom/accessibility/texts/kaleidoscope_eng.json +++ b/soh/assets/custom/accessibility/texts/kaleidoscope_eng.json @@ -2,6 +2,7 @@ "health": "Health - $0 Hearts", "magic": "Magic - $0", "rupees": "Rupees - $0", + "keys": "Keys - $0", "floor": "Floor $0", "basement": "Basement $0", "item_menu": "Select Item", diff --git a/soh/assets/custom/accessibility/texts/kaleidoscope_fra.json b/soh/assets/custom/accessibility/texts/kaleidoscope_fra.json index 116c19a41..93e0058dc 100644 --- a/soh/assets/custom/accessibility/texts/kaleidoscope_fra.json +++ b/soh/assets/custom/accessibility/texts/kaleidoscope_fra.json @@ -2,6 +2,7 @@ "health": "Vie - $0 Coeurs", "magic": "Magie - $0", "rupees": "Rubis - $0", + "keys": "Clés - $0", "floor": "Étage $0", "basement": "Sous-sol $0", "item_menu": "Inventaire", diff --git a/soh/assets/custom/accessibility/texts/kaleidoscope_ger.json b/soh/assets/custom/accessibility/texts/kaleidoscope_ger.json index 649790da3..f66b82736 100644 --- a/soh/assets/custom/accessibility/texts/kaleidoscope_ger.json +++ b/soh/assets/custom/accessibility/texts/kaleidoscope_ger.json @@ -2,6 +2,7 @@ "health": "Energie - $0 Herzen", "magic": "Magie - $0", "rupees": "Rubine - $0", + "keys": "Schlüssel - $0", "floor": "Etage $0", "basement": "Keller $0", "item_menu": "Gegenstände", diff --git a/soh/soh/Enhancements/tts/tts.cpp b/soh/soh/Enhancements/tts/tts.cpp index 13dd9f183..1dc8a1ba6 100644 --- a/soh/soh/Enhancements/tts/tts.cpp +++ b/soh/soh/Enhancements/tts/tts.cpp @@ -370,9 +370,16 @@ void RegisterOnKaleidoscopeUpdateHook() { auto translation = GetParameritizedText("magic", TEXT_BANK_KALEIDO, arg); SpeechSynthesizer::Instance->Speak(translation.c_str(), GetLanguageCode()); } else if (CHECK_BTN_ALL(input->press.button, BTN_DDOWN)) { - snprintf(arg, sizeof(arg), "%d", gSaveContext.rupees); - auto translation = GetParameritizedText("rupees", TEXT_BANK_KALEIDO, arg); - SpeechSynthesizer::Instance->Speak(translation.c_str(), GetLanguageCode()); + if (gPlayState->sceneNum >= SCENE_FOREST_TEMPLE && gPlayState->sceneNum <= SCENE_INSIDE_GANONS_CASTLE) { + snprintf(arg, sizeof(arg), "%d", + std::max(gSaveContext.inventory.dungeonKeys[gPlayState->sceneNum], (s8)0)); + auto translation = GetParameritizedText("keys", TEXT_BANK_KALEIDO, arg); + SpeechSynthesizer::Instance->Speak(translation.c_str(), GetLanguageCode()); + } else { + snprintf(arg, sizeof(arg), "%d", gSaveContext.rupees); + auto translation = GetParameritizedText("rupees", TEXT_BANK_KALEIDO, arg); + SpeechSynthesizer::Instance->Speak(translation.c_str(), GetLanguageCode()); + } } else if (CHECK_BTN_ALL(input->press.button, BTN_DRIGHT)) { // TODO: announce timer? } From ec54d02c0c01e7bf9dc0a6d66698575be89df47b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20Dub=C3=A9?= Date: Tue, 1 Jul 2025 19:04:26 +0000 Subject: [PATCH 30/31] Spirit Flags (#5631) 1. skip cutscene delay for sun on floor & sun on block 2. persist sun on floor temp flag 3. persist big mirror being solved before platform lowered 2 removes need for weird bomb key logic 3 needed for shuffle doors --- .../Enhancements/randomizer/hook_handlers.cpp | 40 ++++++++++++++++++- .../dungeons/spirit_temple.cpp | 31 +++++++------- .../Enhancements/randomizer/randomizer_inf.h | 2 + .../Enhancements/timesaver_hook_handlers.cpp | 31 ++++++++++++-- soh/src/code/z_actor.c | 4 +- 5 files changed, 85 insertions(+), 23 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 92d210300..d73cebca7 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -22,6 +22,7 @@ extern "C" { #include "soh/Enhancements/randomizer/randomizer_entrance.h" #include "soh/Enhancements/randomizer/randomizer_grotto.h" #include "src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h" +#include "src/overlays/actors/ovl_Bg_Jya_Bigmirror/z_bg_jya_bigmirror.h" #include "src/overlays/actors/ovl_En_Si/z_en_si.h" #include "src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.h" #include "src/overlays/actors/ovl_En_Dns/z_en_dns.h" @@ -263,6 +264,14 @@ void RandomizerOnSceneFlagSetHandler(int16_t sceneNum, int16_t flagType, int16_t Flags_SetRandomizerInf(RAND_INF_GF_GTG_GATE_PERMANENTLY_OPEN); } + if (sceneNum == SCENE_SPIRIT_TEMPLE && flagType == FLAG_SCENE_SWITCH) { + bool isVanilla = + Rando::Context::GetInstance()->GetDungeons()->GetDungeonFromScene(SCENE_SPIRIT_TEMPLE)->IsVanilla(); + if (isVanilla && flag == 0x23) { + Flags_SetRandomizerInf(RAND_INF_SPIRIT_SUN_ON_FLOOR_ON); + } + } + RandomizerCheck rc = GetRandomizerCheckFromSceneFlag(sceneNum, flagType, flag); if (rc == RC_UNKNOWN_CHECK) return; @@ -1783,7 +1792,7 @@ void RandomizerOnSceneInitHandler(int16_t sceneNum) { Entrance_OverrideSpawnScene(sceneNum, gPlayState->curSpawn); } - // LACs & Prelude checks + // LACS & Prelude checks static uint32_t updateHook = 0; if (updateHook) { @@ -1855,6 +1864,16 @@ void EnDns_RandomizerPurchase(EnDns* enDns) { void RandomizerOnActorInitHandler(void* actorRef) { Actor* actor = static_cast(actorRef); + if (actor->id == ACTOR_PLAYER) { + if (gPlayState->sceneNum == SCENE_SPIRIT_TEMPLE) { + bool isVanilla = + Rando::Context::GetInstance()->GetDungeons()->GetDungeonFromScene(SCENE_SPIRIT_TEMPLE)->IsVanilla(); + if (isVanilla && Flags_GetRandomizerInf(RAND_INF_SPIRIT_SUN_ON_FLOOR_ON)) { + Flags_SetSwitch(gPlayState, 0x23); + } + } + } + if (actor->id == ACTOR_EN_SI) { RandomizerCheck rc = OTRGlobals::Instance->gRandomizer->GetCheckFromActor(actor->id, gPlayState->sceneNum, actor->params); @@ -1986,6 +2005,15 @@ void RandomizerOnActorInitHandler(void* actorRef) { } } + if (actor->id == ACTOR_BG_JYA_BIGMIRROR && Flags_GetRandomizerInf(RAND_INF_SPIRIT_BIG_MIRROR_STATUE_TURNED)) { + Flags_SetSwitch(gPlayState, 0x29); // destroy wall + auto jyaBigMirror = static_cast(actorRef); + jyaBigMirror->puzzleFlags |= + BIGMIR_PUZZLE_COBRA1_SOLVED | BIGMIR_PUZZLE_COBRA2_SOLVED | BIGMIR_PUZZLE_BOMBIWA_DESTROYED; + jyaBigMirror->cobraInfo[0].rotY = 0x4000; + jyaBigMirror->cobraInfo[1].rotY = 0x8000; + } + if (actor->id == ACTOR_DEMO_KEKKAI && actor->params == 0) { // 0 == KEKKAI_TOWER if (CompletedAllTrials()) { Actor_Kill(actor); @@ -2151,6 +2179,16 @@ void RandomizerOnActorUpdateHandler(void* refActor) { } } + if (actor->id == ACTOR_BG_JYA_BIGMIRROR) { + auto jyaBigMirror = reinterpret_cast(actor); + if ((jyaBigMirror->puzzleFlags & (BIGMIR_PUZZLE_COBRA1_SOLVED | BIGMIR_PUZZLE_COBRA2_SOLVED)) == + (BIGMIR_PUZZLE_COBRA1_SOLVED | BIGMIR_PUZZLE_COBRA2_SOLVED)) { + Flags_SetRandomizerInf(RAND_INF_SPIRIT_BIG_MIRROR_STATUE_TURNED); + } else { + Flags_UnsetRandomizerInf(RAND_INF_SPIRIT_BIG_MIRROR_STATUE_TURNED); + } + } + // In ER, override the warp song locations. Also removes the warp song cutscene if (RAND_GET_OPTION(RSK_SHUFFLE_ENTRANCES) && actor->id == ACTOR_DEMO_KANKYO && actor->params == 0x000F) { // Warp Song particles diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp index 2755fe453..e2a13ecc1 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp @@ -48,12 +48,12 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_CHILD_CLIMB] = Region("Child Spirit Temple Climb", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, logic->HasProjectile(HasProjectileAge::Both) || ((logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->HasProjectile(HasProjectileAge::Adult)) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->IsChild && logic->HasProjectile(HasProjectileAge::Child))), - LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, logic->HasProjectile(HasProjectileAge::Both) || ((logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->HasProjectile(HasProjectileAge::Adult)) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->IsChild && logic->HasProjectile(HasProjectileAge::Child))), + LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, logic->HasProjectile(HasProjectileAge::Both) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->HasProjectile(HasProjectileAge::Adult)) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->IsChild && logic->HasProjectile(HasProjectileAge::Child))), + LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, logic->HasProjectile(HasProjectileAge::Both) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->HasProjectile(HasProjectileAge::Adult)) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->IsChild && logic->HasProjectile(HasProjectileAge::Child))), LOCATION(RC_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM, logic->HasProjectile(HasProjectileAge::Both) || logic->CanUse(RG_DINS_FIRE) || (logic->TakeDamage() && (logic->CanJumpslashExceptHammer() || logic->HasProjectile(HasProjectileAge::Child))) || (logic->IsChild && logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->HasProjectile(HasProjectileAge::Child)) || - ((logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && logic->CanUse(RG_SILVER_GAUNTLETS) && (logic->HasProjectile(HasProjectileAge::Adult) || (logic->TakeDamage() && logic->CanJumpslashExceptHammer())))), + (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && logic->CanUse(RG_SILVER_GAUNTLETS) && (logic->HasProjectile(HasProjectileAge::Adult) || (logic->TakeDamage() && logic->CanJumpslashExceptHammer())))), LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_POT_1, logic->CanBreakPots()), }, { //Exits @@ -75,11 +75,11 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_CENTRAL_CHAMBER] = Region("Spirit Temple Central Chamber", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MAP_CHEST, ((logic->HasExplosives() || logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && + LOCATION(RC_SPIRIT_TEMPLE_MAP_CHEST, ((logic->HasExplosives() || logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)) && (logic->CanUse(RG_DINS_FIRE) || ((logic->CanUse(RG_FIRE_ARROWS) || ctx->GetTrickOption(RT_SPIRIT_MAP_CHEST)) && logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_STICKS) ))) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->HasExplosives() && logic->CanUse(RG_STICKS)) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && (logic->CanUse(RG_FIRE_ARROWS) || (ctx->GetTrickOption(RT_SPIRIT_MAP_CHEST) && logic->CanUse(RG_FAIRY_BOW))) && logic->CanUse(RG_SILVER_GAUNTLETS))), - LOCATION(RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, ((logic->HasExplosives() || logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && + LOCATION(RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, ((logic->HasExplosives() || logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)) && (logic->CanUse(RG_DINS_FIRE) || ((logic->CanUse(RG_FIRE_ARROWS) || ctx->GetTrickOption(RT_SPIRIT_SUN_CHEST)) && logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_STICKS) ))) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->HasExplosives() && logic->CanUse(RG_STICKS)) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && (logic->CanUse(RG_FIRE_ARROWS) || (ctx->GetTrickOption(RT_SPIRIT_SUN_CHEST) && logic->CanUse(RG_FAIRY_BOW))) && logic->CanUse(RG_SILVER_GAUNTLETS))), @@ -87,20 +87,19 @@ void RegionTable_Init_SpiritTemple() { LOCATION(RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->CanUse(RG_ZELDAS_LULLABY) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP))), LOCATION(RC_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM, (logic->HasExplosives() && logic->CanUse(RG_BOOMERANG) && logic->CanUse(RG_HOOKSHOT)) || (logic->CanUse(RG_BOOMERANG) && logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->HasExplosives()) || - (logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_SILVER_GAUNTLETS) && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && - logic->CanUse(RG_BOOMERANG) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))))), - LOCATION(RC_SPIRIT_TEMPLE_GS_LOBBY, ((logic->HasExplosives() || logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && + (logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2))), + LOCATION(RC_SPIRIT_TEMPLE_GS_LOBBY, ((logic->HasExplosives() || logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)) && ctx->GetTrickOption(RT_SPIRIT_LOBBY_GS) && logic->CanUse(RG_BOOMERANG) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP))) || (ctx->GetTrickOption(RT_SPIRIT_LOBBY_GS) && logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->HasExplosives() && logic->CanUse(RG_BOOMERANG)) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && logic->CanUse(RG_SILVER_GAUNTLETS) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP)))), - LOCATION(RC_SPIRIT_TEMPLE_AFTER_SUN_BLOCK_POT_1, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))), - LOCATION(RC_SPIRIT_TEMPLE_AFTER_SUN_BLOCK_POT_2, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))), - LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_1, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))), - LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_2, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))), - LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_3, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))), - LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_4, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))), - LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_5, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))), - LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_6, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))), + LOCATION(RC_SPIRIT_TEMPLE_AFTER_SUN_BLOCK_POT_1, logic->CanBreakPots() && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)), + LOCATION(RC_SPIRIT_TEMPLE_AFTER_SUN_BLOCK_POT_2, logic->CanBreakPots() && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)), + LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_1, logic->CanBreakPots() && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)), + LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_2, logic->CanBreakPots() && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)), + LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_3, logic->CanBreakPots() && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)), + LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_4, logic->CanBreakPots() && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)), + LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_5, logic->CanBreakPots() && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)), + LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_6, logic->CanBreakPots() && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_OUTDOOR_HANDS, []{return logic->CanJumpslashExceptHammer() || logic->HasExplosives();}), diff --git a/soh/soh/Enhancements/randomizer/randomizer_inf.h b/soh/soh/Enhancements/randomizer/randomizer_inf.h index cf2f83d3a..d42e14cb1 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_inf.h +++ b/soh/soh/Enhancements/randomizer/randomizer_inf.h @@ -1091,6 +1091,8 @@ DEFINE_RAND_INF(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_5) DEFINE_RAND_INF(RAND_INF_TH_ITEM_FROM_LEADER_OF_FORTRESS) DEFINE_RAND_INF(RAND_INF_GF_GTG_GATE_PERMANENTLY_OPEN) +DEFINE_RAND_INF(RAND_INF_SPIRIT_SUN_ON_FLOOR_ON) +DEFINE_RAND_INF(RAND_INF_SPIRIT_BIG_MIRROR_STATUE_TURNED) DEFINE_RAND_INF(RAND_INF_ZELDAS_LETTER) DEFINE_RAND_INF(RAND_INF_WEIRD_EGG) diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index 45cc03eb4..662c0d857 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -9,6 +9,7 @@ extern "C" { #include "src/overlays/actors/ovl_En_Wonder_Talk2/z_en_wonder_talk2.h" #include "src/overlays/actors/ovl_Elf_Msg/z_elf_msg.h" #include "src/overlays/actors/ovl_Obj_Switch/z_obj_switch.h" +#include "src/overlays/actors/ovl_Obj_Lightswitch/z_obj_lightswitch.h" #include "src/overlays/actors/ovl_Bg_Bdan_Switch/z_bg_bdan_switch.h" #include "src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h" #include "src/overlays/actors/ovl_En_Owl/z_en_owl.h" @@ -31,6 +32,7 @@ extern "C" { #include "src/overlays/actors/ovl_Bg_Spot03_Taki/z_bg_spot03_taki.h" #include "src/overlays/actors/ovl_Bg_Spot06_Objects/z_bg_spot06_objects.h" #include "src/overlays/actors/ovl_Bg_Hidan_Kousi/z_bg_hidan_kousi.h" +#include "src/overlays/actors/ovl_Bg_Jya_Bombchuiwa/z_bg_jya_bombchuiwa.h" #include "src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.h" #include "src/overlays/actors/ovl_En_Dnt_Demo/z_en_dnt_demo.h" #include "src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.h" @@ -1426,14 +1428,35 @@ void TimeSaverRegisterHooks() { }); } -void RegisterSkipWaterTempleGateDelay() { +void RegisterSkipTimerDelay() { + // Skip Water Temple gate delay COND_ID_HOOK(OnActorUpdate, ACTOR_BG_SPOT06_OBJECTS, CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO), [](void* actor) { - BgSpot06Objects* spot06 = static_cast(actor); + auto spot06 = static_cast(actor); if (spot06->dyna.actor.params == 0) { spot06->timer = 0; } - }) + }); + + // Skip Spirit Sun on Floor activation delay + COND_ID_HOOK(OnActorUpdate, ACTOR_BG_JYA_BOMBCHUIWA, + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO), [](void* actor) { + auto jya = static_cast(actor); + if (!(jya->drawFlags & 4) && jya->timer > 0 && jya->timer < 9) { + jya->timer = 9; + } + }); + + // Skip Spirit Sun on Floor & Sun on Block activation delay + COND_ID_HOOK(OnActorUpdate, ACTOR_OBJ_LIGHTSWITCH, + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO), [](void* actor) { + if (gPlayState->sceneNum == SCENE_SPIRIT_TEMPLE && + (gPlayState->roomCtx.curRoom.num == 4 || gPlayState->roomCtx.curRoom.num == 8)) { + auto sun = static_cast(actor); + sun->toggleDelay = 0; + } + }); } -static RegisterShipInitFunc skipWaterTempleGateDelay(RegisterSkipWaterTempleGateDelay); +static RegisterShipInitFunc skipTimerDelay(RegisterSkipTimerDelay, + { CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), "IS_RANDO" }); diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index 620cb4959..d8263f5de 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -5055,8 +5055,8 @@ void Flags_SetRandomizerInf(RandomizerInf flag) { */ s32 previouslyOff = !Flags_GetRandomizerInf(flag); - gSaveContext.ship.randomizerInf[flag >> 4] |= (1 << (flag & 0xF)); if (previouslyOff) { + gSaveContext.ship.randomizerInf[flag >> 4] |= (1 << (flag & 0xF)); LUSLOG_INFO("RandomizerInf Flag Set - %#x", flag); GameInteractor_ExecuteOnFlagSet(FLAG_RANDOMIZER_INF, flag); } @@ -5076,8 +5076,8 @@ void Flags_UnsetRandomizerInf(RandomizerInf flag) { */ s32 previouslyOn = Flags_GetRandomizerInf(flag); - gSaveContext.ship.randomizerInf[flag >> 4] &= ~(1 << (flag & 0xF)); if (previouslyOn) { + gSaveContext.ship.randomizerInf[flag >> 4] &= ~(1 << (flag & 0xF)); LUSLOG_INFO("RandomizerInf Flag Unset - %#x", flag); GameInteractor_ExecuteOnFlagUnset(FLAG_RANDOMIZER_INF, flag); } From 237dcfec7444075f2fc657bcf6ce65ad7ecf8cb7 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Tue, 1 Jul 2025 17:40:42 -0700 Subject: [PATCH 31/31] Move all maps from Menu.h to the source files that use them. (#5644) --- soh/soh/SohGui/SohMenu.h | 159 ------------------------- soh/soh/SohGui/SohMenuDevTools.cpp | 12 ++ soh/soh/SohGui/SohMenuEnhancements.cpp | 120 ++++++++++++++++++- soh/soh/SohGui/SohMenuRandomizer.cpp | 6 + soh/soh/SohGui/SohMenuSettings.cpp | 33 +++++ soh/soh/SohGui/UIWidgets.hpp | 49 ++++++++ 6 files changed, 214 insertions(+), 165 deletions(-) diff --git a/soh/soh/SohGui/SohMenu.h b/soh/soh/SohGui/SohMenu.h index c3c3f4fd1..ec5f7705c 100644 --- a/soh/soh/SohGui/SohMenu.h +++ b/soh/soh/SohGui/SohMenu.h @@ -27,7 +27,6 @@ void disableBetaQuest(); #endif namespace SohGui { - static std::unordered_map languages = { { LANGUAGE_ENG, "English" }, { LANGUAGE_GER, "German" }, @@ -35,164 +34,6 @@ static std::unordered_map languages = { { LANGUAGE_JPN, "Japanese" }, }; -static const std::unordered_map menuThemeOptions = { - { UIWidgets::Colors::Red, "Red" }, - { UIWidgets::Colors::DarkRed, "Dark Red" }, - { UIWidgets::Colors::Orange, "Orange" }, - { UIWidgets::Colors::Green, "Green" }, - { UIWidgets::Colors::DarkGreen, "Dark Green" }, - { UIWidgets::Colors::LightBlue, "Light Blue" }, - { UIWidgets::Colors::Blue, "Blue" }, - { UIWidgets::Colors::DarkBlue, "Dark Blue" }, - { UIWidgets::Colors::Indigo, "Indigo" }, - { UIWidgets::Colors::Violet, "Violet" }, - { UIWidgets::Colors::Purple, "Purple" }, - { UIWidgets::Colors::Brown, "Brown" }, - { UIWidgets::Colors::Gray, "Gray" }, - { UIWidgets::Colors::DarkGray, "Dark Gray" }, -}; - -static const std::unordered_map textureFilteringMap = { - { Fast::FILTER_THREE_POINT, "Three-Point" }, - { Fast::FILTER_LINEAR, "Linear" }, - { Fast::FILTER_NONE, "None" }, -}; - -static const std::unordered_map logLevels = { - { DEBUG_LOG_TRACE, "Trace" }, { DEBUG_LOG_DEBUG, "Debug" }, { DEBUG_LOG_INFO, "Info" }, - { DEBUG_LOG_WARN, "Warn" }, { DEBUG_LOG_ERROR, "Error" }, { DEBUG_LOG_CRITICAL, "Critical" }, - { DEBUG_LOG_OFF, "Off" }, -}; - -static const std::unordered_map notificationPosition = { - { 0, "Top Left" }, { 1, "Top Right" }, { 2, "Bottom Left" }, { 3, "Bottom Right" }, { 4, "Hidden" }, -}; - -static const std::unordered_map dekuStickCheat = { - { DEKU_STICK_NORMAL, "Normal" }, - { DEKU_STICK_UNBREAKABLE, "Unbreakable" }, - { DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE, "Unbreakable + Always on Fire" }, -}; - -static const std::unordered_map skipForcedDialogOptions = { - { FORCED_DIALOG_SKIP_NONE, "None" }, - { FORCED_DIALOG_SKIP_NAVI, "Navi" }, - { FORCED_DIALOG_SKIP_NPC, "NPCs" }, - { FORCED_DIALOG_SKIP_ALL, "All" }, -}; - -static const std::unordered_map skipGetItemAnimationOptions = { - { SGIA_DISABLED, "Disabled" }, - { SGIA_JUNK, "Junk Items" }, - { SGIA_ALL, "All Items" }, -}; - -static const std::unordered_map chestStyleMatchesContentsOptions = { - { CSMC_DISABLED, "Disabled" }, - { CSMC_BOTH, "Both" }, - { CSMC_TEXTURE, "Texture Only" }, - { CSMC_SIZE, "Size Only" }, -}; - -static const std::unordered_map timeTravelOptions = { - { TIME_TRAVEL_DISABLED, "Disabled" }, - { TIME_TRAVEL_OOT, "Ocarina of Time" }, - { TIME_TRAVEL_ANY, "Any Ocarina" }, -}; - -static const std::unordered_map sleepingWaterfallOptions = { - { WATERFALL_ALWAYS, "Always" }, - { WATERFALL_ONCE, "Once" }, - { WATERFALL_NEVER, "Never" }, -}; - -static const std::unordered_map allPowers = { - { DAMAGE_VANILLA, "Vanilla (1x)" }, { DAMAGE_DOUBLE, "Double (2x)" }, - { DAMAGE_QUADRUPLE, "Quadruple (4x)" }, { DAMAGE_OCTUPLE, "Octuple (8x)" }, - { DAMAGE_FOOLISH, "Foolish (16x)" }, { DAMAGE_RIDICULOUS, "Ridiculous (32x)" }, - { DAMAGE_MERCILESS, "Merciless (64x)" }, { DAMAGE_TORTURE, "Pure Torture (128x)" }, - { DAMAGE_OHKO, "OHKO (256x)" }, -}; - -static const std::unordered_map subPowers = { - { DAMAGE_VANILLA, "Vanilla (1x)" }, { DAMAGE_DOUBLE, "Double (2x)" }, - { DAMAGE_QUADRUPLE, "Quadruple (4x)" }, { DAMAGE_OCTUPLE, "Octuple (8x)" }, - { DAMAGE_FOOLISH, "Foolish (16x)" }, { DAMAGE_RIDICULOUS, "Ridiculous (32x)" }, - { DAMAGE_MERCILESS, "Merciless (64x)" }, { DAMAGE_TORTURE, "Pure Torture (128x)" }, -}; - -static const std::unordered_map subSubPowers = { - { DAMAGE_VANILLA, "Vanilla (1x)" }, { DAMAGE_DOUBLE, "Double (2x)" }, - { DAMAGE_QUADRUPLE, "Quadruple (4x)" }, { DAMAGE_OCTUPLE, "Octuple (8x)" }, - { DAMAGE_FOOLISH, "Foolish (16x)" }, { DAMAGE_RIDICULOUS, "Ridiculous (32x)" }, - { DAMAGE_MERCILESS, "Merciless (64x)" }, -}; - -static const std::unordered_map bonkDamageValues = { - { BONK_DAMAGE_NONE, "No Damage" }, { BONK_DAMAGE_QUARTER_HEART, "0.25 Hearts" }, - { BONK_DAMAGE_HALF_HEART, "0.5 Hearts" }, { BONK_DAMAGE_1_HEART, "1 Heart" }, - { BONK_DAMAGE_2_HEARTS, "2 Hearts" }, { BONK_DAMAGE_4_HEARTS, "4 Hearts" }, - { BONK_DAMAGE_8_HEARTS, "8 Hearts" }, { BONK_DAMAGE_OHKO, "OHKO" }, -}; - -static const std::unordered_map dampeDropRates = { - { DAMPE_NONE, "None" }, - { DAMPE_NORMAL, "Vanilla" }, - { DAMPE_JALAPENO, "Jalapeño" }, - { DAMPE_CHIPOTLE, "Serrano" }, - { DAMPE_SCOTCH_BONNET, "Habanero" }, - { DAMPE_GHOST_PEPPER, "Ghost Pepper" }, - { DAMPE_INFERNO, "Dampe's Inferno" }, -}; - -static const std::unordered_map cursorAnywhereValues = { - { PAUSE_ANY_CURSOR_RANDO_ONLY, "Only in Rando" }, - { PAUSE_ANY_CURSOR_ALWAYS_ON, "Always" }, - { PAUSE_ANY_CURSOR_ALWAYS_OFF, "Never" }, -}; - -static const std::unordered_map swordToggleModes = { - { SWORD_TOGGLE_NONE, "None" }, - { SWORD_TOGGLE_CHILD, "Child Toggle" }, - { SWORD_TOGGLE_BOTH_AGES, "Both Ages" }, -}; - -static const std::unordered_map zFightingOptions = { - { ZFIGHT_FIX_DISABLED, "Disabled" }, - { ZFIGHT_FIX_CONSISTENT_VANISH, "Consistent Vanish" }, - { ZFIGHT_FIX_NO_VANISH, "No Vanish" }, -}; - -static const std::unordered_map mirroredWorldModes = { - { MIRRORED_WORLD_OFF, "Disabled" }, - { MIRRORED_WORLD_ALWAYS, "Always" }, - { MIRRORED_WORLD_RANDOM, "Random" }, - { MIRRORED_WORLD_RANDOM_SEEDED, "Random (Seeded)" }, - { MIRRORED_WORLD_DUNGEONS_ALL, "Dungeons" }, - { MIRRORED_WORLD_DUNGEONS_VANILLA, "Dungeons (Vanilla)" }, - { MIRRORED_WORLD_DUNGEONS_MQ, "Dungeons (MQ)" }, - { MIRRORED_WORLD_DUNGEONS_RANDOM, "Dungeons Random" }, - { MIRRORED_WORLD_DUNGEONS_RANDOM_SEEDED, "Dungeons Random (Seeded)" }, -}; - -static const std::unordered_map enemyRandomizerModes = { - { ENEMY_RANDOMIZER_OFF, "Disabled" }, - { ENEMY_RANDOMIZER_RANDOM, "Random" }, - { ENEMY_RANDOMIZER_RANDOM_SEEDED, "Random (Seeded)" }, -}; - -static const std::unordered_map debugSaveFileModes = { - { 0, "Off" }, - { 1, "Vanilla" }, - { 2, "Maxed" }, -}; - -static const std::unordered_map bootSequenceLabels = { - { BOOTSEQUENCE_DEFAULT, "Default" }, - { BOOTSEQUENCE_AUTHENTIC, "Authentic" }, - { BOOTSEQUENCE_FILESELECT, "File Select" }, -}; - class SohMenu : public Ship::Menu { public: SohMenu(const std::string& consoleVariable, const std::string& name); diff --git a/soh/soh/SohGui/SohMenuDevTools.cpp b/soh/soh/SohGui/SohMenuDevTools.cpp index 3e87af890..2a0fcd62a 100644 --- a/soh/soh/SohGui/SohMenuDevTools.cpp +++ b/soh/soh/SohGui/SohMenuDevTools.cpp @@ -5,6 +5,18 @@ namespace SohGui { extern std::shared_ptr mSohMenu; using namespace UIWidgets; +static const std::unordered_map logLevels = { + { DEBUG_LOG_TRACE, "Trace" }, { DEBUG_LOG_DEBUG, "Debug" }, { DEBUG_LOG_INFO, "Info" }, + { DEBUG_LOG_WARN, "Warn" }, { DEBUG_LOG_ERROR, "Error" }, { DEBUG_LOG_CRITICAL, "Critical" }, + { DEBUG_LOG_OFF, "Off" }, +}; + +static const std::unordered_map debugSaveFileModes = { + { 0, "Off" }, + { 1, "Vanilla" }, + { 2, "Maxed" }, +}; + void SohMenu::AddMenuDevTools() { // Add Dev Tools Menu AddMenuEntry("Dev Tools", CVAR_SETTING("Menu.DevToolsSidebarSection")); diff --git a/soh/soh/SohGui/SohMenuEnhancements.cpp b/soh/soh/SohGui/SohMenuEnhancements.cpp index 3fb161a2b..eda3d85bb 100644 --- a/soh/soh/SohGui/SohMenuEnhancements.cpp +++ b/soh/soh/SohGui/SohMenuEnhancements.cpp @@ -1,4 +1,4 @@ -#include "SohMenu.h" +#include "SohMenu.h" #include #include #include @@ -12,11 +12,6 @@ static std::string comboboxTooltip = ""; bool isBetaQuestEnabled = false; -static std::unordered_map bunnyHoodEffectMap = { - { BUNNY_HOOD_VANILLA, "Vanilla" }, - { BUNNY_HOOD_FAST, "Faster Run" }, - { BUNNY_HOOD_FAST_AND_JUMP, "Faster + Longer Jump" }, -}; extern "C" { void enableBetaQuest() { @@ -32,6 +27,119 @@ namespace SohGui { extern std::shared_ptr mSohMenu; using namespace UIWidgets; +static std::unordered_map bunnyHoodEffectMap = { + { BUNNY_HOOD_VANILLA, "Vanilla" }, + { BUNNY_HOOD_FAST, "Faster Run" }, + { BUNNY_HOOD_FAST_AND_JUMP, "Faster + Longer Jump" }, +}; + +static const std::unordered_map dekuStickCheat = { + { DEKU_STICK_NORMAL, "Normal" }, + { DEKU_STICK_UNBREAKABLE, "Unbreakable" }, + { DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE, "Unbreakable + Always on Fire" }, +}; + +static const std::unordered_map skipForcedDialogOptions = { + { FORCED_DIALOG_SKIP_NONE, "None" }, + { FORCED_DIALOG_SKIP_NAVI, "Navi" }, + { FORCED_DIALOG_SKIP_NPC, "NPCs" }, + { FORCED_DIALOG_SKIP_ALL, "All" }, +}; + +static const std::unordered_map chestStyleMatchesContentsOptions = { + { CSMC_DISABLED, "Disabled" }, + { CSMC_BOTH, "Both" }, + { CSMC_TEXTURE, "Texture Only" }, + { CSMC_SIZE, "Size Only" }, +}; + +static const std::unordered_map timeTravelOptions = { + { TIME_TRAVEL_DISABLED, "Disabled" }, + { TIME_TRAVEL_OOT, "Ocarina of Time" }, + { TIME_TRAVEL_ANY, "Any Ocarina" }, +}; + +static const std::unordered_map sleepingWaterfallOptions = { + { WATERFALL_ALWAYS, "Always" }, + { WATERFALL_ONCE, "Once" }, + { WATERFALL_NEVER, "Never" }, +}; + +static const std::unordered_map allPowers = { + { DAMAGE_VANILLA, "Vanilla (1x)" }, { DAMAGE_DOUBLE, "Double (2x)" }, + { DAMAGE_QUADRUPLE, "Quadruple (4x)" }, { DAMAGE_OCTUPLE, "Octuple (8x)" }, + { DAMAGE_FOOLISH, "Foolish (16x)" }, { DAMAGE_RIDICULOUS, "Ridiculous (32x)" }, + { DAMAGE_MERCILESS, "Merciless (64x)" }, { DAMAGE_TORTURE, "Pure Torture (128x)" }, + { DAMAGE_OHKO, "OHKO (256x)" }, +}; + +static const std::unordered_map subPowers = { + { DAMAGE_VANILLA, "Vanilla (1x)" }, { DAMAGE_DOUBLE, "Double (2x)" }, + { DAMAGE_QUADRUPLE, "Quadruple (4x)" }, { DAMAGE_OCTUPLE, "Octuple (8x)" }, + { DAMAGE_FOOLISH, "Foolish (16x)" }, { DAMAGE_RIDICULOUS, "Ridiculous (32x)" }, + { DAMAGE_MERCILESS, "Merciless (64x)" }, { DAMAGE_TORTURE, "Pure Torture (128x)" }, +}; + +static const std::unordered_map subSubPowers = { + { DAMAGE_VANILLA, "Vanilla (1x)" }, { DAMAGE_DOUBLE, "Double (2x)" }, + { DAMAGE_QUADRUPLE, "Quadruple (4x)" }, { DAMAGE_OCTUPLE, "Octuple (8x)" }, + { DAMAGE_FOOLISH, "Foolish (16x)" }, { DAMAGE_RIDICULOUS, "Ridiculous (32x)" }, + { DAMAGE_MERCILESS, "Merciless (64x)" }, +}; + +static const std::unordered_map bonkDamageValues = { + { BONK_DAMAGE_NONE, "No Damage" }, { BONK_DAMAGE_QUARTER_HEART, "0.25 Hearts" }, + { BONK_DAMAGE_HALF_HEART, "0.5 Hearts" }, { BONK_DAMAGE_1_HEART, "1 Heart" }, + { BONK_DAMAGE_2_HEARTS, "2 Hearts" }, { BONK_DAMAGE_4_HEARTS, "4 Hearts" }, + { BONK_DAMAGE_8_HEARTS, "8 Hearts" }, { BONK_DAMAGE_OHKO, "OHKO" }, +}; + +static const std::unordered_map dampeDropRates = { + { DAMPE_NONE, "None" }, + { DAMPE_NORMAL, "Vanilla" }, + { DAMPE_JALAPENO, "Jalapeño" }, + { DAMPE_CHIPOTLE, "Serrano" }, + { DAMPE_SCOTCH_BONNET, "Habanero" }, + { DAMPE_GHOST_PEPPER, "Ghost Pepper" }, + { DAMPE_INFERNO, "Dampe's Inferno" }, +}; + +static const std::unordered_map cursorAnywhereValues = { + { PAUSE_ANY_CURSOR_RANDO_ONLY, "Only in Rando" }, + { PAUSE_ANY_CURSOR_ALWAYS_ON, "Always" }, + { PAUSE_ANY_CURSOR_ALWAYS_OFF, "Never" }, +}; + +static const std::unordered_map zFightingOptions = { + { ZFIGHT_FIX_DISABLED, "Disabled" }, + { ZFIGHT_FIX_CONSISTENT_VANISH, "Consistent Vanish" }, + { ZFIGHT_FIX_NO_VANISH, "No Vanish" }, +}; + +static const std::unordered_map swordToggleModes = { + { SWORD_TOGGLE_NONE, "None" }, + { SWORD_TOGGLE_CHILD, "Child Toggle" }, + { SWORD_TOGGLE_BOTH_AGES, "Both Ages" }, +}; + +static const std::unordered_map mirroredWorldModes = { + { MIRRORED_WORLD_OFF, "Disabled" }, + { MIRRORED_WORLD_ALWAYS, "Always" }, + { MIRRORED_WORLD_RANDOM, "Random" }, + { MIRRORED_WORLD_RANDOM_SEEDED, "Random (Seeded)" }, + { MIRRORED_WORLD_DUNGEONS_ALL, "Dungeons" }, + { MIRRORED_WORLD_DUNGEONS_VANILLA, "Dungeons (Vanilla)" }, + { MIRRORED_WORLD_DUNGEONS_MQ, "Dungeons (MQ)" }, + { MIRRORED_WORLD_DUNGEONS_RANDOM, "Dungeons Random" }, + { MIRRORED_WORLD_DUNGEONS_RANDOM_SEEDED, "Dungeons Random (Seeded)" }, +}; + +static const std::unordered_map enemyRandomizerModes = { + { ENEMY_RANDOMIZER_OFF, "Disabled" }, + { ENEMY_RANDOMIZER_RANDOM, "Random" }, + { ENEMY_RANDOMIZER_RANDOM_SEEDED, "Random (Seeded)" }, +}; + void SohMenu::AddMenuEnhancements() { // Add Enhancements Menu AddMenuEntry("Enhancements", CVAR_SETTING("Menu.EnhancementsSidebarSection")); diff --git a/soh/soh/SohGui/SohMenuRandomizer.cpp b/soh/soh/SohGui/SohMenuRandomizer.cpp index b95a8049c..47e651408 100644 --- a/soh/soh/SohGui/SohMenuRandomizer.cpp +++ b/soh/soh/SohGui/SohMenuRandomizer.cpp @@ -6,6 +6,12 @@ namespace SohGui { extern std::shared_ptr mSohMenu; using namespace UIWidgets; +static const std::unordered_map skipGetItemAnimationOptions = { + { SGIA_DISABLED, "Disabled" }, + { SGIA_JUNK, "Junk Items" }, + { SGIA_ALL, "All Items" }, +}; + void SohMenu::AddMenuRandomizer() { // Add Randomizer Menu AddMenuEntry("Randomizer", CVAR_SETTING("Menu.RandomizerSidebarSection")); diff --git a/soh/soh/SohGui/SohMenuSettings.cpp b/soh/soh/SohGui/SohMenuSettings.cpp index 0221ae3f7..bb7c82574 100644 --- a/soh/soh/SohGui/SohMenuSettings.cpp +++ b/soh/soh/SohGui/SohMenuSettings.cpp @@ -23,6 +23,39 @@ static std::unordered_map imguiScaleOptions = { { 3, "X-Large" }, }; +static const std::unordered_map menuThemeOptions = { + { UIWidgets::Colors::Red, "Red" }, + { UIWidgets::Colors::DarkRed, "Dark Red" }, + { UIWidgets::Colors::Orange, "Orange" }, + { UIWidgets::Colors::Green, "Green" }, + { UIWidgets::Colors::DarkGreen, "Dark Green" }, + { UIWidgets::Colors::LightBlue, "Light Blue" }, + { UIWidgets::Colors::Blue, "Blue" }, + { UIWidgets::Colors::DarkBlue, "Dark Blue" }, + { UIWidgets::Colors::Indigo, "Indigo" }, + { UIWidgets::Colors::Violet, "Violet" }, + { UIWidgets::Colors::Purple, "Purple" }, + { UIWidgets::Colors::Brown, "Brown" }, + { UIWidgets::Colors::Gray, "Gray" }, + { UIWidgets::Colors::DarkGray, "Dark Gray" }, +}; + +static const std::unordered_map textureFilteringMap = { + { Fast::FILTER_THREE_POINT, "Three-Point" }, + { Fast::FILTER_LINEAR, "Linear" }, + { Fast::FILTER_NONE, "None" }, +}; + +static const std::unordered_map notificationPosition = { + { 0, "Top Left" }, { 1, "Top Right" }, { 2, "Bottom Left" }, { 3, "Bottom Right" }, { 4, "Hidden" }, +}; + +static const std::unordered_map bootSequenceLabels = { + { BOOTSEQUENCE_DEFAULT, "Default" }, + { BOOTSEQUENCE_AUTHENTIC, "Authentic" }, + { BOOTSEQUENCE_FILESELECT, "File Select" }, +}; + const char* GetGameVersionString(uint32_t index) { uint32_t gameVersion = ResourceMgr_GetGameVersion(index); switch (gameVersion) { diff --git a/soh/soh/SohGui/UIWidgets.hpp b/soh/soh/SohGui/UIWidgets.hpp index caf2e912b..0ed88bade 100644 --- a/soh/soh/SohGui/UIWidgets.hpp +++ b/soh/soh/SohGui/UIWidgets.hpp @@ -115,10 +115,12 @@ struct WidgetOptions { tooltip = tooltip_; return *this; } + WidgetOptions& Disabled(bool disabled_) { disabled = disabled_; return *this; } + WidgetOptions& DisabledTooltip(const char* disabledTooltip_) { disabledTooltip = disabledTooltip_; return *this; @@ -143,14 +145,17 @@ struct ButtonOptions : WidgetOptions { size = size_; return *this; } + ButtonOptions& Padding(ImVec2 padding_) { padding = padding_; return *this; } + ButtonOptions& Tooltip(const char* tooltip_) { WidgetOptions::tooltip = tooltip_; return *this; } + ButtonOptions& Color(Colors color_) { color = color_; return *this; @@ -168,22 +173,27 @@ struct WindowButtonOptions : WidgetOptions { size = size_; return *this; } + WindowButtonOptions& Padding(ImVec2 padding_) { padding = padding_; return *this; } + WindowButtonOptions& Tooltip(const char* tooltip_) { WidgetOptions::tooltip = tooltip_; return *this; } + WindowButtonOptions& Color(Colors color_) { color = color_; return *this; } + WindowButtonOptions& ShowButton(bool showButton_) { showButton = showButton_; return *this; } + WindowButtonOptions& EmbedWindow(bool embedWindow_) { embedWindow = embedWindow_; return *this; @@ -201,26 +211,32 @@ struct CheckboxOptions : WidgetOptions { defaultValue = defaultValue_; return *this; } + CheckboxOptions& ComponentAlignment(ComponentAlignments alignment_) { alignment = alignment_; return *this; } + CheckboxOptions& LabelPosition(LabelPositions labelPosition_) { labelPosition = labelPosition_; return *this; } + CheckboxOptions& Tooltip(const char* tooltip_) { WidgetOptions::tooltip = tooltip_; return *this; } + CheckboxOptions& Color(Colors color_) { color = color_; return *this; } + CheckboxOptions& DisabledTooltip(const char* disabledTooltip_) { WidgetOptions::disabledTooltip = disabledTooltip_; return *this; } + CheckboxOptions& Padding(ImVec2 padding_) { padding = padding_; return *this; @@ -239,22 +255,27 @@ struct ComboboxOptions : WidgetOptions { comboMap = comboMap_; return *this; } + ComboboxOptions& DefaultIndex(uint32_t defaultIndex_) { defaultIndex = defaultIndex_; return *this; } + ComboboxOptions& ComponentAlignment(ComponentAlignments alignment_) { alignment = alignment_; return *this; } + ComboboxOptions& LabelPosition(LabelPositions labelPosition_) { labelPosition = labelPosition_; return *this; } + ComboboxOptions& Tooltip(const char* tooltip_) { WidgetOptions::tooltip = tooltip_; return *this; } + ComboboxOptions& Color(Colors color_) { color = color_; return *this; @@ -279,46 +300,57 @@ struct IntSliderOptions : WidgetOptions { showButtons = showButtons_; return *this; } + IntSliderOptions& Format(const char* format_) { format = format_; return *this; } + IntSliderOptions& Step(int32_t step_) { step = step_; return *this; } + IntSliderOptions& Min(int32_t min_) { min = min_; return *this; } + IntSliderOptions& Max(int32_t max_) { max = max_; return *this; } + IntSliderOptions& DefaultValue(int32_t defaultValue_) { defaultValue = defaultValue_; return *this; } + IntSliderOptions& ComponentAlignment(ComponentAlignments alignment_) { alignment = alignment_; return *this; } + IntSliderOptions& LabelPosition(LabelPositions labelPosition_) { labelPosition = labelPosition_; return *this; } + IntSliderOptions& Tooltip(const char* tooltip_) { WidgetOptions::tooltip = tooltip_; return *this; } + IntSliderOptions& Color(Colors color_) { color = color_; return *this; } + IntSliderOptions& Size(ImVec2 size_) { size = size_; return *this; } + IntSliderOptions& Clamp(bool clamp_) { clamp = clamp_; return *this; @@ -344,34 +376,42 @@ struct FloatSliderOptions : WidgetOptions { showButtons = showButtons_; return *this; } + FloatSliderOptions& Format(const char* format_) { format = format_; return *this; } + FloatSliderOptions& Step(float step_) { step = step_; return *this; } + FloatSliderOptions& Min(float min_) { min = min_; return *this; } + FloatSliderOptions& Max(float max_) { max = max_; return *this; } + FloatSliderOptions& DefaultValue(float defaultValue_) { defaultValue = defaultValue_; return *this; } + FloatSliderOptions& ComponentAlignment(ComponentAlignments alignment_) { alignment = alignment_; return *this; } + FloatSliderOptions& LabelPosition(LabelPositions labelPosition_) { labelPosition = labelPosition_; return *this; } + FloatSliderOptions& IsPercentage(bool isPercentage_ = true) { isPercentage = isPercentage_; format = "%.0f%%"; @@ -379,18 +419,22 @@ struct FloatSliderOptions : WidgetOptions { max = 1.0f; return *this; } + FloatSliderOptions& Tooltip(const char* tooltip_) { WidgetOptions::tooltip = tooltip_; return *this; } + FloatSliderOptions& Color(Colors color_) { color = color_; return *this; } + FloatSliderOptions& Size(ImVec2 size_) { size = size_; return *this; } + FloatSliderOptions& Clamp(bool clamp_) { clamp = clamp_; return *this; @@ -406,14 +450,17 @@ struct RadioButtonsOptions : WidgetOptions { buttonMap = buttonMap_; return *this; } + RadioButtonsOptions& Tooltip(const char* tooltip_) { WidgetOptions::tooltip = tooltip_; return *this; } + RadioButtonsOptions& Color(Colors color_) { color = color_; return *this; } + RadioButtonsOptions& DefaultIndex(int32_t defaultIndex_) { defaultIndex = defaultIndex_; return *this; @@ -437,10 +484,12 @@ struct InputOptions : WidgetOptions { WidgetOptions::tooltip = tooltip_; return *this; } + InputOptions& Color(Colors color_) { color = color_; return *this; } + InputOptions& Size(ImVec2 size_) { size = size_; return *this;