about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--ap_state.cpp245
-rw-r--r--ap_state.h66
-rw-r--r--area_popup.cpp2
-rw-r--r--tracker_frame.cpp9
-rw-r--r--tracker_panel.cpp27
-rw-r--r--tracker_state.cpp24
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
19constexpr int AP_MAJOR = 0; 24constexpr int AP_MAJOR = 0;
@@ -22,29 +27,81 @@ constexpr int AP_REVISION = 0;
22 27
23constexpr int ITEM_HANDLING = 7; // <- all 28constexpr int ITEM_HANDLING = 7; // <- all
24 29
25static APClient* apclient = nullptr; 30namespace {
26 31
27APState::APState() { 32APClient* apclient = nullptr;
28 std::thread([this]() { 33
29 for (;;) { 34bool initialized = false;
30 { 35
31 std::lock_guard client_guard(client_mutex_); 36TrackerFrame* tracker_frame;
32 if (apclient) { 37
33 apclient->poll(); 38bool client_active = false;
39std::mutex client_mutex;
40
41bool connected = false;
42bool has_connection_result = false;
43
44std::map<int64_t, int> inventory;
45std::set<int64_t> checked_locations;
46
47std::map<std::tuple<int, int>, int64_t> ap_id_by_location_id;
48std::map<std::string, int64_t> ap_id_by_item_name;
49std::map<LingoColor, int64_t> ap_id_by_color;
50std::map<int64_t, std::string> progressive_item_by_ap_id;
51
52DoorShuffleMode door_shuffle_mode = kNO_DOORS;
53bool color_shuffle = false;
54bool painting_shuffle = false;
55
56std::map<std::string, std::string> painting_mapping;
57
58void RefreshTracker() {
59 GetTrackerState().CalculateState();
60 tracker_frame->UpdateIndicators();
61}
62
63int64_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
72void DestroyClient() {
73 client_active = false;
74 apclient->reset();
75 delete apclient;
76 apclient = nullptr;
77}
78
79} // namespace
80
81void AP_SetTrackerFrame(TrackerFrame* arg) { tracker_frame = arg; }
82
83void 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
42void 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
231bool APState::HasCheckedGameLocation(int area_id, int section_id) const { 288bool 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
241bool APState::HasColorItem(LingoColor color) const { 298bool 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
249bool APState::HasItem(const std::string& item, int quantity) const { 306bool 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
258void APState::RefreshTracker() { 315DoorShuffleMode AP_GetDoorShuffleMode() { return door_shuffle_mode; }
259 GetTrackerState().CalculateState();
260 tracker_frame_->UpdateIndicators();
261}
262
263int64_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; 317bool AP_IsColorShuffle() { return color_shuffle; }
270}
271 318
272void APState::DestroyClient() { 319bool AP_IsPaintingShuffle() { return painting_shuffle; }
273 client_active_ = false;
274 apclient->reset();
275 delete apclient;
276 apclient = nullptr;
277}
278 320
279APState& GetAPState() { 321const 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
13enum DoorShuffleMode { kNO_DOORS = 0, kSIMPLE_DOORS = 1, kCOMPLEX_DOORS = 2 }; 9class TrackerFrame;
14
15class 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_; } 11enum 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(); 13void AP_SetTrackerFrame(TrackerFrame* tracker_frame);
47 14
48 TrackerFrame* tracker_frame_; 15void AP_Connect(std::string server, std::string player, std::string password);
49 16
50 bool client_active_ = false; 17bool AP_HasCheckedGameLocation(int area_id, int section_id);
51 std::mutex client_mutex_;
52 18
53 bool connected_ = false; 19bool AP_HasColorItem(LingoColor color);
54 bool has_connection_result_ = false;
55 20
56 std::map<int64_t, int> inventory_; 21bool 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_; 23DoorShuffleMode 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; 25bool AP_IsColorShuffle();
65 bool color_shuffle_ = false;
66 bool painting_shuffle_ = false;
67 26
68 std::map<std::string, std::string> painting_mapping_; 27bool AP_IsPaintingShuffle();
69};
70 28
71APState& GetAPState(); 29const 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);
11wxDEFINE_EVENT(STATUS_CHANGED, wxCommandEvent); 11wxDEFINE_EVENT(STATUS_CHANGED, wxCommandEvent);
12 12
13TrackerFrame::TrackerFrame() 13TrackerFrame::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) {
34void TrackerPanel::UpdateIndicators() { 34void 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,
42bool IsDoorReachable_Helper(int door_id, const std::set<int>& reachable_rooms) { 42bool 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);