diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/game_data.cpp | 17 | ||||
-rw-r--r-- | src/game_data.h | 6 | ||||
-rw-r--r-- | src/network_set.cpp | 29 | ||||
-rw-r--r-- | src/network_set.h | 16 | ||||
-rw-r--r-- | src/subway_map.cpp | 83 | ||||
-rw-r--r-- | src/tracker_frame.cpp | 1 | ||||
-rw-r--r-- | src/version.h | 2 |
7 files changed, 117 insertions, 37 deletions
diff --git a/src/game_data.cpp b/src/game_data.cpp index 4d448d3..828808f 100644 --- a/src/game_data.cpp +++ b/src/game_data.cpp | |||
@@ -756,6 +756,18 @@ struct GameData { | |||
756 | } | 756 | } |
757 | } | 757 | } |
758 | 758 | ||
759 | if (subway_it["entrances"]) { | ||
760 | for (const auto &entrance_it : subway_it["entrances"]) { | ||
761 | subway_item.entrances.push_back(entrance_it.as<std::string>()); | ||
762 | } | ||
763 | } | ||
764 | |||
765 | if (subway_it["exits"]) { | ||
766 | for (const auto &exit_it : subway_it["exits"]) { | ||
767 | subway_item.exits.push_back(exit_it.as<std::string>()); | ||
768 | } | ||
769 | } | ||
770 | |||
759 | if (subway_it["sunwarp"]) { | 771 | if (subway_it["sunwarp"]) { |
760 | SubwaySunwarp sunwarp; | 772 | SubwaySunwarp sunwarp; |
761 | sunwarp.dots = subway_it["sunwarp"]["dots"].as<int>(); | 773 | sunwarp.dots = subway_it["sunwarp"]["dots"].as<int>(); |
@@ -879,6 +891,11 @@ GameData &GetState() { | |||
879 | 891 | ||
880 | } // namespace | 892 | } // namespace |
881 | 893 | ||
894 | bool SubwayItem::HasWarps() const { | ||
895 | return !(this->tags.empty() && this->entrances.empty() && | ||
896 | this->exits.empty()); | ||
897 | } | ||
898 | |||
882 | bool SubwaySunwarp::operator<(const SubwaySunwarp &rhs) const { | 899 | bool SubwaySunwarp::operator<(const SubwaySunwarp &rhs) const { |
883 | return std::tie(dots, type) < std::tie(rhs.dots, rhs.type); | 900 | return std::tie(dots, type) < std::tie(rhs.dots, rhs.type); |
884 | } | 901 | } |
diff --git a/src/game_data.h b/src/game_data.h index 9b6f3b2..b00bac9 100644 --- a/src/game_data.h +++ b/src/game_data.h | |||
@@ -155,9 +155,13 @@ struct SubwayItem { | |||
155 | int y; | 155 | int y; |
156 | std::optional<int> door; | 156 | std::optional<int> door; |
157 | std::vector<std::string> paintings; | 157 | std::vector<std::string> paintings; |
158 | std::vector<std::string> tags; | 158 | std::vector<std::string> tags; // 2-way teleports |
159 | std::vector<std::string> entrances; // teleport entrances | ||
160 | std::vector<std::string> exits; // teleport exits | ||
159 | std::optional<SubwaySunwarp> sunwarp; | 161 | std::optional<SubwaySunwarp> sunwarp; |
160 | std::optional<std::string> special; | 162 | std::optional<std::string> special; |
163 | |||
164 | bool HasWarps() const; | ||
161 | }; | 165 | }; |
162 | 166 | ||
163 | const std::vector<MapArea>& GD_GetMapAreas(); | 167 | const std::vector<MapArea>& GD_GetMapAreas(); |
diff --git a/src/network_set.cpp b/src/network_set.cpp index 2a9e12c..45911e3 100644 --- a/src/network_set.cpp +++ b/src/network_set.cpp | |||
@@ -4,9 +4,8 @@ void NetworkSet::Clear() { | |||
4 | network_by_item_.clear(); | 4 | network_by_item_.clear(); |
5 | } | 5 | } |
6 | 6 | ||
7 | void NetworkSet::AddLink(int id1, int id2) { | 7 | void NetworkSet::AddLink(int id1, int id2, bool two_way) { |
8 | if (id2 > id1) { | 8 | if (two_way && id2 > id1) { |
9 | // Make sure id1 < id2 | ||
10 | std::swap(id1, id2); | 9 | std::swap(id1, id2); |
11 | } | 10 | } |
12 | 11 | ||
@@ -17,13 +16,14 @@ void NetworkSet::AddLink(int id1, int id2) { | |||
17 | network_by_item_[id2] = {}; | 16 | network_by_item_[id2] = {}; |
18 | } | 17 | } |
19 | 18 | ||
20 | network_by_item_[id1].insert({id1, id2}); | 19 | NetworkNode node = {id1, id2, two_way}; |
21 | network_by_item_[id2].insert({id1, id2}); | 20 | |
21 | network_by_item_[id1].insert(node); | ||
22 | network_by_item_[id2].insert(node); | ||
22 | } | 23 | } |
23 | 24 | ||
24 | void NetworkSet::AddLinkToNetwork(int network_id, int id1, int id2) { | 25 | void NetworkSet::AddLinkToNetwork(int network_id, int id1, int id2, bool two_way) { |
25 | if (id2 > id1) { | 26 | if (two_way && id2 > id1) { |
26 | // Make sure id1 < id2 | ||
27 | std::swap(id1, id2); | 27 | std::swap(id1, id2); |
28 | } | 28 | } |
29 | 29 | ||
@@ -31,13 +31,22 @@ void NetworkSet::AddLinkToNetwork(int network_id, int id1, int id2) { | |||
31 | network_by_item_[network_id] = {}; | 31 | network_by_item_[network_id] = {}; |
32 | } | 32 | } |
33 | 33 | ||
34 | network_by_item_[network_id].insert({id1, id2}); | 34 | NetworkNode node = {id1, id2, two_way}; |
35 | |||
36 | network_by_item_[network_id].insert(node); | ||
35 | } | 37 | } |
36 | 38 | ||
37 | bool NetworkSet::IsItemInNetwork(int id) const { | 39 | bool NetworkSet::IsItemInNetwork(int id) const { |
38 | return network_by_item_.count(id); | 40 | return network_by_item_.count(id); |
39 | } | 41 | } |
40 | 42 | ||
41 | const std::set<std::pair<int, int>>& NetworkSet::GetNetworkGraph(int id) const { | 43 | const std::set<NetworkNode>& NetworkSet::GetNetworkGraph(int id) const { |
42 | return network_by_item_.at(id); | 44 | return network_by_item_.at(id); |
43 | } | 45 | } |
46 | |||
47 | bool NetworkNode::operator<(const NetworkNode& rhs) const { | ||
48 | if (entry != rhs.entry) return entry < rhs.entry; | ||
49 | if (exit != rhs.exit) return exit < rhs.exit; | ||
50 | if (two_way != rhs.two_way) return two_way < rhs.two_way; | ||
51 | return false; | ||
52 | } | ||
diff --git a/src/network_set.h b/src/network_set.h index cec3f39..0f72052 100644 --- a/src/network_set.h +++ b/src/network_set.h | |||
@@ -7,21 +7,29 @@ | |||
7 | #include <utility> | 7 | #include <utility> |
8 | #include <vector> | 8 | #include <vector> |
9 | 9 | ||
10 | struct NetworkNode { | ||
11 | int entry; | ||
12 | int exit; | ||
13 | bool two_way; | ||
14 | |||
15 | bool operator<(const NetworkNode& rhs) const; | ||
16 | }; | ||
17 | |||
10 | class NetworkSet { | 18 | class NetworkSet { |
11 | public: | 19 | public: |
12 | void Clear(); | 20 | void Clear(); |
13 | 21 | ||
14 | void AddLink(int id1, int id2); | 22 | void AddLink(int id1, int id2, bool two_way); |
15 | 23 | ||
16 | void AddLinkToNetwork(int network_id, int id1, int id2); | 24 | void AddLinkToNetwork(int network_id, int id1, int id2, bool two_way); |
17 | 25 | ||
18 | bool IsItemInNetwork(int id) const; | 26 | bool IsItemInNetwork(int id) const; |
19 | 27 | ||
20 | const std::set<std::pair<int, int>>& GetNetworkGraph(int id) const; | 28 | const std::set<NetworkNode>& GetNetworkGraph(int id) const; |
21 | 29 | ||
22 | private: | 30 | private: |
23 | 31 | ||
24 | std::map<int, std::set<std::pair<int, int>>> network_by_item_; | 32 | std::map<int, std::set<NetworkNode>> network_by_item_; |
25 | }; | 33 | }; |
26 | 34 | ||
27 | #endif /* end of include guard: NETWORK_SET_H_3036B8E3 */ | 35 | #endif /* end of include guard: NETWORK_SET_H_3036B8E3 */ |
diff --git a/src/subway_map.cpp b/src/subway_map.cpp index 5b3ff5f..f896693 100644 --- a/src/subway_map.cpp +++ b/src/subway_map.cpp | |||
@@ -91,10 +91,12 @@ void SubwayMap::OnConnect() { | |||
91 | networks_.Clear(); | 91 | networks_.Clear(); |
92 | 92 | ||
93 | std::map<std::string, std::vector<int>> tagged; | 93 | std::map<std::string, std::vector<int>> tagged; |
94 | std::map<std::string, std::vector<int>> entrances; | ||
95 | std::map<std::string, std::vector<int>> exits; | ||
94 | for (const SubwayItem &subway_item : GD_GetSubwayItems()) { | 96 | for (const SubwayItem &subway_item : GD_GetSubwayItems()) { |
95 | if (AP_HasEarlyColorHallways() && | 97 | if (AP_HasEarlyColorHallways() && |
96 | subway_item.special == "starting_room_paintings") { | 98 | subway_item.special == "starting_room_paintings") { |
97 | tagged["early_ch"].push_back(subway_item.id); | 99 | entrances["early_ch"].push_back(subway_item.id); |
98 | } | 100 | } |
99 | 101 | ||
100 | if (AP_IsPaintingShuffle() && !subway_item.paintings.empty()) { | 102 | if (AP_IsPaintingShuffle() && !subway_item.paintings.empty()) { |
@@ -104,17 +106,33 @@ void SubwayMap::OnConnect() { | |||
104 | for (const std::string &tag : subway_item.tags) { | 106 | for (const std::string &tag : subway_item.tags) { |
105 | tagged[tag].push_back(subway_item.id); | 107 | tagged[tag].push_back(subway_item.id); |
106 | } | 108 | } |
109 | for (const std::string &tag : subway_item.entrances) { | ||
110 | entrances[tag].push_back(subway_item.id); | ||
111 | } | ||
112 | for (const std::string &tag : subway_item.exits) { | ||
113 | exits[tag].push_back(subway_item.id); | ||
114 | } | ||
107 | 115 | ||
108 | if (!AP_IsSunwarpShuffle() && subway_item.sunwarp && | 116 | if (!AP_IsSunwarpShuffle() && subway_item.sunwarp) { |
109 | subway_item.sunwarp->type != SubwaySunwarpType::kFinal) { | ||
110 | std::string tag = fmt::format("sunwarp{}", subway_item.sunwarp->dots); | 117 | std::string tag = fmt::format("sunwarp{}", subway_item.sunwarp->dots); |
111 | tagged[tag].push_back(subway_item.id); | 118 | switch (subway_item.sunwarp->type) { |
119 | case SubwaySunwarpType::kEnter: | ||
120 | entrances[tag].push_back(subway_item.id); | ||
121 | break; | ||
122 | case SubwaySunwarpType::kExit: | ||
123 | exits[tag].push_back(subway_item.id); | ||
124 | break; | ||
125 | default: | ||
126 | break; | ||
127 | } | ||
112 | } | 128 | } |
113 | 129 | ||
114 | if (!AP_IsPilgrimageEnabled() && | 130 | if (!AP_IsPilgrimageEnabled()) { |
115 | (subway_item.special == "sun_painting" || | 131 | if (subway_item.special == "sun_painting") { |
116 | subway_item.special == "sun_painting_exit")) { | 132 | entrances["sun_painting"].push_back(subway_item.id); |
117 | tagged["sun_painting"].push_back(subway_item.id); | 133 | } else if (subway_item.special == "sun_painting_exit") { |
134 | exits["sun_painting"].push_back(subway_item.id); | ||
135 | } | ||
118 | } | 136 | } |
119 | } | 137 | } |
120 | 138 | ||
@@ -143,13 +161,14 @@ void SubwayMap::OnConnect() { | |||
143 | toWarp.type = SubwaySunwarpType::kExit; | 161 | toWarp.type = SubwaySunwarpType::kExit; |
144 | } | 162 | } |
145 | 163 | ||
146 | tagged[tag].push_back(GD_GetSubwayItemForSunwarp(fromWarp)); | 164 | entrances[tag].push_back(GD_GetSubwayItemForSunwarp(fromWarp)); |
147 | tagged[tag].push_back(GD_GetSubwayItemForSunwarp(toWarp)); | 165 | exits[tag].push_back(GD_GetSubwayItemForSunwarp(toWarp)); |
148 | 166 | ||
149 | networks_.AddLinkToNetwork( | 167 | networks_.AddLinkToNetwork( |
150 | final_sunwarp_item, GD_GetSubwayItemForSunwarp(fromWarp), | 168 | final_sunwarp_item, GD_GetSubwayItemForSunwarp(fromWarp), |
151 | mapping.dots == 6 ? final_sunwarp_item | 169 | mapping.dots == 6 ? final_sunwarp_item |
152 | : GD_GetSubwayItemForSunwarp(toWarp)); | 170 | : GD_GetSubwayItemForSunwarp(toWarp), |
171 | false); | ||
153 | } | 172 | } |
154 | } | 173 | } |
155 | 174 | ||
@@ -159,7 +178,17 @@ void SubwayMap::OnConnect() { | |||
159 | tag_it1++) { | 178 | tag_it1++) { |
160 | for (auto tag_it2 = std::next(tag_it1); tag_it2 != items.end(); | 179 | for (auto tag_it2 = std::next(tag_it1); tag_it2 != items.end(); |
161 | tag_it2++) { | 180 | tag_it2++) { |
162 | networks_.AddLink(*tag_it1, *tag_it2); | 181 | // two links because tags are bi-directional |
182 | networks_.AddLink(*tag_it1, *tag_it2, true); | ||
183 | } | ||
184 | } | ||
185 | } | ||
186 | |||
187 | for (const auto &[tag, items] : entrances) { | ||
188 | if (!exits.contains(tag)) continue; | ||
189 | for (auto exit : exits[tag]) { | ||
190 | for (auto entrance : items) { | ||
191 | networks_.AddLink(entrance, exit, false); | ||
163 | } | 192 | } |
164 | } | 193 | } |
165 | } | 194 | } |
@@ -179,7 +208,7 @@ void SubwayMap::UpdateIndicators() { | |||
179 | AP_GetPaintingMapping().at(painting_id)); | 208 | AP_GetPaintingMapping().at(painting_id)); |
180 | 209 | ||
181 | if (from_id && to_id) { | 210 | if (from_id && to_id) { |
182 | networks_.AddLink(*from_id, *to_id); | 211 | networks_.AddLink(*from_id, *to_id, false); |
183 | } | 212 | } |
184 | } | 213 | } |
185 | } | 214 | } |
@@ -192,7 +221,7 @@ void SubwayMap::UpdateIndicators() { | |||
192 | void SubwayMap::UpdateSunwarp(SubwaySunwarp from_sunwarp, | 221 | void SubwayMap::UpdateSunwarp(SubwaySunwarp from_sunwarp, |
193 | SubwaySunwarp to_sunwarp) { | 222 | SubwaySunwarp to_sunwarp) { |
194 | networks_.AddLink(GD_GetSubwayItemForSunwarp(from_sunwarp), | 223 | networks_.AddLink(GD_GetSubwayItemForSunwarp(from_sunwarp), |
195 | GD_GetSubwayItemForSunwarp(to_sunwarp)); | 224 | GD_GetSubwayItemForSunwarp(to_sunwarp), false); |
196 | } | 225 | } |
197 | 226 | ||
198 | void SubwayMap::Zoom(bool in) { | 227 | void SubwayMap::Zoom(bool in) { |
@@ -358,10 +387,9 @@ void SubwayMap::OnPaint(wxPaintEvent &event) { | |||
358 | if (networks_.IsItemInNetwork(*hovered_item_)) { | 387 | if (networks_.IsItemInNetwork(*hovered_item_)) { |
359 | dc.SetBrush(*wxTRANSPARENT_BRUSH); | 388 | dc.SetBrush(*wxTRANSPARENT_BRUSH); |
360 | 389 | ||
361 | for (const auto &[item_id1, item_id2] : | 390 | for (const auto node : networks_.GetNetworkGraph(*hovered_item_)) { |
362 | networks_.GetNetworkGraph(*hovered_item_)) { | 391 | const SubwayItem &item1 = GD_GetSubwayItem(node.entry); |
363 | const SubwayItem &item1 = GD_GetSubwayItem(item_id1); | 392 | const SubwayItem &item2 = GD_GetSubwayItem(node.exit); |
364 | const SubwayItem &item2 = GD_GetSubwayItem(item_id2); | ||
365 | 393 | ||
366 | wxPoint item1_pos = MapPosToRenderPos( | 394 | wxPoint item1_pos = MapPosToRenderPos( |
367 | {item1.x + AREA_ACTUAL_SIZE / 2, item1.y + AREA_ACTUAL_SIZE / 2}); | 395 | {item1.x + AREA_ACTUAL_SIZE / 2, item1.y + AREA_ACTUAL_SIZE / 2}); |
@@ -381,6 +409,12 @@ void SubwayMap::OnPaint(wxPaintEvent &event) { | |||
381 | dc.DrawLine(item1_pos, item2_pos); | 409 | dc.DrawLine(item1_pos, item2_pos); |
382 | dc.SetPen(*wxThePenList->FindOrCreatePen(*wxCYAN, 2)); | 410 | dc.SetPen(*wxThePenList->FindOrCreatePen(*wxCYAN, 2)); |
383 | dc.DrawLine(item1_pos, item2_pos); | 411 | dc.DrawLine(item1_pos, item2_pos); |
412 | if (!node.two_way) { | ||
413 | dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, 2)); | ||
414 | dc.SetBrush(*wxCYAN_BRUSH); | ||
415 | dc.DrawCircle(item2_pos, 4); | ||
416 | dc.SetBrush(*wxTRANSPARENT_BRUSH); | ||
417 | } | ||
384 | } else { | 418 | } else { |
385 | int ellipse_x; | 419 | int ellipse_x; |
386 | int ellipse_y; | 420 | int ellipse_y; |
@@ -423,6 +457,12 @@ void SubwayMap::OnPaint(wxPaintEvent &event) { | |||
423 | dc.SetPen(*wxThePenList->FindOrCreatePen(*wxCYAN, 2)); | 457 | dc.SetPen(*wxThePenList->FindOrCreatePen(*wxCYAN, 2)); |
424 | dc.DrawEllipticArc(ellipse_x, ellipse_y, halfwidth * 2, | 458 | dc.DrawEllipticArc(ellipse_x, ellipse_y, halfwidth * 2, |
425 | halfheight * 2, start, end); | 459 | halfheight * 2, start, end); |
460 | if (!node.two_way) { | ||
461 | dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, 2)); | ||
462 | dc.SetBrush(*wxCYAN_BRUSH); | ||
463 | dc.DrawCircle(item2_pos, 4); | ||
464 | dc.SetBrush(*wxTRANSPARENT_BRUSH); | ||
465 | } | ||
426 | } | 466 | } |
427 | } | 467 | } |
428 | } | 468 | } |
@@ -543,7 +583,8 @@ void SubwayMap::OnClickHelp(wxCommandEvent &event) { | |||
543 | "corner.\nClick on a side of the screen to start panning. It will follow " | 583 | "corner.\nClick on a side of the screen to start panning. It will follow " |
544 | "your mouse. Click again to stop.\nHover over a door to see the " | 584 | "your mouse. Click again to stop.\nHover over a door to see the " |
545 | "requirements to open it.\nHover over a warp or active painting to see " | 585 | "requirements to open it.\nHover over a warp or active painting to see " |
546 | "what it is connected to.\nIn painting shuffle, paintings that have not " | 586 | "what it is connected to.\nFor one-way connections, there will be a " |
587 | "circle at the exit.\nIn painting shuffle, paintings that have not " | ||
547 | "yet been checked will not show their connections.\nA green shaded owl " | 588 | "yet been checked will not show their connections.\nA green shaded owl " |
548 | "means that there is a painting entrance there.\nA red shaded owl means " | 589 | "means that there is a painting entrance there.\nA red shaded owl means " |
549 | "that there are only painting exits there.\nClick on a door or " | 590 | "that there are only painting exits there.\nClick on a door or " |
@@ -622,7 +663,7 @@ void SubwayMap::Redraw() { | |||
622 | } | 663 | } |
623 | } | 664 | } |
624 | } | 665 | } |
625 | } else if (!subway_item.tags.empty()) { | 666 | } else if (subway_item.HasWarps()) { |
626 | draw_type = ItemDrawType::kOwl; | 667 | draw_type = ItemDrawType::kOwl; |
627 | } | 668 | } |
628 | } else if (subway_door) { | 669 | } else if (subway_door) { |
diff --git a/src/tracker_frame.cpp b/src/tracker_frame.cpp index 3b6beda..b9282f5 100644 --- a/src/tracker_frame.cpp +++ b/src/tracker_frame.cpp | |||
@@ -137,6 +137,7 @@ void TrackerFrame::OnAbout(wxCommandEvent &event) { | |||
137 | about_info.SetName("Lingo Archipelago Tracker"); | 137 | about_info.SetName("Lingo Archipelago Tracker"); |
138 | about_info.SetVersion(kTrackerVersion.ToString()); | 138 | about_info.SetVersion(kTrackerVersion.ToString()); |
139 | about_info.AddDeveloper("hatkirby"); | 139 | about_info.AddDeveloper("hatkirby"); |
140 | about_info.AddDeveloper("art0007i"); | ||
140 | about_info.AddArtist("Brenton Wildes"); | 141 | about_info.AddArtist("Brenton Wildes"); |
141 | about_info.AddArtist("kinrah"); | 142 | about_info.AddArtist("kinrah"); |
142 | 143 | ||
diff --git a/src/version.h b/src/version.h index 24c04b4..ec52f44 100644 --- a/src/version.h +++ b/src/version.h | |||
@@ -36,6 +36,6 @@ struct Version { | |||
36 | } | 36 | } |
37 | }; | 37 | }; |
38 | 38 | ||
39 | constexpr const Version kTrackerVersion = Version(0, 11, 1); | 39 | constexpr const Version kTrackerVersion = Version(0, 11, 2); |
40 | 40 | ||
41 | #endif /* end of include guard: VERSION_H_C757E53C */ \ No newline at end of file | 41 | #endif /* end of include guard: VERSION_H_C757E53C */ \ No newline at end of file |