Skip to content

Commit

Permalink
Implement waypoint sql generation
Browse files Browse the repository at this point in the history
  • Loading branch information
killerwife committed Oct 9, 2024
1 parent 01c0e51 commit 4e0ec47
Show file tree
Hide file tree
Showing 11 changed files with 332 additions and 15 deletions.
11 changes: 10 additions & 1 deletion WowPacketParser/App.config
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,8 @@
<add key="hotfix_optional_data" value="false"/>
<add key="hotfixes" value="false"/>

<add key="creature_movement" value="false"/>


<!--
Option: ParseAllHotfixes
Expand Down Expand Up @@ -246,11 +248,18 @@
<add key="GenerateCreateObject2SpawnsOnly" value="false"/>

<!--
Option: SkipIntermediatePoints
Description: Skips intermediate points for waypoint paths
Default: "true"
-->
<add key="SkipIntermediatePoints" value="false"/>

<!--
Option: SkipDuplicateSpawns
Description: Skip generation of duplicate spawns (grouped by: entry, phases, position)
Default: "true"
-->
<add key="SkipDuplicateSpawns" value="true"/>
<add key="SkipDuplicateSpawns" value="true"/>

<!--
Option: SplitSQLFile
Expand Down
1 change: 1 addition & 0 deletions WowPacketParser/Enums/SQLOutput.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public enum SQLOutput
creature_addon,
creature_equip_template,
creature_model_info,
creature_movement,
creature_queststarter,
creature_questender,
creature_template,
Expand Down
1 change: 1 addition & 0 deletions WowPacketParser/Misc/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public static class Settings
public static readonly bool ForcePhaseZero = Conf.GetBoolean("ForcePhaseZero", false);
public static readonly bool GenerateCreateObject2SpawnsOnly = Conf.GetBoolean("GenerateCreateObject2SpawnsOnly", false);
public static readonly bool SkipDuplicateSpawns = Conf.GetBoolean("SkipDuplicateSpawns", false);
public static readonly bool SkipIntermediatePoints = Conf.GetBoolean("SkipDuplicateSpawns", false);
public static readonly string SQLFileName = Conf.GetString("SQLFileName", string.Empty);
public static readonly bool SplitSQLFile = Conf.GetBoolean("SplitSQLFile", false);
public static readonly bool ShowEndPrompt = Conf.GetBoolean("ShowEndPrompt", false);
Expand Down
118 changes: 118 additions & 0 deletions WowPacketParser/SQL/Builders/Movement.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
using System;
using WowPacketParser.Enums;
using WowPacketParser.Misc;
using WowPacketParser.Store;
using WowPacketParser.SQL;
using System.Linq;

namespace WowPacketParser.SQL.Builders
{
[BuilderClass]
public static class Movement
{
[BuilderMethod]
public static string MovementData()
{
if (Storage.CreatureMovement.IsEmpty())
return string.Empty;

if (!Settings.SQLOutputFlag.HasAnyFlagBit(SQLOutput.creature_movement))
return string.Empty;

string output = "SET @MOVID = 0;\n";
int pathIdCounter = 0;
if (Settings.TargetedProject == TargetedProject.Cmangos)
{
string nodeSql = "INSERT INTO waypoint_path (PathId, Point, PositionX, PositionY, PositionZ, Orientation, WaitTime, ScriptId, Comment) VALUES\n";
foreach (var data in Storage.CreatureMovement.ToList())
{
var creatureMovement = data.Item1;
if (creatureMovement.Waypoints.Count == 0)
continue;

string creatureName = SQLUtil.EscapeString(StoreGetters.GetName(Utilities.ObjectTypeToStore(creatureMovement.GUID.GetObjectType()), (int)creatureMovement.GUID.GetEntry()));
output += "-- " + $"GUID: {creatureMovement.GUID} PathType: {creatureMovement.Type}" + "\n" + $"INSERT INTO waypoint_path_name(PathId, Name) VALUES(@MOVID + {pathIdCounter},'{creatureName}');\n" + nodeSql;

int pointIdCounter = 1;
int actualPoint = 1;
foreach (var node in creatureMovement.Waypoints)
{
bool finalP = creatureMovement.Destination == null && creatureMovement.Waypoints.Count == actualPoint;
++actualPoint;
float ori = finalP ? (creatureMovement.FinalOrientation != null ? creatureMovement.FinalOrientation.Value : 100f) : 100f;
if (node.Point == false)
{
if (Settings.SkipIntermediatePoints == true)
continue;
output += "-- ";
}

output += $"(@MOVID + {pathIdCounter}, '{pointIdCounter}', '{node.Position.X}', '{node.Position.Y}', '{node.Position.Z}', '{ori}', '0', '0', NULL)";

if (!finalP)
output += ",\n";
else
output += ";\n\n";

++pointIdCounter;
}

if (creatureMovement.Destination != null)
{
float ori = creatureMovement.FinalOrientation != null ? creatureMovement.FinalOrientation.Value : 100f;
output += $"(@MOVID + {pathIdCounter}, '{pointIdCounter}', '{creatureMovement.Destination.Position.X}', '{creatureMovement.Destination.Position.Y}', '{creatureMovement.Destination.Position.Z}', '{ori}', '0', '0', NULL);\n";
}

++pathIdCounter;
}
}
else if (Settings.TargetedProject == TargetedProject.TrinityCore)
{
string nodeSql = "INSERT INTO waypoint_path_node (PathId, NodeId, PositionX, PositionY, PositionZ, Orientation, Delay) VALUES\n";
foreach (var data in Storage.CreatureMovement.ToList())
{
var creatureMovement = data.Item1;
if (creatureMovement.Waypoints.Count == 0)
continue;

string commentInformation = $"GUID: {creatureMovement.GUID} PathType: {creatureMovement.Type}";
output += "-- " + commentInformation + "\n";
output += nodeSql;

int pointIdCounter = 1;
int actualPoint = 1;
foreach (var node in creatureMovement.Waypoints)
{
bool finalP = creatureMovement.Destination == null && creatureMovement.Waypoints.Count == actualPoint;
++actualPoint;
float ori = finalP ? (creatureMovement.FinalOrientation != null ? creatureMovement.FinalOrientation.Value : 100f) : 100f;
if (node.Point == false)
{
if (Settings.SkipIntermediatePoints == true)
continue;
output += "-- ";
}
output += $"(@MOVID + {pathIdCounter}, '{pointIdCounter}', '{node.Position.X}', '{node.Position.Y}', '{node.Position.Z}', '{ori}')";

if (!finalP)
output += ",\n";
else
output += ";\n\n";

++pointIdCounter;
}

if (creatureMovement.Destination != null)
{
float ori = creatureMovement.FinalOrientation != null ? creatureMovement.FinalOrientation.Value : 100f;
output += $"(@MOVID + {pathIdCounter}, '{pointIdCounter}', '{creatureMovement.Destination.Position.X}', '{creatureMovement.Destination.Position.Y}', '{creatureMovement.Destination.Position.Z}', '{ori}', '0', '0', NULL);\n\n";
}

++pathIdCounter;
}
}

return output;
}
}
}
16 changes: 16 additions & 0 deletions WowPacketParser/Store/Objects/Movement/CreatureMovement.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.Collections.Generic;
using WowPacketParser.Misc;

