aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2023-10-28 22:13:59 +0200
committerShauren <shauren.trinity@gmail.com>2023-10-28 22:13:59 +0200
commit73e0b3e77c04a7821f58d79211f344b9129602f1 (patch)
tree315e6970f0c97c4b45019b564446b358b08c5969 /src
parentb8770d96e43679c873f6643bcc81e46b6dcd497f (diff)
Core/Creatures: Taxi improvements
* Fixed flight master minimap icon * Fixed crash on Argus * Implemented teleport taxi nodes Closes #29389
Diffstat (limited to 'src')
-rw-r--r--src/server/game/DataStores/DB2Stores.cpp6
-rw-r--r--src/server/game/DataStores/DB2Structure.h17
-rw-r--r--src/server/game/DataStores/DBCEnums.h15
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp8
-rw-r--r--src/server/game/Entities/Player/Player.cpp2
-rw-r--r--src/server/game/Entities/Taxi/TaxiPathGraph.cpp70
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp4
-rw-r--r--src/server/game/Handlers/MovementHandler.cpp22
-rw-r--r--src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.cpp32
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;