diff options
author | Shauren <shauren.trinity@gmail.com> | 2023-10-28 22:13:59 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2023-10-28 22:13:59 +0200 |
commit | 73e0b3e77c04a7821f58d79211f344b9129602f1 (patch) | |
tree | 315e6970f0c97c4b45019b564446b358b08c5969 /src/server/game | |
parent | b8770d96e43679c873f6643bcc81e46b6dcd497f (diff) |
Core/Creatures: Taxi improvements
* Fixed flight master minimap icon
* Fixed crash on Argus
* Implemented teleport taxi nodes
Closes #29389
Diffstat (limited to 'src/server/game')
-rw-r--r-- | src/server/game/DataStores/DB2Stores.cpp | 6 | ||||
-rw-r--r-- | src/server/game/DataStores/DB2Structure.h | 17 | ||||
-rw-r--r-- | src/server/game/DataStores/DBCEnums.h | 15 | ||||
-rw-r--r-- | src/server/game/Entities/Creature/Creature.cpp | 8 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Taxi/TaxiPathGraph.cpp | 70 | ||||
-rw-r--r-- | src/server/game/Globals/ObjectMgr.cpp | 4 | ||||
-rw-r--r-- | src/server/game/Handlers/MovementHandler.cpp | 22 | ||||
-rw-r--r-- | src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.cpp | 32 |
9 files changed, 117 insertions, 59 deletions
diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp index 79e80accdb7..6de4f4b423e 100644 --- a/src/server/game/DataStores/DB2Stores.cpp +++ b/src/server/game/DataStores/DB2Stores.cpp @@ -1598,7 +1598,7 @@ uint32 DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaul // include existed nodes that have at least single not spell base (scripted) path for (TaxiNodesEntry const* node : sTaxiNodesStore) { - if (!(node->Flags & (TAXI_NODE_FLAG_ALLIANCE | TAXI_NODE_FLAG_HORDE))) + if (!node->IsPartOfTaxiNetwork()) continue; // valid taxi network node @@ -1606,9 +1606,9 @@ uint32 DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaul TaxiMask::value_type submask = TaxiMask::value_type(1 << ((node->ID - 1) % (sizeof(TaxiMask::value_type) * 8))); sTaxiNodesMask[field] |= submask; - if (node->Flags & TAXI_NODE_FLAG_HORDE) + if (node->GetFlags().HasFlag(TaxiNodeFlags::ShowOnHordeMap)) sHordeTaxiNodesMask[field] |= submask; - if (node->Flags & TAXI_NODE_FLAG_ALLIANCE) + if (node->GetFlags().HasFlag(TaxiNodeFlags::ShowOnAllianceMap)) sAllianceTaxiNodesMask[field] |= submask; int32 uiMapId = -1; diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h index 9c540d5cfed..18b16e9d51b 100644 --- a/src/server/game/DataStores/DB2Structure.h +++ b/src/server/game/DataStores/DB2Structure.h @@ -4002,6 +4002,23 @@ struct TaxiNodesEntry uint32 SpecialIconConditionID; uint32 VisibilityConditionID; std::array<int32, 2> MountCreatureID; + + EnumFlag<TaxiNodeFlags> GetFlags() const { return static_cast<TaxiNodeFlags>(Flags); } + + bool IsPartOfTaxiNetwork() const + { + return GetFlags().HasFlag(TaxiNodeFlags::ShowOnAllianceMap | TaxiNodeFlags::ShowOnHordeMap) + // manually whitelisted nodes + || ID == 1985 // [Hidden] Argus Ground Points Hub (Ground TP out to here, TP to Vindicaar from here) + || ID == 1986 // [Hidden] Argus Vindicaar Ground Hub (Vindicaar TP out to here, TP to ground from here) + || ID == 1987 // [Hidden] Argus Vindicaar No Load Hub (Vindicaar No Load transition goes through here) + || ID == 2627 // [Hidden] 9.0 Bastion Ground Points Hub (Ground TP out to here, TP to Sanctum from here) + || ID == 2628 // [Hidden] 9.0 Bastion Ground Hub (Sanctum TP out to here, TP to ground from here) + || ID == 2732 // [HIDDEN] 9.2 Resonant Peaks - Teleport Network - Hidden Hub (Connects all Nodes to each other without unique paths) + || ID == 2835 // [Hidden] 10.0 Travel Network - Destination Input + || ID == 2843 // [Hidden] 10.0 Travel Network - Destination Output + ; + } }; struct TaxiPathEntry diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h index 15fff9739a6..83ef2bf8075 100644 --- a/src/server/game/DataStores/DBCEnums.h +++ b/src/server/game/DataStores/DBCEnums.h @@ -2123,13 +2123,20 @@ DEFINE_ENUM_FLAG(SummonPropertiesFlags); #define MAX_TALENT_COLUMNS 3 #define MAX_PVP_TALENT_SLOTS 4 -enum TaxiNodeFlags +enum class TaxiNodeFlags : int32 { - TAXI_NODE_FLAG_ALLIANCE = 0x01, - TAXI_NODE_FLAG_HORDE = 0x02, - TAXI_NODE_FLAG_USE_FAVORITE_MOUNT = 0x10 + ShowOnAllianceMap = 0x00000001, + ShowOnHordeMap = 0x00000002, + ShowOnMapBorder = 0x00000004, + ShowIfClientPassesCondition = 0x00000008, + UsePlayerFavoriteMount = 0x00000010, + EndPointPnly = 0x00000020, + IgnoreForFindNearest = 0x00000040, + DoNotShowInWorldMapUI = 0x00000080, }; +DEFINE_ENUM_FLAG(TaxiNodeFlags); + enum TaxiPathNodeFlags { TAXI_PATH_NODE_FLAG_TELEPORT = 0x1, diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 0b09a1a2316..304f3d2df8d 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -643,7 +643,15 @@ bool Creature::UpdateEntry(uint32 entry, CreatureData const* data /*= nullptr*/, // checked and error show at loading templates if (FactionTemplateEntry const* factionTemplate = sFactionTemplateStore.LookupEntry(cInfo->faction)) + { SetPvP((factionTemplate->Flags & FACTION_TEMPLATE_FLAG_PVP) != 0); + if (IsTaxi()) + { + uint32 taxiNodesId = sObjectMgr->GetNearestTaxiNode(GetPositionX(), GetPositionY(), GetPositionZ(), GetMapId(), + factionTemplate->FactionGroup & FACTION_MASK_ALLIANCE ? ALLIANCE : HORDE); + SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::TaxiNodesID), taxiNodesId); + } + } // updates spell bars for vehicles and set player's faction - should be called here, to overwrite faction that is set from the new template if (IsVehicle()) diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 4a780774155..aa8c5596d8c 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -22409,7 +22409,7 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc // change but I couldn't find a suitable alternative. OK to use class because only DK // can use this taxi. uint32 mount_display_id; - if (node->Flags & TAXI_NODE_FLAG_USE_FAVORITE_MOUNT && preferredMountDisplay) + if (node->GetFlags().HasFlag(TaxiNodeFlags::UsePlayerFavoriteMount) && preferredMountDisplay) mount_display_id = preferredMountDisplay; else mount_display_id = sObjectMgr->GetTaxiMountDisplayId(sourcenode, GetTeam(), npc == nullptr || (sourcenode == 315 && GetClass() == CLASS_DEATH_KNIGHT)); diff --git a/src/server/game/Entities/Taxi/TaxiPathGraph.cpp b/src/server/game/Entities/Taxi/TaxiPathGraph.cpp index 39bdb65b2b2..2ef20331ff0 100644 --- a/src/server/game/Entities/Taxi/TaxiPathGraph.cpp +++ b/src/server/game/Entities/Taxi/TaxiPathGraph.cpp @@ -17,6 +17,7 @@ #include "TaxiPathGraph.h" #include "DB2Stores.h" +#include "MapUtils.h" #include "ObjectMgr.h" #include "Player.h" #include <boost/graph/adjacency_list.hpp> @@ -32,8 +33,8 @@ struct EdgeCost uint32 Distance; uint32 EvaluateDistance(Player const* player) const { - uint32 requireFlag = (player->GetTeam() == ALLIANCE) ? TAXI_NODE_FLAG_ALLIANCE : TAXI_NODE_FLAG_HORDE; - if (!(To->Flags & requireFlag)) + TaxiNodeFlags requireFlag = (player->GetTeam() == ALLIANCE) ? TaxiNodeFlags::ShowOnAllianceMap : TaxiNodeFlags::ShowOnHordeMap; + if (!To->GetFlags().HasFlag(requireFlag)) return std::numeric_limits<uint16>::max(); if (PlayerConditionEntry const* condition = sPlayerConditionStore.LookupEntry(To->ConditionID)) @@ -122,10 +123,9 @@ void AddVerticeAndEdgeFromNodeInfo(TaxiNodesEntry const* from, TaxiNodesEntry co } } -vertex_descriptor GetVertexIDFromNodeID(TaxiNodesEntry const* node) +vertex_descriptor const* GetVertexIDFromNodeID(TaxiNodesEntry const* node) { - auto itr = m_verticesByNode.find(node->ID); - return itr != m_verticesByNode.end() ? itr->second : std::numeric_limits<vertex_descriptor>::max(); + return Trinity::Containers::MapGetValuePtr(m_verticesByNode, node->ID); } uint32 GetNodeIDFromVertexID(vertex_descriptor vertexID) @@ -172,7 +172,7 @@ void TaxiPathGraph::Initialize() { TaxiNodesEntry const* from = sTaxiNodesStore.LookupEntry(path->FromTaxiNode); TaxiNodesEntry const* to = sTaxiNodesStore.LookupEntry(path->ToTaxiNode); - if (from && to && from->Flags & (TAXI_NODE_FLAG_ALLIANCE | TAXI_NODE_FLAG_HORDE) && to->Flags & (TAXI_NODE_FLAG_ALLIANCE | TAXI_NODE_FLAG_HORDE)) + if (from && to && from->IsPartOfTaxiNetwork() && to->IsPartOfTaxiNetwork()) AddVerticeAndEdgeFromNodeInfo(from, to, path->ID, edges); } @@ -206,31 +206,37 @@ std::size_t TaxiPathGraph::GetCompleteNodeRoute(TaxiNodesEntry const* from, Taxi else { shortestPath.clear(); - std::vector<vertex_descriptor> p(boost::num_vertices(m_graph)); - std::vector<uint32> d(boost::num_vertices(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))) - .distance_map(boost::make_iterator_property_map(d.begin(), boost::get(boost::vertex_index, m_graph))) - .vertex_index_map(boost::get(boost::vertex_index, m_graph)) - .distance_compare(std::less<uint32>()) - .distance_combine(boost::closed_plus<uint32>()) - .distance_inf(std::numeric_limits<uint32>::max()) - .distance_zero(0) - .visitor(boost::dijkstra_visitor<boost::null_visitor>()) - .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(to); ; v = p[v]) + + vertex_descriptor const* fromVertexId = GetVertexIDFromNodeID(from); + vertex_descriptor const* toVertexId = GetVertexIDFromNodeID(to); + if (fromVertexId && toVertexId) { - shortestPath.push_back(GetNodeIDFromVertexID(v)); - if (v == p[v]) - break; + std::vector<vertex_descriptor> p(boost::num_vertices(m_graph)); + std::vector<uint32> d(boost::num_vertices(m_graph)); + + boost::dijkstra_shortest_paths(m_graph, *fromVertexId, + boost::predecessor_map(boost::make_iterator_property_map(p.begin(), boost::get(boost::vertex_index, m_graph))) + .distance_map(boost::make_iterator_property_map(d.begin(), boost::get(boost::vertex_index, m_graph))) + .vertex_index_map(boost::get(boost::vertex_index, m_graph)) + .distance_compare(std::less<uint32>()) + .distance_combine(boost::closed_plus<uint32>()) + .distance_inf(std::numeric_limits<uint32>::max()) + .distance_zero(0) + .visitor(boost::dijkstra_visitor<boost::null_visitor>()) + .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 = *toVertexId; ; v = p[v]) + { + shortestPath.push_back(GetNodeIDFromVertexID(v)); + if (v == p[v]) + break; + } + + std::reverse(shortestPath.begin(), shortestPath.end()); } - - std::reverse(shortestPath.begin(), shortestPath.end()); } return shortestPath.size(); @@ -238,9 +244,13 @@ std::size_t TaxiPathGraph::GetCompleteNodeRoute(TaxiNodesEntry const* from, Taxi void TaxiPathGraph::GetReachableNodesMask(TaxiNodesEntry const* from, TaxiMask* mask) { + vertex_descriptor const* vertexId = GetVertexIDFromNodeID(from); + if (!vertexId) + return; + boost::vector_property_map<boost::default_color_type> color(boost::num_vertices(m_graph)); std::fill(color.storage_begin(), color.storage_end(), boost::white_color); - boost::depth_first_visit(m_graph, GetVertexIDFromNodeID(from), make_discover_vertex_dfs_visitor([mask](vertex_descriptor vertex) + boost::depth_first_visit(m_graph, *vertexId, make_discover_vertex_dfs_visitor([mask](vertex_descriptor vertex) { if (TaxiNodesEntry const* taxiNode = sTaxiNodesStore.LookupEntry(GetNodeIDFromVertexID(vertex))) (*mask)[(taxiNode->ID - 1) / 8] |= 1 << ((taxiNode->ID - 1) % 8); diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index e53fbe9730d..e882198834a 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -6670,10 +6670,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; + TaxiNodeFlags requireFlag = (team == ALLIANCE) ? TaxiNodeFlags::ShowOnAllianceMap : TaxiNodeFlags::ShowOnHordeMap; for (TaxiNodesEntry const* node : sTaxiNodesStore) { - if (!node || node->ContinentID != mapid || !(node->Flags & requireFlag)) + if (!node || node->ContinentID != mapid || !node->GetFlags().HasFlag(requireFlag) || node->GetFlags().HasFlag(TaxiNodeFlags::IgnoreForFindNearest)) continue; uint32 field = uint32((node->ID - 1) / 8); diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index 103daba53d3..d7e9ca22edd 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -685,16 +685,26 @@ void WorldSession::HandleMoveSplineDoneOpcode(WorldPackets::Movement::MoveSpline TaxiNodesEntry const* curDestNode = sTaxiNodesStore.LookupEntry(curDest); // far teleport case - if (curDestNode && curDestNode->ContinentID != GetPlayer()->GetMapId() && GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE) + if (GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE) { if (FlightPathMovementGenerator* flight = dynamic_cast<FlightPathMovementGenerator*>(GetPlayer()->GetMotionMaster()->GetCurrentMovementGenerator())) { - // short preparations to continue flight - flight->SetCurrentNodeAfterTeleport(); - TaxiPathNodeEntry const* node = flight->GetPath()[flight->GetCurrentNode()]; - flight->SkipCurrentNode(); + bool shouldTeleport = curDestNode && curDestNode->ContinentID != GetPlayer()->GetMapId(); + if (!shouldTeleport) + { + TaxiPathNodeEntry const* currentNode = flight->GetPath()[flight->GetCurrentNode()]; + shouldTeleport = currentNode->Flags & TAXI_PATH_NODE_FLAG_TELEPORT; + } - GetPlayer()->TeleportTo(curDestNode->ContinentID, node->Loc.X, node->Loc.Y, node->Loc.Z, GetPlayer()->GetOrientation()); + if (shouldTeleport) + { + // short preparations to continue flight + flight->SetCurrentNodeAfterTeleport(); + TaxiPathNodeEntry const* node = flight->GetPath()[flight->GetCurrentNode()]; + flight->SkipCurrentNode(); + + GetPlayer()->TeleportTo(curDestNode->ContinentID, node->Loc.X, node->Loc.Y, node->Loc.Z, GetPlayer()->GetOrientation()); + } } } diff --git a/src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.cpp index 797d706c44d..dd45d94b088 100644 --- a/src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.cpp @@ -158,20 +158,20 @@ void FlightPathMovementGenerator::DoFinalize(Player* owner, bool active, bool/* if (!active) return; - uint32 taxiNodeId = owner->m_taxi.GetTaxiDestination(); owner->m_taxi.ClearTaxiDestinations(); owner->Dismount(); owner->RemoveUnitFlag(UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_ON_TAXI); - if (owner->m_taxi.empty()) - { - // update z position to ground and orientation for landing point - // this prevent cheating with landing point at lags - // when client side flight end early in comparison server side - owner->StopMoving(); + // update z position to ground and orientation for landing point + // this prevent cheating with landing point at lags + // when client side flight end early in comparison server side + owner->StopMoving(); - // When the player reaches the last flight point, teleport to destination taxi node location - if (TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(taxiNodeId)) + // When the player reaches the last flight point, teleport to destination taxi node location + if (!_path.empty() && (_path.size() < 2 || !(_path[_path.size() - 2]->Flags & TAXI_PATH_NODE_FLAG_TELEPORT))) + { + TaxiPathEntry const* lastPath = sTaxiPathStore.AssertEntry(_path.back()->PathID); + if (TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(lastPath->ToTaxiNode)) { owner->SetFallInformation(0, node->Pos.Z); owner->TeleportTo(node->ContinentID, node->Pos.X, node->Pos.Y, node->Pos.Z, owner->GetOrientation()); @@ -191,6 +191,8 @@ uint32 FlightPathMovementGenerator::GetPathAtMapEnd() const { if (_path[itr]->ContinentID != curMapId) return itr; + if (itr > 0 && _path[itr - 1]->Flags & TAXI_PATH_NODE_FLAG_TELEPORT) + return itr; } return _path.size(); @@ -198,7 +200,10 @@ uint32 FlightPathMovementGenerator::GetPathAtMapEnd() const bool IsNodeIncludedInShortenedPath(TaxiPathNodeEntry const* p1, TaxiPathNodeEntry const* p2) { - return p1->ContinentID != p2->ContinentID || std::pow(p1->Loc.X - p2->Loc.X, 2) + std::pow(p1->Loc.Y - p2->Loc.Y, 2) > SKIP_SPLINE_POINT_DISTANCE_SQ; + return p1->ContinentID != p2->ContinentID + || std::pow(p1->Loc.X - p2->Loc.X, 2) + std::pow(p1->Loc.Y - p2->Loc.Y, 2) > SKIP_SPLINE_POINT_DISTANCE_SQ + || p2->Flags & TAXI_PATH_NODE_FLAG_TELEPORT + || (p2->Flags & TAXI_PATH_NODE_FLAG_STOP && p2->Delay); } void FlightPathMovementGenerator::LoadPath(Player* owner, uint32 startNode /*= 0*/) @@ -226,7 +231,8 @@ void FlightPathMovementGenerator::LoadPath(Player* owner, uint32 startNode /*= 0 if (passedPreviousSegmentProximityCheck || !src || _path.empty() || IsNodeIncludedInShortenedPath(_path.back(), nodes[i])) { if ((!src || (IsNodeIncludedInShortenedPath(start, nodes[i]) && i >= 2)) && - (dst == taxi.size() - 1 || (IsNodeIncludedInShortenedPath(end, nodes[i]) && i < nodes.size() - 1))) + (dst == taxi.size() - 1 || (IsNodeIncludedInShortenedPath(end, nodes[i]) && (i < nodes.size() - 1 || _path.empty()))) && + (!(nodes[i]->Flags & TAXI_PATH_NODE_FLAG_TELEPORT) || _path.empty() || !(_path.back()->Flags & TAXI_PATH_NODE_FLAG_TELEPORT))) // skip consecutive teleports, only keep the first one { passedPreviousSegmentProximityCheck = true; _path.push_back(nodes[i]); @@ -240,7 +246,7 @@ void FlightPathMovementGenerator::LoadPath(Player* owner, uint32 startNode /*= 0 } } - _pointsForPathSwitch.push_back({ uint32(_path.size() - 1), int64(ceil(cost * discount)) }); + _pointsForPathSwitch.push_back({ uint32(std::max<std::size_t>(_path.size(), 1) - 1), int64(ceil(cost * discount)) }); } } @@ -252,7 +258,7 @@ void FlightPathMovementGenerator::SetCurrentNodeAfterTeleport() uint32 map0 = _path[_currentNode]->ContinentID; for (size_t i = _currentNode + 1; i < _path.size(); ++i) { - if (_path[i]->ContinentID != map0) + if (_path[i]->ContinentID != map0 || _path[i - 1]->Flags & TAXI_PATH_NODE_FLAG_TELEPORT) { _currentNode = i; return; |