23#include <boost/graph/adjacency_list.hpp>
24#include <boost/graph/depth_first_search.hpp>
25#include <boost/graph/dijkstra_shortest_paths.hpp>
26#include <boost/property_map/transform_value_property_map.hpp>
37 if (!To->
GetFlags().HasFlag(requireFlag))
38 return std::numeric_limits<uint16>::max();
41 if (!
sConditionMgr->IsPlayerMeetingCondition(player, condition))
42 return std::numeric_limits<uint16>::max();
48typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, uint32>, boost::property<boost::edge_weight_t, EdgeCost>> Graph;
49typedef boost::property_map<Graph, boost::edge_weight_t>::type WeightMap;
50typedef Graph::vertex_descriptor vertex_descriptor;
51typedef Graph::edge_descriptor edge_descriptor;
52typedef std::pair<vertex_descriptor, vertex_descriptor> edge;
55std::vector<TaxiNodesEntry const*> m_nodesByVertex;
56std::unordered_map<uint32, vertex_descriptor> m_verticesByNode;
60 if (!
DB2Manager::GetUiMapPosition(position.
X, position.
Y, position.
Z, mapId, 0, 0, 0,
UI_MAP_SYSTEM_ADVENTURE,
false, uiMapId, uiMapPosition))
61 DB2Manager::GetUiMapPosition(position.
X, position.
Y, position.
Z, mapId, 0, 0, 0,
UI_MAP_SYSTEM_TAXI,
false, uiMapId, uiMapPosition);
64vertex_descriptor CreateVertexFromFromNodeInfoIfNeeded(
TaxiNodesEntry const* node)
66 auto itr = m_verticesByNode.find(node->
ID);
67 if (itr == m_verticesByNode.end())
69 itr = m_verticesByNode.emplace(node->
ID, m_nodesByVertex.size()).first;
70 m_nodesByVertex.push_back(node);
80 vertex_descriptor fromVertexID = CreateVertexFromFromNodeInfoIfNeeded(from);
81 vertex_descriptor toVertexID = CreateVertexFromFromNodeInfoIfNeeded(to);
83 float totalDist = 0.0f;
87 edges.emplace_back(edge(fromVertexID, toVertexID), EdgeCost{ to, 0xFFFF });
91 std::size_t last = nodes.size();
92 std::size_t first = 0;
99 for (std::size_t i = first + 1; i < last; ++i)
104 int32 uiMap1, uiMap2;
107 GetTaxiMapPosition(nodes[i - 1]->Loc, nodes[i - 1]->ContinentID, &pos1, &uiMap1);
108 GetTaxiMapPosition(nodes[i]->Loc, nodes[i]->ContinentID, &pos2, &uiMap2);
110 if (uiMap1 != uiMap2)
113 totalDist += std::sqrt(
114 std::pow(pos2.
X - pos1.
X, 2) +
115 std::pow(pos2.
Y - pos1.
Y, 2));
122 edges.emplace_back(edge(fromVertexID, toVertexID), EdgeCost{ to, dist });
126vertex_descriptor
const* GetVertexIDFromNodeID(
TaxiNodesEntry const* node)
131uint32 GetNodeIDFromVertexID(vertex_descriptor vertexID)
133 if (vertexID < m_nodesByVertex.size())
134 return m_nodesByVertex[vertexID]->ID;
136 return std::numeric_limits<uint32>::max();
140struct DiscoverVertexVisitor :
public boost::base_visitor<DiscoverVertexVisitor<T>>
142 using event_filter = boost::on_discover_vertex;
144 DiscoverVertexVisitor(T&& func) : _func(
std::forward<T>(func)) { }
146 template <
class Vertex,
class Graph>
147 void operator()(Vertex v, Graph& )
157auto make_discover_vertex_dfs_visitor(T&& t)
159 return boost::make_dfs_visitor(DiscoverVertexVisitor<T>(std::forward<T>(t)));
165 if (boost::num_vertices(m_graph) > 0)
168 std::vector<std::pair<edge, EdgeCost>> edges;
176 AddVerticeAndEdgeFromNodeInfo(from, to, path->
ID, edges);
180 m_graph = Graph(m_nodesByVertex.size());
181 WeightMap weightmap = boost::get(boost::edge_weight, m_graph);
183 for (std::size_t j = 0; j < edges.size(); ++j)
185 edge_descriptor e = boost::add_edge(edges[j].first.first, edges[j].first.second, m_graph).first;
186 weightmap[e] = edges[j].second;
205 shortestPath = { from->
ID, to->
ID };
208 shortestPath.clear();
210 vertex_descriptor
const* fromVertexId = GetVertexIDFromNodeID(from);
211 vertex_descriptor
const* toVertexId = GetVertexIDFromNodeID(to);
212 if (fromVertexId && toVertexId)
214 std::vector<vertex_descriptor> p(boost::num_vertices(m_graph));
215 std::vector<uint32> d(boost::num_vertices(m_graph));
217 boost::dijkstra_shortest_paths(m_graph, *fromVertexId,
218 boost::predecessor_map(boost::make_iterator_property_map(p.begin(), boost::get(boost::vertex_index, m_graph)))
219 .distance_map(boost::make_iterator_property_map(d.begin(), boost::get(boost::vertex_index, m_graph)))
220 .vertex_index_map(boost::get(boost::vertex_index, m_graph))
221 .distance_compare(std::less<uint32>())
222 .distance_combine(boost::closed_plus<uint32>())
223 .distance_inf(std::numeric_limits<uint32>::max())
225 .visitor(boost::dijkstra_visitor<boost::null_visitor>())
226 .weight_map(boost::make_transform_value_property_map(
227 [player](EdgeCost
const& edgeCost) { return edgeCost.EvaluateDistance(player); },
228 boost::get(boost::edge_weight, m_graph))));
231 for (vertex_descriptor v = *toVertexId; ; v = p[v])
233 shortestPath.push_back(GetNodeIDFromVertexID(v));
238 std::reverse(shortestPath.begin(), shortestPath.end());
242 return shortestPath.size();
247 vertex_descriptor
const* vertexId = GetVertexIDFromNodeID(from);
251 boost::vector_property_map<boost::default_color_type> color(boost::num_vertices(m_graph));
252 std::fill(color.storage_begin(), color.storage_end(), boost::white_color);
253 boost::depth_first_visit(m_graph, *vertexId, make_discover_vertex_dfs_visitor([mask](vertex_descriptor vertex)
256 (*mask)[(taxiNode->ID - 1) / 8] |= 1 << ((taxiNode->ID - 1) % 8);
DB2Storage< TaxiNodesEntry > sTaxiNodesStore("TaxiNodes.db2", &TaxiNodesLoadInfo::Instance)
TaxiPathNodesByPath sTaxiPathNodesByPath
DB2Storage< PlayerConditionEntry > sPlayerConditionStore("PlayerCondition.db2", &PlayerConditionLoadInfo::Instance)
DB2Storage< TaxiPathEntry > sTaxiPathStore("TaxiPath.db2", &TaxiPathLoadInfo::Instance)
std::vector< TaxiPathNodeEntry const * > TaxiPathNodeList
@ UI_MAP_SYSTEM_ADVENTURE
@ TAXI_PATH_NODE_FLAG_TELEPORT
static bool GetUiMapPosition(float x, float y, float z, int32 mapId, int32 areaId, int32 wmoDoodadPlacementId, int32 wmoGroupId, UiMapSystem system, bool local, int32 *uiMapId=nullptr, DBCPosition2D *newPos=nullptr)
void GetReachableNodesMask(TaxiNodesEntry const *from, TaxiMask *mask)
std::size_t GetCompleteNodeRoute(TaxiNodesEntry const *from, TaxiNodesEntry const *to, Player const *player, std::vector< uint32 > &shortestPath)
auto MapGetValuePtr(M &map, typename M::key_type const &key)
EnumFlag< TaxiNodeFlags > GetFlags() const
bool IsPartOfTaxiNetwork() const