namespace WowPacketParser.Store.Objects.Movement
{
public class CreatureMovement
{
public CreatureMovementFlags Type { get; set; }
public WowGuid GUID { get; set; }
public int PathId { get; set; }
public int Id { get; set; }
public List<CreatureMovementNode> Waypoints { get; set; } = new();
public CreatureMovementNode? Destination { get; set; } = null;

Check warning on line 13 in WowPacketParser/Store/Objects/Movement/CreatureMovement.cs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, Debug)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 13 in WowPacketParser/Store/Objects/Movement/CreatureMovement.cs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, Debug)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 13 in WowPacketParser/Store/Objects/Movement/CreatureMovement.cs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, Release)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 13 in WowPacketParser/Store/Objects/Movement/CreatureMovement.cs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, Release)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 13 in WowPacketParser/Store/Objects/Movement/CreatureMovement.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest, Debug)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 13 in WowPacketParser/Store/Objects/Movement/CreatureMovement.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest, Debug)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 13 in WowPacketParser/Store/Objects/Movement/CreatureMovement.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest, Release)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 13 in WowPacketParser/Store/Objects/Movement/CreatureMovement.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest, Release)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 13 in WowPacketParser/Store/Objects/Movement/CreatureMovement.cs

View workflow job for this annotation

GitHub Actions / build (macos-14, Debug)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 13 in WowPacketParser/Store/Objects/Movement/CreatureMovement.cs

View workflow job for this annotation

GitHub Actions / build (macos-14, Debug)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 13 in WowPacketParser/Store/Objects/Movement/CreatureMovement.cs

View workflow job for this annotation

GitHub Actions / build (macos-14, Release)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 13 in WowPacketParser/Store/Objects/Movement/CreatureMovement.cs

View workflow job for this annotation

GitHub Actions / build (macos-14, Release)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
public float? FinalOrientation { get; set; } = null; // signals end of current path and wait time
}
}
12 changes: 12 additions & 0 deletions WowPacketParser/Store/Objects/Movement/CreatureMovementFlags.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace WowPacketParser.Store.Objects.Movement
{
public enum CreatureMovementFlags
{
None = 0, // pathfinding
ExactPath = 1, // sent fully
ExactPathFlying = 2, // sent fully + flying flag
ExactPathFlyingCyclic = 3, // sent fully + flying flag + cyclic flag
ExactPathAndJump = 4, // sent fully + parabolic movement at the end
Invalid = 100,
}
}
10 changes: 10 additions & 0 deletions WowPacketParser/Store/Objects/Movement/CreatureMovementNode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using WowPacketParser.Misc;

namespace WowPacketParser.Store.Objects.Movement
{
public class CreatureMovementNode
{
public Vector3 Position { get; set; }
public bool Point { get; set; }
}
}
4 changes: 4 additions & 0 deletions WowPacketParser/Store/Storage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using WowPacketParser.Enums;
using WowPacketParser.Misc;
using WowPacketParser.Store.Objects;
using WowPacketParser.Store.Objects.Movement;

