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:
@@ -569,7 +569,7 @@ namespace Framework.Constants
|
|||||||
CommandReloadSpellGroupStackRules = 703,
|
CommandReloadSpellGroupStackRules = 703,
|
||||||
CommandReloadCypherString = 704,
|
CommandReloadCypherString = 704,
|
||||||
// 705 - 706 previously used, do not reuse
|
// 705 - 706 previously used, do not reuse
|
||||||
CommandReloadWaypointData = 707,
|
CommandReloadWaypointPath = 707,
|
||||||
CommandReloadVehicleAccesory = 708,
|
CommandReloadVehicleAccesory = 708,
|
||||||
CommandReloadVehicleTemplateAccessory = 709,
|
CommandReloadVehicleTemplateAccessory = 709,
|
||||||
CommandReset = 710,
|
CommandReset = 710,
|
||||||
|
|||||||
@@ -28,19 +28,20 @@ namespace Framework.Database
|
|||||||
PrepareStatement(WorldStatements.UPD_CREATURE_WANDER_DISTANCE, "UPDATE creature SET wander_distance = ?, MovementType = ? WHERE guid = ?");
|
PrepareStatement(WorldStatements.UPD_CREATURE_WANDER_DISTANCE, "UPDATE creature SET wander_distance = ?, MovementType = ? WHERE guid = ?");
|
||||||
PrepareStatement(WorldStatements.UPD_CREATURE_SPAWN_TIME_SECS, "UPDATE creature SET spawntimesecs = ? WHERE guid = ?");
|
PrepareStatement(WorldStatements.UPD_CREATURE_SPAWN_TIME_SECS, "UPDATE creature SET spawntimesecs = ? WHERE guid = ?");
|
||||||
PrepareStatement(WorldStatements.INS_CREATURE_FORMATION, "INSERT INTO creature_formations (leaderGUID, memberGUID, dist, angle, groupAI) VALUES (?, ?, ?, ?, ?)");
|
PrepareStatement(WorldStatements.INS_CREATURE_FORMATION, "INSERT INTO creature_formations (leaderGUID, memberGUID, dist, angle, groupAI) VALUES (?, ?, ?, ?, ?)");
|
||||||
PrepareStatement(WorldStatements.INS_WAYPOINT_DATA, "INSERT INTO waypoint_data (id, point, position_x, position_y, position_z, orientation) VALUES (?, ?, ?, ?, ?, ?)");
|
PrepareStatement(WorldStatements.SEL_WAYPOINT_PATH_BY_PATHID, "SELECT PathId, MoveType, Flags FROM waypoint_path WHERE PathId = ?");
|
||||||
PrepareStatement(WorldStatements.DEL_WAYPOINT_DATA, "DELETE FROM waypoint_data WHERE id = ? AND point = ?");
|
PrepareStatement(WorldStatements.INS_WAYPOINT_PATH_NODE, "INSERT INTO waypoint_path_node (PathId, NodeId, PositionX, PositionY, PositionZ, Orientation) VALUES (?, ?, ?, ?, ?, ?)");
|
||||||
PrepareStatement(WorldStatements.UPD_WAYPOINT_DATA_POINT, "UPDATE waypoint_data SET point = point - 1 WHERE id = ? AND point > ?");
|
PrepareStatement(WorldStatements.DEL_WAYPOINT_PATH_NODE, "DELETE FROM waypoint_path_node WHERE PathId = ? AND NodeId = ?");
|
||||||
PrepareStatement(WorldStatements.UPD_WAYPOINT_DATA_POSITION, "UPDATE waypoint_data SET position_x = ?, position_y = ?, position_z = ?, orientation = ? where id = ? AND point = ?");
|
PrepareStatement(WorldStatements.UPD_WAYPOINT_PATH_NODE, "UPDATE waypoint_path_node SET NodeId = NodeId - 1 WHERE PathId = ? AND NodeId > ?");
|
||||||
PrepareStatement(WorldStatements.SEL_WAYPOINT_DATA_MAX_ID, "SELECT MAX(id) FROM waypoint_data");
|
PrepareStatement(WorldStatements.UPD_WAYPOINT_PATH_NODE_POSITION, "UPDATE waypoint_path_node SET PositionX = ?, PositionY = ?, PositionZ = ?, Orientation = ? WHERE PathId = ? AND NodeId = ?");
|
||||||
PrepareStatement(WorldStatements.SEL_WAYPOINT_DATA_MAX_POINT, "SELECT MAX(point) FROM waypoint_data WHERE id = ?");
|
PrepareStatement(WorldStatements.SEL_WAYPOINT_PATH_NODE_MAX_PATHID, "SELECT MAX(PathId) FROM waypoint_path_node");
|
||||||
PrepareStatement(WorldStatements.SEL_WAYPOINT_DATA_BY_ID, "SELECT point, position_x, position_y, position_z, orientation, move_type, delay FROM waypoint_data WHERE id = ? ORDER BY point");
|
PrepareStatement(WorldStatements.SEL_WAYPOINT_PATH_NODE_MAX_NODEID, "SELECT MAX(NodeId) FROM waypoint_path_node WHERE PathId = ?");
|
||||||
PrepareStatement(WorldStatements.SEL_WAYPOINT_DATA_POS_BY_ID, "SELECT point, position_x, position_y, position_z, orientation FROM waypoint_data WHERE id = ?");
|
PrepareStatement(WorldStatements.SEL_WAYPOINT_PATH_NODE_BY_PATHID, "SELECT PathId, NodeId, PositionX, PositionY, PositionZ, Orientation, Delay FROM waypoint_path_node WHERE PathId = ? ORDER BY NodeId");
|
||||||
PrepareStatement(WorldStatements.SEL_WAYPOINT_DATA_POS_FIRST_BY_ID, "SELECT position_x, position_y, position_z, orientation FROM waypoint_data WHERE point = 1 AND id = ?");
|
PrepareStatement(WorldStatements.SEL_WAYPOINT_PATH_NODE_POS_BY_PATHID, "SELECT NodeId, PositionX, PositionY, PositionZ, Orientation FROM waypoint_path_node WHERE PathId = ?");
|
||||||
PrepareStatement(WorldStatements.SEL_WAYPOINT_DATA_POS_LAST_BY_ID, "SELECT position_x, position_y, position_z, orientation FROM waypoint_data WHERE id = ? ORDER BY point DESC LIMIT 1");
|
PrepareStatement(WorldStatements.SEL_WAYPOINT_PATH_NODE_POS_FIRST_BY_PATHID, "SELECT PositionX, PositionY, PositionZ, Orientation FROM waypoint_path_node WHERE NodeId = 1 AND PathId = ?");
|
||||||
PrepareStatement(WorldStatements.SEL_WAYPOINT_DATA_BY_POS, "SELECT id, point FROM waypoint_data WHERE (abs(position_x - ?) <= ?) and (abs(position_y - ?) <= ?) and (abs(position_z - ?) <= ?)");
|
PrepareStatement(WorldStatements.SEL_WAYPOINT_PATH_NODE_POS_LAST_BY_PATHID, "SELECT PositionX, PositionY, PositionZ, Orientation FROM waypoint_path_node WHERE PathId = ? ORDER BY NodeId DESC LIMIT 1");
|
||||||
PrepareStatement(WorldStatements.INS_CREATURE_ADDON, "INSERT INTO creature_addon(guid, path_id) VALUES (?, ?)");
|
PrepareStatement(WorldStatements.SEL_WAYPOINT_PATH_NODE_BY_POS, "SELECT PathId, NodeId FROM waypoint_path_node WHERE (abs(PositionX - ?) <= ?) and (abs(PositionY - ?) <= ?) and (abs(PositionZ - ?) <= ?)");
|
||||||
PrepareStatement(WorldStatements.UPD_CREATURE_ADDON_PATH, "UPDATE creature_addon SET path_id = ? WHERE guid = ?");
|
PrepareStatement(WorldStatements.INS_CREATURE_ADDON, "INSERT INTO creature_addon(guid, PathId) VALUES (?, ?)");
|
||||||
|
PrepareStatement(WorldStatements.UPD_CREATURE_ADDON_PATH, "UPDATE creature_addon SET PathId = ? WHERE guid = ?");
|
||||||
PrepareStatement(WorldStatements.DEL_CREATURE_ADDON, "DELETE FROM creature_addon WHERE guid = ?");
|
PrepareStatement(WorldStatements.DEL_CREATURE_ADDON, "DELETE FROM creature_addon WHERE guid = ?");
|
||||||
PrepareStatement(WorldStatements.SEL_CREATURE_ADDON_BY_GUID, "SELECT guid FROM creature_addon WHERE guid = ?");
|
PrepareStatement(WorldStatements.SEL_CREATURE_ADDON_BY_GUID, "SELECT guid FROM creature_addon WHERE guid = ?");
|
||||||
PrepareStatement(WorldStatements.DEL_CREATURE, "DELETE FROM creature WHERE guid = ?");
|
PrepareStatement(WorldStatements.DEL_CREATURE, "DELETE FROM creature WHERE guid = ?");
|
||||||
@@ -88,22 +89,18 @@ namespace Framework.Database
|
|||||||
UPD_CREATURE_WANDER_DISTANCE,
|
UPD_CREATURE_WANDER_DISTANCE,
|
||||||
UPD_CREATURE_SPAWN_TIME_SECS,
|
UPD_CREATURE_SPAWN_TIME_SECS,
|
||||||
INS_CREATURE_FORMATION,
|
INS_CREATURE_FORMATION,
|
||||||
INS_WAYPOINT_DATA,
|
SEL_WAYPOINT_PATH_BY_PATHID,
|
||||||
DEL_WAYPOINT_DATA,
|
INS_WAYPOINT_PATH_NODE,
|
||||||
UPD_WAYPOINT_DATA_POINT,
|
DEL_WAYPOINT_PATH_NODE,
|
||||||
UPD_WAYPOINT_DATA_POSITION,
|
UPD_WAYPOINT_PATH_NODE,
|
||||||
UPD_WAYPOINT_DATA_WPGUID,
|
UPD_WAYPOINT_PATH_NODE_POSITION,
|
||||||
UPD_WAYPOINT_DATA_ALL_WPGUID,
|
SEL_WAYPOINT_PATH_NODE_MAX_PATHID,
|
||||||
SEL_WAYPOINT_DATA_MAX_ID,
|
SEL_WAYPOINT_PATH_NODE_BY_PATHID,
|
||||||
SEL_WAYPOINT_DATA_BY_ID,
|
SEL_WAYPOINT_PATH_NODE_POS_BY_PATHID,
|
||||||
SEL_WAYPOINT_DATA_POS_BY_ID,
|
SEL_WAYPOINT_PATH_NODE_POS_FIRST_BY_PATHID,
|
||||||
SEL_WAYPOINT_DATA_POS_FIRST_BY_ID,
|
SEL_WAYPOINT_PATH_NODE_POS_LAST_BY_PATHID,
|
||||||
SEL_WAYPOINT_DATA_POS_LAST_BY_ID,
|
SEL_WAYPOINT_PATH_NODE_MAX_NODEID,
|
||||||
SEL_WAYPOINT_DATA_BY_WPGUID,
|
SEL_WAYPOINT_PATH_NODE_BY_POS,
|
||||||
SEL_WAYPOINT_DATA_ALL_BY_WPGUID,
|
|
||||||
SEL_WAYPOINT_DATA_MAX_POINT,
|
|
||||||
SEL_WAYPOINT_DATA_BY_POS,
|
|
||||||
SEL_WAYPOINT_DATA_WPGUID_BY_ID,
|
|
||||||
UPD_CREATURE_ADDON_PATH,
|
UPD_CREATURE_ADDON_PATH,
|
||||||
INS_CREATURE_ADDON,
|
INS_CREATURE_ADDON,
|
||||||
DEL_CREATURE_ADDON,
|
DEL_CREATURE_ADDON,
|
||||||
|
|||||||
@@ -295,13 +295,13 @@ namespace Game.AI
|
|||||||
}
|
}
|
||||||
else if (moveType == MovementGeneratorType.Waypoint)
|
else if (moveType == MovementGeneratorType.Waypoint)
|
||||||
{
|
{
|
||||||
Cypher.Assert(Id < _path.nodes.Count, $"EscortAI::MovementInform: referenced movement id ({Id}) points to non-existing node in loaded path ({me.GetGUID()})");
|
Cypher.Assert(Id < _path.Nodes.Count, $"EscortAI::MovementInform: referenced movement id ({Id}) points to non-existing node in loaded path ({me.GetGUID()})");
|
||||||
WaypointNode waypoint = _path.nodes[(int)Id];
|
WaypointNode waypoint = _path.Nodes[(int)Id];
|
||||||
|
|
||||||
Log.outDebug(LogFilter.ScriptsAi, $"EscortAI::MovementInform: waypoint node {waypoint.id} reached ({me.GetGUID()})");
|
Log.outDebug(LogFilter.ScriptsAi, $"EscortAI::MovementInform: waypoint node {waypoint.Id} reached ({me.GetGUID()})");
|
||||||
|
|
||||||
// last point
|
// last point
|
||||||
if (Id == _path.nodes.Count - 1)
|
if (Id == _path.Nodes.Count - 1)
|
||||||
{
|
{
|
||||||
_started = false;
|
_started = false;
|
||||||
_ended = true;
|
_ended = true;
|
||||||
@@ -310,7 +310,7 @@ namespace Game.AI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddWaypoint(uint id, float x, float y, float z, bool run)
|
public void AddWaypoint(uint id, float x, float y, float z, bool run)
|
||||||
{
|
{
|
||||||
AddWaypoint(id, x, y, z, 0.0f, TimeSpan.Zero, run);
|
AddWaypoint(id, x, y, z, 0.0f, TimeSpan.Zero, run);
|
||||||
}
|
}
|
||||||
@@ -320,20 +320,14 @@ namespace Game.AI
|
|||||||
GridDefines.NormalizeMapCoord(ref x);
|
GridDefines.NormalizeMapCoord(ref x);
|
||||||
GridDefines.NormalizeMapCoord(ref y);
|
GridDefines.NormalizeMapCoord(ref y);
|
||||||
|
|
||||||
WaypointNode waypoint = new();
|
WaypointNode waypoint = new(id, x, y, z, orientation, (uint)waitTime.TotalMilliseconds);
|
||||||
waypoint.id = id;
|
waypoint.MoveType = run ? WaypointMoveType.Run : WaypointMoveType.Walk;
|
||||||
waypoint.x = x;
|
_path.Nodes.Add(waypoint);
|
||||||
waypoint.y = y;
|
|
||||||
waypoint.z = z;
|
|
||||||
waypoint.orientation = orientation;
|
|
||||||
waypoint.moveType = run ? WaypointMoveType.Run : WaypointMoveType.Walk;
|
|
||||||
waypoint.delay = (uint)waitTime.TotalMilliseconds;
|
|
||||||
_path.nodes.Add(waypoint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResetPath()
|
void ResetPath()
|
||||||
{
|
{
|
||||||
_path.nodes.Clear();
|
_path.Nodes.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LoadPath(uint pathId)
|
public void LoadPath(uint pathId)
|
||||||
@@ -350,7 +344,7 @@ namespace Game.AI
|
|||||||
/// todo get rid of this many variables passed in function.
|
/// todo get rid of this many variables passed in function.
|
||||||
public void Start(bool isActiveAttacker = true, ObjectGuid playerGUID = default, Quest quest = null, bool instantRespawn = false, bool canLoopPath = false)
|
public void Start(bool isActiveAttacker = true, ObjectGuid playerGUID = default, Quest quest = null, bool instantRespawn = false, bool canLoopPath = false)
|
||||||
{
|
{
|
||||||
if (_path.nodes.Empty())
|
if (_path.Nodes.Empty())
|
||||||
{
|
{
|
||||||
Log.outError(LogFilter.ScriptsAi, $"EscortAI::Start: (script: {me.GetScriptName()}) path is empty ({me.GetGUID()})");
|
Log.outError(LogFilter.ScriptsAi, $"EscortAI::Start: (script: {me.GetScriptName()}) path is empty ({me.GetGUID()})");
|
||||||
return;
|
return;
|
||||||
@@ -376,7 +370,7 @@ namespace Game.AI
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_path.nodes.Empty())
|
if (_path.Nodes.Empty())
|
||||||
{
|
{
|
||||||
Log.outError(LogFilter.ScriptsAi, $"EscortAI::Start: (script: {me.GetScriptName()} starts with 0 waypoints (possible missing entry in script_waypoint. Quest: {(quest != null ? quest.Id : 0)} ({me.GetGUID()})");
|
Log.outError(LogFilter.ScriptsAi, $"EscortAI::Start: (script: {me.GetScriptName()} starts with 0 waypoints (possible missing entry in script_waypoint. Quest: {(quest != null ? quest.Id : 0)} ({me.GetGUID()})");
|
||||||
return;
|
return;
|
||||||
@@ -404,7 +398,7 @@ namespace Game.AI
|
|||||||
me.SetImmuneToNPC(false);
|
me.SetImmuneToNPC(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.outDebug(LogFilter.ScriptsAi, $"EscortAI::Start: (script: {me.GetScriptName()}, started with {_path.nodes.Count} waypoints. ActiveAttacker = {_activeAttacker}, Player = {_playerGUID} ({me.GetGUID()})");
|
Log.outDebug(LogFilter.ScriptsAi, $"EscortAI::Start: (script: {me.GetScriptName()}, started with {_path.Nodes.Count} waypoints. ActiveAttacker = {_activeAttacker}, Player = {_playerGUID} ({me.GetGUID()})");
|
||||||
|
|
||||||
_started = false;
|
_started = false;
|
||||||
AddEscortState(EscortState.Escorting);
|
AddEscortState(EscortState.Escorting);
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ namespace Game.AI
|
|||||||
SmartEscortState _escortState;
|
SmartEscortState _escortState;
|
||||||
uint _escortNPCFlags;
|
uint _escortNPCFlags;
|
||||||
uint _escortInvokerCheckTimer;
|
uint _escortInvokerCheckTimer;
|
||||||
uint _currentWaypointNode;
|
uint _currentWaypointNodeId;
|
||||||
bool _waypointReached;
|
bool _waypointReached;
|
||||||
uint _waypointPauseTimer;
|
uint _waypointPauseTimer;
|
||||||
bool _waypointPauseForced;
|
bool _waypointPauseForced;
|
||||||
@@ -82,7 +82,7 @@ namespace Game.AI
|
|||||||
if (path == null)
|
if (path == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_currentWaypointNode = nodeId;
|
_currentWaypointNodeId = nodeId;
|
||||||
_waypointPathEnded = false;
|
_waypointPathEnded = false;
|
||||||
|
|
||||||
_repeatWaypointPath = repeat;
|
_repeatWaypointPath = repeat;
|
||||||
@@ -105,7 +105,7 @@ namespace Game.AI
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
WaypointPath path = Global.WaypointMgr.GetPath(entry);
|
WaypointPath path = Global.WaypointMgr.GetPath(entry);
|
||||||
if (path == null || path.nodes.Empty())
|
if (path == null || path.Nodes.Empty())
|
||||||
{
|
{
|
||||||
GetScript().SetPathId(0);
|
GetScript().SetPathId(0);
|
||||||
return null;
|
return null;
|
||||||
@@ -147,7 +147,7 @@ namespace Game.AI
|
|||||||
_waypointReached = false;
|
_waypointReached = false;
|
||||||
|
|
||||||
AddEscortState(SmartEscortState.Paused);
|
AddEscortState(SmartEscortState.Paused);
|
||||||
GetScript().ProcessEventsFor(SmartEvents.WaypointPaused, null, _currentWaypointNode, GetScript().GetPathId());
|
GetScript().ProcessEventsFor(SmartEvents.WaypointPaused, null, _currentWaypointNodeId, GetScript().GetPathId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CanResumePath()
|
public bool CanResumePath()
|
||||||
@@ -196,7 +196,7 @@ namespace Game.AI
|
|||||||
|
|
||||||
me.GetMotionMaster().MoveIdle();
|
me.GetMotionMaster().MoveIdle();
|
||||||
|
|
||||||
GetScript().ProcessEventsFor(SmartEvents.WaypointStopped, null, _currentWaypointNode, GetScript().GetPathId());
|
GetScript().ProcessEventsFor(SmartEvents.WaypointStopped, null, _currentWaypointNodeId, GetScript().GetPathId());
|
||||||
|
|
||||||
EndPath(fail);
|
EndPath(fail);
|
||||||
}
|
}
|
||||||
@@ -262,7 +262,7 @@ namespace Game.AI
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
uint pathid = GetScript().GetPathId();
|
uint pathid = GetScript().GetPathId();
|
||||||
GetScript().ProcessEventsFor(SmartEvents.WaypointEnded, null, _currentWaypointNode, pathid);
|
GetScript().ProcessEventsFor(SmartEvents.WaypointEnded, null, _currentWaypointNodeId, pathid);
|
||||||
|
|
||||||
if (_repeatWaypointPath)
|
if (_repeatWaypointPath)
|
||||||
{
|
{
|
||||||
@@ -278,7 +278,7 @@ namespace Game.AI
|
|||||||
|
|
||||||
public void ResumePath()
|
public void ResumePath()
|
||||||
{
|
{
|
||||||
GetScript().ProcessEventsFor(SmartEvents.WaypointResumed, null, _currentWaypointNode, GetScript().GetPathId());
|
GetScript().ProcessEventsFor(SmartEvents.WaypointResumed, null, _currentWaypointNodeId, GetScript().GetPathId());
|
||||||
|
|
||||||
RemoveEscortState(SmartEscortState.Paused);
|
RemoveEscortState(SmartEscortState.Paused);
|
||||||
|
|
||||||
@@ -378,9 +378,9 @@ namespace Game.AI
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_currentWaypointNode = nodeId;
|
_currentWaypointNodeId = nodeId;
|
||||||
|
|
||||||
GetScript().ProcessEventsFor(SmartEvents.WaypointReached, null, _currentWaypointNode, pathId);
|
GetScript().ProcessEventsFor(SmartEvents.WaypointReached, null, _currentWaypointNodeId, pathId);
|
||||||
|
|
||||||
if (_waypointPauseTimer != 0 && !_waypointPauseForced)
|
if (_waypointPauseTimer != 0 && !_waypointPauseForced)
|
||||||
{
|
{
|
||||||
@@ -391,7 +391,7 @@ namespace Game.AI
|
|||||||
else if (HasEscortState(SmartEscortState.Escorting) && me.GetMotionMaster().GetCurrentMovementGeneratorType() == MovementGeneratorType.Waypoint)
|
else if (HasEscortState(SmartEscortState.Escorting) && me.GetMotionMaster().GetCurrentMovementGeneratorType() == MovementGeneratorType.Waypoint)
|
||||||
{
|
{
|
||||||
WaypointPath path = Global.WaypointMgr.GetPath(pathId);
|
WaypointPath path = Global.WaypointMgr.GetPath(pathId);
|
||||||
if (path != null && _currentWaypointNode == path.nodes.Last()?.id)
|
if (path != null && _currentWaypointNodeId == path.Nodes.Last()?.Id)
|
||||||
_waypointPathEnded = true;
|
_waypointPathEnded = true;
|
||||||
else
|
else
|
||||||
SetRun(_run);
|
SetRun(_run);
|
||||||
@@ -568,8 +568,8 @@ namespace Game.AI
|
|||||||
if (formation == null || formation.GetLeader() == me || !formation.IsFormed())
|
if (formation == null || formation.GetLeader() == me || !formation.IsFormed())
|
||||||
{
|
{
|
||||||
if (me.GetMotionMaster().GetCurrentMovementGeneratorType(MovementSlot.Default) != MovementGeneratorType.Waypoint)
|
if (me.GetMotionMaster().GetCurrentMovementGeneratorType(MovementSlot.Default) != MovementGeneratorType.Waypoint)
|
||||||
if (me.GetWaypointPath() != 0)
|
if (me.GetWaypointPathId() != 0)
|
||||||
me.GetMotionMaster().MovePath(me.GetWaypointPath(), true);
|
me.GetMotionMaster().MovePath(me.GetWaypointPathId(), true);
|
||||||
|
|
||||||
me.ResumeMovement();
|
me.ResumeMovement();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1645,7 +1645,7 @@ namespace Game.AI
|
|||||||
case SmartActions.WpStart:
|
case SmartActions.WpStart:
|
||||||
{
|
{
|
||||||
WaypointPath path = Global.WaypointMgr.GetPath(e.Action.wpStart.pathID);
|
WaypointPath path = Global.WaypointMgr.GetPath(e.Action.wpStart.pathID);
|
||||||
if (path == null || path.nodes.Empty())
|
if (path == null || path.Nodes.Empty())
|
||||||
{
|
{
|
||||||
Log.outError(LogFilter.ScriptsAi, $"SmartAIMgr: {e} uses non-existent WaypointPath id {e.Action.wpStart.pathID}, skipped.");
|
Log.outError(LogFilter.ScriptsAi, $"SmartAIMgr: {e} uses non-existent WaypointPath id {e.Action.wpStart.pathID}, skipped.");
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -2027,17 +2027,17 @@ namespace Game.AI
|
|||||||
foreach (uint pathId in waypoints)
|
foreach (uint pathId in waypoints)
|
||||||
{
|
{
|
||||||
WaypointPath path = Global.WaypointMgr.GetPath(pathId);
|
WaypointPath path = Global.WaypointMgr.GetPath(pathId);
|
||||||
if (path == null || path.nodes.Empty())
|
if (path == null || path.Nodes.Empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
foreach (var waypoint in path.nodes)
|
foreach (var waypoint in path.Nodes)
|
||||||
{
|
{
|
||||||
float distToThisPath = creature.GetDistance(waypoint.x, waypoint.y, waypoint.z);
|
float distanceToThisNode = creature.GetDistance(waypoint.X, waypoint.Y, waypoint.Z);
|
||||||
if (distToThisPath < distanceToClosest)
|
if (distanceToThisNode < distanceToClosest)
|
||||||
{
|
{
|
||||||
distanceToClosest = distToThisPath;
|
distanceToClosest = distanceToThisNode;
|
||||||
closestPathId = pathId;
|
closestPathId = pathId;
|
||||||
closestWaypointId = waypoint.id;
|
closestWaypointId = waypoint.Id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -915,16 +915,16 @@ namespace Game.Chat
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Command("waypoint_data", RBACPermissions.CommandReloadWaypointData, true)]
|
[Command("waypoint_path", RBACPermissions.CommandReloadWaypointPath, true)]
|
||||||
static bool HandleReloadWpCommand(CommandHandler handler, StringArguments args)
|
static bool HandleReloadWpCommand(CommandHandler handler, StringArguments args)
|
||||||
{
|
{
|
||||||
if (args != null)
|
if (args != null)
|
||||||
Log.outInfo(LogFilter.Server, "Re-Loading Waypoints data from 'waypoints_data'");
|
Log.outInfo(LogFilter.Server, "Re-Loading Waypoints data from 'waypoint_path' and 'waypoint_path_node'");
|
||||||
|
|
||||||
Global.WaypointMgr.Load();
|
Global.WaypointMgr.LoadPaths();
|
||||||
|
|
||||||
if (args != null)
|
if (args != null)
|
||||||
handler.SendGlobalGMSysMessage("DB Table 'waypoint_data' reloaded.");
|
handler.SendGlobalGMSysMessage("DB Tables 'waypoint_path' and 'waypoint_path_node' reloaded.");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using Game.Entities;
|
|||||||
using Game.Maps;
|
using Game.Maps;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Game.Chat.Commands
|
namespace Game.Chat.Commands
|
||||||
{
|
{
|
||||||
@@ -15,32 +16,31 @@ namespace Game.Chat.Commands
|
|||||||
class WPCommands
|
class WPCommands
|
||||||
{
|
{
|
||||||
[Command("add", RBACPermissions.CommandWpAdd)]
|
[Command("add", RBACPermissions.CommandWpAdd)]
|
||||||
static bool HandleWpAddCommand(CommandHandler handler, uint? optionalPathId)
|
static bool HandleWpAddCommand(CommandHandler handler, uint? optionalpathId)
|
||||||
{
|
{
|
||||||
uint point = 0;
|
|
||||||
Creature target = handler.GetSelectedCreature();
|
Creature target = handler.GetSelectedCreature();
|
||||||
|
|
||||||
PreparedStatement stmt;
|
PreparedStatement stmt;
|
||||||
uint pathId;
|
uint pathId;
|
||||||
|
|
||||||
if (!optionalPathId.HasValue)
|
if (!optionalpathId.HasValue)
|
||||||
{
|
{
|
||||||
if (target != null)
|
if (target != null)
|
||||||
pathId = target.GetWaypointPath();
|
pathId = target.GetWaypointPathId();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
stmt = WorldDatabase.GetPreparedStatement(WorldStatements.SEL_WAYPOINT_DATA_MAX_ID);
|
stmt = WorldDatabase.GetPreparedStatement(WorldStatements.SEL_WAYPOINT_PATH_NODE_MAX_PATHID);
|
||||||
SQLResult result1 = DB.World.Query(stmt);
|
SQLResult result1 = DB.World.Query(stmt);
|
||||||
|
|
||||||
uint maxpathid = result1.Read<uint>(0);
|
uint maxpathId = result1.Read<uint>(0);
|
||||||
pathId = maxpathid + 1;
|
pathId = maxpathId + 1;
|
||||||
handler.SendSysMessage("|cff00ff00New path started.|r");
|
handler.SendSysMessage("|cff00ff00New path started.|r");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
pathId = optionalPathId.Value;
|
pathId = optionalpathId.Value;
|
||||||
|
|
||||||
// path_id . ID of the Path
|
// pathId . ID of the Path
|
||||||
// point . number of the waypoint (if not 0)
|
// point . number of the waypoint (if not 0)
|
||||||
|
|
||||||
if (pathId == 0)
|
if (pathId == 0)
|
||||||
@@ -49,39 +49,52 @@ namespace Game.Chat.Commands
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt = WorldDatabase.GetPreparedStatement(WorldStatements.SEL_WAYPOINT_DATA_MAX_POINT);
|
stmt = WorldDatabase.GetPreparedStatement(WorldStatements.SEL_WAYPOINT_PATH_NODE_MAX_NODEID);
|
||||||
stmt.AddValue(0, pathId);
|
stmt.AddValue(0, pathId);
|
||||||
SQLResult result = DB.World.Query(stmt);
|
SQLResult result = DB.World.Query(stmt);
|
||||||
|
|
||||||
|
uint nodeId = 0;
|
||||||
if (result.IsEmpty())
|
if (result.IsEmpty())
|
||||||
point = result.Read<uint>(0);
|
nodeId = result.Read<uint>(0);
|
||||||
|
|
||||||
Player player = handler.GetSession().GetPlayer();
|
Player player = handler.GetPlayer();
|
||||||
|
|
||||||
stmt = WorldDatabase.GetPreparedStatement(WorldStatements.INS_WAYPOINT_DATA);
|
stmt = WorldDatabase.GetPreparedStatement(WorldStatements.INS_WAYPOINT_PATH_NODE);
|
||||||
stmt.AddValue(0, pathId);
|
stmt.AddValue(0, pathId);
|
||||||
stmt.AddValue(1, point + 1);
|
stmt.AddValue(1, nodeId);
|
||||||
stmt.AddValue(2, player.GetPositionX());
|
stmt.AddValue(2, player.GetPositionX());
|
||||||
stmt.AddValue(3, player.GetPositionY());
|
stmt.AddValue(3, player.GetPositionY());
|
||||||
stmt.AddValue(4, player.GetPositionZ());
|
stmt.AddValue(4, player.GetPositionZ());
|
||||||
stmt.AddValue(5, player.GetOrientation());
|
stmt.AddValue(5, player.GetOrientation());
|
||||||
|
|
||||||
DB.World.Execute(stmt);
|
DB.World.Execute(stmt);
|
||||||
|
|
||||||
handler.SendSysMessage("|cff00ff00PathID: |r|cff00ffff{0} |r|cff00ff00: Waypoint |r|cff00ffff{1}|r|cff00ff00 created.|r", pathId, point + 1);
|
if (target != null)
|
||||||
|
{
|
||||||
|
uint displayId = target.GetDisplayId();
|
||||||
|
|
||||||
|
WaypointPath path = Global.WaypointMgr.GetPath(pathId);
|
||||||
|
if (path == null)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
Global.WaypointMgr.DevisualizePath(player, path);
|
||||||
|
Global.WaypointMgr.ReloadPath(pathId);
|
||||||
|
Global.WaypointMgr.VisualizePath(player, path, displayId);
|
||||||
|
}
|
||||||
|
|
||||||
|
handler.SendSysMessage("|cff00ff00pathId: |r|cff00ffff{pathId}|r|cff00ff00: Waypoint |r|cff00ffff{nodeId}|r|cff00ff00 created. ");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Command("load", RBACPermissions.CommandWpLoad)]
|
[Command("load", RBACPermissions.CommandWpLoad)]
|
||||||
static bool HandleWpLoadCommand(CommandHandler handler, uint? optionalPathId)
|
static bool HandleWpLoadCommand(CommandHandler handler, uint? optionalpathId)
|
||||||
{
|
{
|
||||||
Creature target = handler.GetSelectedCreature();
|
Creature target = handler.GetSelectedCreature();
|
||||||
|
|
||||||
// Did player provide a path_id?
|
// Did player provide a pathId?
|
||||||
if (!optionalPathId.HasValue)
|
if (!optionalpathId.HasValue)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
uint pathId = optionalPathId.Value;
|
uint pathId = optionalpathId.Value;
|
||||||
|
|
||||||
if (target == null)
|
if (target == null)
|
||||||
{
|
{
|
||||||
@@ -143,19 +156,9 @@ namespace Game.Chat.Commands
|
|||||||
if (subCommand.IsEmpty())
|
if (subCommand.IsEmpty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Check
|
|
||||||
// Remember: "show" must also be the name of a column!
|
|
||||||
if ((subCommand != "delay") && (subCommand != "action") && (subCommand != "action_chance")
|
|
||||||
&& (subCommand != "move_flag") && (subCommand != "del") && (subCommand != "move"))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Did user provide a GUID
|
// Did user provide a GUID
|
||||||
// or did the user select a creature?
|
// or did the user select a creature?
|
||||||
// . variable lowguid is filled with the GUID of the NPC
|
// . variable lowguid is filled with the GUID of the NPC
|
||||||
uint pathid;
|
|
||||||
uint point;
|
|
||||||
Creature target = handler.GetSelectedCreature();
|
Creature target = handler.GetSelectedCreature();
|
||||||
|
|
||||||
// User did select a visual waypoint?
|
// User did select a visual waypoint?
|
||||||
@@ -165,148 +168,50 @@ namespace Game.Chat.Commands
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the creature
|
WaypointPath path = Global.WaypointMgr.GetPathByVisualGUID(target.GetGUID());
|
||||||
PreparedStatement stmt = WorldDatabase.GetPreparedStatement(WorldStatements.SEL_WAYPOINT_DATA_BY_WPGUID);
|
if (path == null)
|
||||||
stmt.AddValue(0, target.GetSpawnId());
|
|
||||||
SQLResult result = DB.World.Query(stmt);
|
|
||||||
|
|
||||||
if (result.IsEmpty())
|
|
||||||
{
|
{
|
||||||
handler.SendSysMessage(CypherStrings.WaypointNotfoundsearch, target.GetGUID().ToString());
|
handler.SendSysMessage("|cff00ff00Path does not exist or target has no path|r");
|
||||||
// Select waypoint number from database
|
return true;
|
||||||
// Since we compare float values, we have to deal with
|
|
||||||
// some difficulties.
|
|
||||||
// Here we search for all waypoints that only differ in one from 1 thousand
|
|
||||||
// See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html
|
|
||||||
string maxDiff = "0.01";
|
|
||||||
|
|
||||||
stmt = WorldDatabase.GetPreparedStatement(WorldStatements.SEL_WAYPOINT_DATA_BY_POS);
|
|
||||||
stmt.AddValue(0, target.GetPositionX());
|
|
||||||
stmt.AddValue(1, maxDiff);
|
|
||||||
stmt.AddValue(2, target.GetPositionY());
|
|
||||||
stmt.AddValue(3, maxDiff);
|
|
||||||
stmt.AddValue(4, target.GetPositionZ());
|
|
||||||
stmt.AddValue(5, maxDiff);
|
|
||||||
result = DB.World.Query(stmt);
|
|
||||||
|
|
||||||
if (result.IsEmpty())
|
|
||||||
{
|
|
||||||
handler.SendSysMessage(CypherStrings.WaypointNotfounddbproblem, target.GetGUID().ToString());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
do
|
WaypointNode node = Global.WaypointMgr.GetNodeByVisualGUID(target.GetGUID());
|
||||||
|
if (node == null)
|
||||||
{
|
{
|
||||||
pathid = result.Read<uint>(0);
|
handler.SendSysMessage("|cff00ff00Path does not exist or target has no path|r");
|
||||||
point = result.Read<uint>(1);
|
return true;
|
||||||
}
|
|
||||||
while (result.NextRow());
|
|
||||||
|
|
||||||
// We have the waypoint number and the GUID of the "master npc"
|
|
||||||
// Text is enclosed in "<>", all other arguments not
|
|
||||||
|
|
||||||
// Check for argument
|
|
||||||
if (subCommand != "del" && subCommand != "move")
|
|
||||||
{
|
|
||||||
handler.SendSysMessage(CypherStrings.WaypointArgumentreq, subCommand);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subCommand == "del")
|
if (subCommand == "del")
|
||||||
{
|
{
|
||||||
handler.SendSysMessage("|cff00ff00DEBUG: wp modify del, PathID: |r|cff00ffff{0}|r", pathid);
|
handler.SendSysMessage($"|cff00ff00DEBUG: .wp modify del, pathId: |r|cff00ffff{path.Id}|r, NodeId: |r|cff00ffff{node.Id}|r");
|
||||||
|
|
||||||
if (Creature.DeleteFromDB(target.GetSpawnId()))
|
uint displayId = target.GetDisplayId();
|
||||||
{
|
|
||||||
|
|
||||||
stmt = WorldDatabase.GetPreparedStatement(WorldStatements.DEL_WAYPOINT_DATA);
|
Global.WaypointMgr.DevisualizePath(handler.GetPlayer(), path);
|
||||||
stmt.AddValue(0, pathid);
|
Global.WaypointMgr.DeleteNode(path, node);
|
||||||
stmt.AddValue(1, point);
|
Global.WaypointMgr.ReloadPath(path.Id);
|
||||||
DB.World.Execute(stmt);
|
Global.WaypointMgr.VisualizePath(handler.GetPlayer(), path, displayId);
|
||||||
|
|
||||||
stmt = WorldDatabase.GetPreparedStatement(WorldStatements.UPD_WAYPOINT_DATA_POINT);
|
handler.SendSysMessage(CypherStrings.WaypointRemoved);
|
||||||
stmt.AddValue(0, pathid);
|
return true;
|
||||||
stmt.AddValue(1, point);
|
}
|
||||||
DB.World.Execute(stmt);
|
else if (subCommand == "move")
|
||||||
|
|
||||||
handler.SendSysMessage(CypherStrings.WaypointRemoved);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
handler.SendSysMessage(CypherStrings.WaypointNotremoved);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} // del
|
|
||||||
|
|
||||||
if (subCommand == "move")
|
|
||||||
{
|
{
|
||||||
handler.SendSysMessage("|cff00ff00DEBUG: wp move, PathID: |r|cff00ffff{0}|r", pathid);
|
handler.SendSysMessage("|cff00ff00DEBUG: .wp move, pathId: |r|cff00ffff%u|r, NodeId: |r|cff00ffff%u|r", path.Id, node.Id);
|
||||||
|
|
||||||
Player chr = handler.GetSession().GetPlayer();
|
uint displayId = target.GetDisplayId();
|
||||||
Map map = chr.GetMap();
|
|
||||||
// What to do:
|
|
||||||
// Move the visual spawnpoint
|
|
||||||
// Respawn the owner of the waypoints
|
|
||||||
if (Creature.DeleteFromDB(target.GetSpawnId()))
|
|
||||||
{
|
|
||||||
handler.SendSysMessage(CypherStrings.WaypointVpNotcreated, 1);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// re-create
|
Global.WaypointMgr.DevisualizePath(handler.GetPlayer(), path);
|
||||||
Creature creature = Creature.CreateCreature(1, map, chr.GetPosition());
|
Global.WaypointMgr.MoveNode(path, node, handler.GetPlayer().GetPosition());
|
||||||
if (creature == null)
|
Global.WaypointMgr.ReloadPath(path.Id);
|
||||||
{
|
Global.WaypointMgr.VisualizePath(handler.GetPlayer(), path, displayId);
|
||||||
handler.SendSysMessage(CypherStrings.WaypointVpNotcreated, 1);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
PhasingHandler.InheritPhaseShift(creature, chr);
|
|
||||||
creature.SaveToDB(map.GetId(), new List<Difficulty>() { map.GetDifficultyID() });
|
|
||||||
|
|
||||||
ulong dbGuid = creature.GetSpawnId();
|
|
||||||
|
|
||||||
// current "wpCreature" variable is deleted and created fresh new, otherwise old values might trigger asserts or cause undefined behavior
|
|
||||||
creature.CleanupsBeforeDelete();
|
|
||||||
creature.Dispose();
|
|
||||||
|
|
||||||
// To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
|
|
||||||
creature = Creature.CreateCreatureFromDB(dbGuid, map, true, true);
|
|
||||||
if (creature == null)
|
|
||||||
{
|
|
||||||
handler.SendSysMessage(CypherStrings.WaypointVpNotcreated, 1);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
stmt = WorldDatabase.GetPreparedStatement(WorldStatements.UPD_WAYPOINT_DATA_POSITION);
|
|
||||||
stmt.AddValue(0, chr.GetPositionX());
|
|
||||||
stmt.AddValue(1, chr.GetPositionY());
|
|
||||||
stmt.AddValue(2, chr.GetPositionZ());
|
|
||||||
stmt.AddValue(3, chr.GetOrientation());
|
|
||||||
stmt.AddValue(4, pathid);
|
|
||||||
stmt.AddValue(5, point);
|
|
||||||
DB.World.Execute(stmt);
|
|
||||||
|
|
||||||
handler.SendSysMessage(CypherStrings.WaypointChanged);
|
handler.SendSysMessage(CypherStrings.WaypointChanged);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} // move
|
|
||||||
|
|
||||||
if (arg.IsEmpty())
|
|
||||||
{
|
|
||||||
// show_str check for present in list of correct values, no sql injection possible
|
|
||||||
DB.World.Execute("UPDATE waypoint_data SET {0}=null WHERE id='{1}' AND point='{2}'", subCommand, pathid, point); // Query can't be a prepared statement
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// show_str check for present in list of correct values, no sql injection possible
|
|
||||||
DB.World.Execute("UPDATE waypoint_data SET {0}='{1}' WHERE id='{2}' AND point='{3}'", subCommand, arg, pathid, point); // Query can't be a prepared statement
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handler.SendSysMessage(CypherStrings.WaypointChangedNo, subCommand);
|
return false;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Command("reload", RBACPermissions.CommandWpReload)]
|
[Command("reload", RBACPermissions.CommandWpReload)]
|
||||||
@@ -321,328 +226,122 @@ namespace Game.Chat.Commands
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Command("show", RBACPermissions.CommandWpShow)]
|
[Command("show", RBACPermissions.CommandWpShow)]
|
||||||
static bool HandleWpShowCommand(CommandHandler handler, string subCommand, uint? optionalPathId)
|
static bool HandleWpShowCommand(CommandHandler handler, string subCommand, uint? optionalpathId)
|
||||||
{
|
{
|
||||||
// first arg: on, off, first, last
|
// first arg: on, off, first, last
|
||||||
if (subCommand.IsEmpty())
|
if (subCommand.IsEmpty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
uint pathId;
|
||||||
Creature target = handler.GetSelectedCreature();
|
Creature target = handler.GetSelectedCreature();
|
||||||
|
|
||||||
// Did player provide a PathID?
|
// Did player provide a pathId?
|
||||||
uint pathId;
|
if (!optionalpathId.HasValue)
|
||||||
|
|
||||||
if (!optionalPathId.HasValue)
|
|
||||||
{
|
{
|
||||||
// No PathID provided
|
// No pathId provided
|
||||||
// . Player must have selected a creature
|
// . Player must have selected a creature
|
||||||
|
|
||||||
if (target == null)
|
if (target == null)
|
||||||
{
|
{
|
||||||
handler.SendSysMessage(CypherStrings.SelectCreature);
|
handler.SendSysMessage(CypherStrings.SelectCreature);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pathId = target.GetWaypointPath();
|
pathId = target.GetWaypointPathId();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// PathID provided
|
// pathId provided
|
||||||
// Warn if player also selected a creature
|
// Warn if player also selected a creature
|
||||||
// . Creature selection is ignored <-
|
// . Creature selection is ignored <-
|
||||||
if (target != null)
|
if (target != null)
|
||||||
handler.SendSysMessage(CypherStrings.WaypointCreatselected);
|
handler.SendSysMessage(CypherStrings.WaypointCreatselected);
|
||||||
|
|
||||||
pathId = optionalPathId.Value;
|
pathId = optionalpathId.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show info for the selected waypoint
|
// Show info for the selected waypoint
|
||||||
if (subCommand == "info")
|
if (subCommand == "info")
|
||||||
{
|
{
|
||||||
// Check if the user did specify a visual waypoint
|
|
||||||
if (target == null || target.GetEntry() != 1)
|
if (target == null || target.GetEntry() != 1)
|
||||||
{
|
{
|
||||||
handler.SendSysMessage(CypherStrings.WaypointVpSelect);
|
handler.SendSysMessage(CypherStrings.WaypointVpSelect);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PreparedStatement stmt = WorldDatabase.GetPreparedStatement(WorldStatements.SEL_WAYPOINT_DATA_ALL_BY_WPGUID);
|
WaypointPath path = Global.WaypointMgr.GetPathByVisualGUID(target.GetGUID());
|
||||||
stmt.AddValue(0, target.GetSpawnId());
|
if (path == null)
|
||||||
SQLResult result = DB.World.Query(stmt);
|
|
||||||
|
|
||||||
if (result.IsEmpty())
|
|
||||||
{
|
{
|
||||||
handler.SendSysMessage(CypherStrings.WaypointNotfounddbproblem, target.GetSpawnId());
|
handler.SendSysMessage("|cff00ff00Path does not exist or target has no path|r");
|
||||||
|
handler.SetSentErrorMessage(true);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
WaypointNode node = Global.WaypointMgr.GetNodeByVisualGUID(target.GetGUID());
|
||||||
|
if (node == null)
|
||||||
|
{
|
||||||
|
handler.SendSysMessage("|cff00ff00Path does not exist or target has no path|r");
|
||||||
|
handler.SetSentErrorMessage(true);
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
handler.SendSysMessage("|cff00ffffDEBUG: .wp show info:|r");
|
||||||
|
handler.SendSysMessage($"|cff00ff00Show info: Path Id: |r|cff00ffff{path.Id}|r");
|
||||||
|
handler.SendSysMessage($"|cff00ff00Show info: Path MoveType: |r|cff00ffff{(uint)path.MoveType}|r");
|
||||||
|
handler.SendSysMessage($"|cff00ff00Show info: Path Flags: |r|cff00ffff{(uint)path.Flags}|r");
|
||||||
|
handler.SendSysMessage($"|cff00ff00Show info: Node Id: |r|cff00ffff{node.Id}|r");
|
||||||
|
handler.SendSysMessage($"|cff00ff00Show info: Node Delay: |r|cff00ffff{node.Id}|r");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (subCommand == "on")
|
||||||
|
{
|
||||||
|
WaypointPath path = Global.WaypointMgr.GetPath(pathId);
|
||||||
|
if (path == null)
|
||||||
|
{
|
||||||
|
handler.SendSysMessage($"|cff00ff00Path does not exist: id {pathId}|r");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
handler.SendSysMessage("|cff00ffffDEBUG: wp show info:|r");
|
if (path.Nodes.Empty())
|
||||||
do
|
|
||||||
{
|
{
|
||||||
pathId = result.Read<uint>(0);
|
handler.SendSysMessage($"|cff00ff00Path does not have any nodes: id {pathId}|r");
|
||||||
uint point = result.Read<uint>(1);
|
return true;
|
||||||
uint delay = result.Read<uint>(2);
|
|
||||||
uint flag = result.Read<uint>(3);
|
|
||||||
|
|
||||||
handler.SendSysMessage("|cff00ff00Show info: for current point: |r|cff00ffff{0}|r|cff00ff00, Path ID: |r|cff00ffff{1}|r", point, pathId);
|
|
||||||
handler.SendSysMessage("|cff00ff00Show info: delay: |r|cff00ffff{0}|r", delay);
|
|
||||||
handler.SendSysMessage("|cff00ff00Show info: Move flag: |r|cff00ffff{0}|r", flag);
|
|
||||||
}
|
|
||||||
while (result.NextRow());
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (subCommand == "on")
|
|
||||||
{
|
|
||||||
PreparedStatement stmt = WorldDatabase.GetPreparedStatement(WorldStatements.SEL_WAYPOINT_DATA_POS_BY_ID);
|
|
||||||
stmt.AddValue(0, pathId);
|
|
||||||
SQLResult result = DB.World.Query(stmt);
|
|
||||||
|
|
||||||
if (result.IsEmpty())
|
|
||||||
{
|
|
||||||
handler.SendSysMessage("|cffff33ffPath no found.|r");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
handler.SendSysMessage("|cff00ff00DEBUG: wp on, PathID: |cff00ffff{0}|r", pathId);
|
|
||||||
|
|
||||||
// Delete all visuals for this NPC
|
|
||||||
stmt = WorldDatabase.GetPreparedStatement(WorldStatements.SEL_WAYPOINT_DATA_WPGUID_BY_ID);
|
|
||||||
stmt.AddValue(0, pathId);
|
|
||||||
SQLResult result2 = DB.World.Query(stmt);
|
|
||||||
|
|
||||||
if (!result2.IsEmpty())
|
|
||||||
{
|
|
||||||
bool hasError = false;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
ulong wpguid = result2.Read<ulong>(0);
|
|
||||||
|
|
||||||
if (Creature.DeleteFromDB(wpguid))
|
|
||||||
{
|
|
||||||
handler.SendSysMessage(CypherStrings.WaypointNotremoved, wpguid);
|
|
||||||
hasError = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
while (result2.NextRow());
|
|
||||||
|
|
||||||
if (hasError)
|
|
||||||
{
|
|
||||||
handler.SendSysMessage(CypherStrings.WaypointToofar1);
|
|
||||||
handler.SendSysMessage(CypherStrings.WaypointToofar2);
|
|
||||||
handler.SendSysMessage(CypherStrings.WaypointToofar3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
uint point = result.Read<uint>(0);
|
|
||||||
float x = result.Read<float>(1);
|
|
||||||
float y = result.Read<float>(2);
|
|
||||||
float z = result.Read<float>(3);
|
|
||||||
float o = result.Read<float>(4);
|
|
||||||
|
|
||||||
uint id = 1;
|
|
||||||
|
|
||||||
Player chr = handler.GetSession().GetPlayer();
|
|
||||||
Map map = chr.GetMap();
|
|
||||||
|
|
||||||
Creature creature = Creature.CreateCreature(id, map, new Position(x, y, z, o));
|
|
||||||
if (creature == null)
|
|
||||||
{
|
|
||||||
handler.SendSysMessage(CypherStrings.WaypointVpNotcreated, id);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
PhasingHandler.InheritPhaseShift(creature, chr);
|
|
||||||
creature.SaveToDB(map.GetId(), new List<Difficulty>() { map.GetDifficultyID() });
|
|
||||||
|
|
||||||
ulong dbGuid = creature.GetSpawnId();
|
|
||||||
|
|
||||||
// current "wpCreature" variable is deleted and created fresh new, otherwise old values might trigger asserts or cause undefined behavior
|
|
||||||
creature.CleanupsBeforeDelete();
|
|
||||||
creature.Dispose();
|
|
||||||
|
|
||||||
// To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
|
|
||||||
creature = Creature.CreateCreatureFromDB(dbGuid, map, true, true);
|
|
||||||
if (creature == null)
|
|
||||||
{
|
|
||||||
handler.SendSysMessage(CypherStrings.WaypointVpNotcreated, id);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (target != null)
|
|
||||||
{
|
|
||||||
creature.SetDisplayId(target.GetDisplayId());
|
|
||||||
creature.SetObjectScale(0.5f);
|
|
||||||
creature.SetLevel(Math.Min(point, SharedConst.StrongMaxLevel));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set "wpguid" column to the visual waypoint
|
|
||||||
stmt = WorldDatabase.GetPreparedStatement(WorldStatements.UPD_WAYPOINT_DATA_WPGUID);
|
|
||||||
stmt.AddValue(0, creature.GetSpawnId());
|
|
||||||
stmt.AddValue(1, pathId);
|
|
||||||
stmt.AddValue(2, point);
|
|
||||||
DB.World.Execute(stmt);
|
|
||||||
}
|
|
||||||
while (result.NextRow());
|
|
||||||
|
|
||||||
handler.SendSysMessage("|cff00ff00Showing the current creature's path.|r");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (subCommand == "first")
|
|
||||||
{
|
|
||||||
handler.SendSysMessage("|cff00ff00DEBUG: wp first, pathid: {0}|r", pathId);
|
|
||||||
|
|
||||||
PreparedStatement stmt = WorldDatabase.GetPreparedStatement(WorldStatements.SEL_WAYPOINT_DATA_POS_FIRST_BY_ID);
|
|
||||||
stmt.AddValue(0, pathId);
|
|
||||||
SQLResult result = DB.World.Query(stmt);
|
|
||||||
|
|
||||||
if (result.IsEmpty())
|
|
||||||
{
|
|
||||||
handler.SendSysMessage(CypherStrings.WaypointNotfound, pathId);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
float x = result.Read<float>(0);
|
|
||||||
float y = result.Read<float>(1);
|
|
||||||
float z = result.Read<float>(2);
|
|
||||||
float o = result.Read<float>(3);
|
|
||||||
|
|
||||||
Player chr = handler.GetSession().GetPlayer();
|
|
||||||
Map map = chr.GetMap();
|
|
||||||
|
|
||||||
Creature creature = Creature.CreateCreature(1, map, new Position(x, y, z, 0));
|
|
||||||
if (creature == null)
|
|
||||||
{
|
|
||||||
handler.SendSysMessage(CypherStrings.WaypointVpNotcreated, 1);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
PhasingHandler.InheritPhaseShift(creature, chr);
|
|
||||||
creature.SaveToDB(map.GetId(), new List<Difficulty>() { map.GetDifficultyID() });
|
|
||||||
|
|
||||||
ulong dbGuid = creature.GetSpawnId();
|
|
||||||
|
|
||||||
// current "creature" variable is deleted and created fresh new, otherwise old values might trigger asserts or cause undefined behavior
|
|
||||||
creature.CleanupsBeforeDelete();
|
|
||||||
creature.Dispose();
|
|
||||||
|
|
||||||
creature = Creature.CreateCreatureFromDB(dbGuid, map, true, true);
|
|
||||||
if (creature == null)
|
|
||||||
{
|
|
||||||
handler.SendSysMessage(CypherStrings.WaypointVpNotcreated, 1);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint? displayId = null;
|
||||||
if (target != null)
|
if (target != null)
|
||||||
|
displayId = target.GetDisplayId();
|
||||||
|
|
||||||
|
Global.WaypointMgr.VisualizePath(handler.GetPlayer(), path, displayId);
|
||||||
|
|
||||||
|
ObjectGuid guid = Global.WaypointMgr.GetVisualGUIDByNode(path.Id, path.Nodes.First().Id);
|
||||||
|
if (!guid.IsEmpty())
|
||||||
{
|
{
|
||||||
creature.SetDisplayId(target.GetDisplayId());
|
handler.SendSysMessage($"|cff00ff00Path with id {pathId} is already showing.|r");
|
||||||
creature.SetObjectScale(0.5f);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handler.SendSysMessage($"|cff00ff00Showing path with id {pathId}.|r");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if (subCommand == "off")
|
||||||
if (subCommand == "last")
|
|
||||||
{
|
{
|
||||||
handler.SendSysMessage("|cff00ff00DEBUG: wp last, PathID: |r|cff00ffff{0}|r", pathId);
|
WaypointPath path = Global.WaypointMgr.GetPath(pathId);
|
||||||
|
if (path == null)
|
||||||
PreparedStatement stmt = WorldDatabase.GetPreparedStatement(WorldStatements.SEL_WAYPOINT_DATA_POS_LAST_BY_ID);
|
|
||||||
stmt.AddValue(0, pathId);
|
|
||||||
SQLResult result = DB.World.Query(stmt);
|
|
||||||
|
|
||||||
if (result.IsEmpty())
|
|
||||||
{
|
{
|
||||||
handler.SendSysMessage(CypherStrings.WaypointNotfoundlast, pathId);
|
handler.SendSysMessage($"|cff00ff00Path does not exist: id {pathId}|r");
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
float x = result.Read<float>(0);
|
Global.WaypointMgr.DevisualizePath(handler.GetPlayer(), path);
|
||||||
float y = result.Read<float>(1);
|
|
||||||
float z = result.Read<float>(2);
|
|
||||||
float o = result.Read<float>(3);
|
|
||||||
|
|
||||||
Player chr = handler.GetSession().GetPlayer();
|
|
||||||
Map map = chr.GetMap();
|
|
||||||
Position pos = new(x, y, z, o);
|
|
||||||
|
|
||||||
Creature creature = Creature.CreateCreature(1, map, pos);
|
|
||||||
if (creature == null)
|
|
||||||
{
|
|
||||||
handler.SendSysMessage(CypherStrings.WaypointNotcreated, 1);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
PhasingHandler.InheritPhaseShift(creature, chr);
|
|
||||||
creature.SaveToDB(map.GetId(), new List<Difficulty>() { map.GetDifficultyID() });
|
|
||||||
|
|
||||||
ulong dbGuid = creature.GetSpawnId();
|
|
||||||
|
|
||||||
// current "creature" variable is deleted and created fresh new, otherwise old values might trigger asserts or cause undefined behavior
|
|
||||||
creature.CleanupsBeforeDelete();
|
|
||||||
creature.Dispose();
|
|
||||||
|
|
||||||
creature = Creature.CreateCreatureFromDB(dbGuid, map, true, true);
|
|
||||||
if (creature == null)
|
|
||||||
{
|
|
||||||
handler.SendSysMessage(CypherStrings.WaypointNotcreated, 1);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (target != null)
|
|
||||||
{
|
|
||||||
creature.SetDisplayId(target.GetDisplayId());
|
|
||||||
creature.SetObjectScale(0.5f);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (subCommand == "off")
|
|
||||||
{
|
|
||||||
PreparedStatement stmt = WorldDatabase.GetPreparedStatement(WorldStatements.SEL_CREATURE_BY_ID);
|
|
||||||
stmt.AddValue(0, 1);
|
|
||||||
SQLResult result = DB.World.Query(stmt);
|
|
||||||
|
|
||||||
if (result.IsEmpty())
|
|
||||||
{
|
|
||||||
handler.SendSysMessage(CypherStrings.WaypointVpNotfound);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool hasError = false;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
ulong lowguid = result.Read<ulong>(0);
|
|
||||||
|
|
||||||
if (Creature.DeleteFromDB(lowguid))
|
|
||||||
{
|
|
||||||
handler.SendSysMessage(CypherStrings.WaypointNotremoved, lowguid);
|
|
||||||
hasError = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (result.NextRow());
|
|
||||||
// set "wpguid" column to "empty" - no visual waypoint spawned
|
|
||||||
stmt = WorldDatabase.GetPreparedStatement(WorldStatements.UPD_WAYPOINT_DATA_ALL_WPGUID);
|
|
||||||
|
|
||||||
DB.World.Execute(stmt);
|
|
||||||
//DB.World.PExecute("UPDATE creature_movement SET wpguid = '0' WHERE wpguid <> '0'");
|
|
||||||
|
|
||||||
if (hasError)
|
|
||||||
{
|
|
||||||
handler.SendSysMessage(CypherStrings.WaypointToofar1);
|
|
||||||
handler.SendSysMessage(CypherStrings.WaypointToofar2);
|
|
||||||
handler.SendSysMessage(CypherStrings.WaypointToofar3);
|
|
||||||
}
|
|
||||||
|
|
||||||
handler.SendSysMessage(CypherStrings.WaypointVpAllremoved);
|
handler.SendSysMessage(CypherStrings.WaypointVpAllremoved);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
handler.SendSysMessage("|cffff33ffDEBUG: wpshow - no valid command found|r");
|
handler.SendSysMessage("|cffff33ffDEBUG: .wp show - no valid command found|r");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -664,7 +363,7 @@ namespace Game.Chat.Commands
|
|||||||
}
|
}
|
||||||
|
|
||||||
CreatureAddon addon = Global.ObjectMgr.GetCreatureAddon(guidLow);
|
CreatureAddon addon = Global.ObjectMgr.GetCreatureAddon(guidLow);
|
||||||
if (addon == null || addon.path_id == 0)
|
if (addon == null || addon.PathId == 0)
|
||||||
{
|
{
|
||||||
handler.SendSysMessage("|cffff33ffTarget does not have a loaded path.|r");
|
handler.SendSysMessage("|cffff33ffTarget does not have a loaded path.|r");
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -1118,7 +1118,7 @@ namespace Game.Entities
|
|||||||
|
|
||||||
public override string GetDebugInfo()
|
public override string GetDebugInfo()
|
||||||
{
|
{
|
||||||
return $"{base.GetDebugInfo()}\nAIName: {GetAIName()} ScriptName: {GetScriptName()} WaypointPath: {GetWaypointPath()} SpawnId: {GetSpawnId()}";
|
return $"{base.GetDebugInfo()}\nAIName: {GetAIName()} ScriptName: {GetScriptName()} WaypointPath: {GetWaypointPathId()} SpawnId: {GetSpawnId()}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ExitVehicle(Position exitPosition = null)
|
public override void ExitVehicle(Position exitPosition = null)
|
||||||
@@ -2525,8 +2525,8 @@ namespace Game.Entities
|
|||||||
SetVisibilityDistanceOverride(creatureAddon.visibilityDistanceType);
|
SetVisibilityDistanceOverride(creatureAddon.visibilityDistanceType);
|
||||||
|
|
||||||
//Load Path
|
//Load Path
|
||||||
if (creatureAddon.path_id != 0)
|
if (creatureAddon.PathId != 0)
|
||||||
_waypointPathId = creatureAddon.path_id;
|
_waypointPathId = creatureAddon.PathId;
|
||||||
|
|
||||||
if (creatureAddon.auras != null)
|
if (creatureAddon.auras != null)
|
||||||
{
|
{
|
||||||
@@ -3509,7 +3509,7 @@ namespace Game.Entities
|
|||||||
public void GetTransportHomePosition(out float x, out float y, out float z, out float ori) { m_transportHomePosition.GetPosition(out x, out y, out z, out ori); }
|
public void GetTransportHomePosition(out float x, out float y, out float z, out float ori) { m_transportHomePosition.GetPosition(out x, out y, out z, out ori); }
|
||||||
public Position GetTransportHomePosition() { return m_transportHomePosition; }
|
public Position GetTransportHomePosition() { return m_transportHomePosition; }
|
||||||
|
|
||||||
public uint GetWaypointPath() { return _waypointPathId; }
|
public uint GetWaypointPathId() { return _waypointPathId; }
|
||||||
public void LoadPath(uint pathid) { _waypointPathId = pathid; }
|
public void LoadPath(uint pathid) { _waypointPathId = pathid; }
|
||||||
|
|
||||||
public (uint nodeId, uint pathId) GetCurrentWaypointInfo() { return _currentWaypointNodeInfo; }
|
public (uint nodeId, uint pathId) GetCurrentWaypointInfo() { return _currentWaypointNodeInfo; }
|
||||||
|
|||||||
@@ -347,7 +347,7 @@ namespace Game.Entities
|
|||||||
|
|
||||||
public class CreatureAddon
|
public class CreatureAddon
|
||||||
{
|
{
|
||||||
public uint path_id;
|
public uint PathId;
|
||||||
public uint mount;
|
public uint mount;
|
||||||
public byte standState;
|
public byte standState;
|
||||||
public byte animTier;
|
public byte animTier;
|
||||||
|
|||||||
@@ -2081,8 +2081,8 @@ namespace Game
|
|||||||
public void LoadCreatureTemplateAddons()
|
public void LoadCreatureTemplateAddons()
|
||||||
{
|
{
|
||||||
var time = Time.GetMSTime();
|
var time = Time.GetMSTime();
|
||||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13
|
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13
|
||||||
SQLResult result = DB.World.Query("SELECT entry, path_id, mount, StandState, AnimTier, VisFlags, SheathState, PvPFlags, emote, aiAnimKit, movementAnimKit, meleeAnimKit, visibilityDistanceType, auras FROM creature_template_addon");
|
SQLResult result = DB.World.Query("SELECT entry, PathId, mount, StandState, AnimTier, VisFlags, SheathState, PvPFlags, emote, aiAnimKit, movementAnimKit, meleeAnimKit, visibilityDistanceType, auras FROM creature_template_addon");
|
||||||
|
|
||||||
if (result.IsEmpty())
|
if (result.IsEmpty())
|
||||||
{
|
{
|
||||||
@@ -2101,7 +2101,7 @@ namespace Game
|
|||||||
}
|
}
|
||||||
|
|
||||||
CreatureAddon creatureAddon = new();
|
CreatureAddon creatureAddon = new();
|
||||||
creatureAddon.path_id = result.Read<uint>(1);
|
creatureAddon.PathId = result.Read<uint>(1);
|
||||||
creatureAddon.mount = result.Read<uint>(2);
|
creatureAddon.mount = result.Read<uint>(2);
|
||||||
creatureAddon.standState = result.Read<byte>(3);
|
creatureAddon.standState = result.Read<byte>(3);
|
||||||
creatureAddon.animTier = result.Read<byte>(4);
|
creatureAddon.animTier = result.Read<byte>(4);
|
||||||
@@ -2214,8 +2214,8 @@ namespace Game
|
|||||||
public void LoadCreatureAddons()
|
public void LoadCreatureAddons()
|
||||||
{
|
{
|
||||||
var time = Time.GetMSTime();
|
var time = Time.GetMSTime();
|
||||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13
|
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13
|
||||||
SQLResult result = DB.World.Query("SELECT guid, path_id, mount, StandState, AnimTier, VisFlags, SheathState, PvPFlags, emote, aiAnimKit, movementAnimKit, meleeAnimKit, visibilityDistanceType, auras FROM creature_addon");
|
SQLResult result = DB.World.Query("SELECT guid, PathId, mount, StandState, AnimTier, VisFlags, SheathState, PvPFlags, emote, aiAnimKit, movementAnimKit, meleeAnimKit, visibilityDistanceType, auras FROM creature_addon");
|
||||||
|
|
||||||
if (result.IsEmpty())
|
if (result.IsEmpty())
|
||||||
{
|
{
|
||||||
@@ -2236,8 +2236,8 @@ namespace Game
|
|||||||
|
|
||||||
CreatureAddon creatureAddon = new();
|
CreatureAddon creatureAddon = new();
|
||||||
|
|
||||||
creatureAddon.path_id = result.Read<uint>(1);
|
creatureAddon.PathId = result.Read<uint>(1);
|
||||||
if (creData.movementType == (byte)MovementGeneratorType.Waypoint && creatureAddon.path_id == 0)
|
if (creData.movementType == (byte)MovementGeneratorType.Waypoint && creatureAddon.PathId == 0)
|
||||||
{
|
{
|
||||||
creData.movementType = (byte)MovementGeneratorType.Idle;
|
creData.movementType = (byte)MovementGeneratorType.Idle;
|
||||||
Log.outError(LogFilter.Sql, $"Creature (GUID {guid}) has movement type set to WAYPOINTMOTIONTYPE but no path assigned");
|
Log.outError(LogFilter.Sql, $"Creature (GUID {guid}) has movement type set to WAYPOINTMOTIONTYPE but no path assigned");
|
||||||
|
|||||||
@@ -113,15 +113,15 @@ namespace Game.Movement
|
|||||||
x = y = z = 0;
|
x = y = z = 0;
|
||||||
|
|
||||||
// prevent a crash at empty waypoint path.
|
// prevent a crash at empty waypoint path.
|
||||||
if (_path == null || _path.nodes.Empty())
|
if (_path == null || _path.Nodes.Empty())
|
||||||
return false;
|
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})");
|
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);
|
WaypointNode waypoint = _path.Nodes.ElementAt(_currentNode);
|
||||||
|
|
||||||
x = waypoint.x;
|
x = waypoint.X;
|
||||||
y = waypoint.y;
|
y = waypoint.Y;
|
||||||
z = waypoint.z;
|
z = waypoint.Z;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,7 +132,7 @@ namespace Game.Movement
|
|||||||
if (_loadedFromDB)
|
if (_loadedFromDB)
|
||||||
{
|
{
|
||||||
if (_pathId == 0)
|
if (_pathId == 0)
|
||||||
_pathId = owner.GetWaypointPath();
|
_pathId = owner.GetWaypointPathId();
|
||||||
|
|
||||||
_path = Global.WaypointMgr.GetPath(_pathId);
|
_path = Global.WaypointMgr.GetPath(_pathId);
|
||||||
}
|
}
|
||||||
@@ -143,6 +143,11 @@ namespace Game.Movement
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_followPathBackwardsFromEndToStart = _path.Flags.HasFlag(WaypointPathFlags.FollowPathBackwardsFromEndToStart);
|
||||||
|
|
||||||
|
if (_path.Nodes.Count == 1)
|
||||||
|
_repeating = false;
|
||||||
|
|
||||||
owner.StopMoving();
|
owner.StopMoving();
|
||||||
|
|
||||||
_nextMoveTime.Reset(1000);
|
_nextMoveTime.Reset(1000);
|
||||||
@@ -163,7 +168,7 @@ namespace Game.Movement
|
|||||||
if (owner == null || !owner.IsAlive())
|
if (owner == null || !owner.IsAlive())
|
||||||
return true;
|
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;
|
return true;
|
||||||
|
|
||||||
if (_duration != null)
|
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();
|
CreatureAI ai = owner.GetAI();
|
||||||
if (ai != null)
|
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)
|
void OnArrived(Creature owner)
|
||||||
{
|
{
|
||||||
if (_path == null || _path.nodes.Empty())
|
if (_path == null || _path.Nodes.Empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Cypher.Assert(_currentNode < _path.nodes.Count, $"WaypointMovementGenerator.OnArrived: tried to reference a node id ({_currentNode}) which is not included in path ({_path.id})");
|
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);
|
WaypointNode waypoint = _path.Nodes.ElementAt(_currentNode);
|
||||||
if (waypoint.delay != 0)
|
if (waypoint.Delay != 0)
|
||||||
{
|
{
|
||||||
owner.ClearUnitState(UnitState.RoamingMove);
|
owner.ClearUnitState(UnitState.RoamingMove);
|
||||||
_nextMoveTime.Reset(waypoint.delay);
|
_nextMoveTime.Reset(waypoint.Delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_waitTimeRangeAtPathEnd.HasValue && _followPathBackwardsFromEndToStart
|
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);
|
owner.ClearUnitState(UnitState.RoamingMove);
|
||||||
TimeSpan waitTime = RandomHelper.RandTime(_waitTimeRangeAtPathEnd.Value.min, _waitTimeRangeAtPathEnd.Value.max);
|
TimeSpan waitTime = RandomHelper.RandTime(_waitTimeRangeAtPathEnd.Value.min, _waitTimeRangeAtPathEnd.Value.max);
|
||||||
@@ -301,21 +310,15 @@ namespace Game.Movement
|
|||||||
_nextMoveTime.Reset(waitTime);
|
_nextMoveTime.Reset(waitTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
// inform AI
|
MovementInform(owner);
|
||||||
CreatureAI ai = owner.GetAI();
|
|
||||||
if (ai != null)
|
|
||||||
{
|
|
||||||
ai.MovementInform(MovementGeneratorType.Waypoint, (uint)_currentNode);
|
|
||||||
ai.WaypointReached(waypoint.id, _path.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
owner.UpdateCurrentWaypointInfo(waypoint.id, _path.id);
|
owner.UpdateCurrentWaypointInfo(waypoint.Id, _path.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StartMove(Creature owner, bool relaunch = false)
|
void StartMove(Creature owner, bool relaunch = false)
|
||||||
{
|
{
|
||||||
// sanity checks
|
// 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;
|
return;
|
||||||
|
|
||||||
if (owner.HasUnitState(UnitState.NotMove) || owner.IsMovementPreventedByCasting() || (owner.IsFormationLeader() && !owner.IsFormationLeaderMoveAllowed())) // if cannot move OR cannot move because of formation
|
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())
|
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
|
// inform AI
|
||||||
CreatureAI ai = owner.GetAI();
|
CreatureAI ai = owner.GetAI();
|
||||||
if (ai != null)
|
if (ai != null)
|
||||||
ai.WaypointStarted(_path.nodes[_currentNode].id, _path.id);
|
ai.WaypointStarted(_path.Nodes[_currentNode].Id, _path.Id);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
WaypointNode currentWaypoint = _path.nodes[_currentNode];
|
WaypointNode currentWaypoint = _path.Nodes[_currentNode];
|
||||||
float x = currentWaypoint.x;
|
float x = currentWaypoint.X;
|
||||||
float y = currentWaypoint.y;
|
float y = currentWaypoint.Y;
|
||||||
float z = currentWaypoint.z;
|
float z = currentWaypoint.Z;
|
||||||
float o = owner.GetOrientation();
|
float o = owner.GetOrientation();
|
||||||
|
|
||||||
if (!transportPath)
|
if (!transportPath)
|
||||||
@@ -365,7 +368,7 @@ namespace Game.Movement
|
|||||||
// inform AI
|
// inform AI
|
||||||
CreatureAI ai = owner.GetAI();
|
CreatureAI ai = owner.GetAI();
|
||||||
if (ai != null)
|
if (ai != null)
|
||||||
ai.WaypointPathEnded(currentWaypoint.id, _path.id);
|
ai.WaypointPathEnded(currentWaypoint.Id, _path.Id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -376,11 +379,11 @@ namespace Game.Movement
|
|||||||
// inform AI
|
// inform AI
|
||||||
CreatureAI ai = owner.GetAI();
|
CreatureAI ai = owner.GetAI();
|
||||||
if (ai != null)
|
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})");
|
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];
|
WaypointNode waypoint = _path.Nodes[_currentNode];
|
||||||
|
|
||||||
RemoveFlag(MovementGeneratorFlags.Transitory | MovementGeneratorFlags.InformEnabled | MovementGeneratorFlags.TimedPaused);
|
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
|
//! Do not use formationDest here, MoveTo requires transport offsets due to DisableTransportPathTransformations() call
|
||||||
//! but formationDest contains global coordinates
|
//! 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))
|
if (waypoint.Orientation.HasValue && (waypoint.Delay > 0 || _currentNode == _path.Nodes.Count - 1))
|
||||||
init.SetFacing(waypoint.orientation.Value);
|
init.SetFacing(waypoint.Orientation.Value);
|
||||||
|
|
||||||
switch (waypoint.moveType)
|
switch (_path.MoveType)
|
||||||
{
|
{
|
||||||
case WaypointMoveType.Land:
|
case WaypointMoveType.Land:
|
||||||
init.SetAnimation(AnimTier.Ground);
|
init.SetAnimation(AnimTier.Ground);
|
||||||
@@ -440,16 +443,16 @@ namespace Game.Movement
|
|||||||
|
|
||||||
bool ComputeNextNode()
|
bool ComputeNextNode()
|
||||||
{
|
{
|
||||||
if ((_currentNode == _path.nodes.Count - 1) && !_repeating)
|
if ((_currentNode == _path.Nodes.Count - 1) && !_repeating)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!_followPathBackwardsFromEndToStart || _path.nodes.Count < 2)
|
if (!_followPathBackwardsFromEndToStart || _path.Nodes.Count < 2)
|
||||||
_currentNode = (_currentNode + 1) % _path.nodes.Count;
|
_currentNode = (_currentNode + 1) % _path.Nodes.Count;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!_isReturningToStart)
|
if (!_isReturningToStart)
|
||||||
{
|
{
|
||||||
if (++_currentNode >= _path.nodes.Count)
|
if (++_currentNode >= _path.Nodes.Count)
|
||||||
{
|
{
|
||||||
_currentNode -= 2;
|
_currentNode -= 2;
|
||||||
_isReturningToStart = true;
|
_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,
|
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)
|
(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);
|
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.
|
// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information.
|
||||||
|
|
||||||
using Framework.Database;
|
using Framework.Database;
|
||||||
|
using Game.Entities;
|
||||||
using Game.Maps;
|
using Game.Maps;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Game
|
namespace Game
|
||||||
{
|
{
|
||||||
@@ -11,16 +14,24 @@ namespace Game
|
|||||||
{
|
{
|
||||||
WaypointManager() { }
|
WaypointManager() { }
|
||||||
|
|
||||||
public void Load()
|
public void LoadPaths()
|
||||||
{
|
{
|
||||||
|
_LoadPaths();
|
||||||
|
_LoadPathNodes();
|
||||||
|
DoPostLoadingChecks();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _LoadPaths()
|
||||||
|
{
|
||||||
|
_pathStorage.Clear();
|
||||||
|
|
||||||
var oldMSTime = Time.GetMSTime();
|
var oldMSTime = Time.GetMSTime();
|
||||||
|
|
||||||
// 0 1 2 3 4 5 6 7
|
// 0 1 2
|
||||||
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");
|
SQLResult result = DB.World.Query("SELECT PathId, MoveType, Flags FROM waypoint_path");
|
||||||
|
|
||||||
if (result.IsEmpty())
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,143 +39,308 @@ namespace Game
|
|||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
uint pathId = result.Read<uint>(0);
|
LoadPathFromDB(result.GetFields());
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
++count;
|
++count;
|
||||||
} while (result.NextRow());
|
} 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);
|
uint oldMSTime = Time.GetMSTime();
|
||||||
|
|
||||||
PreparedStatement stmt = WorldDatabase.GetPreparedStatement(WorldStatements.SEL_WAYPOINT_DATA_BY_ID);
|
|
||||||
stmt.AddValue(0, id);
|
|
||||||
SQLResult result = DB.World.Query(stmt);
|
|
||||||
|
|
||||||
|
// 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())
|
if (result.IsEmpty())
|
||||||
|
{
|
||||||
|
Log.outInfo(LogFilter.ServerLoading, "Loaded 0 waypoint path nodes. DB table `waypoint_path_node` is empty!");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint count = 0;
|
||||||
|
|
||||||
List<WaypointNode> values = new();
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
float x = result.Read<float>(1);
|
LoadPathNodesFromDB(result.GetFields());
|
||||||
float y = result.Read<float>(2);
|
++count;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
while (result.NextRow());
|
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 class WaypointNode
|
||||||
{
|
{
|
||||||
public WaypointNode() { moveType = WaypointMoveType.Run; }
|
public WaypointNode() { MoveType = WaypointMoveType.Run; }
|
||||||
public WaypointNode(uint _id, float _x, float _y, float _z, float? _orientation = null, uint _delay = 0)
|
public WaypointNode(uint id, float x, float y, float z, float? orientation = null, uint delay = 0)
|
||||||
{
|
{
|
||||||
id = _id;
|
Id = id;
|
||||||
x = _x;
|
X = x;
|
||||||
y = _y;
|
Y = y;
|
||||||
z = _z;
|
Z = z;
|
||||||
orientation = _orientation;
|
Orientation = orientation;
|
||||||
delay = _delay;
|
Delay = delay;
|
||||||
moveType = WaypointMoveType.Walk;
|
MoveType = WaypointMoveType.Walk;
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint id;
|
public uint Id;
|
||||||
public float x, y, z;
|
public float X;
|
||||||
public float? orientation;
|
public float Y;
|
||||||
public uint delay;
|
public float Z;
|
||||||
public WaypointMoveType moveType;
|
public float? Orientation;
|
||||||
|
public uint Delay;
|
||||||
|
public WaypointMoveType MoveType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class WaypointPath
|
public class WaypointPath
|
||||||
{
|
{
|
||||||
public WaypointPath() { }
|
public WaypointPath() { }
|
||||||
public WaypointPath(uint _id, List<WaypointNode> _nodes)
|
public WaypointPath(uint id, List<WaypointNode> nodes)
|
||||||
{
|
{
|
||||||
id = _id;
|
Id = id;
|
||||||
nodes = _nodes;
|
Nodes = nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<WaypointNode> nodes = new();
|
public List<WaypointNode> Nodes = new();
|
||||||
public uint id;
|
public uint Id;
|
||||||
|
public WaypointMoveType MoveType;
|
||||||
|
public WaypointPathFlags Flags = WaypointPathFlags.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum WaypointMoveType
|
public enum WaypointMoveType
|
||||||
{
|
{
|
||||||
Walk,
|
Walk = 0,
|
||||||
Run,
|
Run = 1,
|
||||||
Land,
|
Land = 2,
|
||||||
Takeoff,
|
Takeoff = 3,
|
||||||
|
|
||||||
Max
|
Max
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum WaypointPathFlags
|
||||||
|
{
|
||||||
|
None = 0x00,
|
||||||
|
FollowPathBackwardsFromEndToStart = 0x01,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -898,7 +898,7 @@ namespace Game
|
|||||||
Global.ObjectMgr.LoadVendors(); // must be after load CreatureTemplate and ItemTemplate
|
Global.ObjectMgr.LoadVendors(); // must be after load CreatureTemplate and ItemTemplate
|
||||||
|
|
||||||
Log.outInfo(LogFilter.ServerLoading, "Loading Waypoints...");
|
Log.outInfo(LogFilter.ServerLoading, "Loading Waypoints...");
|
||||||
Global.WaypointMgr.Load();
|
Global.WaypointMgr.LoadPaths();
|
||||||
|
|
||||||
Log.outInfo(LogFilter.ServerLoading, "Loading Creature Formations...");
|
Log.outInfo(LogFilter.ServerLoading, "Loading Creature Formations...");
|
||||||
FormationMgr.LoadCreatureFormations();
|
FormationMgr.LoadCreatureFormations();
|
||||||
|
|||||||
Reference in New Issue
Block a user