about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md34
-rw-r--r--VERSION2
-rw-r--r--assets/player.pngbin0 -> 1457 bytes
-rw-r--r--src/ap_state.cpp60
-rw-r--r--src/ap_state.h4
-rw-r--r--src/game_data.cpp4
-rw-r--r--src/tracker_panel.cpp32
-rw-r--r--src/tracker_panel.h7
-rw-r--r--src/version.h2
9 files changed, 121 insertions, 24 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 0bbde7d..8a2eff1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md
@@ -1,5 +1,39 @@
1# lingo-ap-tracker Releases 1# lingo-ap-tracker Releases
2 2
3## v0.8.0 - 2024-04-03
4
5- Added ability to display the player's position on the map (requires v2.1.0 of
6 the client).
7
8Download:
9[lingo-ap-tracker-v0.8.0-win64.zip](https://files.fourisland.com/releases/lingo-ap-tracker/lingo-ap-tracker-v0.8.0-win64.zip)<br/>
10Source: [v0.8.0](https://code.fourisland.com/lingo-ap-tracker/tag/?h=v0.8.0)
11
12## v0.7.1 - 2024-04-01
13
14- Fixed an issue where door groups in simple doors mode would be ignored.
15
16Download:
17[lingo-ap-tracker-v0.7.1-win64.zip](https://files.fourisland.com/releases/lingo-ap-tracker/lingo-ap-tracker-v0.7.1-win64.zip)<br/>
18Source: [v0.7.1](https://code.fourisland.com/lingo-ap-tracker/tag/?h=v0.7.1)
19
20## v0.7.0 - 2024-04-01
21
22- Compatibility update for Archipelago 0.4.5
23
24Download:
25[lingo-ap-tracker-v0.7.0-win64.zip](https://files.fourisland.com/releases/lingo-ap-tracker/lingo-ap-tracker-v0.7.0-win64.zip)<br/>
26Source: [v0.7.0](https://code.fourisland.com/lingo-ap-tracker/tag/?h=v0.7.0)
27
28## Initial Testing: v0.6.6 - 2024-03-07
29
30- The last five connections are now saved in a list so that you can easily
31 switch between concurrent multiworlds.
32
33Download:
34[lingo-ap-tracker-v0.6.6-win64.zip](https://files.fourisland.com/releases/lingo-ap-tracker/lingo-ap-tracker-v0.6.6-win64.zip)<br/>
35Source: [v0.6.6](https://code.fourisland.com/lingo-ap-tracker/tag/?h=v0.6.6)
36
3## Initial Testing: v0.6.5 - 2024-02-18 37## Initial Testing: v0.6.5 - 2024-02-18
4 38
5- Victory condition will now be checked off when the player reaches the goal. 39- Victory condition will now be checked off when the player reaches the goal.
diff --git a/VERSION b/VERSION index bc21b44..4ea5caf 100644 --- a/VERSION +++ b/VERSION
@@ -1 +1 @@
v0.6.5 \ No newline at end of file v0.8.0 \ No newline at end of file
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 1ac6575..aeed914 100644 --- a/src/ap_state.cpp +++ b/src/ap_state.cpp
@@ -27,7 +27,7 @@
27 27
28constexpr int AP_MAJOR = 0; 28constexpr int AP_MAJOR = 0;
29constexpr int AP_MINOR = 4; 29constexpr int AP_MINOR = 4;
30constexpr int AP_REVISION = 0; 30constexpr int AP_REVISION = 5;
31 31
32constexpr const char* CERT_STORE_PATH = "cacert.pem"; 32constexpr const char* CERT_STORE_PATH = "cacert.pem";
33constexpr int ITEM_HANDLING = 7; // <- all 33constexpr int ITEM_HANDLING = 7; // <- all
@@ -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;
@@ -101,6 +102,8 @@ struct APState {
101 } 102 }
102 } 103 }
103 104
105 tracked_data_storage_keys.push_back("PlayerPos");
106
104 initialized = true; 107 initialized = true;
105 } 108 }
106 109
@@ -128,6 +131,7 @@ struct APState {
128 inventory.clear(); 131 inventory.clear();
129 checked_locations.clear(); 132 checked_locations.clear();
130 data_storage.clear(); 133 data_storage.clear();
134 player_pos = std::nullopt;
131 victory_data_storage_key.clear(); 135 victory_data_storage_key.clear();
132 door_shuffle_mode = kNO_DOORS; 136 door_shuffle_mode = kNO_DOORS;
133 color_shuffle = false; 137 color_shuffle = false;
@@ -199,15 +203,7 @@ struct APState {
199 apclient->set_retrieved_handler( 203 apclient->set_retrieved_handler(
200 [this](const std::map<std::string, nlohmann::json>& data) { 204 [this](const std::map<std::string, nlohmann::json>& data) {
201 for (const auto& [key, value] : data) { 205 for (const auto& [key, value] : data) {
202 if (value.is_boolean()) { 206 HandleDataStorage(key, value);
203 data_storage[key] = value.get<bool>();
204 TrackerLog("Data storage " + key + " retrieved as " +
205 (value.get<bool>() ? "true" : "false"));
206 } else if (value.is_number()) {
207 data_storage[key] = value.get<int>();
208 TrackerLog("Data storage " + key + " retrieved as " +
209 std::to_string(value.get<int>()));
210 }
211 } 207 }
212 208
213 RefreshTracker(); 209 RefreshTracker();
@@ -216,16 +212,7 @@ struct APState {
216 apclient->set_set_reply_handler([this](const std::string& key, 212 apclient->set_set_reply_handler([this](const std::string& key,
217 const nlohmann::json& value, 213 const nlohmann::json& value,
218 const nlohmann::json&) { 214 const nlohmann::json&) {
219 if (value.is_boolean()) { 215 HandleDataStorage(key, value);
220 data_storage[key] = value.get<bool>();
221 TrackerLog("Data storage " + key + " retrieved as " +
222 (value.get<bool>() ? "true" : "false"));
223 } else if (value.is_number()) {
224 data_storage[key] = value.get<int>();
225 TrackerLog("Data storage " + key + " retrieved as " +
226 std::to_string(value.get<int>()));
227 }
228
229 RefreshTracker(); 216 RefreshTracker();
230 }); 217 });
231 218
@@ -369,6 +356,35 @@ struct APState {
369 } 356 }
370 } 357 }
371 358
359 void HandleDataStorage(const std::string& key, const nlohmann::json& value) {
360 if (value.is_boolean()) {
361 data_storage[key] = value.get<bool>();
362 TrackerLog("Data storage " + key + " retrieved as " +
363 (value.get<bool>() ? "true" : "false"));
364 } else if (value.is_number()) {
365 data_storage[key] = value.get<int>();
366 TrackerLog("Data storage " + key + " retrieved as " +
367 std::to_string(value.get<int>()));
368 } else if (value.is_object()) {
369 if (key.ends_with("PlayerPos")) {
370 auto map_value = value.get<std::map<std::string, int>>();
371 player_pos = std::tuple<int, int>(map_value["x"], map_value["z"]);
372 } else {
373 data_storage[key] = value.get<std::map<std::string, int>>();
374 }
375
376 TrackerLog("Data storage " + key + " retrieved as dictionary");
377 } else if (value.is_null()) {
378 if (key.ends_with("PlayerPos")) {
379 player_pos = std::nullopt;
380 } else {
381 data_storage.erase(key);
382 }
383
384 TrackerLog("Data storage " + key + " retrieved as null");
385 }
386 }
387
372 bool HasCheckedGameLocation(int location_id) { 388 bool HasCheckedGameLocation(int location_id) {
373 return checked_locations.count(location_id); 389 return checked_locations.count(location_id);
374 } 390 }
@@ -498,3 +514,7 @@ const std::map<int, SunwarpMapping>& AP_GetSunwarpMapping() {
498} 514}
499 515
500bool AP_HasReachedGoal() { return GetState().HasReachedGoal(); } 516bool AP_HasReachedGoal() { return GetState().HasReachedGoal(); }
517
518std::optional<std::tuple<int, int>> AP_GetPlayerPosition() {
519 return GetState().player_pos;
520}
diff --git a/src/ap_state.h b/src/ap_state.h index 36694b2..6667e0d 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
@@ -80,4 +82,6 @@ const std::map<int, SunwarpMapping>& AP_GetSunwarpMapping();
80 82
81bool AP_HasReachedGoal(); 83bool AP_HasReachedGoal();
82 84
85std::optional<std::tuple<int, int>> AP_GetPlayerPosition();
86
83#endif /* end of include guard: AP_STATE_H_664A4180 */ 87#endif /* end of include guard: AP_STATE_H_664A4180 */
diff --git a/src/game_data.cpp b/src/game_data.cpp index d354854..c98f532 100644 --- a/src/game_data.cpp +++ b/src/game_data.cpp
@@ -350,9 +350,9 @@ struct GameData {
350 } 350 }
351 } 351 }
352 352
353 if (door_it.second["group"]) { 353 if (door_it.second["door_group"]) {
354 doors_[door_id].group_name = 354 doors_[door_id].group_name =
355 door_it.second["group"].as<std::string>(); 355 door_it.second["door_group"].as<std::string>();
356 356
357 if (ids_config["door_groups"] && 357 if (ids_config["door_groups"] &&
358 ids_config["door_groups"][doors_[door_id].group_name]) { 358 ids_config["door_groups"][doors_[door_id].group_name]) {
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 @@
10constexpr int AREA_ACTUAL_SIZE = 64; 10constexpr int AREA_ACTUAL_SIZE = 64;
11constexpr int AREA_BORDER_SIZE = 5; 11constexpr int AREA_BORDER_SIZE = 5;
12constexpr int AREA_EFFECTIVE_SIZE = AREA_ACTUAL_SIZE + AREA_BORDER_SIZE * 2; 12constexpr int AREA_EFFECTIVE_SIZE = AREA_ACTUAL_SIZE + AREA_BORDER_SIZE * 2;
13constexpr int PLAYER_SIZE = 96;
13 14
14TrackerPanel::TrackerPanel(wxWindow *parent) : wxPanel(parent, wxID_ANY) { 15TrackerPanel::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 2dc034c..06ec7a0 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};
diff --git a/src/version.h b/src/version.h index 62a4cd1..8c567e9 100644 --- a/src/version.h +++ b/src/version.h
@@ -35,6 +35,6 @@ std::ostream& operator<<(std::ostream& out, const Version& ver) {
35 return out << "v" << ver.major << "." << ver.minor << "." << ver.revision; 35 return out << "v" << ver.major << "." << ver.minor << "." << ver.revision;
36} 36}
37 37
38constexpr const Version kTrackerVersion = Version(0, 6, 5); 38constexpr const Version kTrackerVersion = Version(0, 8, 0);
39 39
40#endif /* end of include guard: VERSION_H_C757E53C */ \ No newline at end of file 40#endif /* end of include guard: VERSION_H_C757E53C */ \ No newline at end of file