namespace WowPacketParser.Store
{
Expand Down Expand Up @@ -117,6 +118,9 @@ public static class Storage
// Weather updates
public static readonly DataBag<WeatherUpdate> WeatherUpdates = new DataBag<WeatherUpdate>(new List<SQLOutput> { SQLOutput.weather_updates });

// Movement
public static readonly StoreBag<CreatureMovement> CreatureMovement = new StoreBag<CreatureMovement>(new List<SQLOutput> { SQLOutput.creature_movement });

// Npc Spell Click
public static readonly StoreBag<WowGuid> NpcSpellClicks = new StoreBag<WowGuid>(new List<SQLOutput> { SQLOutput.npc_spellclick_spells });
public static readonly DataBag<NpcSpellClick> SpellClicks = new DataBag<NpcSpellClick>(new List<SQLOutput> { SQLOutput.npc_spellclick_spells });
Expand Down
46 changes: 42 additions & 4 deletions WowPacketParserModule.V2_5_1_38707/Parsers/UpdateHandler.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
using WowPacketParser.Enums;
using System.Drawing;
using System.Linq;
using WowPacketParser.Enums;
using WowPacketParser.Misc;
using WowPacketParser.PacketStructures;
using WowPacketParser.Parsing;
using WowPacketParser.Proto;
using WowPacketParser.Store;
using WowPacketParser.Store.Objects;
using WowPacketParser.Store.Objects.Movement;
using WowPacketParser.Store.Objects.UpdateFields;
using CoreFields = WowPacketParser.Enums.Version;
using CoreParsers = WowPacketParser.Parsing.Parsers;
Expand Down Expand Up @@ -441,14 +444,35 @@ private static MovementInfo ReadMovementUpdateBlock(Packet packet, WowGuid guid,
{
packet.ResetBitReader();
packet.ReadInt32("ID", index);
packet.ReadVector3("Destination", index);

CreatureMovement movement = Storage.CreatureMovement.Where(p => p.Item1.GUID == guid).SingleOrDefault()?.Item1;
bool add = false;
if (movement == null)
{
movement = new CreatureMovement()
{
GUID = guid
};
add = true;
}

var destination = packet.ReadVector3("Destination", index);

var hasMovementSplineMove = packet.ReadBit("MovementSplineMove", index);
if (hasMovementSplineMove)
{
packet.ResetBitReader();

packet.ReadUInt32E<SplineFlag>("SplineFlags", index);
var splineFlag = packet.ReadUInt32E<SplineFlag>("SplineFlags", index);
CreatureMovementFlags moveType = CreatureMovementFlags.None;

if (splineFlag.HasFlag(SplineFlag.EnterCycle) || splineFlag.HasFlag(SplineFlag.Cyclic))
moveType = CreatureMovementFlags.ExactPathFlyingCyclic;
else if (splineFlag.HasFlag(SplineFlag.Flying))
moveType = CreatureMovementFlags.ExactPathFlying;
else if (splineFlag.HasFlag(SplineFlag.UncompressedPath))
moveType = CreatureMovementFlags.ExactPath;

packet.ReadInt32("Elapsed", index);
packet.ReadUInt32("Duration", index);
packet.ReadSingle("DurationModifier", index);
Expand Down Expand Up @@ -493,6 +517,7 @@ private static MovementInfo ReadMovementUpdateBlock(Packet packet, WowGuid guid,
break;
case 3:
orientation = packet.ReadSingle("FaceDirection", index);
moveType = CreatureMovementFlags.Invalid;
break;
default:
break;
Expand All @@ -504,13 +529,23 @@ private static MovementInfo ReadMovementUpdateBlock(Packet packet, WowGuid guid,
for (var i = 0; i < pointsCount; ++i)
{
var spot = packet.ReadVector3("Points", index, i);
if (moveType != CreatureMovementFlags.Invalid)
movement.Waypoints.Add(new CreatureMovementNode
{
Position = spot,
Point = splineFlag.HasFlag(SplineFlag.EnterCycle) || splineFlag.HasFlag(SplineFlag.Cyclic)
});
}

if (hasSpellEffectExtraData)
V8_0_1_27101.Parsers.MovementHandler.ReadMonsterSplineSpellEffectExtraData(packet, index);

if (hasJumpExtraData)
V8_0_1_27101.Parsers.MovementHandler.ReadMonsterSplineJumpExtraData(packet, index);
{
var jumpData = V8_0_1_27101.Parsers.MovementHandler.ReadMonsterSplineJumpExtraData(packet, index);
if (jumpData.StartTime > 0)
moveType = CreatureMovementFlags.ExactPathAndJump;
}

if (hasAnimationTierTransition)
{
Expand All @@ -531,6 +566,9 @@ private static MovementInfo ReadMovementUpdateBlock(Packet packet, WowGuid guid,
}
}
}

if (movement.Type != CreatureMovementFlags.Invalid && add)
Storage.CreatureMovement.Add(movement);
}
}

Expand Down
Loading

0 comments on commit 4e0ec47

Please sign in to comment.