diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/ap_state.cpp | 6 | ||||
| -rw-r--r-- | src/ap_state.h | 2 | ||||
| -rw-r--r-- | src/area_popup.cpp | 11 | ||||
| -rw-r--r-- | src/game_data.cpp | 4 | ||||
| -rw-r--r-- | src/global.cpp | 16 | ||||
| -rw-r--r-- | src/global.h | 2 | ||||
| -rw-r--r-- | src/tracker_panel.cpp | 12 | ||||
| -rw-r--r-- | src/tracker_state.cpp | 164 | ||||
| -rw-r--r-- | src/tracker_state.h | 6 |
9 files changed, 186 insertions, 37 deletions
| diff --git a/src/ap_state.cpp b/src/ap_state.cpp index 2236d6a..cbe622a 100644 --- a/src/ap_state.cpp +++ b/src/ap_state.cpp | |||
| @@ -82,6 +82,7 @@ struct APState { | |||
| 82 | bool pilgrimage_allows_paintings = false; | 82 | bool pilgrimage_allows_paintings = false; |
| 83 | SunwarpAccess sunwarp_access = kSUNWARP_ACCESS_NORMAL; | 83 | SunwarpAccess sunwarp_access = kSUNWARP_ACCESS_NORMAL; |
| 84 | bool sunwarp_shuffle = false; | 84 | bool sunwarp_shuffle = false; |
| 85 | bool postgame_shuffle = true; | ||
| 85 | 86 | ||
| 86 | std::map<std::string, std::string> painting_mapping; | 87 | std::map<std::string, std::string> painting_mapping; |
| 87 | std::set<std::string> painting_codomain; | 88 | std::set<std::string> painting_codomain; |
| @@ -146,6 +147,7 @@ struct APState { | |||
| 146 | sunwarp_access = kSUNWARP_ACCESS_NORMAL; | 147 | sunwarp_access = kSUNWARP_ACCESS_NORMAL; |
| 147 | sunwarp_shuffle = false; | 148 | sunwarp_shuffle = false; |
| 148 | sunwarp_mapping.clear(); | 149 | sunwarp_mapping.clear(); |
| 150 | postgame_shuffle = true; | ||
| 149 | } | 151 | } |
| 150 | 152 | ||
| 151 | apclient->set_room_info_handler( | 153 | apclient->set_room_info_handler( |
| @@ -470,6 +472,8 @@ struct APState { | |||
| 470 | : kSUNWARP_ACCESS_NORMAL; | 472 | : kSUNWARP_ACCESS_NORMAL; |
| 471 | sunwarp_shuffle = slot_data.contains("shuffle_sunwarps") && | 473 | sunwarp_shuffle = slot_data.contains("shuffle_sunwarps") && |
| 472 | slot_data["shuffle_sunwarps"].get<int>() == 1; | 474 | slot_data["shuffle_sunwarps"].get<int>() == 1; |
| 475 | postgame_shuffle = slot_data.contains("shuffle_postgame") && | ||
| 476 | slot_data["shuffle_postgame"].get<int>() == 1; | ||
| 473 | 477 | ||
| 474 | if (painting_shuffle && slot_data.contains("painting_entrance_to_exit")) { | 478 | if (painting_shuffle && slot_data.contains("painting_entrance_to_exit")) { |
| 475 | painting_mapping.clear(); | 479 | painting_mapping.clear(); |
| @@ -798,6 +802,8 @@ std::map<int, SunwarpMapping> AP_GetSunwarpMapping() { | |||
| 798 | return GetState().sunwarp_mapping; | 802 | return GetState().sunwarp_mapping; |
| 799 | } | 803 | } |
| 800 | 804 | ||
| 805 | bool AP_IsPostgameShuffle() { return GetState().postgame_shuffle; } | ||
| 806 | |||
| 801 | bool AP_HasReachedGoal() { return GetState().HasReachedGoal(); } | 807 | bool AP_HasReachedGoal() { return GetState().HasReachedGoal(); } |
| 802 | 808 | ||
| 803 | std::optional<std::tuple<int, int>> AP_GetPlayerPosition() { | 809 | std::optional<std::tuple<int, int>> AP_GetPlayerPosition() { |
| diff --git a/src/ap_state.h b/src/ap_state.h index 2da0b8e..e2ff22b 100644 --- a/src/ap_state.h +++ b/src/ap_state.h | |||
| @@ -100,6 +100,8 @@ bool AP_IsSunwarpShuffle(); | |||
| 100 | 100 | ||
| 101 | std::map<int, SunwarpMapping> AP_GetSunwarpMapping(); | 101 | std::map<int, SunwarpMapping> AP_GetSunwarpMapping(); |
| 102 | 102 | ||
| 103 | bool AP_IsPostgameShuffle(); | ||
| 104 | |||
| 103 | bool AP_HasReachedGoal(); | 105 | bool AP_HasReachedGoal(); |
| 104 | 106 | ||
| 105 | std::optional<std::tuple<int, int>> AP_GetPlayerPosition(); | 107 | std::optional<std::tuple<int, int>> AP_GetPlayerPosition(); |
| diff --git a/src/area_popup.cpp b/src/area_popup.cpp index 9c7406b..d7f45b6 100644 --- a/src/area_popup.cpp +++ b/src/area_popup.cpp | |||
| @@ -52,6 +52,9 @@ void AreaPopup::UpdateIndicators() { | |||
| 52 | for (int section_id = 0; section_id < map_area.locations.size(); | 52 | for (int section_id = 0; section_id < map_area.locations.size(); |
| 53 | section_id++) { | 53 | section_id++) { |
| 54 | const Location& location = map_area.locations.at(section_id); | 54 | const Location& location = map_area.locations.at(section_id); |
| 55 | if (IsLocationPostgame(location.ap_location_id)) { | ||
| 56 | continue; | ||
| 57 | } | ||
| 55 | 58 | ||
| 56 | if (tracker_panel->IsPanelsMode()) { | 59 | if (tracker_panel->IsPanelsMode()) { |
| 57 | if (!location.single_panel) { | 60 | if (!location.single_panel) { |
| @@ -78,6 +81,10 @@ void AreaPopup::UpdateIndicators() { | |||
| 78 | 81 | ||
| 79 | if (AP_IsPaintingShuffle() && !tracker_panel->IsPanelsMode()) { | 82 | if (AP_IsPaintingShuffle() && !tracker_panel->IsPanelsMode()) { |
| 80 | for (int painting_id : map_area.paintings) { | 83 | for (int painting_id : map_area.paintings) { |
| 84 | if (IsPaintingPostgame(painting_id)) { | ||
| 85 | continue; | ||
| 86 | } | ||
| 87 | |||
| 81 | const PaintingExit& painting = GD_GetPaintingExit(painting_id); | 88 | const PaintingExit& painting = GD_GetPaintingExit(painting_id); |
| 82 | wxSize item_extent = mem_dc.GetTextExtent(painting.display_name); | 89 | wxSize item_extent = mem_dc.GetTextExtent(painting.display_name); |
| 83 | int item_height = | 90 | int item_height = |
| @@ -149,6 +156,10 @@ void AreaPopup::UpdateIndicators() { | |||
| 149 | 156 | ||
| 150 | if (AP_IsPaintingShuffle() && !tracker_panel->IsPanelsMode()) { | 157 | if (AP_IsPaintingShuffle() && !tracker_panel->IsPanelsMode()) { |
| 151 | for (int painting_id : map_area.paintings) { | 158 | for (int painting_id : map_area.paintings) { |
| 159 | if (IsPaintingPostgame(painting_id)) { | ||
| 160 | continue; | ||
| 161 | } | ||
| 162 | |||
| 152 | const PaintingExit& painting = GD_GetPaintingExit(painting_id); | 163 | const PaintingExit& painting = GD_GetPaintingExit(painting_id); |
| 153 | 164 | ||
| 154 | bool reachable = IsPaintingReachable(painting_id); | 165 | bool reachable = IsPaintingReachable(painting_id); |
| diff --git a/src/game_data.cpp b/src/game_data.cpp index e92e6a2..5fbd244 100644 --- a/src/game_data.cpp +++ b/src/game_data.cpp | |||
| @@ -609,7 +609,7 @@ struct GameData { | |||
| 609 | // Only locations for the panels are kept here. | 609 | // Only locations for the panels are kept here. |
| 610 | std::map<std::string, std::tuple<int, int>> locations_by_name; | 610 | std::map<std::string, std::tuple<int, int>> locations_by_name; |
| 611 | 611 | ||
| 612 | for (const Panel &panel : panels_) { | 612 | for (Panel &panel : panels_) { |
| 613 | int room_id = panel.room; | 613 | int room_id = panel.room; |
| 614 | std::string room_name = rooms_[room_id].name; | 614 | std::string room_name = rooms_[room_id].name; |
| 615 | 615 | ||
| @@ -625,6 +625,8 @@ struct GameData { | |||
| 625 | area_name = location_name.substr(0, divider_pos); | 625 | area_name = location_name.substr(0, divider_pos); |
| 626 | section_name = location_name.substr(divider_pos + 3); | 626 | section_name = location_name.substr(divider_pos + 3); |
| 627 | } | 627 | } |
| 628 | } else { | ||
| 629 | panel.location_name = location_name; | ||
| 628 | } | 630 | } |
| 629 | 631 | ||
| 630 | if (fold_areas.count(area_name)) { | 632 | if (fold_areas.count(area_name)) { |
| diff --git a/src/global.cpp b/src/global.cpp index 1eb3f8d..63f4a19 100644 --- a/src/global.cpp +++ b/src/global.cpp | |||
| @@ -26,17 +26,19 @@ std::string GetAbsolutePath(std::string_view path) { | |||
| 26 | return (GetExecutableDirectory() / path).string(); | 26 | return (GetExecutableDirectory() / path).string(); |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | bool IsLocationWinCondition(const Location& location) { | 29 | std::string GetWinCondition() { |
| 30 | switch (AP_GetVictoryCondition()) { | 30 | switch (AP_GetVictoryCondition()) { |
| 31 | case kTHE_END: | 31 | case kTHE_END: |
| 32 | return location.ap_location_name == | 32 | return "Orange Tower Seventh Floor - THE END"; |
| 33 | "Orange Tower Seventh Floor - THE END"; | ||
| 34 | case kTHE_MASTER: | 33 | case kTHE_MASTER: |
| 35 | return location.ap_location_name == | 34 | return "Orange Tower Seventh Floor - THE MASTER"; |
| 36 | "Orange Tower Seventh Floor - THE MASTER"; | ||
| 37 | case kLEVEL_2: | 35 | case kLEVEL_2: |
| 38 | return location.ap_location_name == "Second Room - LEVEL 2"; | 36 | return "Second Room - LEVEL 2"; |
| 39 | case kPILGRIMAGE: | 37 | case kPILGRIMAGE: |
| 40 | return location.ap_location_name == "Pilgrim Antechamber - PILGRIM"; | 38 | return "Pilgrim Antechamber - PILGRIM"; |
| 41 | } | 39 | } |
| 42 | } | 40 | } |
| 41 | |||
| 42 | bool IsLocationWinCondition(const Location& location) { | ||
| 43 | return location.ap_location_name == GetWinCondition(); | ||
| 44 | } | ||
| diff --git a/src/global.h b/src/global.h index 31ebde3..bdfa7ae 100644 --- a/src/global.h +++ b/src/global.h | |||
| @@ -10,6 +10,8 @@ const std::filesystem::path& GetExecutableDirectory(); | |||
| 10 | 10 | ||
| 11 | std::string GetAbsolutePath(std::string_view path); | 11 | std::string GetAbsolutePath(std::string_view path); |
| 12 | 12 | ||
| 13 | std::string GetWinCondition(); | ||
| 14 | |||
| 13 | bool IsLocationWinCondition(const Location& location); | 15 | bool IsLocationWinCondition(const Location& location); |
| 14 | 16 | ||
| 15 | #endif /* end of include guard: GLOBAL_H_44945DBA */ | 17 | #endif /* end of include guard: GLOBAL_H_44945DBA */ |
| diff --git a/src/tracker_panel.cpp b/src/tracker_panel.cpp index 81b58cc..b4e6697 100644 --- a/src/tracker_panel.cpp +++ b/src/tracker_panel.cpp | |||
| @@ -203,7 +203,9 @@ void TrackerPanel::Redraw() { | |||
| 203 | 203 | ||
| 204 | for (AreaIndicator &area : areas_) { | 204 | for (AreaIndicator &area : areas_) { |
| 205 | const MapArea &map_area = GD_GetMapArea(area.area_id); | 205 | const MapArea &map_area = GD_GetMapArea(area.area_id); |
| 206 | if (panels_mode_) { | 206 | if (IsAreaPostgame(area.area_id)) { |
| 207 | area.active = false; | ||
| 208 | } else if (panels_mode_) { | ||
| 207 | area.active = map_area.has_single_panel; | 209 | area.active = map_area.has_single_panel; |
| 208 | } else if (!AP_IsLocationVisible(map_area.classification) && | 210 | } else if (!AP_IsLocationVisible(map_area.classification) && |
| 209 | !(map_area.hunt && GetTrackerConfig().show_hunt_panels) && | 211 | !(map_area.hunt && GetTrackerConfig().show_hunt_panels) && |
| @@ -221,7 +223,9 @@ void TrackerPanel::Redraw() { | |||
| 221 | bool has_unreachable_unchecked = false; | 223 | bool has_unreachable_unchecked = false; |
| 222 | for (const Location §ion : map_area.locations) { | 224 | for (const Location §ion : map_area.locations) { |
| 223 | bool has_unchecked = false; | 225 | bool has_unchecked = false; |
| 224 | if (IsLocationWinCondition(section)) { | 226 | if (IsLocationPostgame(section.ap_location_id)) { |
| 227 | // Nope. | ||
| 228 | } else if (IsLocationWinCondition(section)) { | ||
| 225 | has_unchecked = !AP_HasReachedGoal(); | 229 | has_unchecked = !AP_HasReachedGoal(); |
| 226 | } else if (panels_mode_) { | 230 | } else if (panels_mode_) { |
| 227 | if (section.single_panel) { | 231 | if (section.single_panel) { |
| @@ -249,6 +253,10 @@ void TrackerPanel::Redraw() { | |||
| 249 | 253 | ||
| 250 | if (AP_IsPaintingShuffle() && !panels_mode_) { | 254 | if (AP_IsPaintingShuffle() && !panels_mode_) { |
| 251 | for (int painting_id : map_area.paintings) { | 255 | for (int painting_id : map_area.paintings) { |
| 256 | if (IsPaintingPostgame(painting_id)) { | ||
| 257 | continue; | ||
| 258 | } | ||
| 259 | |||
| 252 | const PaintingExit &painting = GD_GetPaintingExit(painting_id); | 260 | const PaintingExit &painting = GD_GetPaintingExit(painting_id); |
| 253 | bool reachable = IsPaintingReachable(painting_id); | 261 | bool reachable = IsPaintingReachable(painting_id); |
| 254 | if (!reachable || !AP_IsPaintingChecked(painting.internal_id)) { | 262 | if (!reachable || !AP_IsPaintingChecked(painting.internal_id)) { |
| diff --git a/src/tracker_state.cpp b/src/tracker_state.cpp index f7244a7..bcee1d6 100644 --- a/src/tracker_state.cpp +++ b/src/tracker_state.cpp | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | #include "ap_state.h" | 13 | #include "ap_state.h" |
| 14 | #include "game_data.h" | 14 | #include "game_data.h" |
| 15 | #include "global.h" | ||
| 15 | #include "logger.h" | 16 | #include "logger.h" |
| 16 | 17 | ||
| 17 | namespace { | 18 | namespace { |
| @@ -25,6 +26,7 @@ struct Requirements { | |||
| 25 | std::set<int> rooms; // maybe | 26 | std::set<int> rooms; // maybe |
| 26 | bool mastery = false; // maybe | 27 | bool mastery = false; // maybe |
| 27 | bool panel_hunt = false; // maybe | 28 | bool panel_hunt = false; // maybe |
| 29 | bool postgame = false; | ||
| 28 | 30 | ||
| 29 | void Merge(const Requirements& rhs) { | 31 | void Merge(const Requirements& rhs) { |
| 30 | if (rhs.disabled) { | 32 | if (rhs.disabled) { |
| @@ -45,6 +47,7 @@ struct Requirements { | |||
| 45 | } | 47 | } |
| 46 | mastery = mastery || rhs.mastery; | 48 | mastery = mastery || rhs.mastery; |
| 47 | panel_hunt = panel_hunt || rhs.panel_hunt; | 49 | panel_hunt = panel_hunt || rhs.panel_hunt; |
| 50 | postgame = postgame || rhs.postgame; | ||
| 48 | } | 51 | } |
| 49 | }; | 52 | }; |
| 50 | 53 | ||
| @@ -146,6 +149,10 @@ class RequirementCalculator { | |||
| 146 | } | 149 | } |
| 147 | } | 150 | } |
| 148 | 151 | ||
| 152 | if (panel_obj.location_name == GetWinCondition()) { | ||
| 153 | requirements.postgame = true; | ||
| 154 | } | ||
| 155 | |||
| 149 | panels_[panel_id] = requirements; | 156 | panels_[panel_id] = requirements; |
| 150 | } | 157 | } |
| 151 | 158 | ||
| @@ -165,6 +172,11 @@ struct TrackerState { | |||
| 165 | RequirementCalculator requirements; | 172 | RequirementCalculator requirements; |
| 166 | std::map<int, std::map<std::string, bool>> door_reports; | 173 | std::map<int, std::map<std::string, bool>> door_reports; |
| 167 | bool pilgrimage_doable = false; | 174 | bool pilgrimage_doable = false; |
| 175 | |||
| 176 | // If these are empty, it actually means everything is non-postgame. | ||
| 177 | std::set<int> non_postgame_areas; | ||
| 178 | std::set<int> non_postgame_locations; | ||
| 179 | std::set<int> non_postgame_paintings; | ||
| 168 | }; | 180 | }; |
| 169 | 181 | ||
| 170 | enum Decision { kYes, kNo, kMaybe }; | 182 | enum Decision { kYes, kNo, kMaybe }; |
| @@ -179,6 +191,11 @@ class StateCalculator; | |||
| 179 | struct StateCalculatorOptions { | 191 | struct StateCalculatorOptions { |
| 180 | int start; | 192 | int start; |
| 181 | bool pilgrimage = false; | 193 | bool pilgrimage = false; |
| 194 | |||
| 195 | // Treats all items as collected and all paintings as checked, but postgame | ||
| 196 | // areas cannot be reached. | ||
| 197 | bool postgame_detection = false; | ||
| 198 | |||
| 182 | StateCalculator* parent = nullptr; | 199 | StateCalculator* parent = nullptr; |
| 183 | }; | 200 | }; |
| 184 | 201 | ||
| @@ -234,7 +251,8 @@ class StateCalculator { | |||
| 234 | 251 | ||
| 235 | PaintingExit cur_painting = GD_GetPaintingExit(painting_id); | 252 | PaintingExit cur_painting = GD_GetPaintingExit(painting_id); |
| 236 | if (painting_mapping_.count(cur_painting.internal_id) && | 253 | if (painting_mapping_.count(cur_painting.internal_id) && |
| 237 | checked_paintings_.count(cur_painting.internal_id)) { | 254 | (checked_paintings_.count(cur_painting.internal_id) || |
| 255 | options_.postgame_detection)) { | ||
| 238 | Exit painting_exit; | 256 | Exit painting_exit; |
| 239 | PaintingExit target_painting = | 257 | PaintingExit target_painting = |
| 240 | GD_GetPaintingExit(GD_GetPaintingByName( | 258 | GD_GetPaintingExit(GD_GetPaintingByName( |
| @@ -419,43 +437,49 @@ class StateCalculator { | |||
| 419 | return kNo; | 437 | return kNo; |
| 420 | } | 438 | } |
| 421 | 439 | ||
| 440 | if (reqs.postgame && options_.postgame_detection) { | ||
| 441 | return kNo; | ||
| 442 | } | ||
| 443 | |||
| 422 | Decision final_decision = kYes; | 444 | Decision final_decision = kYes; |
| 423 | 445 | ||
| 424 | for (int door_id : reqs.doors) { | 446 | if (!options_.postgame_detection) { |
| 425 | const Door& door_obj = GD_GetDoor(door_id); | 447 | for (int door_id : reqs.doors) { |
| 426 | Decision decision = IsNonGroupedDoorReachable(door_obj); | 448 | const Door& door_obj = GD_GetDoor(door_id); |
| 449 | Decision decision = IsNonGroupedDoorReachable(door_obj); | ||
| 427 | 450 | ||
| 428 | if (report) { | 451 | if (report) { |
| 429 | (*report)[door_obj.item_name] = (decision == kYes); | 452 | (*report)[door_obj.item_name] = (decision == kYes); |
| 430 | } | 453 | } |
| 431 | 454 | ||
| 432 | if (decision != kYes) { | 455 | if (decision != kYes) { |
| 433 | final_decision = decision; | 456 | final_decision = decision; |
| 457 | } | ||
| 434 | } | 458 | } |
| 435 | } | ||
| 436 | 459 | ||
| 437 | for (int panel_door_id : reqs.panel_doors) { | 460 | for (int panel_door_id : reqs.panel_doors) { |
| 438 | const PanelDoor& panel_door_obj = GD_GetPanelDoor(panel_door_id); | 461 | const PanelDoor& panel_door_obj = GD_GetPanelDoor(panel_door_id); |
| 439 | Decision decision = IsNonGroupedDoorReachable(panel_door_obj); | 462 | Decision decision = IsNonGroupedDoorReachable(panel_door_obj); |
| 440 | 463 | ||
| 441 | if (report) { | 464 | if (report) { |
| 442 | (*report)[AP_GetItemName(panel_door_obj.ap_item_id)] = | 465 | (*report)[AP_GetItemName(panel_door_obj.ap_item_id)] = |
| 443 | (decision == kYes); | 466 | (decision == kYes); |
| 444 | } | 467 | } |
| 445 | 468 | ||
| 446 | if (decision != kYes) { | 469 | if (decision != kYes) { |
| 447 | final_decision = decision; | 470 | final_decision = decision; |
| 471 | } | ||
| 448 | } | 472 | } |
| 449 | } | ||
| 450 | 473 | ||
| 451 | for (int item_id : reqs.items) { | 474 | for (int item_id : reqs.items) { |
| 452 | bool has_item = AP_HasItem(item_id); | 475 | bool has_item = AP_HasItem(item_id); |
| 453 | if (report) { | 476 | if (report) { |
| 454 | (*report)[AP_GetItemName(item_id)] = has_item; | 477 | (*report)[AP_GetItemName(item_id)] = has_item; |
| 455 | } | 478 | } |
| 456 | 479 | ||
| 457 | if (!has_item) { | 480 | if (!has_item) { |
| 458 | final_decision = kNo; | 481 | final_decision = kNo; |
| 482 | } | ||
| 459 | } | 483 | } |
| 460 | } | 484 | } |
| 461 | 485 | ||
| @@ -658,6 +682,62 @@ class StateCalculator { | |||
| 658 | void ResetReachabilityRequirements() { | 682 | void ResetReachabilityRequirements() { |
| 659 | std::lock_guard reachability_guard(GetState().reachability_mutex); | 683 | std::lock_guard reachability_guard(GetState().reachability_mutex); |
| 660 | GetState().requirements.Reset(); | 684 | GetState().requirements.Reset(); |
| 685 | |||
| 686 | if (AP_IsPostgameShuffle()) { | ||
| 687 | GetState().non_postgame_areas.clear(); | ||
| 688 | GetState().non_postgame_locations.clear(); | ||
| 689 | GetState().non_postgame_paintings.clear(); | ||
| 690 | } else { | ||
| 691 | StateCalculator postgame_calculator( | ||
| 692 | {.start = GD_GetRoomByName("Menu"), .postgame_detection = true}); | ||
| 693 | postgame_calculator.Calculate(); | ||
| 694 | |||
| 695 | std::set<int>& non_postgame_areas = GetState().non_postgame_areas; | ||
| 696 | non_postgame_areas.clear(); | ||
| 697 | |||
| 698 | std::set<int>& non_postgame_locations = GetState().non_postgame_locations; | ||
| 699 | non_postgame_locations.clear(); | ||
| 700 | |||
| 701 | const std::set<int>& reachable_rooms = | ||
| 702 | postgame_calculator.GetReachableRooms(); | ||
| 703 | const std::set<int>& solveable_panels = | ||
| 704 | postgame_calculator.GetSolveablePanels(); | ||
| 705 | |||
| 706 | for (const MapArea& map_area : GD_GetMapAreas()) { | ||
| 707 | bool area_reachable = false; | ||
| 708 | |||
| 709 | for (const Location& location_section : map_area.locations) { | ||
| 710 | bool reachable = reachable_rooms.count(location_section.room); | ||
| 711 | if (reachable) { | ||
| 712 | for (int panel_id : location_section.panels) { | ||
| 713 | reachable &= (solveable_panels.count(panel_id) == 1); | ||
| 714 | } | ||
| 715 | } | ||
| 716 | |||
| 717 | if (!reachable && IsLocationWinCondition(location_section)) { | ||
| 718 | reachable = true; | ||
| 719 | } | ||
| 720 | |||
| 721 | if (reachable) { | ||
| 722 | non_postgame_locations.insert(location_section.ap_location_id); | ||
| 723 | area_reachable = true; | ||
| 724 | } | ||
| 725 | } | ||
| 726 | |||
| 727 | for (int painting_id : map_area.paintings) { | ||
| 728 | if (postgame_calculator.GetReachablePaintings().count(painting_id)) { | ||
| 729 | area_reachable = true; | ||
| 730 | } | ||
| 731 | } | ||
| 732 | |||
| 733 | if (area_reachable) { | ||
| 734 | non_postgame_areas.insert(map_area.id); | ||
| 735 | } | ||
| 736 | } | ||
| 737 | |||
| 738 | GetState().non_postgame_paintings = | ||
| 739 | postgame_calculator.GetReachablePaintings(); | ||
| 740 | } | ||
| 661 | } | 741 | } |
| 662 | 742 | ||
| 663 | void RecalculateReachability() { | 743 | void RecalculateReachability() { |
| @@ -736,3 +816,33 @@ bool IsPilgrimageDoable() { | |||
| 736 | 816 | ||
| 737 | return GetState().pilgrimage_doable; | 817 | return GetState().pilgrimage_doable; |
| 738 | } | 818 | } |
| 819 | |||
| 820 | bool IsAreaPostgame(int area_id) { | ||
| 821 | std::lock_guard reachability_guard(GetState().reachability_mutex); | ||
| 822 | |||
| 823 | if (GetState().non_postgame_areas.empty()) { | ||
| 824 | return false; | ||
| 825 | } else { | ||
| 826 | return !GetState().non_postgame_areas.count(area_id); | ||
| 827 | } | ||
| 828 | } | ||
| 829 | |||
| 830 | bool IsLocationPostgame(int location_id) { | ||
| 831 | std::lock_guard reachability_guard(GetState().reachability_mutex); | ||
| 832 | |||
| 833 | if (GetState().non_postgame_locations.empty()) { | ||
| 834 | return false; | ||
| 835 | } else { | ||
| 836 | return !GetState().non_postgame_locations.count(location_id); | ||
| 837 | } | ||
| 838 | } | ||
| 839 | |||
| 840 | bool IsPaintingPostgame(int painting_id) { | ||
| 841 | std::lock_guard reachability_guard(GetState().reachability_mutex); | ||
| 842 | |||
| 843 | if (GetState().non_postgame_paintings.empty()) { | ||
| 844 | return false; | ||
| 845 | } else { | ||
| 846 | return !GetState().non_postgame_paintings.count(painting_id); | ||
| 847 | } | ||
| 848 | } | ||
| diff --git a/src/tracker_state.h b/src/tracker_state.h index a8f155d..8f1002f 100644 --- a/src/tracker_state.h +++ b/src/tracker_state.h | |||
| @@ -18,4 +18,10 @@ const std::map<std::string, bool>& GetDoorRequirements(int door_id); | |||
| 18 | 18 | ||
| 19 | bool IsPilgrimageDoable(); | 19 | bool IsPilgrimageDoable(); |
| 20 | 20 | ||
| 21 | bool IsAreaPostgame(int area_id); | ||
| 22 | |||
| 23 | bool IsLocationPostgame(int location_id); | ||
| 24 | |||
| 25 | bool IsPaintingPostgame(int painting_id); | ||
| 26 | |||
| 21 | #endif /* end of include guard: TRACKER_STATE_H_8639BC90 */ | 27 | #endif /* end of include guard: TRACKER_STATE_H_8639BC90 */ |
