diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/DataStores/DB2Stores.cpp | 9 | ||||
-rw-r--r-- | src/server/game/DataStores/DB2Stores.h | 1 | ||||
-rw-r--r-- | src/server/game/DataStores/DBCEnums.h | 8 | ||||
-rw-r--r-- | src/server/game/DataStores/DBCStores.cpp | 48 | ||||
-rw-r--r-- | src/server/game/DataStores/DBCStores.h | 3 | ||||
-rw-r--r-- | src/server/game/DataStores/DBCStructure.h | 20 | ||||
-rw-r--r-- | src/server/game/DataStores/DBCfmt.h | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Object/Object.h | 33 | ||||
-rw-r--r-- | src/server/game/Entities/Object/Position.h | 33 | ||||
-rw-r--r-- | src/server/game/Entities/Taxi/TaxiPathGraph.cpp | 211 | ||||
-rw-r--r-- | src/server/game/Entities/Taxi/TaxiPathGraph.h | 91 | ||||
-rw-r--r-- | src/server/game/Globals/ObjectMgr.cpp | 3 | ||||
-rw-r--r-- | src/server/game/Handlers/CharacterHandler.cpp | 39 | ||||
-rw-r--r-- | src/server/game/Handlers/TaxiHandler.cpp | 18 | ||||
-rw-r--r-- | src/server/game/Maps/TransportMgr.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Maps/TransportMgr.h | 2 | ||||
-rw-r--r-- | src/server/game/World/World.cpp | 4 |
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; |