Calculate accessible checks and show them in the check tracker.

This commit is contained in:
Anthony Stewart 2025-02-20 18:23:27 -06:00
commit 8e24bc3069
6 changed files with 133 additions and 4 deletions

View file

@ -337,6 +337,7 @@ void RandomizerOnItemReceiveHandler(GetItemEntry receivedItemEntry) {
loc->SetCheckStatus(RCSHOW_COLLECTED);
CheckTracker::SpoilAreaFromCheck(randomizerQueuedCheck);
CheckTracker::RecalculateAllAreaTotals();
CheckTracker::RecalculateAccessibleChecks();
SaveManager::Instance->SaveSection(gSaveContext.fileNum, SECTION_ID_TRACKER_DATA, true);
randomizerQueuedCheck = RC_UNKNOWN_CHECK;
randomizerQueuedItemEntry = GET_ITEM_NONE;

View file

@ -228,5 +228,14 @@ void ItemLocation::ResetVariables() {
areas = {};
status = RCSHOW_UNCHECKED;
isSkipped = false;
isAccessible = false;
}
bool ItemLocation::IsAccessible() const {
return isAccessible;
}
void ItemLocation::SetAccessible(bool isAccessible_) {
isAccessible = isAccessible_;
}
}

View file

@ -56,6 +56,8 @@ class ItemLocation {
bool IsFoolishCandidate() const;
void SetBarrenCandidate();
void ResetVariables();
bool IsAccessible() const;
void SetAccessible(bool isAccessible_);
private:
RandomizerCheck rc;
@ -76,5 +78,6 @@ class ItemLocation {
bool barrenCandidate = false;
RandomizerCheckStatus status = RCSHOW_UNCHECKED;
bool isSkipped = false;
bool isAccessible = false;
};
} // namespace Rando

View file

@ -196,9 +196,15 @@ class Region {
bool pastAdult = logic->IsAdult;
bool pastChild = logic->IsChild;
if (logic->mSaveContext != nullptr) {
logic->IsChild = logic->mSaveContext->linkAge == LinkAge::LINK_AGE_CHILD;
logic->IsAdult = logic->mSaveContext->linkAge == LinkAge::LINK_AGE_ADULT;
}
else {
//set age access as this areas ages
logic->IsChild = Child();
logic->IsAdult = Adult();
}
//heck condition as well as having at least child or adult access
bool hereVal = condition() && (logic->IsAdult || logic->IsChild);

View file

@ -8,6 +8,7 @@
#include "soh/ResourceManagerHelpers.h"
#include "soh/SohGui/UIWidgets.hpp"
#include "dungeon.h"
#include "entrance.h"
#include "location_access.h"
#include <string>
@ -821,6 +822,16 @@ void LoadFile() {
SaveManager::Instance->LoadData("areasSpoiled", areasSpoiled, (uint32_t)0);
UpdateAllOrdering();
UpdateAllAreas();
if (gSaveContext.fileNum >= 0 && gSaveContext.fileNum <= 2) {
if (areaTable[RR_ROOT].regionName.empty()) {
RegionTable_Init();
}
if (Rando::Context::GetInstance() == nullptr) {
Rando::Context::CreateInstance();
}
RecalculateAccessibleChecks();
}
}
void Teardown() {
@ -1623,7 +1634,13 @@ void DrawLocation(RandomizerCheck rc) {
if (conditionStr != "true") {
UIWidgets::InsertHelpHoverText(conditionStr);
}
return;
if (!itemLoc->HasObtained() && itemLoc->IsAccessible()) {
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(extraColor.r / 255.0f, extraColor.g / 255.0f, extraColor.b / 255.0f, extraColor.a / 255.0f));
ImGui::SameLine();
ImGui::Text(" (Accessible)");
ImGui::PopStyleColor();
}
break;
}
}
}
@ -1713,6 +1730,98 @@ void ImGuiDrawTwoColorPickerSection(const char* text, const char* cvarMainName,
}
}
void CalculateAccessibleEntrances(const Region& region,
bool isParentAccessible,
std::unordered_map<const Rando::Entrance*, bool>& entranceAccessible,
std::vector<RandomizerRegion>& visitedRegions,
std::stop_token stopToken) {
for (const auto& entranceInRegion : region.exits) {
if (stopToken.stop_requested()) {
return;
}
auto pair = entranceAccessible.find(&entranceInRegion);
bool isEntranceAccessible = true;
if (pair == entranceAccessible.end()) {
isEntranceAccessible = isParentAccessible && entranceInRegion.GetConditionsMet();
entranceAccessible[&entranceInRegion] = isEntranceAccessible;
} else if (!pair->second) {
isEntranceAccessible = isParentAccessible && entranceInRegion.GetConditionsMet();
pair->second = isEntranceAccessible;
}
else {
return;
}
if (std::find(visitedRegions.begin(), visitedRegions.end(), entranceInRegion.GetConnectedRegionKey()) == visitedRegions.end()) {
visitedRegions.emplace_back(entranceInRegion.GetConnectedRegionKey());
CalculateAccessibleEntrances(*entranceInRegion.GetConnectedRegion(),
isEntranceAccessible,
entranceAccessible,
visitedRegions,
stopToken);
visitedRegions.pop_back();
}
}
}
void _RecalculateAccessibleChecks(std::stop_token stopToken) {
logic->IsChild = logic->mSaveContext->linkAge == LinkAge::LINK_AGE_CHILD;
logic->IsAdult = logic->mSaveContext->linkAge == LinkAge::LINK_AGE_ADULT;
logic->AtDay = true;
logic->AtNight = true;
for (auto& region : areaTable) {
for (auto& event : region.events) {
if (!event.GetEvent() && event.ConditionsMet()) {
event.EventOccurred();
}
}
}
if (stopToken.stop_requested()) {
return;
}
std::vector<RandomizerRegion> visitedRegions;
visitedRegions.reserve(70);
std::unordered_map<const Rando::Entrance*, bool> entranceAccessible;
entranceAccessible.reserve(1450);
CalculateAccessibleEntrances(areaTable[RR_ROOT], true, entranceAccessible, visitedRegions, stopToken);
if (stopToken.stop_requested()) {
return;
}
for (auto& region : areaTable) {
for (auto& locationInRegion : region.locations) {
auto rc = locationInRegion.GetLocation();
auto itemLoc = OTRGlobals::Instance->gRandoContext->GetItemLocation(rc);
if (!itemLoc->HasObtained()) {
bool regionAccessible = false;
for (auto& entranceInRegion : region.entrances) {
if (entranceAccessible[entranceInRegion]) {
regionAccessible = true;
break;
}
}
bool locationAccessible = locationInRegion.GetConditionsMet();
itemLoc->SetAccessible(regionAccessible && locationAccessible);
}
}
}
}
std::jthread recalculateAccessibleChecksThread;
void RecalculateAccessibleChecks() {
if (recalculateAccessibleChecksThread.joinable()) {
recalculateAccessibleChecksThread.request_stop();
recalculateAccessibleChecksThread.join();
}
recalculateAccessibleChecksThread = std::jthread(_RecalculateAccessibleChecks);
}
void CheckTrackerWindow::Draw() {
if (!IsVisible()) {
return;

View file

@ -60,4 +60,5 @@ void UpdateAllOrdering();
void UpdateAllAreas();
void RecalculateAllAreaTotals();
void SpoilAreaFromCheck(RandomizerCheck rc);
void RecalculateAccessibleChecks();
} // namespace CheckTracker