diff options
Diffstat (limited to 'src/ap_state.cpp')
-rw-r--r-- | src/ap_state.cpp | 62 |
1 files changed, 43 insertions, 19 deletions
diff --git a/src/ap_state.cpp b/src/ap_state.cpp index 1e5621d..8ba6633 100644 --- a/src/ap_state.cpp +++ b/src/ap_state.cpp | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <any> | 10 | #include <any> |
11 | #include <apclient.hpp> | 11 | #include <apclient.hpp> |
12 | #include <apuuid.hpp> | 12 | #include <apuuid.hpp> |
13 | #include <bitset> | ||
13 | #include <chrono> | 14 | #include <chrono> |
14 | #include <exception> | 15 | #include <exception> |
15 | #include <filesystem> | 16 | #include <filesystem> |
@@ -37,6 +38,10 @@ constexpr int ITEM_HANDLING = 7; // <- all | |||
37 | constexpr int CONNECTION_TIMEOUT = 50000; // 50 seconds | 38 | constexpr int CONNECTION_TIMEOUT = 50000; // 50 seconds |
38 | constexpr int CONNECTION_BACKOFF_INTERVAL = 100; | 39 | constexpr int CONNECTION_BACKOFF_INTERVAL = 100; |
39 | 40 | ||
41 | constexpr int PANEL_COUNT = 803; | ||
42 | constexpr int PANEL_BITFIELD_LENGTH = 48; | ||
43 | constexpr int PANEL_BITFIELDS = 17; | ||
44 | |||
40 | namespace { | 45 | namespace { |
41 | 46 | ||
42 | const std::set<long> kNonProgressionItems = { | 47 | const std::set<long> kNonProgressionItems = { |
@@ -79,6 +84,7 @@ struct APState { | |||
79 | std::set<int64_t> checked_locations; | 84 | std::set<int64_t> checked_locations; |
80 | std::map<std::string, std::any> data_storage; | 85 | std::map<std::string, std::any> data_storage; |
81 | std::optional<std::tuple<int, int>> player_pos; | 86 | std::optional<std::tuple<int, int>> player_pos; |
87 | std::bitset<PANEL_COUNT> solved_panels; | ||
82 | 88 | ||
83 | DoorShuffleMode door_shuffle_mode = kNO_DOORS; | 89 | DoorShuffleMode door_shuffle_mode = kNO_DOORS; |
84 | bool group_doors = false; | 90 | bool group_doors = false; |
@@ -142,6 +148,7 @@ struct APState { | |||
142 | checked_locations.clear(); | 148 | checked_locations.clear(); |
143 | data_storage.clear(); | 149 | data_storage.clear(); |
144 | player_pos = std::nullopt; | 150 | player_pos = std::nullopt; |
151 | solved_panels.reset(); | ||
145 | victory_data_storage_key.clear(); | 152 | victory_data_storage_key.clear(); |
146 | door_shuffle_mode = kNO_DOORS; | 153 | door_shuffle_mode = kNO_DOORS; |
147 | group_doors = false; | 154 | group_doors = false; |
@@ -216,18 +223,15 @@ struct APState { | |||
216 | return checked_locations.count(location_id); | 223 | return checked_locations.count(location_id); |
217 | } | 224 | } |
218 | 225 | ||
219 | bool HasCheckedHuntPanel(int location_id) { | ||
220 | std::lock_guard state_guard(state_mutex); | ||
221 | |||
222 | std::string key = | ||
223 | fmt::format("{}Hunt|{}", data_storage_prefix, location_id); | ||
224 | return data_storage.count(key) && std::any_cast<bool>(data_storage.at(key)); | ||
225 | } | ||
226 | |||
227 | bool HasItem(int item_id, int quantity) { | 226 | bool HasItem(int item_id, int quantity) { |
228 | return inventory.count(item_id) && inventory.at(item_id) >= quantity; | 227 | return inventory.count(item_id) && inventory.at(item_id) >= quantity; |
229 | } | 228 | } |
230 | 229 | ||
230 | bool HasItemSafe(int item_id, int quantity) { | ||
231 | std::lock_guard state_guard(state_mutex); | ||
232 | return HasItem(item_id, quantity); | ||
233 | } | ||
234 | |||
231 | bool HasAchievement(const std::string& name) { | 235 | bool HasAchievement(const std::string& name) { |
232 | std::lock_guard state_guard(state_mutex); | 236 | std::lock_guard state_guard(state_mutex); |
233 | 237 | ||
@@ -283,6 +287,12 @@ struct APState { | |||
283 | 30; // CLIENT_GOAL | 287 | 30; // CLIENT_GOAL |
284 | } | 288 | } |
285 | 289 | ||
290 | bool IsPanelSolved(int solve_index) { | ||
291 | std::lock_guard state_guard(state_mutex); | ||
292 | |||
293 | return solved_panels.test(solve_index); | ||
294 | } | ||
295 | |||
286 | private: | 296 | private: |
287 | void Initialize() { | 297 | void Initialize() { |
288 | if (!initialized) { | 298 | if (!initialized) { |
@@ -295,11 +305,8 @@ struct APState { | |||
295 | "Achievement|{}", GD_GetPanel(panel_id).achievement_name)); | 305 | "Achievement|{}", GD_GetPanel(panel_id).achievement_name)); |
296 | } | 306 | } |
297 | 307 | ||
298 | for (const MapArea& map_area : GD_GetMapAreas()) { | 308 | for (int i = 0; i < PANEL_BITFIELDS; i++) { |
299 | for (const Location& location : map_area.locations) { | 309 | tracked_data_storage_keys.push_back(fmt::format("Panels_{}", i)); |
300 | tracked_data_storage_keys.push_back( | ||
301 | fmt::format("Hunt|{}", location.ap_location_id)); | ||
302 | } | ||
303 | } | 310 | } |
304 | 311 | ||
305 | tracked_data_storage_keys.push_back("PlayerPos"); | 312 | tracked_data_storage_keys.push_back("PlayerPos"); |
@@ -605,8 +612,6 @@ struct APState { | |||
605 | 612 | ||
606 | if (key.find("Achievement|") != std::string::npos) { | 613 | if (key.find("Achievement|") != std::string::npos) { |
607 | state_update.achievements = true; | 614 | state_update.achievements = true; |
608 | } else if (key.find("Hunt|") != std::string::npos) { | ||
609 | state_update.hunt_panels = true; | ||
610 | } | 615 | } |
611 | } else if (value.is_number()) { | 616 | } else if (value.is_number()) { |
612 | data_storage[key] = value.get<int>(); | 617 | data_storage[key] = value.get<int>(); |
@@ -615,6 +620,21 @@ struct APState { | |||
615 | 620 | ||
616 | if (key == victory_data_storage_key) { | 621 | if (key == victory_data_storage_key) { |
617 | state_update.cleared_locations = true; | 622 | state_update.cleared_locations = true; |
623 | } else if (key.find("Panels_") != std::string::npos) { | ||
624 | int bitfield_num = | ||
625 | std::stoi(key.substr(data_storage_prefix.size() + 7)); | ||
626 | uint64_t bitfield_value = value.get<uint64_t>(); | ||
627 | for (int i = 0; i < PANEL_BITFIELD_LENGTH; i++) { | ||
628 | if ((bitfield_value & (1LL << i)) != 0) { | ||
629 | int solve_index = bitfield_num * PANEL_BITFIELD_LENGTH + i; | ||
630 | |||
631 | if (!solved_panels.test(solve_index)) { | ||
632 | state_update.panels.insert(solve_index); | ||
633 | } | ||
634 | |||
635 | solved_panels.set(solve_index); | ||
636 | } | ||
637 | } | ||
618 | } | 638 | } |
619 | } else if (value.is_object()) { | 639 | } else if (value.is_object()) { |
620 | if (key.ends_with("PlayerPos")) { | 640 | if (key.ends_with("PlayerPos")) { |
@@ -715,14 +735,14 @@ bool AP_HasCheckedGameLocation(int location_id) { | |||
715 | return GetState().HasCheckedGameLocation(location_id); | 735 | return GetState().HasCheckedGameLocation(location_id); |
716 | } | 736 | } |
717 | 737 | ||
718 | bool AP_HasCheckedHuntPanel(int location_id) { | ||
719 | return GetState().HasCheckedHuntPanel(location_id); | ||
720 | } | ||
721 | |||
722 | bool AP_HasItem(int item_id, int quantity) { | 738 | bool AP_HasItem(int item_id, int quantity) { |
723 | return GetState().HasItem(item_id, quantity); | 739 | return GetState().HasItem(item_id, quantity); |
724 | } | 740 | } |
725 | 741 | ||
742 | bool AP_HasItemSafe(int item_id, int quantity) { | ||
743 | return GetState().HasItemSafe(item_id, quantity); | ||
744 | } | ||
745 | |||
726 | std::string AP_GetItemName(int item_id) { | 746 | std::string AP_GetItemName(int item_id) { |
727 | return GetState().GetItemName(item_id); | 747 | return GetState().GetItemName(item_id); |
728 | } | 748 | } |
@@ -883,3 +903,7 @@ std::optional<std::tuple<int, int>> AP_GetPlayerPosition() { | |||
883 | 903 | ||
884 | return GetState().player_pos; | 904 | return GetState().player_pos; |
885 | } | 905 | } |
906 | |||
907 | bool AP_IsPanelSolved(int solve_index) { | ||
908 | return GetState().IsPanelSolved(solve_index); | ||
909 | } | ||