From 738d970d26794db8bb3dcf459c4a787b624910ba Mon Sep 17 00:00:00 2001 From: art0007i Date: Tue, 24 Sep 2024 15:11:32 +0200 Subject: make paintings 1 directional and add "arrows" the "arrows" are circles because I couldn't figure out how to use the DrawPolygon function... --- src/game_data.cpp | 17 ++++++++++++ src/game_data.h | 6 +++- src/network_set.cpp | 29 ++++++++++++------- src/network_set.h | 16 ++++++++--- src/subway_map.cpp | 80 +++++++++++++++++++++++++++++++++++++++-------------- 5 files changed, 113 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/game_data.cpp b/src/game_data.cpp index c39e239..7b805df 100644 --- a/src/game_data.cpp +++ b/src/game_data.cpp @@ -681,6 +681,18 @@ struct GameData { } } + if (subway_it["entrances"]) { + for (const auto &entrance_it : subway_it["entrances"]) { + subway_item.entrances.push_back(entrance_it.as()); + } + } + + if (subway_it["exits"]) { + for (const auto &exit_it : subway_it["exits"]) { + subway_item.exits.push_back(exit_it.as()); + } + } + if (subway_it["sunwarp"]) { SubwaySunwarp sunwarp; sunwarp.dots = subway_it["sunwarp"]["dots"].as(); @@ -792,6 +804,11 @@ GameData &GetState() { } // namespace +bool SubwayItem::HasWarps() const { + return !(this->tags.empty() && this->entrances.empty() && + this->exits.empty()); +} + bool SubwaySunwarp::operator<(const SubwaySunwarp &rhs) const { return std::tie(dots, type) < std::tie(rhs.dots, rhs.type); } diff --git a/src/game_data.h b/src/game_data.h index 3179365..1f6d247 100644 --- a/src/game_data.h +++ b/src/game_data.h @@ -148,9 +148,13 @@ struct SubwayItem { int y; std::optional door; std::vector paintings; - std::vector tags; + std::vector tags; // 2-way teleports + std::vector entrances; // teleport entrances + std::vector exits; // teleport exits std::optional sunwarp; std::optional special; + + bool HasWarps() const; }; const std::vector& GD_GetMapAreas(); diff --git a/src/network_set.cpp b/src/network_set.cpp index 2a9e12c..c7639ad 100644 --- a/src/network_set.cpp +++ b/src/network_set.cpp @@ -4,9 +4,8 @@ void NetworkSet::Clear() { network_by_item_.clear(); } -void NetworkSet::AddLink(int id1, int id2) { - if (id2 > id1) { - // Make sure id1 < id2 +void NetworkSet::AddLink(int id1, int id2, bool two_way) { + if (two_way && id2 > id1) { std::swap(id1, id2); } @@ -17,13 +16,14 @@ void NetworkSet::AddLink(int id1, int id2) { network_by_item_[id2] = {}; } - network_by_item_[id1].insert({id1, id2}); - network_by_item_[id2].insert({id1, id2}); + NetworkNode node = {id1, id2, two_way}; + + network_by_item_[id1].insert(node); + network_by_item_[id2].insert(node); } -void NetworkSet::AddLinkToNetwork(int network_id, int id1, int id2) { - if (id2 > id1) { - // Make sure id1 < id2 +void NetworkSet::AddLinkToNetwork(int network_id, int id1, int id2, bool two_way) { + if (two_way && id2 > id1) { std::swap(id1, id2); } @@ -31,13 +31,22 @@ void NetworkSet::AddLinkToNetwork(int network_id, int id1, int id2) { network_by_item_[network_id] = {}; } - network_by_item_[network_id].insert({id1, id2}); + NetworkNode node = {id1, id2, two_way}; + + network_by_item_[network_id].insert(node); } bool NetworkSet::IsItemInNetwork(int id) const { return network_by_item_.count(id); } -const std::set>& NetworkSet::GetNetworkGraph(int id) const { +const std::set& NetworkSet::GetNetworkGraph(int id) const { return network_by_item_.at(id); } + +bool NetworkNode::operator<(const NetworkNode& rhs) const { + if (entry != rhs.entry) return entry < rhs.entry; + if (exit != rhs.exit) return exit < rhs.exit; + if (two_way != rhs.two_way) return two_way < rhs.two_way; + return false; +} \ No newline at end of file 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 @@ #include #include +struct NetworkNode { + int entry; + int exit; + bool two_way; + + bool operator<(const NetworkNode& rhs) const; +}; + class NetworkSet { public: void Clear(); - void AddLink(int id1, int id2); + void AddLink(int id1, int id2, bool two_way); - void AddLinkToNetwork(int network_id, int id1, int id2); + void AddLinkToNetwork(int network_id, int id1, int id2, bool two_way); bool IsItemInNetwork(int id) const; - const std::set>& GetNetworkGraph(int id) const; + const std::set& GetNetworkGraph(int id) const; private: - std::map>> network_by_item_; + std::map> network_by_item_; }; #endif /* end of include guard: NETWORK_SET_H_3036B8E3 */ diff --git a/src/subway_map.cpp b/src/subway_map.cpp index 5b3ff5f..44f754f 100644 --- a/src/subway_map.cpp +++ b/src/subway_map.cpp @@ -91,10 +91,12 @@ void SubwayMap::OnConnect() { networks_.Clear(); std::map> tagged; + std::map> entrances; + std::map> exits; for (const SubwayItem &subway_item : GD_GetSubwayItems()) { if (AP_HasEarlyColorHallways() && subway_item.special == "starting_room_paintings") { - tagged["early_ch"].push_back(subway_item.id); + entrances["early_ch"].push_back(subway_item.id); } if (AP_IsPaintingShuffle() && !subway_item.paintings.empty()) { @@ -104,17 +106,33 @@ void SubwayMap::OnConnect() { for (const std::string &tag : subway_item.tags) { tagged[tag].push_back(subway_item.id); } + for (const std::string &tag : subway_item.entrances) { + entrances[tag].push_back(subway_item.id); + } + for (const std::string &tag : subway_item.exits) { + exits[tag].push_back(subway_item.id); + } - if (!AP_IsSunwarpShuffle() && subway_item.sunwarp && - subway_item.sunwarp->type != SubwaySunwarpType::kFinal) { + if (!AP_IsSunwarpShuffle() && subway_item.sunwarp) { std::string tag = fmt::format("sunwarp{}", subway_item.sunwarp->dots); - tagged[tag].push_back(subway_item.id); + switch (subway_item.sunwarp->type) { + case SubwaySunwarpType::kEnter: + entrances[tag].push_back(subway_item.id); + break; + case SubwaySunwarpType::kExit: + exits[tag].push_back(subway_item.id); + break; + default: + break; + } } - if (!AP_IsPilgrimageEnabled() && - (subway_item.special == "sun_painting" || - subway_item.special == "sun_painting_exit")) { - tagged["sun_painting"].push_back(subway_item.id); + if (!AP_IsPilgrimageEnabled()) { + if (subway_item.special == "sun_painting") { + entrances["sun_painting"].push_back(subway_item.id); + } else if (subway_item.special == "sun_painting_exit") { + exits["sun_painting"].push_back(subway_item.id); + } } } @@ -143,13 +161,14 @@ void SubwayMap::OnConnect() { toWarp.type = SubwaySunwarpType::kExit; } - tagged[tag].push_back(GD_GetSubwayItemForSunwarp(fromWarp)); - tagged[tag].push_back(GD_GetSubwayItemForSunwarp(toWarp)); - + entrances[tag].push_back(GD_GetSubwayItemForSunwarp(fromWarp)); + exits[tag].push_back(GD_GetSubwayItemForSunwarp(toWarp)); + networks_.AddLinkToNetwork( final_sunwarp_item, GD_GetSubwayItemForSunwarp(fromWarp), mapping.dots == 6 ? final_sunwarp_item - : GD_GetSubwayItemForSunwarp(toWarp)); + : GD_GetSubwayItemForSunwarp(toWarp), + false); } } @@ -159,7 +178,17 @@ void SubwayMap::OnConnect() { tag_it1++) { for (auto tag_it2 = std::next(tag_it1); tag_it2 != items.end(); tag_it2++) { - networks_.AddLink(*tag_it1, *tag_it2); + // two links because tags are bi-directional + networks_.AddLink(*tag_it1, *tag_it2, true); + } + } + } + + for (const auto &[tag, items] : entrances) { + if (!exits.contains(tag)) continue; + for (auto exit : exits[tag]) { + for (auto entrance : items) { + networks_.AddLink(entrance, exit, false); } } } @@ -179,7 +208,7 @@ void SubwayMap::UpdateIndicators() { AP_GetPaintingMapping().at(painting_id)); if (from_id && to_id) { - networks_.AddLink(*from_id, *to_id); + networks_.AddLink(*from_id, *to_id, false); } } } @@ -192,7 +221,7 @@ void SubwayMap::UpdateIndicators() { void SubwayMap::UpdateSunwarp(SubwaySunwarp from_sunwarp, SubwaySunwarp to_sunwarp) { networks_.AddLink(GD_GetSubwayItemForSunwarp(from_sunwarp), - GD_GetSubwayItemForSunwarp(to_sunwarp)); + GD_GetSubwayItemForSunwarp(to_sunwarp), false); } void SubwayMap::Zoom(bool in) { @@ -358,10 +387,9 @@ void SubwayMap::OnPaint(wxPaintEvent &event) { if (networks_.IsItemInNetwork(*hovered_item_)) { dc.SetBrush(*wxTRANSPARENT_BRUSH); - for (const auto &[item_id1, item_id2] : - networks_.GetNetworkGraph(*hovered_item_)) { - const SubwayItem &item1 = GD_GetSubwayItem(item_id1); - const SubwayItem &item2 = GD_GetSubwayItem(item_id2); + for (const auto node : networks_.GetNetworkGraph(*hovered_item_)) { + const SubwayItem &item1 = GD_GetSubwayItem(node.entry); + const SubwayItem &item2 = GD_GetSubwayItem(node.exit); wxPoint item1_pos = MapPosToRenderPos( {item1.x + AREA_ACTUAL_SIZE / 2, item1.y + AREA_ACTUAL_SIZE / 2}); @@ -381,6 +409,12 @@ void SubwayMap::OnPaint(wxPaintEvent &event) { dc.DrawLine(item1_pos, item2_pos); dc.SetPen(*wxThePenList->FindOrCreatePen(*wxCYAN, 2)); dc.DrawLine(item1_pos, item2_pos); + if (!node.two_way) { + dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, 2)); + dc.SetBrush(*wxCYAN_BRUSH); + dc.DrawCircle(item2_pos, 4); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + } } else { int ellipse_x; int ellipse_y; @@ -423,6 +457,12 @@ void SubwayMap::OnPaint(wxPaintEvent &event) { dc.SetPen(*wxThePenList->FindOrCreatePen(*wxCYAN, 2)); dc.DrawEllipticArc(ellipse_x, ellipse_y, halfwidth * 2, halfheight * 2, start, end); + if (!node.two_way) { + dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, 2)); + dc.SetBrush(*wxCYAN_BRUSH); + dc.DrawCircle(item2_pos, 4); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + } } } } @@ -622,7 +662,7 @@ void SubwayMap::Redraw() { } } } - } else if (!subway_item.tags.empty()) { + } else if (subway_item.HasWarps()) { draw_type = ItemDrawType::kOwl; } } else if (subway_door) { -- cgit 1.4.1