Core/Waypoints: Refactor to split data into path and node related info in db
Port From (https://github.com/TrinityCore/TrinityCore/commit/12186ef8573f60abeff4747da58767ee71092600)
This commit is contained in:
@@ -113,15 +113,15 @@ namespace Game.Movement
|
||||
x = y = z = 0;
|
||||
|
||||
// prevent a crash at empty waypoint path.
|
||||
if (_path == null || _path.nodes.Empty())
|
||||
if (_path == null || _path.Nodes.Empty())
|
||||
return false;
|
||||
|
||||
Cypher.Assert(_currentNode < _path.nodes.Count, $"WaypointMovementGenerator::GetResetPosition: tried to reference a node id ({_currentNode}) which is not included in path ({_path.id})");
|
||||
WaypointNode waypoint = _path.nodes.ElementAt(_currentNode);
|
||||
Cypher.Assert(_currentNode < _path.Nodes.Count, $"WaypointMovementGenerator::GetResetPosition: tried to reference a node id ({_currentNode}) which is not included in path ({_path.Id})");
|
||||
WaypointNode waypoint = _path.Nodes.ElementAt(_currentNode);
|
||||
|
||||
x = waypoint.x;
|
||||
y = waypoint.y;
|
||||
z = waypoint.z;
|
||||
x = waypoint.X;
|
||||
y = waypoint.Y;
|
||||
z = waypoint.Z;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ namespace Game.Movement
|
||||
if (_loadedFromDB)
|
||||
{
|
||||
if (_pathId == 0)
|
||||
_pathId = owner.GetWaypointPath();
|
||||
_pathId = owner.GetWaypointPathId();
|
||||
|
||||
_path = Global.WaypointMgr.GetPath(_pathId);
|
||||
}
|
||||
@@ -143,6 +143,11 @@ namespace Game.Movement
|
||||
return;
|
||||
}
|
||||
|
||||
_followPathBackwardsFromEndToStart = _path.Flags.HasFlag(WaypointPathFlags.FollowPathBackwardsFromEndToStart);
|
||||
|
||||
if (_path.Nodes.Count == 1)
|
||||
_repeating = false;
|
||||
|
||||
owner.StopMoving();
|
||||
|
||||
_nextMoveTime.Reset(1000);
|
||||
@@ -163,7 +168,7 @@ namespace Game.Movement
|
||||
if (owner == null || !owner.IsAlive())
|
||||
return true;
|
||||
|
||||
if (HasFlag(MovementGeneratorFlags.Finalized | MovementGeneratorFlags.Paused) || _path == null || _path.nodes.Empty())
|
||||
if (HasFlag(MovementGeneratorFlags.Finalized | MovementGeneratorFlags.Paused) || _path == null || _path.Nodes.Empty())
|
||||
return true;
|
||||
|
||||
if (_duration != null)
|
||||
@@ -267,28 +272,32 @@ namespace Game.Movement
|
||||
}
|
||||
}
|
||||
|
||||
void MovementInform(Creature owner)
|
||||
public void MovementInform(Creature owner)
|
||||
{
|
||||
WaypointNode waypoint = _path.Nodes.ElementAt(_currentNode);
|
||||
CreatureAI ai = owner.GetAI();
|
||||
if (ai != null)
|
||||
ai.MovementInform(MovementGeneratorType.Waypoint, (uint)_currentNode);
|
||||
{
|
||||
ai.MovementInform(MovementGeneratorType.Waypoint, waypoint.Id);
|
||||
ai.WaypointReached(waypoint.Id, _path.Id);
|
||||
}
|
||||
}
|
||||
|
||||
void OnArrived(Creature owner)
|
||||
{
|
||||
if (_path == null || _path.nodes.Empty())
|
||||
if (_path == null || _path.Nodes.Empty())
|
||||
return;
|
||||
|
||||
Cypher.Assert(_currentNode < _path.nodes.Count, $"WaypointMovementGenerator.OnArrived: tried to reference a node id ({_currentNode}) which is not included in path ({_path.id})");
|
||||
WaypointNode waypoint = _path.nodes.ElementAt(_currentNode);
|
||||
if (waypoint.delay != 0)
|
||||
Cypher.Assert(_currentNode < _path.Nodes.Count, $"WaypointMovementGenerator.OnArrived: tried to reference a node id ({_currentNode}) which is not included in path ({_path.Id})");
|
||||
WaypointNode waypoint = _path.Nodes.ElementAt(_currentNode);
|
||||
if (waypoint.Delay != 0)
|
||||
{
|
||||
owner.ClearUnitState(UnitState.RoamingMove);
|
||||
_nextMoveTime.Reset(waypoint.delay);
|
||||
_nextMoveTime.Reset(waypoint.Delay);
|
||||
}
|
||||
|
||||
if (_waitTimeRangeAtPathEnd.HasValue && _followPathBackwardsFromEndToStart
|
||||
&& ((_isReturningToStart && _currentNode == 0) || (!_isReturningToStart && _currentNode == _path.nodes.Count - 1)))
|
||||
&& ((_isReturningToStart && _currentNode == 0) || (!_isReturningToStart && _currentNode == _path.Nodes.Count - 1)))
|
||||
{
|
||||
owner.ClearUnitState(UnitState.RoamingMove);
|
||||
TimeSpan waitTime = RandomHelper.RandTime(_waitTimeRangeAtPathEnd.Value.min, _waitTimeRangeAtPathEnd.Value.max);
|
||||
@@ -301,21 +310,15 @@ namespace Game.Movement
|
||||
_nextMoveTime.Reset(waitTime);
|
||||
}
|
||||
|
||||
// inform AI
|
||||
CreatureAI ai = owner.GetAI();
|
||||
if (ai != null)
|
||||
{
|
||||
ai.MovementInform(MovementGeneratorType.Waypoint, (uint)_currentNode);
|
||||
ai.WaypointReached(waypoint.id, _path.id);
|
||||
}
|
||||
MovementInform(owner);
|
||||
|
||||
owner.UpdateCurrentWaypointInfo(waypoint.id, _path.id);
|
||||
owner.UpdateCurrentWaypointInfo(waypoint.Id, _path.Id);
|
||||
}
|
||||
|
||||
void StartMove(Creature owner, bool relaunch = false)
|
||||
{
|
||||
// sanity checks
|
||||
if (owner == null || !owner.IsAlive() || HasFlag(MovementGeneratorFlags.Finalized) || _path == null || _path.nodes.Empty() || (relaunch && (HasFlag(MovementGeneratorFlags.InformEnabled) || !HasFlag(MovementGeneratorFlags.Initialized))))
|
||||
if (owner == null || !owner.IsAlive() || HasFlag(MovementGeneratorFlags.Finalized) || _path == null || _path.Nodes.Empty() || (relaunch && (HasFlag(MovementGeneratorFlags.InformEnabled) || !HasFlag(MovementGeneratorFlags.Initialized))))
|
||||
return;
|
||||
|
||||
if (owner.HasUnitState(UnitState.NotMove) || owner.IsMovementPreventedByCasting() || (owner.IsFormationLeader() && !owner.IsFormationLeaderMoveAllowed())) // if cannot move OR cannot move because of formation
|
||||
@@ -330,18 +333,18 @@ namespace Game.Movement
|
||||
{
|
||||
if (ComputeNextNode())
|
||||
{
|
||||
Cypher.Assert(_currentNode < _path.nodes.Count, $"WaypointMovementGenerator.StartMove: tried to reference a node id ({_currentNode}) which is not included in path ({_path.id})");
|
||||
Cypher.Assert(_currentNode < _path.Nodes.Count, $"WaypointMovementGenerator.StartMove: tried to reference a node id ({_currentNode}) which is not included in path ({_path.Id})");
|
||||
// inform AI
|
||||
CreatureAI ai = owner.GetAI();
|
||||
if (ai != null)
|
||||
ai.WaypointStarted(_path.nodes[_currentNode].id, _path.id);
|
||||
ai.WaypointStarted(_path.Nodes[_currentNode].Id, _path.Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
WaypointNode currentWaypoint = _path.nodes[_currentNode];
|
||||
float x = currentWaypoint.x;
|
||||
float y = currentWaypoint.y;
|
||||
float z = currentWaypoint.z;
|
||||
WaypointNode currentWaypoint = _path.Nodes[_currentNode];
|
||||
float x = currentWaypoint.X;
|
||||
float y = currentWaypoint.Y;
|
||||
float z = currentWaypoint.Z;
|
||||
float o = owner.GetOrientation();
|
||||
|
||||
if (!transportPath)
|
||||
@@ -365,7 +368,7 @@ namespace Game.Movement
|
||||
// inform AI
|
||||
CreatureAI ai = owner.GetAI();
|
||||
if (ai != null)
|
||||
ai.WaypointPathEnded(currentWaypoint.id, _path.id);
|
||||
ai.WaypointPathEnded(currentWaypoint.Id, _path.Id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -376,11 +379,11 @@ namespace Game.Movement
|
||||
// inform AI
|
||||
CreatureAI ai = owner.GetAI();
|
||||
if (ai != null)
|
||||
ai.WaypointStarted(_path.nodes[_currentNode].id, _path.id);
|
||||
ai.WaypointStarted(_path.Nodes[_currentNode].Id, _path.Id);
|
||||
}
|
||||
|
||||
Cypher.Assert(_currentNode < _path.nodes.Count, $"WaypointMovementGenerator.StartMove: tried to reference a node id ({_currentNode}) which is not included in path ({_path.id})");
|
||||
WaypointNode waypoint = _path.nodes[_currentNode];
|
||||
Cypher.Assert(_currentNode < _path.Nodes.Count, $"WaypointMovementGenerator.StartMove: tried to reference a node id ({_currentNode}) which is not included in path ({_path.Id})");
|
||||
WaypointNode waypoint = _path.Nodes[_currentNode];
|
||||
|
||||
RemoveFlag(MovementGeneratorFlags.Transitory | MovementGeneratorFlags.InformEnabled | MovementGeneratorFlags.TimedPaused);
|
||||
|
||||
@@ -394,12 +397,12 @@ namespace Game.Movement
|
||||
|
||||
//! Do not use formationDest here, MoveTo requires transport offsets due to DisableTransportPathTransformations() call
|
||||
//! but formationDest contains global coordinates
|
||||
init.MoveTo(waypoint.x, waypoint.y, waypoint.z, _generatePath);
|
||||
init.MoveTo(waypoint.X, waypoint.Y, waypoint.Z, _generatePath);
|
||||
|
||||
if (waypoint.orientation.HasValue && (waypoint.delay > 0 || _currentNode == _path.nodes.Count - 1))
|
||||
init.SetFacing(waypoint.orientation.Value);
|
||||
if (waypoint.Orientation.HasValue && (waypoint.Delay > 0 || _currentNode == _path.Nodes.Count - 1))
|
||||
init.SetFacing(waypoint.Orientation.Value);
|
||||
|
||||
switch (waypoint.moveType)
|
||||
switch (_path.MoveType)
|
||||
{
|
||||
case WaypointMoveType.Land:
|
||||
init.SetAnimation(AnimTier.Ground);
|
||||
@@ -440,16 +443,16 @@ namespace Game.Movement
|
||||
|
||||
bool ComputeNextNode()
|
||||
{
|
||||
if ((_currentNode == _path.nodes.Count - 1) && !_repeating)
|
||||
if ((_currentNode == _path.Nodes.Count - 1) && !_repeating)
|
||||
return false;
|
||||
|
||||
if (!_followPathBackwardsFromEndToStart || _path.nodes.Count < 2)
|
||||
_currentNode = (_currentNode + 1) % _path.nodes.Count;
|
||||
if (!_followPathBackwardsFromEndToStart || _path.Nodes.Count < 2)
|
||||
_currentNode = (_currentNode + 1) % _path.Nodes.Count;
|
||||
else
|
||||
{
|
||||
if (!_isReturningToStart)
|
||||
{
|
||||
if (++_currentNode >= _path.nodes.Count)
|
||||
if (++_currentNode >= _path.Nodes.Count)
|
||||
{
|
||||
_currentNode -= 2;
|
||||
_isReturningToStart = true;
|
||||
|
||||
@@ -1035,7 +1035,7 @@ namespace Game.Movement
|
||||
public void MovePath(WaypointPath path, bool repeatable, TimeSpan? duration = null, float? speed = null, MovementWalkRunSpeedSelectionMode speedSelectionMode = MovementWalkRunSpeedSelectionMode.Default,
|
||||
(TimeSpan min, TimeSpan max)? waitTimeRangeAtPathEnd = null, float? wanderDistanceAtPathEnds = null, bool followPathBackwardsFromEndToStart = false, bool generatePath = true)
|
||||
{
|
||||
Log.outDebug(LogFilter.Movement, $"MotionMaster::MovePath: '{_owner.GetGUID()}', starts moving over path Id: {path.id} (repeatable: {repeatable})");
|
||||
Log.outDebug(LogFilter.Movement, $"MotionMaster::MovePath: '{_owner.GetGUID()}', starts moving over path Id: {path.Id} (repeatable: {repeatable})");
|
||||
Add(new WaypointMovementGenerator(path, repeatable, duration, speed, speedSelectionMode, waitTimeRangeAtPathEnd, wanderDistanceAtPathEnds, followPathBackwardsFromEndToStart, generatePath), MovementSlot.Default);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,11 @@
|
||||
// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Framework.Database;
|
||||
using Game.Entities;
|
||||
using Game.Maps;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Game
|
||||
{
|
||||
@@ -11,16 +14,24 @@ namespace Game
|
||||
{
|
||||
WaypointManager() { }
|
||||
|
||||
public void Load()
|
||||
public void LoadPaths()
|
||||
{
|
||||
_LoadPaths();
|
||||
_LoadPathNodes();
|
||||
DoPostLoadingChecks();
|
||||
}
|
||||
|
||||
void _LoadPaths()
|
||||
{
|
||||
_pathStorage.Clear();
|
||||
|
||||
var oldMSTime = Time.GetMSTime();
|
||||
|
||||
// 0 1 2 3 4 5 6 7
|
||||
SQLResult result = DB.World.Query("SELECT id, point, position_x, position_y, position_z, orientation, move_type, delay FROM waypoint_data ORDER BY id, point");
|
||||
|
||||
// 0 1 2
|
||||
SQLResult result = DB.World.Query("SELECT PathId, MoveType, Flags FROM waypoint_path");
|
||||
if (result.IsEmpty())
|
||||
{
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loaded 0 waypoints. DB table `waypoint_data` is empty!");
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loaded 0 waypoint paths. DB table `waypoint_path` is empty!");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -28,143 +39,308 @@ namespace Game
|
||||
|
||||
do
|
||||
{
|
||||
uint pathId = result.Read<uint>(0);
|
||||
|
||||
float x = result.Read<float>(2);
|
||||
float y = result.Read<float>(3);
|
||||
float z = result.Read<float>(4);
|
||||
float? o = null;
|
||||
if (!result.IsNull(5))
|
||||
o = result.Read<float>(5);
|
||||
|
||||
GridDefines.NormalizeMapCoord(ref x);
|
||||
GridDefines.NormalizeMapCoord(ref y);
|
||||
|
||||
WaypointNode waypoint = new();
|
||||
waypoint.id = result.Read<uint>(1);
|
||||
waypoint.x = x;
|
||||
waypoint.y = y;
|
||||
waypoint.z = z;
|
||||
waypoint.orientation = o;
|
||||
waypoint.moveType = (WaypointMoveType)result.Read<uint>(6);
|
||||
|
||||
if (waypoint.moveType >= WaypointMoveType.Max)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, $"Waypoint {waypoint.id} in waypoint_data has invalid move_type, ignoring");
|
||||
continue;
|
||||
}
|
||||
|
||||
waypoint.delay = result.Read<uint>(7);
|
||||
|
||||
if (!_waypointStore.ContainsKey(pathId))
|
||||
_waypointStore[pathId] = new WaypointPath();
|
||||
|
||||
WaypointPath path = _waypointStore[pathId];
|
||||
path.id = pathId;
|
||||
path.nodes.Add(waypoint);
|
||||
|
||||
LoadPathFromDB(result.GetFields());
|
||||
++count;
|
||||
} while (result.NextRow());
|
||||
|
||||
Log.outInfo(LogFilter.ServerLoading, $"Loaded {count} waypoints in {Time.GetMSTimeDiffToNow(oldMSTime)} ms");
|
||||
Log.outInfo(LogFilter.ServerLoading, $"Loaded {count} waypoint paths in {Time.GetMSTimeDiffToNow(oldMSTime)} ms");
|
||||
}
|
||||
|
||||
public void ReloadPath(uint id)
|
||||
void _LoadPathNodes()
|
||||
{
|
||||
_waypointStore.Remove(id);
|
||||
|
||||
PreparedStatement stmt = WorldDatabase.GetPreparedStatement(WorldStatements.SEL_WAYPOINT_DATA_BY_ID);
|
||||
stmt.AddValue(0, id);
|
||||
SQLResult result = DB.World.Query(stmt);
|
||||
uint oldMSTime = Time.GetMSTime();
|
||||
|
||||
// 0 1 2 3 4 5 6
|
||||
SQLResult result = DB.World.Query("SELECT PathId, NodeId, PositionX, PositionY, PositionZ, Orientation, Delay FROM waypoint_path_node ORDER BY PathId, NodeId");
|
||||
if (result.IsEmpty())
|
||||
{
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loaded 0 waypoint path nodes. DB table `waypoint_path_node` is empty!");
|
||||
return;
|
||||
}
|
||||
|
||||
uint count = 0;
|
||||
|
||||
List<WaypointNode> values = new();
|
||||
do
|
||||
{
|
||||
float x = result.Read<float>(1);
|
||||
float y = result.Read<float>(2);
|
||||
float z = result.Read<float>(3);
|
||||
float? o = null;
|
||||
if (!result.IsNull(4))
|
||||
o = result.Read<float>(4);
|
||||
|
||||
GridDefines.NormalizeMapCoord(ref x);
|
||||
GridDefines.NormalizeMapCoord(ref y);
|
||||
|
||||
WaypointNode waypoint = new();
|
||||
waypoint.id = result.Read<uint>(0);
|
||||
waypoint.x = x;
|
||||
waypoint.y = y;
|
||||
waypoint.z = z;
|
||||
waypoint.orientation = o;
|
||||
waypoint.moveType = (WaypointMoveType)result.Read<uint>(5);
|
||||
|
||||
if (waypoint.moveType >= WaypointMoveType.Max)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, $"Waypoint {waypoint.id} in waypoint_data has invalid move_type, ignoring");
|
||||
continue;
|
||||
}
|
||||
|
||||
waypoint.delay = result.Read<uint>(6);
|
||||
|
||||
values.Add(waypoint);
|
||||
LoadPathNodesFromDB(result.GetFields());
|
||||
++count;
|
||||
}
|
||||
while (result.NextRow());
|
||||
|
||||
_waypointStore[id] = new WaypointPath(id, values);
|
||||
Log.outInfo(LogFilter.ServerLoading, $"Loaded {count} waypoint path nodes in {Time.GetMSTimeDiffToNow(oldMSTime)} ms");
|
||||
DoPostLoadingChecks();
|
||||
}
|
||||
|
||||
public WaypointPath GetPath(uint id)
|
||||
void LoadPathFromDB(SQLFields fields)
|
||||
{
|
||||
return _waypointStore.LookupByKey(id);
|
||||
uint pathId = fields.Read<uint>(0);
|
||||
|
||||
WaypointPath path = new();
|
||||
path.Id = pathId;
|
||||
path.MoveType = (WaypointMoveType)fields.Read<byte>(1);
|
||||
|
||||
if (path.MoveType >= WaypointMoveType.Max)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, $"PathId {pathId} in `waypoint_path` has invalid MoveType {path.MoveType}, ignoring");
|
||||
return;
|
||||
}
|
||||
path.Flags = (WaypointPathFlags)fields.Read<byte>(2);
|
||||
path.Nodes.Clear();
|
||||
|
||||
_pathStorage.Add(pathId, path);
|
||||
}
|
||||
|
||||
Dictionary<uint, WaypointPath> _waypointStore = new();
|
||||
void LoadPathNodesFromDB(SQLFields fields)
|
||||
{
|
||||
uint pathId = fields.Read<uint>(0);
|
||||
|
||||
if (!_pathStorage.ContainsKey(pathId))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, $"PathId {pathId} in `waypoint_path_node` does not exist in `waypoint_path`, ignoring");
|
||||
return;
|
||||
}
|
||||
|
||||
float x = fields.Read<float>(2);
|
||||
float y = fields.Read<float>(3);
|
||||
float z = fields.Read<float>(4);
|
||||
float? o = null;
|
||||
if (!fields.IsNull(5))
|
||||
o = fields.Read<float>(5);
|
||||
|
||||
GridDefines.NormalizeMapCoord(ref x);
|
||||
GridDefines.NormalizeMapCoord(ref y);
|
||||
|
||||
WaypointNode waypoint = new(fields.Read<uint>(1), x, y, z, o, fields.Read<uint>(6));
|
||||
_pathStorage[pathId].Nodes.Add(waypoint);
|
||||
}
|
||||
|
||||
void DoPostLoadingChecks()
|
||||
{
|
||||
foreach (var path in _pathStorage)
|
||||
{
|
||||
WaypointPath pathInfo = path.Value;
|
||||
if (pathInfo.Nodes.Empty())
|
||||
Log.outError(LogFilter.Sql, $"PathId {pathInfo.Id} in `waypoint_path` has no assigned nodes in `waypoint_path_node`");
|
||||
|
||||
if (pathInfo.Flags.HasFlag(WaypointPathFlags.FollowPathBackwardsFromEndToStart) && pathInfo.Nodes.Count < 2)
|
||||
Log.outError(LogFilter.Sql, $"PathId {pathInfo.Id} in `waypoint_path` has FollowPathBackwardsFromEndToStart set, but only {pathInfo.Nodes.Count} nodes, requires {2}");
|
||||
}
|
||||
}
|
||||
|
||||
public void ReloadPath(uint pathId)
|
||||
{
|
||||
// waypoint_path
|
||||
PreparedStatement stmt = WorldDatabase.GetPreparedStatement(WorldStatements.SEL_WAYPOINT_PATH_BY_PATHID);
|
||||
stmt.AddValue(0, pathId);
|
||||
SQLResult result = DB.World.Query(stmt);
|
||||
if (result.IsEmpty())
|
||||
{
|
||||
Log.outError(LogFilter.Sql, $"PathId {pathId} in `waypoint_path` not found, ignoring");
|
||||
return;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
LoadPathFromDB(result.GetFields());
|
||||
} while (result.NextRow());
|
||||
|
||||
// waypoint_path_data
|
||||
stmt = WorldDatabase.GetPreparedStatement(WorldStatements.SEL_WAYPOINT_PATH_NODE_BY_PATHID);
|
||||
stmt.AddValue(0, pathId);
|
||||
|
||||
result = DB.World.Query(stmt);
|
||||
if (result.IsEmpty())
|
||||
{
|
||||
Log.outError(LogFilter.Sql, $"PathId {pathId} in `waypoint_path_node` not found, ignoring");
|
||||
return;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
LoadPathNodesFromDB(result.GetFields());
|
||||
} while (result.NextRow());
|
||||
}
|
||||
|
||||
public void VisualizePath(Unit owner, WaypointPath path, uint? displayId)
|
||||
{
|
||||
foreach (WaypointNode node in path.Nodes)
|
||||
{
|
||||
var pathNodePair = (path.Id, node.Id);
|
||||
if (!_nodeToVisualWaypointGUIDsMap.ContainsKey(pathNodePair))
|
||||
continue;
|
||||
|
||||
TempSummon summon = owner.SummonCreature(1, node.X, node.Y, node.Z, node.Orientation.HasValue ? node.Orientation.Value : 0.0f);
|
||||
if (summon == null)
|
||||
continue;
|
||||
|
||||
if (displayId.HasValue)
|
||||
{
|
||||
summon.SetDisplayId(displayId.Value, true);
|
||||
summon.SetObjectScale(0.5f);
|
||||
}
|
||||
_nodeToVisualWaypointGUIDsMap[pathNodePair] = summon.GetGUID();
|
||||
_visualWaypointGUIDToNodeMap[summon.GetGUID()] = (path, node);
|
||||
}
|
||||
}
|
||||
|
||||
public void DevisualizePath(Unit owner, WaypointPath path)
|
||||
{
|
||||
foreach (WaypointNode node in path.Nodes)
|
||||
{
|
||||
var pathNodePair = (path.Id, node.Id);
|
||||
if (!_nodeToVisualWaypointGUIDsMap.TryGetValue(pathNodePair, out ObjectGuid guid))
|
||||
continue;
|
||||
|
||||
Creature creature = ObjectAccessor.GetCreature(owner, guid);
|
||||
if (creature == null)
|
||||
continue;
|
||||
|
||||
_visualWaypointGUIDToNodeMap.Remove(guid);
|
||||
_nodeToVisualWaypointGUIDsMap.Remove(pathNodePair);
|
||||
|
||||
creature.DespawnOrUnsummon();
|
||||
}
|
||||
}
|
||||
|
||||
public void MoveNode(WaypointPath path, WaypointNode node, Position pos)
|
||||
{
|
||||
PreparedStatement stmt = WorldDatabase.GetPreparedStatement(WorldStatements.UPD_WAYPOINT_PATH_NODE_POSITION);
|
||||
stmt.AddValue(0, pos.GetPositionX());
|
||||
stmt.AddValue(1, pos.GetPositionY());
|
||||
stmt.AddValue(2, pos.GetPositionZ());
|
||||
stmt.AddValue(3, pos.GetOrientation());
|
||||
stmt.AddValue(4, path.Id);
|
||||
stmt.AddValue(5, node.Id);
|
||||
DB.World.Execute(stmt);
|
||||
}
|
||||
|
||||
public void DeleteNode(WaypointPath path, WaypointNode node)
|
||||
{
|
||||
PreparedStatement stmt = WorldDatabase.GetPreparedStatement(WorldStatements.DEL_WAYPOINT_PATH_NODE);
|
||||
stmt.AddValue(0, path.Id);
|
||||
stmt.AddValue(1, node.Id);
|
||||
DB.World.Execute(stmt);
|
||||
|
||||
stmt = WorldDatabase.GetPreparedStatement(WorldStatements.UPD_WAYPOINT_PATH_NODE);
|
||||
stmt.AddValue(0, path.Id);
|
||||
stmt.AddValue(1, node.Id);
|
||||
DB.World.Execute(stmt);
|
||||
}
|
||||
|
||||
void DeleteNode(uint pathId, uint nodeId)
|
||||
{
|
||||
WaypointPath path = GetPath(pathId);
|
||||
if (path == null)
|
||||
return;
|
||||
|
||||
WaypointNode node = GetNode(path, nodeId);
|
||||
if (node == null)
|
||||
return;
|
||||
|
||||
DeleteNode(path, node);
|
||||
}
|
||||
|
||||
public WaypointPath GetPath(uint pathId)
|
||||
{
|
||||
return _pathStorage.LookupByKey(pathId);
|
||||
}
|
||||
|
||||
public WaypointNode GetNode(WaypointPath path, uint nodeId)
|
||||
{
|
||||
return path.Nodes.FirstOrDefault(node => node.Id == nodeId); ;
|
||||
}
|
||||
|
||||
public WaypointNode GetNode(uint pathId, uint nodeId)
|
||||
{
|
||||
WaypointPath path = GetPath(pathId);
|
||||
if (path == null)
|
||||
return null;
|
||||
|
||||
return GetNode(path.Id, nodeId);
|
||||
}
|
||||
|
||||
public WaypointPath GetPathByVisualGUID(ObjectGuid guid)
|
||||
{
|
||||
if (!_visualWaypointGUIDToNodeMap.TryGetValue(guid, out var pair))
|
||||
return null;
|
||||
|
||||
return pair.Item1;
|
||||
}
|
||||
|
||||
public WaypointNode GetNodeByVisualGUID(ObjectGuid guid)
|
||||
{
|
||||
if (!_visualWaypointGUIDToNodeMap.TryGetValue(guid, out var pair))
|
||||
return null;
|
||||
|
||||
return pair.Item2;
|
||||
}
|
||||
|
||||
public ObjectGuid GetVisualGUIDByNode(uint pathId, uint nodeId)
|
||||
{
|
||||
if (!_nodeToVisualWaypointGUIDsMap.TryGetValue((pathId, nodeId), out var guid))
|
||||
return ObjectGuid.Empty;
|
||||
|
||||
return guid;
|
||||
}
|
||||
|
||||
Dictionary<uint /*pathId*/, WaypointPath> _pathStorage = new();
|
||||
|
||||
Dictionary<(uint /*pathId*/, uint /*nodeId*/), ObjectGuid> _nodeToVisualWaypointGUIDsMap = new();
|
||||
Dictionary<ObjectGuid, (WaypointPath, WaypointNode)> _visualWaypointGUIDToNodeMap = new();
|
||||
}
|
||||
|
||||
public class WaypointNode
|
||||
{
|
||||
public WaypointNode() { moveType = WaypointMoveType.Run; }
|
||||
public WaypointNode(uint _id, float _x, float _y, float _z, float? _orientation = null, uint _delay = 0)
|
||||
public WaypointNode() { MoveType = WaypointMoveType.Run; }
|
||||
public WaypointNode(uint id, float x, float y, float z, float? orientation = null, uint delay = 0)
|
||||
{
|
||||
id = _id;
|
||||
x = _x;
|
||||
y = _y;
|
||||
z = _z;
|
||||
orientation = _orientation;
|
||||
delay = _delay;
|
||||
moveType = WaypointMoveType.Walk;
|
||||
Id = id;
|
||||
X = x;
|
||||
Y = y;
|
||||
Z = z;
|
||||
Orientation = orientation;
|
||||
Delay = delay;
|
||||
MoveType = WaypointMoveType.Walk;
|
||||
}
|
||||
|
||||
public uint id;
|
||||
public float x, y, z;
|
||||
public float? orientation;
|
||||
public uint delay;
|
||||
public WaypointMoveType moveType;
|
||||
public uint Id;
|
||||
public float X;
|
||||
public float Y;
|
||||
public float Z;
|
||||
public float? Orientation;
|
||||
public uint Delay;
|
||||
public WaypointMoveType MoveType;
|
||||
}
|
||||
|
||||
public class WaypointPath
|
||||
{
|
||||
public WaypointPath() { }
|
||||
public WaypointPath(uint _id, List<WaypointNode> _nodes)
|
||||
public WaypointPath(uint id, List<WaypointNode> nodes)
|
||||
{
|
||||
id = _id;
|
||||
nodes = _nodes;
|
||||
Id = id;
|
||||
Nodes = nodes;
|
||||
}
|
||||
|
||||
public List<WaypointNode> nodes = new();
|
||||
public uint id;
|
||||
public List<WaypointNode> Nodes = new();
|
||||
public uint Id;
|
||||
public WaypointMoveType MoveType;
|
||||
public WaypointPathFlags Flags = WaypointPathFlags.None;
|
||||
}
|
||||
|
||||
public enum WaypointMoveType
|
||||
{
|
||||
Walk,
|
||||
Run,
|
||||
Land,
|
||||
Takeoff,
|
||||
Walk = 0,
|
||||
Run = 1,
|
||||
Land = 2,
|
||||
Takeoff = 3,
|
||||
|
||||
Max
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum WaypointPathFlags
|
||||
{
|
||||
None = 0x00,
|
||||
FollowPathBackwardsFromEndToStart = 0x01,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user