diff options
-rw-r--r-- | assets/player.png | bin | 0 -> 1457 bytes | |||
-rw-r--r-- | src/ap_state.cpp | 58 | ||||
-rw-r--r-- | src/ap_state.h | 4 | ||||
-rw-r--r-- | src/tracker_panel.cpp | 32 | ||||
-rw-r--r-- | src/tracker_panel.h | 7 |
5 files changed, 82 insertions, 19 deletions
diff --git a/assets/player.png b/assets/player.png new file mode 100644 index 0000000..6e0cba4 --- /dev/null +++ b/assets/player.png | |||
Binary files differ | |||
diff --git a/src/ap_state.cpp b/src/ap_state.cpp index 8134cdb..58670e6 100644 --- a/src/ap_state.cpp +++ b/src/ap_state.cpp | |||
@@ -54,6 +54,7 @@ struct APState { | |||
54 | std::map<int64_t, int> inventory; | 54 | std::map<int64_t, int> inventory; |
55 | std::set<int64_t> checked_locations; | 55 | std::set<int64_t> checked_locations; |
56 | std::map<std::string, std::any> data_storage; | 56 | std::map<std::string, std::any> data_storage; |
57 | std::optional<std::tuple<int, int>> player_pos; | ||
57 | 58 | ||
58 | DoorShuffleMode door_shuffle_mode = kNO_DOORS; | 59 | DoorShuffleMode door_shuffle_mode = kNO_DOORS; |
59 | bool color_shuffle = false; | 60 | bool color_shuffle = false; |
@@ -95,6 +96,8 @@ struct APState { | |||
95 | } | 96 | } |
96 | } | 97 | } |
97 | 98 | ||
99 | tracked_data_storage_keys.push_back("PlayerPos"); | ||
100 | |||
98 | initialized = true; | 101 | initialized = true; |
99 | } | 102 | } |
100 | 103 | ||
@@ -122,6 +125,7 @@ struct APState { | |||
122 | inventory.clear(); | 125 | inventory.clear(); |
123 | checked_locations.clear(); | 126 | checked_locations.clear(); |
124 | data_storage.clear(); | 127 | data_storage.clear(); |
128 | player_pos = std::nullopt; | ||
125 | victory_data_storage_key.clear(); | 129 | victory_data_storage_key.clear(); |
126 | door_shuffle_mode = kNO_DOORS; | 130 | door_shuffle_mode = kNO_DOORS; |
127 | color_shuffle = false; | 131 | color_shuffle = false; |
@@ -187,15 +191,7 @@ struct APState { | |||
187 | apclient->set_retrieved_handler( | 191 | apclient->set_retrieved_handler( |
188 | [this](const std::map<std::string, nlohmann::json>& data) { | 192 | [this](const std::map<std::string, nlohmann::json>& data) { |
189 | for (const auto& [key, value] : data) { | 193 | for (const auto& [key, value] : data) { |
190 | if (value.is_boolean()) { | 194 | HandleDataStorage(key, value); |
191 | data_storage[key] = value.get<bool>(); | ||
192 | TrackerLog("Data storage " + key + " retrieved as " + | ||
193 | (value.get<bool>() ? "true" : "false")); | ||
194 | } else if (value.is_number()) { | ||
195 | data_storage[key] = value.get<int>(); | ||
196 | TrackerLog("Data storage " + key + " retrieved as " + | ||
197 | std::to_string(value.get<int>())); | ||
198 | } | ||
199 | } | 195 | } |
200 | 196 | ||
201 | RefreshTracker(); | 197 | RefreshTracker(); |
@@ -204,16 +200,7 @@ struct APState { | |||
204 | apclient->set_set_reply_handler([this](const std::string& key, | 200 | apclient->set_set_reply_handler([this](const std::string& key, |
205 | const nlohmann::json& value, | 201 | const nlohmann::json& value, |
206 | const nlohmann::json&) { | 202 | const nlohmann::json&) { |
207 | if (value.is_boolean()) { | 203 | HandleDataStorage(key, value); |
208 | data_storage[key] = value.get<bool>(); | ||
209 | TrackerLog("Data storage " + key + " retrieved as " + | ||
210 | (value.get<bool>() ? "true" : "false")); | ||
211 | } else if (value.is_number()) { | ||
212 | data_storage[key] = value.get<int>(); | ||
213 | TrackerLog("Data storage " + key + " retrieved as " + | ||
214 | std::to_string(value.get<int>())); | ||
215 | } | ||
216 | |||
217 | RefreshTracker(); | 204 | RefreshTracker(); |
218 | }); | 205 | }); |
219 | 206 | ||
@@ -335,6 +322,35 @@ struct APState { | |||
335 | } | 322 | } |
336 | } | 323 | } |
337 | 324 | ||
325 | void HandleDataStorage(const std::string& key, const nlohmann::json& value) { | ||
326 | if (value.is_boolean()) { | ||
327 | data_storage[key] = value.get<bool>(); | ||
328 | TrackerLog("Data storage " + key + " retrieved as " + | ||
329 | (value.get<bool>() ? "true" : "false")); | ||
330 | } else if (value.is_number()) { | ||
331 | data_storage[key] = value.get<int>(); | ||
332 | TrackerLog("Data storage " + key + " retrieved as " + | ||
333 | std::to_string(value.get<int>())); | ||
334 | } else if (value.is_object()) { | ||
335 | if (key.ends_with("PlayerPos")) { | ||
336 | auto map_value = value.get<std::map<std::string, int>>(); | ||
337 | player_pos = std::tuple<int, int>(map_value["x"], map_value["z"]); | ||
338 | } else { | ||
339 | data_storage[key] = value.get<std::map<std::string, int>>(); | ||
340 | } | ||
341 | |||
342 | TrackerLog("Data storage " + key + " retrieved as dictionary"); | ||
343 | } else if (value.is_null()) { | ||
344 | if (key.ends_with("PlayerPos")) { | ||
345 | player_pos = std::nullopt; | ||
346 | } else { | ||
347 | data_storage.erase(key); | ||
348 | } | ||
349 | |||
350 | TrackerLog("Data storage " + key + " retrieved as null"); | ||
351 | } | ||
352 | } | ||
353 | |||
338 | bool HasCheckedGameLocation(int location_id) { | 354 | bool HasCheckedGameLocation(int location_id) { |
339 | return checked_locations.count(location_id); | 355 | return checked_locations.count(location_id); |
340 | } | 356 | } |
@@ -446,3 +462,7 @@ bool AP_HasAchievement(const std::string& achievement_name) { | |||
446 | bool AP_HasEarlyColorHallways() { return GetState().early_color_hallways; } | 462 | bool AP_HasEarlyColorHallways() { return GetState().early_color_hallways; } |
447 | 463 | ||
448 | bool AP_HasReachedGoal() { return GetState().HasReachedGoal(); } | 464 | bool AP_HasReachedGoal() { return GetState().HasReachedGoal(); } |
465 | |||
466 | std::optional<std::tuple<int, int>> AP_GetPlayerPosition() { | ||
467 | return GetState().player_pos; | ||
468 | } | ||
diff --git a/src/ap_state.h b/src/ap_state.h index cc51a78..420a032 100644 --- a/src/ap_state.h +++ b/src/ap_state.h | |||
@@ -2,7 +2,9 @@ | |||
2 | #define AP_STATE_H_664A4180 | 2 | #define AP_STATE_H_664A4180 |
3 | 3 | ||
4 | #include <map> | 4 | #include <map> |
5 | #include <optional> | ||
5 | #include <string> | 6 | #include <string> |
7 | #include <tuple> | ||
6 | 8 | ||
7 | #include "game_data.h" | 9 | #include "game_data.h" |
8 | 10 | ||
@@ -46,4 +48,6 @@ bool AP_HasEarlyColorHallways(); | |||
46 | 48 | ||
47 | bool AP_HasReachedGoal(); | 49 | bool AP_HasReachedGoal(); |
48 | 50 | ||
51 | std::optional<std::tuple<int, int>> AP_GetPlayerPosition(); | ||
52 | |||
49 | #endif /* end of include guard: AP_STATE_H_664A4180 */ | 53 | #endif /* end of include guard: AP_STATE_H_664A4180 */ |
diff --git a/src/tracker_panel.cpp b/src/tracker_panel.cpp index daaeff7..5f9f8ea 100644 --- a/src/tracker_panel.cpp +++ b/src/tracker_panel.cpp | |||
@@ -10,6 +10,7 @@ | |||
10 | constexpr int AREA_ACTUAL_SIZE = 64; | 10 | constexpr int AREA_ACTUAL_SIZE = 64; |
11 | constexpr int AREA_BORDER_SIZE = 5; | 11 | constexpr int AREA_BORDER_SIZE = 5; |
12 | constexpr int AREA_EFFECTIVE_SIZE = AREA_ACTUAL_SIZE + AREA_BORDER_SIZE * 2; | 12 | constexpr int AREA_EFFECTIVE_SIZE = AREA_ACTUAL_SIZE + AREA_BORDER_SIZE * 2; |
13 | constexpr int PLAYER_SIZE = 96; | ||
13 | 14 | ||
14 | TrackerPanel::TrackerPanel(wxWindow *parent) : wxPanel(parent, wxID_ANY) { | 15 | TrackerPanel::TrackerPanel(wxWindow *parent) : wxPanel(parent, wxID_ANY) { |
15 | map_image_ = wxImage(GetAbsolutePath("assets/lingo_map.png").c_str(), | 16 | map_image_ = wxImage(GetAbsolutePath("assets/lingo_map.png").c_str(), |
@@ -18,6 +19,12 @@ TrackerPanel::TrackerPanel(wxWindow *parent) : wxPanel(parent, wxID_ANY) { | |||
18 | return; | 19 | return; |
19 | } | 20 | } |
20 | 21 | ||
22 | player_image_ = | ||
23 | wxImage(GetAbsolutePath("assets/player.png").c_str(), wxBITMAP_TYPE_PNG); | ||
24 | if (!player_image_.IsOk()) { | ||
25 | return; | ||
26 | } | ||
27 | |||
21 | for (const MapArea &map_area : GD_GetMapAreas()) { | 28 | for (const MapArea &map_area : GD_GetMapAreas()) { |
22 | AreaIndicator area; | 29 | AreaIndicator area; |
23 | area.area_id = map_area.id; | 30 | area.area_id = map_area.id; |
@@ -50,6 +57,20 @@ void TrackerPanel::OnPaint(wxPaintEvent &event) { | |||
50 | wxPaintDC dc(this); | 57 | wxPaintDC dc(this); |
51 | dc.DrawBitmap(rendered_, 0, 0); | 58 | dc.DrawBitmap(rendered_, 0, 0); |
52 | 59 | ||
60 | if (AP_GetPlayerPosition().has_value()) { | ||
61 | // 1588, 1194 | ||
62 | // 14x14 -> 154x154 | ||
63 | double intended_x = | ||
64 | 1588.0 + (std::get<0>(*AP_GetPlayerPosition()) * (154.0 / 14.0)); | ||
65 | double intended_y = | ||
66 | 1194.0 + (std::get<1>(*AP_GetPlayerPosition()) * (154.0 / 14.0)); | ||
67 | |||
68 | int real_x = offset_x_ + scale_x_ * intended_x - scaled_player_.GetWidth() / 2; | ||
69 | int real_y = offset_y_ + scale_y_ * intended_y - scaled_player_.GetHeight() / 2; | ||
70 | |||
71 | dc.DrawBitmap(scaled_player_, real_x, real_y); | ||
72 | } | ||
73 | |||
53 | event.Skip(); | 74 | event.Skip(); |
54 | } | 75 | } |
55 | 76 | ||
@@ -91,6 +112,17 @@ void TrackerPanel::Redraw() { | |||
91 | map_image_.Scale(final_width, final_height, wxIMAGE_QUALITY_NORMAL) | 112 | map_image_.Scale(final_width, final_height, wxIMAGE_QUALITY_NORMAL) |
92 | .Size(panel_size, {final_x, final_y}, 0, 0, 0)); | 113 | .Size(panel_size, {final_x, final_y}, 0, 0, 0)); |
93 | 114 | ||
115 | offset_x_ = final_x; | ||
116 | offset_y_ = final_y; | ||
117 | scale_x_ = static_cast<double>(final_width) / image_size.GetWidth(); | ||
118 | scale_y_ = static_cast<double>(final_height) / image_size.GetHeight(); | ||
119 | |||
120 | int player_width = PLAYER_SIZE * scale_x_; | ||
121 | int player_height = PLAYER_SIZE * scale_y_; | ||
122 | scaled_player_ = | ||
123 | wxBitmap(player_image_.Scale(player_width > 0 ? player_width : 1, | ||
124 | player_height > 0 ? player_height : 1)); | ||
125 | |||
94 | wxMemoryDC dc; | 126 | wxMemoryDC dc; |
95 | dc.SelectObject(rendered_); | 127 | dc.SelectObject(rendered_); |
96 | 128 | ||
diff --git a/src/tracker_panel.h b/src/tracker_panel.h index cb4f082..b26d971 100644 --- a/src/tracker_panel.h +++ b/src/tracker_panel.h | |||
@@ -32,7 +32,14 @@ class TrackerPanel : public wxPanel { | |||
32 | void Redraw(); | 32 | void Redraw(); |
33 | 33 | ||
34 | wxImage map_image_; | 34 | wxImage map_image_; |
35 | wxImage player_image_; | ||
35 | wxBitmap rendered_; | 36 | wxBitmap rendered_; |
37 | wxBitmap scaled_player_; | ||
38 | |||
39 | int offset_x_ = 0; | ||
40 | int offset_y_ = 0; | ||
41 | double scale_x_ = 0; | ||
42 | double scale_y_ = 0; | ||
36 | 43 | ||
37 | std::vector<AreaIndicator> areas_; | 44 | std::vector<AreaIndicator> areas_; |
38 | }; | 45 | }; |