aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2015-09-19 16:44:33 +0200
committerShauren <shauren.trinity@gmail.com>2015-09-19 16:44:33 +0200
commitf1b047b826e92278e566d376b80989b600c0d7c0 (patch)
tree6914e46320f754f363ca70617728d370db390b29
parent2c7459da6daf1d563825f3039b1c7112da2560ae (diff)
Core/Taxi: Further improvements
* Updated segment distance calculations - now selected path fully matches clientside preview * Fixed building sOldContinentsNodesMask to also include any new taxi node added in future * Implemented filtering possible hops when searching for shortest path by faction (and in future PlayerCondition) * Changed ObjectMgr::GetNearestTaxiNode to filter faction nodes by flags instead of mount display
-rw-r--r--src/server/game/DataStores/DB2Stores.cpp9
-rw-r--r--src/server/game/DataStores/DB2Stores.h1
-rw-r--r--src/server/game/DataStores/DBCEnums.h8
-rw-r--r--src/server/game/DataStores/DBCStores.cpp48
-rw-r--r--src/server/game/DataStores/DBCStores.h3
-rw-r--r--src/server/game/DataStores/DBCStructure.h20
-rw-r--r--src/server/game/DataStores/DBCfmt.h2
-rw-r--r--src/server/game/Entities/Object/Object.h33
-rw-r--r--src/server/game/Entities/Object/Position.h33
-rw-r--r--src/server/game/Entities/Taxi/TaxiPathGraph.cpp211
-rw-r--r--src/server/game/Entities/Taxi/TaxiPathGraph.h91
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp3
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp39
-rw-r--r--src/server/game/Handlers/TaxiHandler.cpp18
-rw-r--r--src/server/game/Maps/TransportMgr.cpp2
-rw-r--r--src/server/game/Maps/TransportMgr.h2
-rw-r--r--src/server/game/World/World.cpp4
17 files changed, 274 insertions, 253 deletions
diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp
index f4ccf767c52..61b5da47b7f 100644
--- a/src/server/game/DataStores/DB2Stores.cpp
+++ b/src/server/game/DataStores/DB2Stores.cpp
@@ -134,7 +134,6 @@ TaxiMask sTaxiNodesMask;
TaxiMask sOldContinentsNodesMask;
TaxiMask sHordeTaxiNodesMask;
TaxiMask sAllianceTaxiNodesMask;
-TaxiMask sDeathKnightTaxiNodesMask;
TaxiPathSetBySource sTaxiPathSetBySource;
TaxiPathNodesByPath sTaxiPathNodesByPath;
@@ -459,7 +458,6 @@ void DB2Manager::LoadStores(std::string const& dataPath, uint32 defaultLocale)
sOldContinentsNodesMask.fill(0);
sHordeTaxiNodesMask.fill(0);
sAllianceTaxiNodesMask.fill(0);
- sDeathKnightTaxiNodesMask.fill(0);
for (TaxiNodesEntry const* node : sTaxiNodesStore)
{
if (!(node->Flags & (TAXI_NODE_FLAG_ALLIANCE | TAXI_NODE_FLAG_HORDE)))
@@ -474,11 +472,10 @@ void DB2Manager::LoadStores(std::string const& dataPath, uint32 defaultLocale)
sHordeTaxiNodesMask[field] |= submask;
if (node->Flags & TAXI_NODE_FLAG_ALLIANCE)
sAllianceTaxiNodesMask[field] |= submask;
- if (node->MountCreatureID[0] == 32981 || node->MountCreatureID[1] == 32981)
- sDeathKnightTaxiNodesMask[field] |= submask;
- // todo: use WorldMapTransforms.dbc for this
- if (node->MapID < 2 || node->ID == 82 || node->ID == 83 || node->ID == 93 || node->ID == 94)
+ uint32 nodeMap;
+ DeterminaAlternateMapPosition(node->MapID, node->Pos.X, node->Pos.Y, node->Pos.Z, &nodeMap);
+ if (nodeMap < 2)
sOldContinentsNodesMask[field] |= submask;
}
}
diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h
index 4184ab5b5d4..0769e6e9739 100644
--- a/src/server/game/DataStores/DB2Stores.h
+++ b/src/server/game/DataStores/DB2Stores.h
@@ -110,7 +110,6 @@ extern TaxiMask sTaxiNodesMask;
extern TaxiMask sOldContinentsNodesMask;
extern TaxiMask sHordeTaxiNodesMask;
extern TaxiMask sAllianceTaxiNodesMask;
-extern TaxiMask sDeathKnightTaxiNodesMask;
extern TaxiPathSetBySource sTaxiPathSetBySource;
extern TaxiPathNodesByPath sTaxiPathNodesByPath;
diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h
index a89ffddd99d..6a230bc9d1e 100644
--- a/src/server/game/DataStores/DBCEnums.h
+++ b/src/server/game/DataStores/DBCEnums.h
@@ -687,7 +687,13 @@ enum SummonPropFlags
enum TaxiNodeFlags
{
TAXI_NODE_FLAG_ALLIANCE = 0x1,
- TAXI_NODE_FLAG_HORDE = 0x2,
+ TAXI_NODE_FLAG_HORDE = 0x2
+};
+
+enum TaxiPathNodeFlags
+{
+ TAXI_PATH_NODE_FLAG_TELEPORT = 0x1,
+ TAXI_PATH_NODE_FLAG_STOP = 0x2
};
enum VehicleSeatFlags
diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp
index 61d97043523..1d3a982d586 100644
--- a/src/server/game/DataStores/DBCStores.cpp
+++ b/src/server/game/DataStores/DBCStores.cpp
@@ -895,3 +895,51 @@ SkillRaceClassInfoEntry const* GetSkillRaceClassInfo(uint32 skill, uint8 race, u
return NULL;
}
+
+void DeterminaAlternateMapPosition(uint32 mapId, float x, float y, float z, uint32* newMapId /*= nullptr*/, DBCPosition2D* newPos /*= nullptr*/)
+{
+ WorldMapTransformsEntry const* transformation = nullptr;
+ for (WorldMapTransformsEntry const* transform : sWorldMapTransformsStore)
+ {
+ if (transform->MapID != mapId)
+ continue;
+
+ if (transform->RegionMin.X > x || transform->RegionMax.X < x)
+ continue;
+ if (transform->RegionMin.Y > y || transform->RegionMax.Y < y)
+ continue;
+ if (transform->RegionMin.Z > z || transform->RegionMax.Z < z)
+ continue;
+
+ transformation = transform;
+ break;
+ }
+
+ if (!transformation)
+ {
+ if (newMapId)
+ *newMapId = mapId;
+
+ if (newPos)
+ {
+ newPos->X = x;
+ newPos->Y = y;
+ }
+ return;
+ }
+
+ if (newMapId)
+ *newMapId = transformation->NewMapID;
+
+ if (!newPos)
+ return;
+
+ if (transformation->RegionScale > 0.0f && transformation->RegionScale < 1.0f)
+ {
+ newPos->X = (x - transformation->RegionMin.X) * transformation->RegionScale + transformation->RegionMin.X;
+ newPos->Y = (y - transformation->RegionMin.Y) * transformation->RegionScale + transformation->RegionMin.Y;
+ }
+
+ newPos->X += transformation->RegionOffset.X;
+ newPos->Y += transformation->RegionOffset.Y;
+}
diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h
index 2d59afa7c5a..63cff4a4fea 100644
--- a/src/server/game/DataStores/DBCStores.h
+++ b/src/server/game/DataStores/DBCStores.h
@@ -93,6 +93,8 @@ uint32 GetVirtualMapForMapAndZone(uint32 mapid, uint32 zoneId);
void Zone2MapCoordinates(float &x, float &y, uint32 worldMapAreaId);
void Map2ZoneCoordinates(float &x, float &y, uint32 worldMapAreaId);
+// WorldMapTransforms
+void DeterminaAlternateMapPosition(uint32 mapId, float x, float y, float z, uint32* newMapId = nullptr, DBCPosition2D* newPos = nullptr);
uint32 GetMaxLevelForExpansion(uint32 expansion);
uint32 GetExpansionForLevel(uint32 level);
@@ -206,7 +208,6 @@ extern TalentsByPosition sTalentByPos;
extern DBCStorage<VehicleEntry> sVehicleStore;
extern DBCStorage<VehicleSeatEntry> sVehicleSeatStore;
extern DBCStorage<WMOAreaTableEntry> sWMOAreaTableStore;
-extern DBCStorage<WorldMapTransformsEntry> sWorldMapTransformsStore;
extern DBCStorage<WorldSafeLocsEntry> sWorldSafeLocsStore;
extern GameTable<GtBarberShopCostBaseEntry> sGtBarberShopCostBaseStore;
diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h
index 94e577e9a26..76487aadffc 100644
--- a/src/server/game/DataStores/DBCStructure.h
+++ b/src/server/game/DataStores/DBCStructure.h
@@ -1413,16 +1413,16 @@ struct WorldMapAreaEntry
struct WorldMapTransformsEntry
{
- //uint32 ID; //
- uint32 MapID; //
- DBCPosition3D RegionMin; //
- DBCPosition3D RegionMax; //
- //uint32 NewMapID; //
- DBCPosition2D RegionOffset; //
- //uint32 NewDungeonMapID; //
- //uint32 Flags; //
- //uint32 NewAreaID; //
- float RegionScale; //
+ //uint32 ID; // 0
+ uint32 MapID; // 1
+ DBCPosition3D RegionMin; // 2
+ DBCPosition3D RegionMax; // 3
+ uint32 NewMapID; // 4
+ DBCPosition2D RegionOffset; // 5
+ //uint32 NewDungeonMapID; // 6
+ //uint32 Flags; // 7
+ //uint32 NewAreaID; // 8
+ float RegionScale; // 9
};
struct WorldSafeLocsEntry
diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h
index 8a01eac733e..900df980021 100644
--- a/src/server/game/DataStores/DBCfmt.h
+++ b/src/server/game/DataStores/DBCfmt.h
@@ -120,7 +120,7 @@ char const Vehiclefmt[] = "niiffffiiiiiiiifffffffffffffffxxxxfifiiii";
char const VehicleSeatfmt[] = "niiffffffffffiiiiiifffffffiiifffiiiiiiiffiiiiffffffffffffiiiiiiiii";
char const WMOAreaTablefmt[] = "niiixxxxxiixxxx";
char const WorldMapAreafmt[] = "xinxffffixxxxx";
-char const WorldMapTransformsfmt[] = "diffffffxffxxxf";
+char const WorldMapTransformsfmt[] = "diffffffiffxxxf";
char const WorldSafeLocsfmt[] = "niffffx";
#endif
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index 9be3dddf456..a466de3f62e 100644
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -351,39 +351,6 @@ struct MovementInfo
void OutDebug();
};
-#define MAPID_INVALID 0xFFFFFFFF
-
-class WorldLocation : public Position
-{
- public:
- explicit WorldLocation(uint32 _mapId = MAPID_INVALID, float _x = 0.f, float _y = 0.f, float _z = 0.f, float _o = 0.f)
- : Position(_x, _y, _z, _o), m_mapId(_mapId) { }
-
- WorldLocation(WorldLocation const& loc)
- : Position(loc), m_mapId(loc.GetMapId()) { }
-
- void WorldRelocate(WorldLocation const& loc)
- {
- m_mapId = loc.GetMapId();
- Relocate(loc);
- }
-
- void WorldRelocate(uint32 _mapId = MAPID_INVALID, float _x = 0.f, float _y = 0.f, float _z = 0.f, float _o = 0.f)
- {
- m_mapId = _mapId;
- Relocate(_x, _y, _z, _o);
- }
-
- WorldLocation GetWorldLocation() const
- {
- return *this;
- }
-
- uint32 GetMapId() const { return m_mapId; }
-
- uint32 m_mapId;
-};
-
template<class T>
class GridObject
{
diff --git a/src/server/game/Entities/Object/Position.h b/src/server/game/Entities/Object/Position.h
index 5bd37567811..109ff09d66c 100644
--- a/src/server/game/Entities/Object/Position.h
+++ b/src/server/game/Entities/Object/Position.h
@@ -215,6 +215,39 @@ public:
}
};
+#define MAPID_INVALID 0xFFFFFFFF
+
+class WorldLocation : public Position
+{
+public:
+ explicit WorldLocation(uint32 mapId = MAPID_INVALID, float x = 0.f, float y = 0.f, float z = 0.f, float o = 0.f)
+ : Position(x, y, z, o), m_mapId(mapId) { }
+
+ WorldLocation(WorldLocation const& loc)
+ : Position(loc), m_mapId(loc.GetMapId()) { }
+
+ void WorldRelocate(WorldLocation const& loc)
+ {
+ m_mapId = loc.GetMapId();
+ Relocate(loc);
+ }
+
+ void WorldRelocate(uint32 mapId = MAPID_INVALID, float x = 0.f, float y = 0.f, float z = 0.f, float o = 0.f)
+ {
+ m_mapId = mapId;
+ Relocate(x, y, z, o);
+ }
+
+ WorldLocation GetWorldLocation() const
+ {
+ return *this;
+ }
+
+ uint32 GetMapId() const { return m_mapId; }
+
+ uint32 m_mapId;
+};
+
ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYStreamer const& streamer);
ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYStreamer const& streamer);
ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer);
diff --git a/src/server/game/Entities/Taxi/TaxiPathGraph.cpp b/src/server/game/Entities/Taxi/TaxiPathGraph.cpp
index f08940c64b8..ef899795bfd 100644
--- a/src/server/game/Entities/Taxi/TaxiPathGraph.cpp
+++ b/src/server/game/Entities/Taxi/TaxiPathGraph.cpp
@@ -1,137 +1,128 @@
+/*
+ * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
#include "TaxiPathGraph.h"
#include "ObjectMgr.h"
+#include "Player.h"
#include "DBCStores.h"
#include "DB2Stores.h"
#include "Config.h"
#include "Util.h"
-
-TaxiPathGraph::Graph TaxiPathGraph::m_graph = TaxiPathGraph::Graph();
-std::vector<TaxiPathGraph::TaxiNodeInfo> TaxiPathGraph::m_vertices = std::vector<TaxiPathGraph::TaxiNodeInfo>();
-std::map<uint32, TaxiPathGraph::vertex_descriptor> TaxiPathGraph::m_nodeIDToVertexID = std::map<uint32, TaxiPathGraph::vertex_descriptor>();
-std::set<TaxiPathGraph::edge> TaxiPathGraph::m_edgeDuplicateControl = std::set<TaxiPathGraph::edge>();
-const int TaxiPathGraph::MaxFlightDistanceThreshold = 4000; //Because the client seems not to chose long flight paths even if that means the chosen path is not the minimum one
-
-TaxiPathGraph::TaxiPathGraph() { }
-
-TaxiPathGraph::~TaxiPathGraph() { }
-
-void DeterminaAlternateMapPosition(TaxiPathGraph::TaxiNodeInfo& info)
-{
- WorldMapTransformsEntry const* transformation = nullptr;
- for (WorldMapTransformsEntry const* transform : sWorldMapTransformsStore)
- {
- if (transform->MapID != info.mapId)
- continue;
-
- if (transform->RegionMin.X > info.pos.x || transform->RegionMax.X < info.pos.x)
- continue;
- if (transform->RegionMin.Y > info.pos.y || transform->RegionMax.Y < info.pos.y)
- continue;
- if (transform->RegionMin.Z > info.pos.z || transform->RegionMax.Z < info.pos.z)
- continue;
-
- transformation = transform;
- break;
- }
-
- if (!transformation)
- return;
-
- if (transformation->RegionScale > 0.0f && transformation->RegionScale < 1.0f)
- {
- info.pos.x = (info.pos.x - transformation->RegionMin.X) * transformation->RegionScale + transformation->RegionMin.X;
- info.pos.y = (info.pos.y - transformation->RegionMin.Y) * transformation->RegionScale + transformation->RegionMin.Y;
- }
-
- info.pos.x += transformation->RegionOffset.X;
- info.pos.y += transformation->RegionOffset.Y;
-}
+#include <boost/graph/dijkstra_shortest_paths.hpp>
+#include <boost/property_map/transform_value_property_map.hpp>
void TaxiPathGraph::Initialize()
{
- if (_getVertexCount() > 0)
+ if (GetVertexCount() > 0)
return;
- m_edgeDuplicateControl.clear();
- std::vector<std::pair<edge, cost>> edges;
+ std::vector<std::pair<edge, EdgeCost>> edges;
// Initialize here
- for (TaxiPathEntry const* nodeInfo : sTaxiPathStore)
+ for (TaxiPathEntry const* path : sTaxiPathStore)
{
- TaxiNodesEntry const* from = sTaxiNodesStore.LookupEntry(nodeInfo->From);
- TaxiNodesEntry const* to = sTaxiNodesStore.LookupEntry(nodeInfo->To);
+ TaxiNodesEntry const* from = sTaxiNodesStore.LookupEntry(path->From);
+ TaxiNodesEntry const* to = sTaxiNodesStore.LookupEntry(path->To);
if (from && to && from->Flags & (TAXI_NODE_FLAG_ALLIANCE | TAXI_NODE_FLAG_HORDE) && to->Flags & (TAXI_NODE_FLAG_ALLIANCE | TAXI_NODE_FLAG_HORDE))
- {
- TaxiNodeInfo fromInfo(from->ID, from->Name->Str[sConfigMgr->GetIntDefault("DBC.Locale", LOCALE_enUS)], from->MapID, from->Pos.X, from->Pos.Y, from->Pos.Z);
- TaxiNodeInfo toInfo(to->ID, to->Name->Str[sConfigMgr->GetIntDefault("DBC.Locale", LOCALE_enUS)], to->MapID, to->Pos.X, to->Pos.Y, to->Pos.Z);
-
- DeterminaAlternateMapPosition(fromInfo);
- DeterminaAlternateMapPosition(toInfo);
-
- _addVerticeAndEdgeFromNodeInfo(fromInfo, toInfo, nodeInfo->Cost, edges);
- }
+ AddVerticeAndEdgeFromNodeInfo(from, to, path->ID, edges);
}
// create graph
- m_graph = Graph(_getVertexCount());
+ m_graph = Graph(GetVertexCount());
WeightMap weightmap = boost::get(boost::edge_weight, m_graph);
for (std::size_t j = 0; j < edges.size(); ++j)
{
- edge_descriptor e;
- bool inserted;
- boost::tie(e, inserted) = boost::add_edge(edges[j].first.first,
- edges[j].first.second,
- m_graph);
+ edge_descriptor e = boost::add_edge(edges[j].first.first, edges[j].first.second, m_graph).first;
weightmap[e] = edges[j].second;
}
- m_edgeDuplicateControl.clear();
}
-uint32 TaxiPathGraph::_getNodeIDFromVertexID(vertex_descriptor vertexID)
+uint32 TaxiPathGraph::GetNodeIDFromVertexID(vertex_descriptor vertexID)
{
if (vertexID < m_vertices.size())
- return m_vertices[vertexID].nodeID;
+ return m_vertices[vertexID]->ID;
return std::numeric_limits<uint32>::max();
}
-TaxiPathGraph::vertex_descriptor TaxiPathGraph::_getVertexIDFromNodeID(uint32 nodeID)
+TaxiPathGraph::vertex_descriptor TaxiPathGraph::GetVertexIDFromNodeID(TaxiNodesEntry const* node)
{
- if (m_nodeIDToVertexID.find(nodeID) != m_nodeIDToVertexID.end())
- return m_nodeIDToVertexID[nodeID];
-
- return std::numeric_limits<vertex_descriptor>::max();
+ return node->LearnableIndex;
}
-TaxiPathGraph::vertex_descriptor TaxiPathGraph::_getVertexIDFromNodeID(TaxiNodeInfo const& nodeInfo)
-{
- if (m_nodeIDToVertexID.find(nodeInfo.nodeID) != m_nodeIDToVertexID.end())
- return m_nodeIDToVertexID[nodeInfo.nodeID];
-
- return std::numeric_limits<vertex_descriptor>::max();
-}
-
-size_t TaxiPathGraph::_getVertexCount()
+std::size_t TaxiPathGraph::GetVertexCount()
{
//So we can use this function for readability, we define either max defined vertices or already loaded in graph count
return std::max(boost::num_vertices(m_graph), m_vertices.size());
}
-void TaxiPathGraph::_addVerticeAndEdgeFromNodeInfo(const TaxiNodeInfo& from, const TaxiNodeInfo& to, uint32 /* money */, std::vector<std::pair<edge, cost>>& edges)
+void TaxiPathGraph::AddVerticeAndEdgeFromNodeInfo(TaxiNodesEntry const* from, TaxiNodesEntry const* to, uint32 pathId, std::vector<std::pair<edge, EdgeCost>>& edges)
{
- if (from.nodeID != to.nodeID && m_edgeDuplicateControl.find(edge(from.nodeID, to.nodeID)) == m_edgeDuplicateControl.end())
+ if (from != to)
{
- vertex_descriptor fromVertexID = _createVertexFromFromNodeInfoIfNeeded(from);
- vertex_descriptor toVertexID = _createVertexFromFromNodeInfoIfNeeded(to);
+ vertex_descriptor fromVertexID = CreateVertexFromFromNodeInfoIfNeeded(from);
+ vertex_descriptor toVertexID = CreateVertexFromFromNodeInfoIfNeeded(to);
+
+ float totalDist = 0.0f;
+ TaxiPathNodeList const& nodes = sTaxiPathNodesByPath[pathId];
+ if (nodes.size() < 2)
+ {
+ edges.push_back(std::make_pair(edge(fromVertexID, toVertexID), EdgeCost{ to, 0xFFFF }));
+ return;
+ }
+
+ std::size_t last = nodes.size();
+ std::size_t first = 0;
+ if (nodes.size() > 2)
+ {
+ --last;
+ ++first;
+ }
+
+ for (std::size_t i = first + 1; i < last; ++i)
+ {
+ if (nodes[i - 1]->Flags & TAXI_PATH_NODE_FLAG_TELEPORT)
+ continue;
+
+ uint32 map1, map2;
+ DBCPosition2D pos1, pos2;
- // TODO: Calculate distance using TaxiPathNode
- edges.push_back(std::make_pair(edge(fromVertexID, toVertexID), from.pos.Distance(to.pos)));
- m_edgeDuplicateControl.insert(edge(from.nodeID, to.nodeID));
+ DeterminaAlternateMapPosition(nodes[i - 1]->MapID, nodes[i - 1]->Loc.X, nodes[i - 1]->Loc.Y, nodes[i - 1]->Loc.Z, &map1, &pos1);
+ DeterminaAlternateMapPosition(nodes[i]->MapID, nodes[i]->Loc.X, nodes[i]->Loc.Y, nodes[i]->Loc.Z, &map2, &pos2);
+
+ if (map1 != map2)
+ continue;
+
+ totalDist += std::sqrt(
+ std::pow(pos2.X - pos1.X, 2) +
+ std::pow(pos2.Y - pos1.Y, 2) +
+ std::pow(nodes[i]->Loc.Z - nodes[i - 1]->Loc.Z, 2));
+ }
+
+ uint32 dist = uint32(totalDist);
+ if (dist > 0xFFFF)
+ return;
+
+ edges.push_back(std::make_pair(edge(fromVertexID, toVertexID), EdgeCost{ to, dist }));
}
}
-size_t TaxiPathGraph::GetCompleteNodeRoute(uint32 sourceNodeID, uint32 destinationNodeID, std::vector<uint32>& shortestPath)
+std::size_t TaxiPathGraph::GetCompleteNodeRoute(TaxiNodesEntry const* from, TaxiNodesEntry const* to, Player const* player, std::vector<uint32>& shortestPath)
{
/*
Information about node algorithm from client
@@ -144,21 +135,24 @@ size_t TaxiPathGraph::GetCompleteNodeRoute(uint32 sourceNodeID, uint32 destinati
// Find if we have a direct path
uint32 pathId, goldCost;
- sObjectMgr->GetTaxiPath(sourceNodeID, destinationNodeID, pathId, goldCost);
+ sObjectMgr->GetTaxiPath(from->ID, to->ID, pathId, goldCost);
if (pathId)
- shortestPath = { sourceNodeID, destinationNodeID };
+ shortestPath = { from->ID, to->ID };
else
{
shortestPath.clear();
std::vector<vertex_descriptor> p(boost::num_vertices(m_graph));
- boost::dijkstra_shortest_paths(m_graph, _getVertexIDFromNodeID(sourceNodeID),
- boost::predecessor_map(boost::make_iterator_property_map(p.begin(), get(boost::vertex_index, m_graph))));
+ boost::dijkstra_shortest_paths(m_graph, GetVertexIDFromNodeID(from),
+ boost::predecessor_map(boost::make_iterator_property_map(p.begin(), boost::get(boost::vertex_index, m_graph)))
+ .weight_map(boost::make_transform_value_property_map(
+ [player](EdgeCost const& edgeCost) { return edgeCost.EvaluateDistance(player); },
+ boost::get(boost::edge_weight, m_graph))));
// found a path to the goal
- for (vertex_descriptor v = _getVertexIDFromNodeID(destinationNodeID); ; v = p[v])
+ for (vertex_descriptor v = GetVertexIDFromNodeID(to); ; v = p[v])
{
- shortestPath.push_back(_getNodeIDFromVertexID(v));
+ shortestPath.push_back(GetNodeIDFromVertexID(v));
if (v == p[v])
break;
}
@@ -169,25 +163,24 @@ size_t TaxiPathGraph::GetCompleteNodeRoute(uint32 sourceNodeID, uint32 destinati
return shortestPath.size();
}
-TaxiPathGraph::TaxiNodeInfo const* TaxiPathGraph::GetTaxiNodeInfoByID(uint32 nodeID)
+TaxiPathGraph::vertex_descriptor TaxiPathGraph::CreateVertexFromFromNodeInfoIfNeeded(TaxiNodesEntry const* node)
{
- vertex_descriptor vertexID = _getVertexIDFromNodeID(nodeID);
- if (m_vertices.size() < vertexID)
- return nullptr;
+ //Check if we need a new one or if it may be already created
+ if (m_vertices.size() <= node->LearnableIndex)
+ m_vertices.resize(node->LearnableIndex + 1);
- return &m_vertices[vertexID];
+ m_vertices[node->LearnableIndex] = node;
+ return node->LearnableIndex;
}
-TaxiPathGraph::vertex_descriptor TaxiPathGraph::_createVertexFromFromNodeInfoIfNeeded(TaxiNodeInfo const& nodeInfo)
+uint32 TaxiPathGraph::EdgeCost::EvaluateDistance(Player const* player) const
{
- //Check if we need a new one or if it may be already created
- if (m_nodeIDToVertexID.find(nodeInfo.nodeID) == m_nodeIDToVertexID.end())
- {
- vertex_descriptor verID = m_vertices.size();
- m_vertices.push_back(nodeInfo);
- m_nodeIDToVertexID[nodeInfo.nodeID] = verID;
- return verID;
- }
+ uint32 requireFlag = (player->GetTeam() == ALLIANCE) ? TAXI_NODE_FLAG_ALLIANCE : TAXI_NODE_FLAG_HORDE;
+ if (!(To->Flags & requireFlag))
+ return std::numeric_limits<uint16>::max();
+
+ //if (To->ConditionID && !player->MeetsCondition(To->ConditionID))
+ // return std::numeric_limits<uint16>::max();
- return m_nodeIDToVertexID[nodeInfo.nodeID];
+ return Distance;
}
diff --git a/src/server/game/Entities/Taxi/TaxiPathGraph.h b/src/server/game/Entities/Taxi/TaxiPathGraph.h
index 43443bbb7fe..15d139fb55d 100644
--- a/src/server/game/Entities/Taxi/TaxiPathGraph.h
+++ b/src/server/game/Entities/Taxi/TaxiPathGraph.h
@@ -1,72 +1,71 @@
+/*
+ * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
#ifndef TAXIPATHGRAPH_HPP
#define TAXIPATHGRAPH_HPP
-#include <boost/graph/dijkstra_shortest_paths.hpp>
-#include <boost/graph/adjacency_list.hpp>
-#include <vector>
+#include "Position.h"
#include "Define.h"
+#include <boost/graph/adjacency_list.hpp>
+
+class Player;
+struct TaxiNodesEntry;
class TaxiPathGraph
{
public:
- struct Location
- {
- Location(float posX, float posY, float posZ): x(posX), y(posY), z(posZ) { }
- float Distance(Location const& to) const { return sqrt(pow(to.x - x, 2) + pow(to.y - y, 2) + pow(to.z - z, 2)); }
- float x;
- float y;
- float z;
- };
- struct TaxiNodeInfo
- {
- TaxiNodeInfo(uint32 id, std::string const& flightName, uint32 mapid, float posX, float posY, float posZ): nodeID(id), name(flightName), mapId(mapid), pos(posX, posY, posZ)
- {
- name.erase(std::remove(name.begin(), name.end(), '\"' ), name.end());
- }
- uint32 nodeID;
- std::string name;
- uint32 mapId;
- Location pos;
- };
- static TaxiPathGraph* instance()
+ static TaxiPathGraph& Instance()
{
static TaxiPathGraph instance;
- return &instance;
+ return instance;
}
- ~TaxiPathGraph();
- static void Initialize();
- static size_t GetCompleteNodeRoute(uint32 /* sourceNodeID */, uint32 /* destinationNodeID */, std::vector<uint32>& /* shortestPath */);
- static TaxiNodeInfo const* GetTaxiNodeInfoByID(uint32 nodeID);
+ void Initialize();
+ std::size_t GetCompleteNodeRoute(TaxiNodesEntry const* from, TaxiNodesEntry const* to, Player const* player, std::vector<uint32>& shortestPath);
private:
- typedef float cost;
-
- // specify some types
- typedef boost::adjacency_list<boost::listS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, uint32>, boost::property<boost::edge_weight_t, cost>> Graph;
+ struct EdgeCost
+ {
+ TaxiNodesEntry const* To;
+ uint32 Distance;
+ uint32 EvaluateDistance(Player const* player) const;
+ };
+ typedef boost::adjacency_list<boost::listS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, uint32>, boost::property<boost::edge_weight_t, EdgeCost>> Graph;
typedef boost::property_map<Graph, boost::edge_weight_t>::type WeightMap;
typedef Graph::vertex_descriptor vertex_descriptor;
typedef Graph::edge_descriptor edge_descriptor;
typedef std::pair<uint32, uint32> edge;
- static Graph m_graph;
- static std::vector<TaxiNodeInfo> m_vertices;
- static std::map<uint32, vertex_descriptor> m_nodeIDToVertexID;
- static std::set<edge> m_edgeDuplicateControl;
- static const int MaxFlightDistanceThreshold;
+ TaxiPathGraph() { }
+ ~TaxiPathGraph() { }
+
+ void AddVerticeAndEdgeFromNodeInfo(TaxiNodesEntry const* from, TaxiNodesEntry const* to, uint32 pathId, std::vector<std::pair<edge, EdgeCost>>& edges);
+ vertex_descriptor GetVertexIDFromNodeID(TaxiNodesEntry const* node);
+ uint32 GetNodeIDFromVertexID(vertex_descriptor vertexID);
+ vertex_descriptor CreateVertexFromFromNodeInfoIfNeeded(TaxiNodesEntry const* node);
+ std::size_t GetVertexCount();
+
+ Graph m_graph;
+ std::vector<TaxiNodesEntry const*> m_vertices;
- static void _addVerticeAndEdgeFromNodeInfo(TaxiNodeInfo const& /* from */, TaxiNodeInfo const& /* to */, uint32 /* money */, std::vector<std::pair<edge, cost>>& /* edgeList */);
- TaxiPathGraph();
TaxiPathGraph(TaxiPathGraph const&) = delete;
TaxiPathGraph& operator=(TaxiPathGraph const&) = delete;
-
- static vertex_descriptor _getVertexIDFromNodeID(uint32 nodeID);
- static vertex_descriptor _getVertexIDFromNodeID(TaxiNodeInfo const& nodeInfo);
- static uint32 _getNodeIDFromVertexID(vertex_descriptor vertexID);
- static vertex_descriptor _createVertexFromFromNodeInfoIfNeeded(TaxiNodeInfo const&);
- static size_t _getVertexCount();
};
-#define sTaxiPathGraph TaxiPathGraph::instance()
+#define sTaxiPathGraph TaxiPathGraph::Instance()
#endif /* TAXIPATHGRAPH_HPP */
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 5352112caca..b048afe16a6 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -5673,9 +5673,10 @@ uint32 ObjectMgr::GetNearestTaxiNode(float x, float y, float z, uint32 mapid, ui
float dist = 10000;
uint32 id = 0;
+ uint32 requireFlag = (team == ALLIANCE) ? TAXI_NODE_FLAG_ALLIANCE : TAXI_NODE_FLAG_HORDE;
for (TaxiNodesEntry const* node : sTaxiNodesStore)
{
- if (!node || node->MapID != mapid || (!node->MountCreatureID[team == ALLIANCE ? 1 : 0] && node->MountCreatureID[0] != 32981)) // dk flight
+ if (!node || node->MapID != mapid || !(node->Flags & requireFlag))
continue;
uint8 field = (uint8)((node->ID - 1) / 8);
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index 39a81b12336..c3ed19fdf71 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -2009,41 +2009,14 @@ void WorldSession::HandleCharRaceOrFactionChangeCallback(PreparedQueryResult res
// Update Taxi path
// this doesn't seem to be 100% blizzlike... but it can't really be helped.
std::ostringstream taximaskstream;
- uint32 numFullTaximasks = level / 7;
- if (numFullTaximasks > 11)
- numFullTaximasks = 11;
-
- if (newTeamId == TEAM_ALLIANCE)
+ TaxiMask const& factionMask = newTeamId == TEAM_HORDE ? sHordeTaxiNodesMask : sAllianceTaxiNodesMask;
+ for (uint8 i = 0; i < TaxiMaskSize; ++i)
{
- if (playerClass != CLASS_DEATH_KNIGHT)
- {
- for (uint8 i = 0; i < numFullTaximasks; ++i)
- taximaskstream << uint32(sAllianceTaxiNodesMask[i]) << ' ';
- }
- else
- {
- for (uint8 i = 0; i < numFullTaximasks; ++i)
- taximaskstream << uint32(sAllianceTaxiNodesMask[i] | sDeathKnightTaxiNodesMask[i]) << ' ';
- }
+ // i = (315 - 1) / 8 = 39
+ // m = 1 << ((315 - 1) % 8) = 4
+ uint8 deathKnightExtraNode = playerClass != CLASS_DEATH_KNIGHT || i != 39 ? 0 : 4;
+ taximaskstream << uint32(factionMask[i] | deathKnightExtraNode) << ' ';
}
- else
- {
- if (playerClass != CLASS_DEATH_KNIGHT)
- {
- for (uint8 i = 0; i < numFullTaximasks; ++i)
- taximaskstream << uint32(sHordeTaxiNodesMask[i]) << ' ';
- }
- else
- {
- for (uint8 i = 0; i < numFullTaximasks; ++i)
- taximaskstream << uint32(sHordeTaxiNodesMask[i] | sDeathKnightTaxiNodesMask[i]) << ' ';
- }
- }
-
- uint32 numEmptyTaximasks = 11 - numFullTaximasks;
- for (uint8 i = 0; i < numEmptyTaximasks; ++i)
- taximaskstream << "0 ";
- taximaskstream << '0';
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_TAXIMASK);
stmt->setString(0, taximaskstream.str());
diff --git a/src/server/game/Handlers/TaxiHandler.cpp b/src/server/game/Handlers/TaxiHandler.cpp
index b4462925e8d..9bd2328f8ab 100644
--- a/src/server/game/Handlers/TaxiHandler.cpp
+++ b/src/server/game/Handlers/TaxiHandler.cpp
@@ -60,7 +60,7 @@ void WorldSession::SendTaxiStatus(ObjectGuid guid)
data.Status = GetPlayer()->m_taxi.IsTaximaskNodeKnown(curloc) ? TAXISTATUS_LEARNED : TAXISTATUS_UNLEARNED;
else
data.Status = TAXISTATUS_NOT_ELIGIBLE;
-
+
SendPacket(data.Write());
TC_LOG_DEBUG("network", "WORLD: Sent SMSG_TAXI_NODE_STATUS");
@@ -104,9 +104,9 @@ void WorldSession::SendTaxiMenu(Creature* unit)
data.WindowInfo = boost::in_place();
data.WindowInfo->UnitGUID = unit->GetGUID();
data.WindowInfo->CurrentNode = curloc;
-
+
GetPlayer()->m_taxi.AppendTaximaskTo(data, lastTaxiCheaterState);
-
+
SendPacket(data.Write());
GetPlayer()->SetTaxiCheater(lastTaxiCheaterState);
@@ -166,10 +166,14 @@ void WorldSession::HandleActivateTaxiOpcode(WorldPackets::Taxi::ActivateTaxi& pa
}
uint32 curloc = sObjectMgr->GetNearestTaxiNode(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ(), unit->GetMapId(), GetPlayer()->GetTeam());
-
if (!curloc)
return;
-
+
+ TaxiNodesEntry const* from = sTaxiNodesStore.LookupEntry(curloc);
+ TaxiNodesEntry const* to = sTaxiNodesStore.LookupEntry(packet.Node);
+ if (!to)
+ return;
+
if (!GetPlayer()->isTaxiCheater())
{
if (!GetPlayer()->m_taxi.IsTaximaskNodeKnown(curloc) || !GetPlayer()->m_taxi.IsTaximaskNodeKnown(packet.Node))
@@ -178,9 +182,9 @@ void WorldSession::HandleActivateTaxiOpcode(WorldPackets::Taxi::ActivateTaxi& pa
return;
}
}
-
+
std::vector<uint32> nodes;
- TaxiPathGraph::GetCompleteNodeRoute(curloc, packet.Node, nodes);
+ sTaxiPathGraph.GetCompleteNodeRoute(from, to, GetPlayer(), nodes);
GetPlayer()->ActivateTaxiPathTo(nodes, unit);
}
diff --git a/src/server/game/Maps/TransportMgr.cpp b/src/server/game/Maps/TransportMgr.cpp
index 86c4fb73108..4540aba77c5 100644
--- a/src/server/game/Maps/TransportMgr.cpp
+++ b/src/server/game/Maps/TransportMgr.cpp
@@ -131,7 +131,7 @@ void TransportMgr::GeneratePath(GameObjectTemplate const* goInfo, TransportTempl
if (!mapChange)
{
TaxiPathNodeEntry const* node_i = path[i];
- if (i != path.size() - 1 && (node_i->Flags & 1 || node_i->MapID != path[i + 1]->MapID))
+ if (i != path.size() - 1 && (node_i->Flags & TAXI_PATH_NODE_FLAG_TELEPORT || node_i->MapID != path[i + 1]->MapID))
{
keyFrames.back().Teleport = true;
mapChange = true;
diff --git a/src/server/game/Maps/TransportMgr.h b/src/server/game/Maps/TransportMgr.h
index 5e032dbd71f..715d82877a0 100644
--- a/src/server/game/Maps/TransportMgr.h
+++ b/src/server/game/Maps/TransportMgr.h
@@ -63,7 +63,7 @@ struct KeyFrame
uint32 NextArriveTime;
bool IsTeleportFrame() const { return Teleport; }
- bool IsStopFrame() const { return Node->Flags == 2; }
+ bool IsStopFrame() const { return (Node->Flags & TAXI_PATH_NODE_FLAG_STOP) != 0; }
};
struct TransportTemplate
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index abbe5d9bd24..3acc8fb47f9 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -1472,8 +1472,8 @@ void World::SetInitialWorldSettings()
LoadGameTables(m_dataPath, m_defaultDbcLocale);
//Load weighted graph on taxi nodes path
- TaxiPathGraph::Initialize();
-
+ sTaxiPathGraph.Initialize();
+
sSpellMgr->LoadPetFamilySpellsStore();
std::unordered_map<uint32, std::vector<uint32>> mapData;