diff options
-rw-r--r-- | ap_state.cpp | 245 | ||||
-rw-r--r-- | ap_state.h | 66 | ||||
-rw-r--r-- | area_popup.cpp | 2 | ||||
-rw-r--r-- | tracker_frame.cpp | 9 | ||||
-rw-r--r-- | tracker_panel.cpp | 27 | ||||
-rw-r--r-- | tracker_state.cpp | 24 |
6 files changed, 185 insertions, 188 deletions
diff --git a/ap_state.cpp b/ap_state.cpp index 8b7339a..c13b87c 100644 --- a/ap_state.cpp +++ b/ap_state.cpp | |||
@@ -11,9 +11,14 @@ | |||
11 | #include <chrono> | 11 | #include <chrono> |
12 | #include <exception> | 12 | #include <exception> |
13 | #include <list> | 13 | #include <list> |
14 | #include <memory> | ||
15 | #include <mutex> | ||
16 | #include <set> | ||
14 | #include <thread> | 17 | #include <thread> |
18 | #include <tuple> | ||
15 | 19 | ||
16 | #include "game_data.h" | 20 | #include "game_data.h" |
21 | #include "tracker_frame.h" | ||
17 | #include "tracker_state.h" | 22 | #include "tracker_state.h" |
18 | 23 | ||
19 | constexpr int AP_MAJOR = 0; | 24 | constexpr int AP_MAJOR = 0; |
@@ -22,29 +27,81 @@ constexpr int AP_REVISION = 0; | |||
22 | 27 | ||
23 | constexpr int ITEM_HANDLING = 7; // <- all | 28 | constexpr int ITEM_HANDLING = 7; // <- all |
24 | 29 | ||
25 | static APClient* apclient = nullptr; | 30 | namespace { |
26 | 31 | ||
27 | APState::APState() { | 32 | APClient* apclient = nullptr; |
28 | std::thread([this]() { | 33 | |
29 | for (;;) { | 34 | bool initialized = false; |
30 | { | 35 | |
31 | std::lock_guard client_guard(client_mutex_); | 36 | TrackerFrame* tracker_frame; |
32 | if (apclient) { | 37 | |
33 | apclient->poll(); | 38 | bool client_active = false; |
39 | std::mutex client_mutex; | ||
40 | |||
41 | bool connected = false; | ||
42 | bool has_connection_result = false; | ||
43 | |||
44 | std::map<int64_t, int> inventory; | ||
45 | std::set<int64_t> checked_locations; | ||
46 | |||
47 | std::map<std::tuple<int, int>, int64_t> ap_id_by_location_id; | ||
48 | std::map<std::string, int64_t> ap_id_by_item_name; | ||
49 | std::map<LingoColor, int64_t> ap_id_by_color; | ||
50 | std::map<int64_t, std::string> progressive_item_by_ap_id; | ||
51 | |||
52 | DoorShuffleMode door_shuffle_mode = kNO_DOORS; | ||
53 | bool color_shuffle = false; | ||
54 | bool painting_shuffle = false; | ||
55 | |||
56 | std::map<std::string, std::string> painting_mapping; | ||
57 | |||
58 | void RefreshTracker() { | ||
59 | GetTrackerState().CalculateState(); | ||
60 | tracker_frame->UpdateIndicators(); | ||
61 | } | ||
62 | |||
63 | int64_t GetItemId(const std::string& item_name) { | ||
64 | int64_t ap_id = apclient->get_item_id(item_name); | ||
65 | if (ap_id == APClient::INVALID_NAME_ID) { | ||
66 | std::cout << "Could not find AP item ID for " << item_name << std::endl; | ||
67 | } | ||
68 | |||
69 | return ap_id; | ||
70 | } | ||
71 | |||
72 | void DestroyClient() { | ||
73 | client_active = false; | ||
74 | apclient->reset(); | ||
75 | delete apclient; | ||
76 | apclient = nullptr; | ||
77 | } | ||
78 | |||
79 | } // namespace | ||
80 | |||
81 | void AP_SetTrackerFrame(TrackerFrame* arg) { tracker_frame = arg; } | ||
82 | |||
83 | void AP_Connect(std::string server, std::string player, std::string password) { | ||
84 | if (!initialized) { | ||
85 | std::thread([]() { | ||
86 | for (;;) { | ||
87 | { | ||
88 | std::lock_guard client_guard(client_mutex); | ||
89 | if (apclient) { | ||
90 | apclient->poll(); | ||
91 | } | ||
34 | } | 92 | } |
93 | |||
94 | std::this_thread::sleep_for(std::chrono::milliseconds(100)); | ||
35 | } | 95 | } |
96 | }).detach(); | ||
36 | 97 | ||
37 | std::this_thread::sleep_for(std::chrono::milliseconds(100)); | 98 | initialized = true; |
38 | } | 99 | } |
39 | }).detach(); | ||
40 | } | ||
41 | 100 | ||
42 | void APState::Connect(std::string server, std::string player, | 101 | tracker_frame->SetStatusMessage("Connecting to Archipelago server...."); |
43 | std::string password) { | ||
44 | tracker_frame_->SetStatusMessage("Connecting to Archipelago server...."); | ||
45 | 102 | ||
46 | { | 103 | { |
47 | std::lock_guard client_guard(client_mutex_); | 104 | std::lock_guard client_guard(client_mutex); |
48 | 105 | ||
49 | if (apclient) { | 106 | if (apclient) { |
50 | DestroyClient(); | 107 | DestroyClient(); |
@@ -53,20 +110,20 @@ void APState::Connect(std::string server, std::string player, | |||
53 | apclient = new APClient(ap_get_uuid(""), "Lingo", server); | 110 | apclient = new APClient(ap_get_uuid(""), "Lingo", server); |
54 | } | 111 | } |
55 | 112 | ||
56 | inventory_.clear(); | 113 | inventory.clear(); |
57 | checked_locations_.clear(); | 114 | checked_locations.clear(); |
58 | door_shuffle_mode_ = kNO_DOORS; | 115 | door_shuffle_mode = kNO_DOORS; |
59 | color_shuffle_ = false; | 116 | color_shuffle = false; |
60 | painting_shuffle_ = false; | 117 | painting_shuffle = false; |
61 | painting_mapping_.clear(); | 118 | painting_mapping.clear(); |
62 | 119 | ||
63 | connected_ = false; | 120 | connected = false; |
64 | has_connection_result_ = false; | 121 | has_connection_result = false; |
65 | 122 | ||
66 | apclient->set_room_info_handler([this, player, password]() { | 123 | apclient->set_room_info_handler([player, password]() { |
67 | inventory_.clear(); | 124 | inventory.clear(); |
68 | 125 | ||
69 | tracker_frame_->SetStatusMessage( | 126 | tracker_frame->SetStatusMessage( |
70 | "Connected to Archipelago server. Authenticating..."); | 127 | "Connected to Archipelago server. Authenticating..."); |
71 | 128 | ||
72 | apclient->ConnectSlot(player, password, ITEM_HANDLING, {"Tracker"}, | 129 | apclient->ConnectSlot(player, password, ITEM_HANDLING, {"Tracker"}, |
@@ -74,61 +131,60 @@ void APState::Connect(std::string server, std::string player, | |||
74 | }); | 131 | }); |
75 | 132 | ||
76 | apclient->set_location_checked_handler( | 133 | apclient->set_location_checked_handler( |
77 | [this](const std::list<int64_t>& locations) { | 134 | [](const std::list<int64_t>& locations) { |
78 | for (const int64_t location_id : locations) { | 135 | for (const int64_t location_id : locations) { |
79 | checked_locations_.insert(location_id); | 136 | checked_locations.insert(location_id); |
80 | std::cout << "Location: " << location_id << std::endl; | 137 | std::cout << "Location: " << location_id << std::endl; |
81 | } | 138 | } |
82 | 139 | ||
83 | RefreshTracker(); | 140 | RefreshTracker(); |
84 | }); | 141 | }); |
85 | 142 | ||
86 | apclient->set_slot_disconnected_handler([this]() { | 143 | apclient->set_slot_disconnected_handler([]() { |
87 | tracker_frame_->SetStatusMessage( | 144 | tracker_frame->SetStatusMessage( |
88 | "Disconnected from Archipelago. Attempting to reconnect..."); | 145 | "Disconnected from Archipelago. Attempting to reconnect..."); |
89 | }); | 146 | }); |
90 | 147 | ||
91 | apclient->set_socket_disconnected_handler([this]() { | 148 | apclient->set_socket_disconnected_handler([]() { |
92 | tracker_frame_->SetStatusMessage( | 149 | tracker_frame->SetStatusMessage( |
93 | "Disconnected from Archipelago. Attempting to reconnect..."); | 150 | "Disconnected from Archipelago. Attempting to reconnect..."); |
94 | }); | 151 | }); |
95 | 152 | ||
96 | apclient->set_items_received_handler( | 153 | apclient->set_items_received_handler( |
97 | [this](const std::list<APClient::NetworkItem>& items) { | 154 | [](const std::list<APClient::NetworkItem>& items) { |
98 | for (const APClient::NetworkItem& item : items) { | 155 | for (const APClient::NetworkItem& item : items) { |
99 | inventory_[item.item]++; | 156 | inventory[item.item]++; |
100 | std::cout << "Item: " << item.item << std::endl; | 157 | std::cout << "Item: " << item.item << std::endl; |
101 | } | 158 | } |
102 | 159 | ||
103 | RefreshTracker(); | 160 | RefreshTracker(); |
104 | }); | 161 | }); |
105 | 162 | ||
106 | apclient->set_slot_connected_handler([this](const nlohmann::json& slot_data) { | 163 | apclient->set_slot_connected_handler([](const nlohmann::json& slot_data) { |
107 | tracker_frame_->SetStatusMessage("Connected to Archipelago!"); | 164 | tracker_frame->SetStatusMessage("Connected to Archipelago!"); |
108 | 165 | ||
109 | door_shuffle_mode_ = slot_data["shuffle_doors"].get<DoorShuffleMode>(); | 166 | door_shuffle_mode = slot_data["shuffle_doors"].get<DoorShuffleMode>(); |
110 | color_shuffle_ = slot_data["shuffle_colors"].get<bool>(); | 167 | color_shuffle = slot_data["shuffle_colors"].get<bool>(); |
111 | painting_shuffle_ = slot_data["shuffle_paintings"].get<bool>(); | 168 | painting_shuffle = slot_data["shuffle_paintings"].get<bool>(); |
112 | 169 | ||
113 | if (painting_shuffle_ && slot_data.contains("painting_entrance_to_exit")) { | 170 | if (painting_shuffle && slot_data.contains("painting_entrance_to_exit")) { |
114 | painting_mapping_.clear(); | 171 | painting_mapping.clear(); |
115 | 172 | ||
116 | for (const auto& mapping_it : | 173 | for (const auto& mapping_it : |
117 | slot_data["painting_entrance_to_exit"].items()) { | 174 | slot_data["painting_entrance_to_exit"].items()) { |
118 | painting_mapping_[mapping_it.key()] = mapping_it.value(); | 175 | painting_mapping[mapping_it.key()] = mapping_it.value(); |
119 | } | 176 | } |
120 | } | 177 | } |
121 | 178 | ||
122 | connected_ = true; | 179 | connected = true; |
123 | has_connection_result_ = true; | 180 | has_connection_result = true; |
124 | }); | 181 | }); |
125 | 182 | ||
126 | apclient->set_slot_refused_handler([this]( | 183 | apclient->set_slot_refused_handler([](const std::list<std::string>& errors) { |
127 | const std::list<std::string>& errors) { | 184 | connected = false; |
128 | connected_ = false; | 185 | has_connection_result = true; |
129 | has_connection_result_ = true; | ||
130 | 186 | ||
131 | tracker_frame_->SetStatusMessage("Disconnected from Archipelago."); | 187 | tracker_frame->SetStatusMessage("Disconnected from Archipelago."); |
132 | 188 | ||
133 | std::vector<std::string> error_messages; | 189 | std::vector<std::string> error_messages; |
134 | error_messages.push_back("Could not connect to Archipelago."); | 190 | error_messages.push_back("Could not connect to Archipelago."); |
@@ -158,19 +214,19 @@ void APState::Connect(std::string server, std::string player, | |||
158 | wxMessageBox(full_message, "Connection failed", wxOK | wxICON_ERROR); | 214 | wxMessageBox(full_message, "Connection failed", wxOK | wxICON_ERROR); |
159 | }); | 215 | }); |
160 | 216 | ||
161 | client_active_ = true; | 217 | client_active = true; |
162 | 218 | ||
163 | int timeout = 5000; // 5 seconds | 219 | int timeout = 5000; // 5 seconds |
164 | int interval = 100; | 220 | int interval = 100; |
165 | int remaining_loops = timeout / interval; | 221 | int remaining_loops = timeout / interval; |
166 | while (!has_connection_result_) { | 222 | while (!has_connection_result) { |
167 | if (interval == 0) { | 223 | if (interval == 0) { |
168 | connected_ = false; | 224 | connected = false; |
169 | has_connection_result_ = true; | 225 | has_connection_result = true; |
170 | 226 | ||
171 | DestroyClient(); | 227 | DestroyClient(); |
172 | 228 | ||
173 | tracker_frame_->SetStatusMessage("Disconnected from Archipelago."); | 229 | tracker_frame->SetStatusMessage("Disconnected from Archipelago."); |
174 | 230 | ||
175 | wxMessageBox("Timeout while connecting to Archipelago server.", | 231 | wxMessageBox("Timeout while connecting to Archipelago server.", |
176 | "Connection failed", wxOK | wxICON_ERROR); | 232 | "Connection failed", wxOK | wxICON_ERROR); |
@@ -181,7 +237,7 @@ void APState::Connect(std::string server, std::string player, | |||
181 | interval--; | 237 | interval--; |
182 | } | 238 | } |
183 | 239 | ||
184 | if (connected_) { | 240 | if (connected) { |
185 | for (const MapArea& map_area : GetGameData().GetMapAreas()) { | 241 | for (const MapArea& map_area : GetGameData().GetMapAreas()) { |
186 | for (int section_id = 0; section_id < map_area.locations.size(); | 242 | for (int section_id = 0; section_id < map_area.locations.size(); |
187 | section_id++) { | 243 | section_id++) { |
@@ -192,91 +248,76 @@ void APState::Connect(std::string server, std::string player, | |||
192 | std::cout << "Could not find AP location ID for " | 248 | std::cout << "Could not find AP location ID for " |
193 | << location.ap_location_name << std::endl; | 249 | << location.ap_location_name << std::endl; |
194 | } else { | 250 | } else { |
195 | ap_id_by_location_id_[{map_area.id, section_id}] = ap_id; | 251 | ap_id_by_location_id[{map_area.id, section_id}] = ap_id; |
196 | } | 252 | } |
197 | } | 253 | } |
198 | } | 254 | } |
199 | 255 | ||
200 | for (const Door& door : GetGameData().GetDoors()) { | 256 | for (const Door& door : GetGameData().GetDoors()) { |
201 | if (!door.skip_item) { | 257 | if (!door.skip_item) { |
202 | ap_id_by_item_name_[door.item_name] = GetItemId(door.item_name); | 258 | ap_id_by_item_name[door.item_name] = GetItemId(door.item_name); |
203 | 259 | ||
204 | if (!door.group_name.empty() && | 260 | if (!door.group_name.empty() && |
205 | !ap_id_by_item_name_.count(door.group_name)) { | 261 | !ap_id_by_item_name.count(door.group_name)) { |
206 | ap_id_by_item_name_[door.group_name] = GetItemId(door.group_name); | 262 | ap_id_by_item_name[door.group_name] = GetItemId(door.group_name); |
207 | } | 263 | } |
208 | 264 | ||
209 | for (const ProgressiveRequirement& prog_req : door.progressives) { | 265 | for (const ProgressiveRequirement& prog_req : door.progressives) { |
210 | ap_id_by_item_name_[prog_req.item_name] = GetItemId(prog_req.item_name); | 266 | ap_id_by_item_name[prog_req.item_name] = |
267 | GetItemId(prog_req.item_name); | ||
211 | } | 268 | } |
212 | } | 269 | } |
213 | } | 270 | } |
214 | 271 | ||
215 | ap_id_by_color_[LingoColor::kBlack] = GetItemId("Black"); | 272 | ap_id_by_color[LingoColor::kBlack] = GetItemId("Black"); |
216 | ap_id_by_color_[LingoColor::kRed] = GetItemId("Red"); | 273 | ap_id_by_color[LingoColor::kRed] = GetItemId("Red"); |
217 | ap_id_by_color_[LingoColor::kBlue] = GetItemId("Blue"); | 274 | ap_id_by_color[LingoColor::kBlue] = GetItemId("Blue"); |
218 | ap_id_by_color_[LingoColor::kYellow] = GetItemId("Yellow"); | 275 | ap_id_by_color[LingoColor::kYellow] = GetItemId("Yellow"); |
219 | ap_id_by_color_[LingoColor::kPurple] = GetItemId("Purple"); | 276 | ap_id_by_color[LingoColor::kPurple] = GetItemId("Purple"); |
220 | ap_id_by_color_[LingoColor::kOrange] = GetItemId("Orange"); | 277 | ap_id_by_color[LingoColor::kOrange] = GetItemId("Orange"); |
221 | ap_id_by_color_[LingoColor::kGreen] = GetItemId("Green"); | 278 | ap_id_by_color[LingoColor::kGreen] = GetItemId("Green"); |
222 | ap_id_by_color_[LingoColor::kBrown] = GetItemId("Brown"); | 279 | ap_id_by_color[LingoColor::kBrown] = GetItemId("Brown"); |
223 | ap_id_by_color_[LingoColor::kGray] = GetItemId("Gray"); | 280 | ap_id_by_color[LingoColor::kGray] = GetItemId("Gray"); |
224 | 281 | ||
225 | RefreshTracker(); | 282 | RefreshTracker(); |
226 | } else { | 283 | } else { |
227 | client_active_ = false; | 284 | client_active = false; |
228 | } | 285 | } |
229 | } | 286 | } |
230 | 287 | ||
231 | bool APState::HasCheckedGameLocation(int area_id, int section_id) const { | 288 | bool AP_HasCheckedGameLocation(int area_id, int section_id) { |
232 | std::tuple<int, int> location_key = {area_id, section_id}; | 289 | std::tuple<int, int> location_key = {area_id, section_id}; |
233 | 290 | ||
234 | if (ap_id_by_location_id_.count(location_key)) { | 291 | if (ap_id_by_location_id.count(location_key)) { |
235 | return checked_locations_.count(ap_id_by_location_id_.at(location_key)); | 292 | return checked_locations.count(ap_id_by_location_id.at(location_key)); |
236 | } else { | 293 | } else { |
237 | return false; | 294 | return false; |
238 | } | 295 | } |
239 | } | 296 | } |
240 | 297 | ||
241 | bool APState::HasColorItem(LingoColor color) const { | 298 | bool AP_HasColorItem(LingoColor color) { |
242 | if (ap_id_by_color_.count(color)) { | 299 | if (ap_id_by_color.count(color)) { |
243 | return inventory_.count(ap_id_by_color_.at(color)); | 300 | return inventory.count(ap_id_by_color.at(color)); |
244 | } else { | 301 | } else { |
245 | return false; | 302 | return false; |
246 | } | 303 | } |
247 | } | 304 | } |
248 | 305 | ||
249 | bool APState::HasItem(const std::string& item, int quantity) const { | 306 | bool AP_HasItem(const std::string& item, int quantity) { |
250 | if (ap_id_by_item_name_.count(item)) { | 307 | if (ap_id_by_item_name.count(item)) { |
251 | int64_t ap_id = ap_id_by_item_name_.at(item); | 308 | int64_t ap_id = ap_id_by_item_name.at(item); |
252 | return inventory_.count(ap_id) && inventory_.at(ap_id) >= quantity; | 309 | return inventory.count(ap_id) && inventory.at(ap_id) >= quantity; |
253 | } else { | 310 | } else { |
254 | return false; | 311 | return false; |
255 | } | 312 | } |
256 | } | 313 | } |
257 | 314 | ||
258 | void APState::RefreshTracker() { | 315 | DoorShuffleMode AP_GetDoorShuffleMode() { return door_shuffle_mode; } |
259 | GetTrackerState().CalculateState(); | ||
260 | tracker_frame_->UpdateIndicators(); | ||
261 | } | ||
262 | |||
263 | int64_t APState::GetItemId(const std::string& item_name) { | ||
264 | int64_t ap_id = apclient->get_item_id(item_name); | ||
265 | if (ap_id == APClient::INVALID_NAME_ID) { | ||
266 | std::cout << "Could not find AP item ID for " << item_name << std::endl; | ||
267 | } | ||
268 | 316 | ||
269 | return ap_id; | 317 | bool AP_IsColorShuffle() { return color_shuffle; } |
270 | } | ||
271 | 318 | ||
272 | void APState::DestroyClient() { | 319 | bool AP_IsPaintingShuffle() { return painting_shuffle; } |
273 | client_active_ = false; | ||
274 | apclient->reset(); | ||
275 | delete apclient; | ||
276 | apclient = nullptr; | ||
277 | } | ||
278 | 320 | ||
279 | APState& GetAPState() { | 321 | const std::map<std::string, std::string> AP_GetPaintingMapping() { |
280 | static APState* instance = new APState(); | 322 | return painting_mapping; |
281 | return *instance; | ||
282 | } | 323 | } |
diff --git a/ap_state.h b/ap_state.h index ce73528..434b7b2 100644 --- a/ap_state.h +++ b/ap_state.h | |||
@@ -1,73 +1,31 @@ | |||
1 | #ifndef AP_STATE_H_664A4180 | 1 | #ifndef AP_STATE_H_664A4180 |
2 | #define AP_STATE_H_664A4180 | 2 | #define AP_STATE_H_664A4180 |
3 | 3 | ||
4 | #include <memory> | 4 | #include <map> |
5 | #include <mutex> | ||
6 | #include <set> | ||
7 | #include <string> | 5 | #include <string> |
8 | #include <tuple> | ||
9 | 6 | ||
10 | #include "game_data.h" | 7 | #include "game_data.h" |
11 | #include "tracker_frame.h" | ||
12 | 8 | ||
13 | enum DoorShuffleMode { kNO_DOORS = 0, kSIMPLE_DOORS = 1, kCOMPLEX_DOORS = 2 }; | 9 | class TrackerFrame; |
14 | |||
15 | class APState { | ||
16 | public: | ||
17 | APState(); | ||
18 | |||
19 | void SetTrackerFrame(TrackerFrame* tracker_frame) { | ||
20 | tracker_frame_ = tracker_frame; | ||
21 | } | ||
22 | |||
23 | void Connect(std::string server, std::string player, std::string password); | ||
24 | |||
25 | bool HasCheckedGameLocation(int area_id, int section_id) const; | ||
26 | |||
27 | bool HasColorItem(LingoColor color) const; | ||
28 | |||
29 | bool HasItem(const std::string& item, int quantity = 1) const; | ||
30 | 10 | ||
31 | DoorShuffleMode GetDoorShuffleMode() const { return door_shuffle_mode_; } | 11 | enum DoorShuffleMode { kNO_DOORS = 0, kSIMPLE_DOORS = 1, kCOMPLEX_DOORS = 2 }; |
32 | |||
33 | bool IsColorShuffle() const { return color_shuffle_; } | ||
34 | |||
35 | bool IsPaintingShuffle() const { return painting_shuffle_; } | ||
36 | |||
37 | const std::map<std::string, std::string> GetPaintingMapping() const { | ||
38 | return painting_mapping_; | ||
39 | } | ||
40 | |||
41 | private: | ||
42 | void RefreshTracker(); | ||
43 | |||
44 | int64_t GetItemId(const std::string& item_name); | ||
45 | 12 | ||
46 | void DestroyClient(); | 13 | void AP_SetTrackerFrame(TrackerFrame* tracker_frame); |
47 | 14 | ||
48 | TrackerFrame* tracker_frame_; | 15 | void AP_Connect(std::string server, std::string player, std::string password); |
49 | 16 | ||
50 | bool client_active_ = false; | 17 | bool AP_HasCheckedGameLocation(int area_id, int section_id); |
51 | std::mutex client_mutex_; | ||
52 | 18 | ||
53 | bool connected_ = false; | 19 | bool AP_HasColorItem(LingoColor color); |
54 | bool has_connection_result_ = false; | ||
55 | 20 | ||
56 | std::map<int64_t, int> inventory_; | 21 | bool AP_HasItem(const std::string& item, int quantity = 1); |
57 | std::set<int64_t> checked_locations_; | ||
58 | 22 | ||
59 | std::map<std::tuple<int, int>, int64_t> ap_id_by_location_id_; | 23 | DoorShuffleMode AP_GetDoorShuffleMode(); |
60 | std::map<std::string, int64_t> ap_id_by_item_name_; | ||
61 | std::map<LingoColor, int64_t> ap_id_by_color_; | ||
62 | std::map<int64_t, std::string> progressive_item_by_ap_id_; | ||
63 | 24 | ||
64 | DoorShuffleMode door_shuffle_mode_ = kNO_DOORS; | 25 | bool AP_IsColorShuffle(); |
65 | bool color_shuffle_ = false; | ||
66 | bool painting_shuffle_ = false; | ||
67 | 26 | ||
68 | std::map<std::string, std::string> painting_mapping_; | 27 | bool AP_IsPaintingShuffle(); |
69 | }; | ||
70 | 28 | ||
71 | APState& GetAPState(); | 29 | const std::map<std::string, std::string> AP_GetPaintingMapping(); |
72 | 30 | ||
73 | #endif /* end of include guard: AP_STATE_H_664A4180 */ | 31 | #endif /* end of include guard: AP_STATE_H_664A4180 */ |
diff --git a/area_popup.cpp b/area_popup.cpp index 4cc3c63..a8ff612 100644 --- a/area_popup.cpp +++ b/area_popup.cpp | |||
@@ -43,7 +43,7 @@ void AreaPopup::UpdateIndicators() { | |||
43 | const MapArea& map_area = GetGameData().GetMapArea(area_id_); | 43 | const MapArea& map_area = GetGameData().GetMapArea(area_id_); |
44 | for (int section_id = 0; section_id < map_area.locations.size(); | 44 | for (int section_id = 0; section_id < map_area.locations.size(); |
45 | section_id++) { | 45 | section_id++) { |
46 | bool checked = GetAPState().HasCheckedGameLocation(area_id_, section_id); | 46 | bool checked = AP_HasCheckedGameLocation(area_id_, section_id); |
47 | bool reachable = | 47 | bool reachable = |
48 | GetTrackerState().IsLocationReachable(area_id_, section_id); | 48 | GetTrackerState().IsLocationReachable(area_id_, section_id); |
49 | const wxColour* text_color = reachable ? wxWHITE : wxRED; | 49 | const wxColour* text_color = reachable ? wxWHITE : wxRED; |
diff --git a/tracker_frame.cpp b/tracker_frame.cpp index 774b710..2a862a5 100644 --- a/tracker_frame.cpp +++ b/tracker_frame.cpp | |||
@@ -11,10 +11,11 @@ wxDEFINE_EVENT(STATE_CHANGED, wxCommandEvent); | |||
11 | wxDEFINE_EVENT(STATUS_CHANGED, wxCommandEvent); | 11 | wxDEFINE_EVENT(STATUS_CHANGED, wxCommandEvent); |
12 | 12 | ||
13 | TrackerFrame::TrackerFrame() | 13 | TrackerFrame::TrackerFrame() |
14 | : wxFrame(nullptr, wxID_ANY, "Lingo Archipelago Tracker", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE | wxFULL_REPAINT_ON_RESIZE) { | 14 | : wxFrame(nullptr, wxID_ANY, "Lingo Archipelago Tracker", wxDefaultPosition, |
15 | wxDefaultSize, wxDEFAULT_FRAME_STYLE | wxFULL_REPAINT_ON_RESIZE) { | ||
15 | ::wxInitAllImageHandlers(); | 16 | ::wxInitAllImageHandlers(); |
16 | 17 | ||
17 | GetAPState().SetTrackerFrame(this); | 18 | AP_SetTrackerFrame(this); |
18 | 19 | ||
19 | SetSize(1280, 728); | 20 | SetSize(1280, 728); |
20 | 21 | ||
@@ -70,8 +71,8 @@ void TrackerFrame::OnConnect(wxCommandEvent &event) { | |||
70 | GetTrackerConfig().ap_password = dlg.GetPasswordValue(); | 71 | GetTrackerConfig().ap_password = dlg.GetPasswordValue(); |
71 | GetTrackerConfig().Save(); | 72 | GetTrackerConfig().Save(); |
72 | 73 | ||
73 | GetAPState().Connect(dlg.GetServerValue(), dlg.GetPlayerValue(), | 74 | AP_Connect(dlg.GetServerValue(), dlg.GetPlayerValue(), |
74 | dlg.GetPasswordValue()); | 75 | dlg.GetPasswordValue()); |
75 | } | 76 | } |
76 | } | 77 | } |
77 | 78 | ||
diff --git a/tracker_panel.cpp b/tracker_panel.cpp index 73cac41..0e0569b 100644 --- a/tracker_panel.cpp +++ b/tracker_panel.cpp | |||
@@ -21,7 +21,7 @@ TrackerPanel::TrackerPanel(wxWindow *parent) : wxPanel(parent, wxID_ANY) { | |||
21 | 21 | ||
22 | area.popup = new AreaPopup(this, map_area.id); | 22 | area.popup = new AreaPopup(this, map_area.id); |
23 | area.popup->SetPosition({0, 0}); | 23 | area.popup->SetPosition({0, 0}); |
24 | 24 | ||
25 | areas_.push_back(area); | 25 | areas_.push_back(area); |
26 | } | 26 | } |
27 | 27 | ||
@@ -34,7 +34,7 @@ TrackerPanel::TrackerPanel(wxWindow *parent) : wxPanel(parent, wxID_ANY) { | |||
34 | void TrackerPanel::UpdateIndicators() { | 34 | void TrackerPanel::UpdateIndicators() { |
35 | Redraw(); | 35 | Redraw(); |
36 | 36 | ||
37 | for (AreaIndicator& area : areas_) { | 37 | for (AreaIndicator &area : areas_) { |
38 | area.popup->UpdateIndicators(); | 38 | area.popup->UpdateIndicators(); |
39 | } | 39 | } |
40 | } | 40 | } |
@@ -90,7 +90,7 @@ void TrackerPanel::Redraw() { | |||
90 | wxMemoryDC dc; | 90 | wxMemoryDC dc; |
91 | dc.SelectObject(rendered_); | 91 | dc.SelectObject(rendered_); |
92 | 92 | ||
93 | for (AreaIndicator& area : areas_) { | 93 | for (AreaIndicator &area : areas_) { |
94 | const wxBrush *brush_color = wxGREY_BRUSH; | 94 | const wxBrush *brush_color = wxGREY_BRUSH; |
95 | 95 | ||
96 | const MapArea &map_area = GetGameData().GetMapArea(area.area_id); | 96 | const MapArea &map_area = GetGameData().GetMapArea(area.area_id); |
@@ -98,10 +98,8 @@ void TrackerPanel::Redraw() { | |||
98 | bool has_unreachable_unchecked = false; | 98 | bool has_unreachable_unchecked = false; |
99 | for (int section_id = 0; section_id < map_area.locations.size(); | 99 | for (int section_id = 0; section_id < map_area.locations.size(); |
100 | section_id++) { | 100 | section_id++) { |
101 | if (!GetAPState().HasCheckedGameLocation(area.area_id, | 101 | if (!AP_HasCheckedGameLocation(area.area_id, section_id)) { |
102 | section_id)) { | 102 | if (GetTrackerState().IsLocationReachable(area.area_id, section_id)) { |
103 | if (GetTrackerState().IsLocationReachable(area.area_id, | ||
104 | section_id)) { | ||
105 | has_reachable_unchecked = true; | 103 | has_reachable_unchecked = true; |
106 | } else { | 104 | } else { |
107 | has_unreachable_unchecked = true; | 105 | has_unreachable_unchecked = true; |
@@ -121,16 +119,15 @@ void TrackerPanel::Redraw() { | |||
121 | final_width * AREA_EFFECTIVE_SIZE / image_size.GetWidth(); | 119 | final_width * AREA_EFFECTIVE_SIZE / image_size.GetWidth(); |
122 | int actual_border_size = | 120 | int actual_border_size = |
123 | real_area_size * AREA_BORDER_SIZE / AREA_EFFECTIVE_SIZE; | 121 | real_area_size * AREA_BORDER_SIZE / AREA_EFFECTIVE_SIZE; |
124 | int real_area_x = | 122 | int real_area_x = final_x + (map_area.map_x - (AREA_EFFECTIVE_SIZE / 2)) * |
125 | final_x + (map_area.map_x - (AREA_EFFECTIVE_SIZE / 2)) * | 123 | final_width / image_size.GetWidth(); |
126 | final_width / image_size.GetWidth(); | 124 | int real_area_y = final_y + (map_area.map_y - (AREA_EFFECTIVE_SIZE / 2)) * |
127 | int real_area_y = | 125 | final_width / image_size.GetWidth(); |
128 | final_y + (map_area.map_y - (AREA_EFFECTIVE_SIZE / 2)) * | 126 | |
129 | final_width / image_size.GetWidth(); | ||
130 | |||
131 | dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, actual_border_size)); | 127 | dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, actual_border_size)); |
132 | dc.SetBrush(*brush_color); | 128 | dc.SetBrush(*brush_color); |
133 | dc.DrawRectangle({real_area_x, real_area_y}, {real_area_size, real_area_size}); | 129 | dc.DrawRectangle({real_area_x, real_area_y}, |
130 | {real_area_size, real_area_size}); | ||
134 | 131 | ||
135 | area.real_x1 = real_area_x; | 132 | area.real_x1 = real_area_x; |
136 | area.real_x2 = real_area_x + real_area_size; | 133 | area.real_x2 = real_area_x + real_area_size; |
diff --git a/tracker_state.cpp b/tracker_state.cpp index 4921d3f..6eaf87a 100644 --- a/tracker_state.cpp +++ b/tracker_state.cpp | |||
@@ -28,9 +28,9 @@ bool IsPanelReachable_Helper(int panel_id, | |||
28 | } | 28 | } |
29 | } | 29 | } |
30 | 30 | ||
31 | if (GetAPState().IsColorShuffle()) { | 31 | if (AP_IsColorShuffle()) { |
32 | for (LingoColor color : panel_obj.colors) { | 32 | for (LingoColor color : panel_obj.colors) { |
33 | if (!GetAPState().HasColorItem(color)) { | 33 | if (!AP_HasColorItem(color)) { |
34 | return false; | 34 | return false; |
35 | } | 35 | } |
36 | } | 36 | } |
@@ -42,7 +42,7 @@ bool IsPanelReachable_Helper(int panel_id, | |||
42 | bool IsDoorReachable_Helper(int door_id, const std::set<int>& reachable_rooms) { | 42 | bool IsDoorReachable_Helper(int door_id, const std::set<int>& reachable_rooms) { |
43 | const Door& door_obj = GetGameData().GetDoor(door_id); | 43 | const Door& door_obj = GetGameData().GetDoor(door_id); |
44 | 44 | ||
45 | if (GetAPState().GetDoorShuffleMode() == kNO_DOORS || door_obj.skip_item) { | 45 | if (AP_GetDoorShuffleMode() == kNO_DOORS || door_obj.skip_item) { |
46 | if (!reachable_rooms.count(door_obj.room)) { | 46 | if (!reachable_rooms.count(door_obj.room)) { |
47 | return false; | 47 | return false; |
48 | } | 48 | } |
@@ -54,15 +54,15 @@ bool IsDoorReachable_Helper(int door_id, const std::set<int>& reachable_rooms) { | |||
54 | } | 54 | } |
55 | 55 | ||
56 | return true; | 56 | return true; |
57 | } else if (GetAPState().GetDoorShuffleMode() == kSIMPLE_DOORS && | 57 | } else if (AP_GetDoorShuffleMode() == kSIMPLE_DOORS && |
58 | !door_obj.group_name.empty()) { | 58 | !door_obj.group_name.empty()) { |
59 | return GetAPState().HasItem(door_obj.group_name); | 59 | return AP_HasItem(door_obj.group_name); |
60 | } else { | 60 | } else { |
61 | bool has_item = GetAPState().HasItem(door_obj.item_name); | 61 | bool has_item = AP_HasItem(door_obj.item_name); |
62 | 62 | ||
63 | if (!has_item) { | 63 | if (!has_item) { |
64 | for (const ProgressiveRequirement& prog_req : door_obj.progressives) { | 64 | for (const ProgressiveRequirement& prog_req : door_obj.progressives) { |
65 | if (GetAPState().HasItem(prog_req.item_name, prog_req.quantity)) { | 65 | if (AP_HasItem(prog_req.item_name, prog_req.quantity)) { |
66 | has_item = true; | 66 | has_item = true; |
67 | break; | 67 | break; |
68 | } | 68 | } |
@@ -96,7 +96,7 @@ void TrackerState::CalculateState() { | |||
96 | if (room_exit.door.has_value()) { | 96 | if (room_exit.door.has_value()) { |
97 | if (IsDoorReachable_Helper(*room_exit.door, reachable_rooms)) { | 97 | if (IsDoorReachable_Helper(*room_exit.door, reachable_rooms)) { |
98 | valid_transition = true; | 98 | valid_transition = true; |
99 | } else if (GetAPState().GetDoorShuffleMode() == kNO_DOORS) { | 99 | } else if (AP_GetDoorShuffleMode() == kNO_DOORS) { |
100 | new_boundary.push_back(room_exit); | 100 | new_boundary.push_back(room_exit); |
101 | } | 101 | } |
102 | } else { | 102 | } else { |
@@ -110,17 +110,17 @@ void TrackerState::CalculateState() { | |||
110 | const Room& room_obj = | 110 | const Room& room_obj = |
111 | GetGameData().GetRoom(room_exit.destination_room); | 111 | GetGameData().GetRoom(room_exit.destination_room); |
112 | for (const Exit& out_edge : room_obj.exits) { | 112 | for (const Exit& out_edge : room_obj.exits) { |
113 | if (!out_edge.painting || !GetAPState().IsPaintingShuffle()) { | 113 | if (!out_edge.painting || !AP_IsPaintingShuffle()) { |
114 | new_boundary.push_back(out_edge); | 114 | new_boundary.push_back(out_edge); |
115 | } | 115 | } |
116 | } | 116 | } |
117 | 117 | ||
118 | if (GetAPState().IsPaintingShuffle()) { | 118 | if (AP_IsPaintingShuffle()) { |
119 | for (const PaintingExit& out_edge : room_obj.paintings) { | 119 | for (const PaintingExit& out_edge : room_obj.paintings) { |
120 | if (GetAPState().GetPaintingMapping().count(out_edge.id)) { | 120 | if (AP_GetPaintingMapping().count(out_edge.id)) { |
121 | Exit painting_exit; | 121 | Exit painting_exit; |
122 | painting_exit.destination_room = GetGameData().GetRoomForPainting( | 122 | painting_exit.destination_room = GetGameData().GetRoomForPainting( |
123 | GetAPState().GetPaintingMapping().at(out_edge.id)); | 123 | AP_GetPaintingMapping().at(out_edge.id)); |
124 | painting_exit.door = out_edge.door; | 124 | painting_exit.door = out_edge.door; |
125 | 125 | ||
126 | new_boundary.push_back(painting_exit); | 126 | new_boundary.push_back(painting_exit); |