diff --git a/soh/soh/Enhancements/randomizer/entrance.cpp b/soh/soh/Enhancements/randomizer/entrance.cpp index 73cbca89d..96dd6e050 100644 --- a/soh/soh/Enhancements/randomizer/entrance.cpp +++ b/soh/soh/Enhancements/randomizer/entrance.cpp @@ -1736,6 +1736,11 @@ void EntranceShuffler::ApplyEntranceOverrides() { entrance->SetAsShuffled(); } } + +const Entrance* EntranceShuffler::GetEntranceByIndex(int16_t index) { + auto iter = entranceMap.find(index); + return iter != entranceMap.end() ? iter->second : nullptr; +} } // namespace Rando extern "C" EntranceOverride* Randomizer_GetEntranceOverrides() { diff --git a/soh/soh/Enhancements/randomizer/entrance.h b/soh/soh/Enhancements/randomizer/entrance.h index bfb4f6109..244ecee44 100644 --- a/soh/soh/Enhancements/randomizer/entrance.h +++ b/soh/soh/Enhancements/randomizer/entrance.h @@ -133,6 +133,8 @@ class EntranceShuffler { void ParseJson(nlohmann::json spoilerFileJson); void ApplyEntranceOverrides(); + static const Entrance* GetEntranceByIndex(int16_t index); + private: std::vector AssumeEntrancePool(std::vector& entrancePool); bool ShuffleOneWayPriorityEntrances(std::map& oneWayPriorities, diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index 9902ae32d..a1a8e2926 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -270,6 +270,8 @@ std::vector buttons = { BTN_A, BTN_B, BTN_CUP, BTN_CDOWN, BTN_CLEFT, BTN_Z, BTN_R, BTN_START, BTN_DUP, BTN_DDOWN, BTN_DLEFT, BTN_DRIGHT }; static ImGuiTextFilter checkSearch; static bool recalculateAvailable = false; +static RandomizerRegion availableChecksStartingRegion = RR_ROOT; +static int16_t previousEntrance = 0; std::array filterAreasHidden = { 0 }; std::array filterChecksHidden = { 0 }; @@ -610,9 +612,7 @@ void CheckTrackerLoadGame(int32_t fileNum) { RegionTable_Init(); - if (Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_ENTRANCES).Get()) { - Rando::Context::GetInstance()->GetEntranceShuffler()->ApplyEntranceOverrides(); - } + Rando::Context::GetInstance()->GetEntranceShuffler()->ApplyEntranceOverrides(); recalculateAvailable = true; } @@ -954,6 +954,8 @@ void SetAreaSpoiled(RandomizerCheckArea rcArea) { SaveManager::Instance->SaveSection(gSaveContext.fileNum, sectionId, true); } +void InternalRecalculateAvailableChecks(RandomizerRegion startingRegion); + void CheckTrackerWindow::DrawElement() { Color_Background = CVarGetColor(CVAR_TRACKER_CHECK("BgColor.Value"), Color_Bg_Default); Color_Area_Incomplete_Main = CVarGetColor(CVAR_TRACKER_CHECK("AreaIncomplete.MainColor.Value"), Color_Main_Default); @@ -1027,9 +1029,15 @@ void CheckTrackerWindow::DrawElement() { return; } + if (gPlayState->nextEntranceIndex != previousEntrance) { + previousEntrance = gPlayState->nextEntranceIndex; + recalculateAvailable = true; + } + if (recalculateAvailable) { recalculateAvailable = false; - RecalculateAvailableChecks(); + InternalRecalculateAvailableChecks(availableChecksStartingRegion); + availableChecksStartingRegion = RR_ROOT; } // Quick Options @@ -2052,7 +2060,7 @@ void ImGuiDrawTwoColorPickerSection(const char* text, const char* cvarMainName, UIWidgets::PopStyleCombobox(); } -void RecalculateAvailableChecks(RandomizerRegion startingRegion /* = RR_ROOT */) { +void InternalRecalculateAvailableChecks(RandomizerRegion startingRegion) { if (!enableAvailableChecks || !GameInteractor::IsSaveLoaded()) { return; } @@ -2063,6 +2071,20 @@ void RecalculateAvailableChecks(RandomizerRegion startingRegion /* = RR_ROOT */) const auto& ctx = Rando::Context::GetInstance(); logic = ctx->GetLogic(); + int16_t entranceIndex = gPlayState->nextEntranceIndex; + if (startingRegion == RR_ROOT && entranceIndex >= 0 && entranceIndex < ENTR_MAX) { + // Try to find a mapped entrance + // e.g. ENTR_DEKU_TREE_0_1 (index 1) is not mapped, but ENTR_DEKU_TREE_ENTRANCE (index 0) is mapped + const int8_t scene = gEntranceTable[entranceIndex].scene; + for (; entranceIndex >= 0 && gEntranceTable[entranceIndex].scene == scene; entranceIndex--) { + const auto entrance = Rando::EntranceShuffler::GetEntranceByIndex(entranceIndex); + if (entrance != nullptr) { + startingRegion = entrance->GetOriginalConnectedRegionKey(); + break; + } + } + } + std::vector targetLocations; targetLocations.reserve(RC_MAX); for (auto& location : Rando::StaticData::GetLocationTable()) { @@ -2097,6 +2119,11 @@ void RecalculateAvailableChecks(RandomizerRegion startingRegion /* = RR_ROOT */) GetPerformanceTimer(PT_RECALCULATE_AVAILABLE_CHECKS).count()); } +void RecalculateAvailableChecks(RandomizerRegion startingRegion /* = RR_ROOT */) { + recalculateAvailable = true; + availableChecksStartingRegion = startingRegion; +} + void CheckTracker_LoadFromPreset(nlohmann::json info) { presetLoaded = true; presetPos = { info["pos"]["x"], info["pos"]["y"] }; diff --git a/soh/soh/Enhancements/randomizer/randomizer_entrance.c b/soh/soh/Enhancements/randomizer/randomizer_entrance.c index 82082a9d0..edb3a0e7b 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_entrance.c +++ b/soh/soh/Enhancements/randomizer/randomizer_entrance.c @@ -820,7 +820,6 @@ void Entrance_SetEntranceDiscovered(u16 entranceIndex, u8 isReversedEntrance) { if (idx < SAVEFILE_ENTRANCES_DISCOVERED_IDX_COUNT) { u32 entranceBit = 1 << (entranceIndex - (idx * bitsPerIndex)); gSaveContext.ship.stats.entrancesDiscovered[idx] |= entranceBit; - CheckTracker_RecalculateAvailableChecks(); // Set reverse entrance when not decoupled if (!Randomizer_GetSettingValue(RSK_DECOUPLED_ENTRANCES) && !isReversedEntrance) { diff --git a/soh/src/code/z_play.c b/soh/src/code/z_play.c index aa51915c1..55c1864fb 100644 --- a/soh/src/code/z_play.c +++ b/soh/src/code/z_play.c @@ -690,6 +690,9 @@ void Play_Init(GameState* thisx) { GET_PLAYER(play)->actor.world.pos.y + Player_GetHeight(GET_PLAYER(play)) + 5.0f, GET_PLAYER(play)->actor.world.pos.z, 0, 0, 0, 1, true); } + + // nextEntranceIndex was not initialized, so the previous value was carried over during soft resets. + gPlayState->nextEntranceIndex = gSaveContext.entranceIndex; } void Play_Update(PlayState* play) {