diff options
author | Star Rauchenberger <fefferburbia@gmail.com> | 2025-03-08 00:29:17 -0500 |
---|---|---|
committer | Star Rauchenberger <fefferburbia@gmail.com> | 2025-03-08 00:29:17 -0500 |
commit | e290161d58c98e73ea185855e79efad19cb111a2 (patch) | |
tree | a03d0e3822b19a1c57dd83d1309ab32814d670fe /src | |
parent | 4fa8f5b6c933dcbab5940d39a515937e86e9d280 (diff) | |
download | lingo-ap-tracker-e290161d58c98e73ea185855e79efad19cb111a2.tar.gz lingo-ap-tracker-e290161d58c98e73ea185855e79efad19cb111a2.tar.bz2 lingo-ap-tracker-e290161d58c98e73ea185855e79efad19cb111a2.zip |
Added postgame detection
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 */ |