From 2c2d9e9f39ea780b5a04159f9c62fd5540471b86 Mon Sep 17 00:00:00 2001 From: Star Rauchenberger Date: Wed, 28 Feb 2024 11:40:26 -0500 Subject: Fix pilgrimage detection for vanilla doors Also add new pilgrimage options. --- src/ap_state.cpp | 18 +++++++++++ src/ap_state.h | 29 ++++++++++++++---- src/game_data.cpp | 19 ++++++++++++ src/game_data.h | 9 ++++++ src/tracker_state.cpp | 83 ++++++++++++++++++++++++++++++++++++++++++--------- 5 files changed, 139 insertions(+), 19 deletions(-) diff --git a/src/ap_state.cpp b/src/ap_state.cpp index 1937597..bdd9cb2 100644 --- a/src/ap_state.cpp +++ b/src/ap_state.cpp @@ -64,6 +64,8 @@ struct APState { VictoryCondition victory_condition = kTHE_END; bool early_color_hallways = false; bool pilgrimage_enabled = false; + bool pilgrimage_allows_roof_access = false; + bool pilgrimage_allows_paintings = false; SunwarpAccess sunwarp_access = kSUNWARP_ACCESS_NORMAL; std::map painting_mapping; @@ -135,6 +137,8 @@ struct APState { victory_condition = kTHE_END; early_color_hallways = false; pilgrimage_enabled = false; + pilgrimage_allows_roof_access = false; + pilgrimage_allows_paintings = false; sunwarp_access = kSUNWARP_ACCESS_NORMAL; connected = false; @@ -240,6 +244,12 @@ struct APState { slot_data["early_color_hallways"].get() == 1; pilgrimage_enabled = slot_data.contains("enable_pilgrimage") && slot_data["enable_pilgrimage"].get() == 1; + pilgrimage_allows_roof_access = + slot_data.contains("pilgrimage_allows_roof_access") && + slot_data["pilgrimage_allows_roof_access"].get() == 1; + pilgrimage_allows_paintings = + slot_data.contains("pilgrimage_allows_paintings") && + slot_data["pilgrimage_allows_paintings"].get() == 1; sunwarp_access = slot_data["sunwarp_access"].get(); if (painting_shuffle && slot_data.contains("painting_entrance_to_exit")) { @@ -454,6 +464,14 @@ bool AP_HasEarlyColorHallways() { return GetState().early_color_hallways; } bool AP_IsPilgrimageEnabled() { return GetState().pilgrimage_enabled; } +bool AP_DoesPilgrimageAllowRoofAccess() { + return GetState().pilgrimage_allows_roof_access; +} + +bool AP_DoesPilgrimageAllowPaintings() { + return GetState().pilgrimage_allows_paintings; +} + SunwarpAccess AP_GetSunwarpAccess() { return GetState().sunwarp_access; } bool AP_HasReachedGoal() { return GetState().HasReachedGoal(); } diff --git a/src/ap_state.h b/src/ap_state.h index e3c2d7f..e1f34c7 100644 --- a/src/ap_state.h +++ b/src/ap_state.h @@ -10,11 +10,26 @@ class TrackerFrame; enum DoorShuffleMode { kNO_DOORS = 0, kSIMPLE_DOORS = 1, kCOMPLEX_DOORS = 2 }; -enum VictoryCondition { kTHE_END = 0, kTHE_MASTER = 1, kLEVEL_2 = 2, kPILGRIMAGE = 3 }; - -enum LocationChecks { kNORMAL_LOCATIONS = 0, kREDUCED_LOCATIONS = 1, kPANELSANITY = 2 }; - -enum SunwarpAccess { kSUNWARP_ACCESS_NORMAL = 0, kSUNWARP_ACCESS_DISABLED = 1, kSUNWARP_ACCESS_UNLOCK = 2, kSUNWARP_ACCESS_PROGRESSIVE = 3 }; +enum VictoryCondition { + kTHE_END = 0, + kTHE_MASTER = 1, + kLEVEL_2 = 2, + kPILGRIMAGE = 3 +}; + +enum LocationChecks { + kNORMAL_LOCATIONS = 0, + kREDUCED_LOCATIONS = 1, + kPANELSANITY = 2 +}; + +enum SunwarpAccess { + kSUNWARP_ACCESS_NORMAL = 0, + kSUNWARP_ACCESS_DISABLED = 1, + kSUNWARP_ACCESS_UNLOCK = 2, + kSUNWARP_ACCESS_INDIVIDUAL = 3, + kSUNWARP_ACCESS_PROGRESSIVE = 4 +}; void AP_SetTrackerFrame(TrackerFrame* tracker_frame); @@ -48,6 +63,10 @@ bool AP_HasEarlyColorHallways(); bool AP_IsPilgrimageEnabled(); +bool AP_DoesPilgrimageAllowRoofAccess(); + +bool AP_DoesPilgrimageAllowPaintings(); + SunwarpAccess AP_GetSunwarpAccess(); bool AP_HasReachedGoal(); diff --git a/src/game_data.cpp b/src/game_data.cpp index 28ca598..75c5b7e 100644 --- a/src/game_data.cpp +++ b/src/game_data.cpp @@ -58,6 +58,8 @@ struct GameData { std::map ap_id_by_color_; + std::vector sunwarp_doors_; + bool loaded_area_data_ = false; std::set malconfigured_areas_; @@ -125,6 +127,11 @@ struct GameData { exit_obj.type = EntranceType::kWarp; } + if (rooms_[from_room_id].name == "Crossroads" && + rooms_[room_id].name == "Roof") { + exit_obj.type == EntranceType::kCrossroadsRoofAccess; + } + rooms_[from_room_id].exits.push_back(exit_obj); }; @@ -401,6 +408,14 @@ struct GameData { doors_[door_id].exclude_reduce = !door_it.second["include_reduce"].as(); } + + if (doors_[door_id].name.ends_with(" Sunwarp")) { + sunwarp_doors_.push_back(door_id); + doors_[door_id].type = DoorType::kSunwarp; + } else if (doors_[door_id].item_name == + "Pilgrim Room - Sun Painting") { + doors_[door_id].type = DoorType::kSunPainting; + } } } @@ -667,3 +682,7 @@ const std::vector &GD_GetAchievementPanels() { int GD_GetItemIdForColor(LingoColor color) { return GetState().ap_id_by_color_.at(color); } + +const std::vector &GD_GetSunwarpDoors() { + return GetState().sunwarp_doors_; +} diff --git a/src/game_data.h b/src/game_data.h index 2c18588..16d006c 100644 --- a/src/game_data.h +++ b/src/game_data.h @@ -29,6 +29,13 @@ enum class EntranceType { kSunwarp, kWarp, kPilgrimage, + kCrossroadsRoofAccess, +}; + +enum class DoorType { + kNormal, + kSunwarp, + kSunPainting, }; struct Panel { @@ -69,6 +76,7 @@ struct Door { int ap_item_id = -1; int group_ap_item_id = -1; int ap_location_id = -1; + DoorType type = DoorType::kNormal; }; struct Exit { @@ -120,5 +128,6 @@ const Panel& GD_GetPanel(int panel_id); int GD_GetRoomForPainting(const std::string& painting_id); const std::vector& GD_GetAchievementPanels(); int GD_GetItemIdForColor(LingoColor color); +const std::vector& GD_GetSunwarpDoors(); #endif /* end of include guard: GAME_DATA_H_9C42AC51 */ diff --git a/src/tracker_state.cpp b/src/tracker_state.cpp index cc941ef..5a99254 100644 --- a/src/tracker_state.cpp +++ b/src/tracker_state.cpp @@ -24,9 +24,12 @@ TrackerState& GetState() { return *instance; } +class StateCalculator; + struct StateCalculatorOptions { std::string start = "Menu"; bool pilgrimage = false; + StateCalculator* parent = nullptr; }; class StateCalculator { @@ -136,15 +139,43 @@ class StateCalculator { const std::set& GetReachableRooms() const { return reachable_rooms_; } + const std::map& GetDoorDecisions() const { return door_decisions_; } + const std::set& GetSolveablePanels() const { return solveable_panels_; } private: - Decision IsDoorReachable(int door_id) { + Decision IsNonGroupedDoorReachable(const Door& door_obj) { + bool has_item = AP_HasItem(door_obj.ap_item_id); + + if (!has_item) { + for (const ProgressiveRequirement& prog_req : door_obj.progressives) { + if (AP_HasItem(prog_req.ap_item_id, prog_req.quantity)) { + has_item = true; + break; + } + } + } + + return has_item ? kYes : kNo; + } + + Decision IsDoorReachable_Helper(int door_id) { const Door& door_obj = GD_GetDoor(door_id); - if (!AP_IsPilgrimageEnabled() && - door_obj.item_name == "Pilgrim Room - Sun Painting") { + if (!AP_IsPilgrimageEnabled() && door_obj.type == DoorType::kSunPainting) { return AP_HasItem(door_obj.ap_item_id) ? kYes : kNo; + } else if (door_obj.type == DoorType::kSunwarp) { + switch (AP_GetSunwarpAccess()) { + case kSUNWARP_ACCESS_NORMAL: + return kYes; + case kSUNWARP_ACCESS_DISABLED: + return kNo; + case kSUNWARP_ACCESS_UNLOCK: + return AP_HasItem(door_obj.group_ap_item_id) ? kYes : kNo; + case kSUNWARP_ACCESS_INDIVIDUAL: + case kSUNWARP_ACCESS_PROGRESSIVE: + return IsNonGroupedDoorReachable(door_obj); + } } else if (AP_GetDoorShuffleMode() == kNO_DOORS || door_obj.skip_item) { if (!reachable_rooms_.count(door_obj.room)) { return kMaybe; @@ -161,19 +192,25 @@ class StateCalculator { !door_obj.group_name.empty()) { return AP_HasItem(door_obj.group_ap_item_id) ? kYes : kNo; } else { - bool has_item = AP_HasItem(door_obj.ap_item_id); + return IsNonGroupedDoorReachable(door_obj); + } + } - if (!has_item) { - for (const ProgressiveRequirement& prog_req : door_obj.progressives) { - if (AP_HasItem(prog_req.ap_item_id, prog_req.quantity)) { - has_item = true; - break; - } - } - } + Decision IsDoorReachable(int door_id) { + if (options_.parent) { + return options_.parent->IsDoorReachable(door_id); + } - return has_item ? kYes : kNo; + if (door_decisions_.count(door_id)) { + return door_decisions_.at(door_id); } + + Decision result = IsDoorReachable_Helper(door_id); + if (result != kMaybe) { + door_decisions_[door_id] = result; + } + + return result; } Decision IsPanelReachable(int panel_id) { @@ -258,6 +295,15 @@ class StateCalculator { return kNo; } + if (AP_GetSunwarpAccess() != kSUNWARP_ACCESS_NORMAL) { + for (int door_id : GD_GetSunwarpDoors()) { + Decision sub_decision = IsDoorReachable(door_id); + if (sub_decision != kYes) { + return sub_decision; + } + } + } + static const std::vector> pilgrimage_pairs = { {"Crossroads", "Hot Crusts Area"}, @@ -268,7 +314,7 @@ class StateCalculator { for (const auto& [from_room, to_room] : pilgrimage_pairs) { StateCalculator pilgrimage_calculator( - {.start = from_room, .pilgrimage = true}); + {.start = from_room, .pilgrimage = true, .parent = this}); pilgrimage_calculator.Calculate(); if (!pilgrimage_calculator.GetReachableRooms().count( @@ -285,6 +331,14 @@ class StateCalculator { room_exit.type == EntranceType::kSunwarp) { return kNo; } + if (room_exit.type == EntranceType::kCrossroadsRoofAccess && + !AP_DoesPilgrimageAllowRoofAccess()) { + return kNo; + } + if (room_exit.type == EntranceType::kPainting && + !AP_DoesPilgrimageAllowPaintings()) { + return kNo; + } } if (room_exit.type == EntranceType::kSunwarp) { @@ -305,6 +359,7 @@ class StateCalculator { StateCalculatorOptions options_; std::set reachable_rooms_; + std::map door_decisions_; std::set solveable_panels_; }; -- cgit 1.4.1