Fix SMSG_MONSTER_MOVE spline flag values causing NPCs to stand still

The parser used wrong SplineFlag bitmask values that don't match WotLK 3.3.5a:
- Animation: 0x00000100 → 0x00400000 (was matching SPLINEFLAG_DONE)
- Parabolic: 0x00000200 → 0x00000800 (was matching SPLINEFLAG_FALLING)
- Uncompressed path: 0x00040000 → Catmullrom|Flying (0x00082000)

The critical bug: SPLINEFLAG_FALLING (0x00000200) is set when NPCs move over
sloped terrain during combat. The parser mistook it for parabolic and read 8
extra bytes, misaligning pointCount and the destination coords. hasDest stayed
false, the move callback never fired, and NPCs appeared frozen in place.

Also fix Animation field read: uint8+int32 (5 bytes) not uint32+uint32 (8 bytes).
This commit is contained in:
Kelsi 2026-02-17 18:16:53 -08:00
parent 68e39a2192
commit 4043e47fd5

View file

@ -2194,21 +2194,27 @@ bool MonsterMoveParser::parse(network::Packet& packet, MonsterMoveData& data) {
if (packet.getReadPos() + 4 > packet.getSize()) return false;
data.splineFlags = packet.readUInt32();
// Check for animation flag (0x00000100)
if (data.splineFlags & 0x00000100) {
if (packet.getReadPos() + 8 > packet.getSize()) return false;
packet.readUInt32(); // animId
packet.readUInt32(); // effectStartTime
// WotLK 3.3.5a SplineFlags (from TrinityCore/MaNGOS MoveSplineFlag.h):
// Animation = 0x00400000
// Parabolic = 0x00000800
// Catmullrom = 0x00080000 \ either means uncompressed (absolute) waypoints
// Flying = 0x00002000 /
// [if Animation] uint8 animationType + int32 effectStartTime (5 bytes)
if (data.splineFlags & 0x00400000) {
if (packet.getReadPos() + 5 > packet.getSize()) return false;
packet.readUInt8(); // animationType
packet.readUInt32(); // effectStartTime (int32, read as uint32 same size)
}
// uint32 duration
if (packet.getReadPos() + 4 > packet.getSize()) return false;
data.duration = packet.readUInt32();
// Check for parabolic flag (0x00000200)
if (data.splineFlags & 0x00000200) {
// [if Parabolic] float verticalAcceleration + int32 effectStartTime (8 bytes)
if (data.splineFlags & 0x00000800) {
if (packet.getReadPos() + 8 > packet.getSize()) return false;
packet.readFloat(); // vertAccel
packet.readFloat(); // verticalAcceleration
packet.readUInt32(); // effectStartTime
}
@ -2218,10 +2224,9 @@ bool MonsterMoveParser::parse(network::Packet& packet, MonsterMoveData& data) {
if (pointCount == 0) return true;
// Read destination point(s)
// If UncompressedPath flag (0x00040000): all points are full float x,y,z
// Otherwise: first is packed destination, rest are packed deltas
bool uncompressed = (data.splineFlags & 0x00040000) != 0;
// Catmullrom or Flying → all waypoints stored as absolute float3 (uncompressed).
// Otherwise: first float3 is final destination, remaining are packed deltas.
bool uncompressed = (data.splineFlags & (0x00080000 | 0x00002000)) != 0;
if (uncompressed) {
// Read last point as destination