From 770f9e11db0e96a3fa1155edcb2181e82476b9ad Mon Sep 17 00:00:00 2001 From: Ovahlord Date: Sat, 19 Aug 2023 15:04:34 +0200 Subject: [PATCH] Core/Movement: sync spline code with master branch --- src/server/game/Entities/Unit/Unit.cpp | 22 +++++- src/server/game/Entities/Unit/Unit.h | 4 +- .../game/Movement/Spline/MoveSpline.cpp | 66 ++++++++--------- src/server/game/Movement/Spline/MoveSpline.h | 5 +- .../game/Movement/Spline/MoveSplineFlag.h | 70 +++++++++---------- .../game/Movement/Spline/MoveSplineInit.cpp | 32 +++++---- .../game/Movement/Spline/MoveSplineInit.h | 15 ++-- .../game/Movement/Spline/MoveSplineInitArgs.h | 15 ++-- .../Movement/Spline/MovementPacketBuilder.cpp | 23 +++--- .../game/Server/Packets/MovementPackets.cpp | 29 ++------ 10 files changed, 143 insertions(+), 138 deletions(-) diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index caff43418e..d45e7d4220 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -542,9 +542,8 @@ void Unit::UpdateSplineMovement(uint32 t_diff) if (arrived) { DisableSpline(); - - if (movespline->HasAnimation()) - SetAnimationTier(movespline->GetAnimationTier()); + if (Optional animTier = movespline->GetAnimation()) + SetAnimationTier(*animTier); } UpdateSplinePosition(); @@ -564,6 +563,8 @@ void Unit::UpdateSplinePosition() if (TransportBase* transport = GetDirectTransport()) transport->CalculatePassengerPosition(loc.x, loc.y, loc.z, &loc.orientation); + else + return; } if (HasUnitState(UNIT_STATE_CANNOT_TURN)) @@ -13649,6 +13650,21 @@ void Unit::SetFacingToObject(WorldObject const* object, bool force) init.Launch(); } +void Unit::SetFacingToPoint(Position const& point, bool force) +{ + // do not face when already moving + if (!force && (!IsStopped() || !movespline->Finalized())) + return; + + /// @todo figure out under what conditions creature will move towards object instead of facing it where it currently is. + Movement::MoveSplineInit init(this); + init.MoveTo(GetPositionX(), GetPositionY(), GetPositionZ(), false); + if (GetTransport()) + init.DisableTransportPathTransformations(); // It makes no sense to target global orientation + init.SetFacing(point.GetPositionX(), point.GetPositionY(), point.GetPositionZ()); + init.Launch(); +} + bool Unit::SetWalk(bool enable) { if (enable == IsWalking()) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index c5be8b8d25..72294e5391 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1214,12 +1214,10 @@ class TC_GAME_API Unit : public WorldObject virtual bool SetHover(bool enable, bool packetOnly = false, bool updateAnimationTier = true); void SendSetVehicleRecId(uint32 vehicleId); - // Sets the internal orientation value to face the provided target. Does NOT have clientside effects. void SetOrientationTowards(WorldObject const* target); - // Launches a spline to face the given orientation. void SetFacingTo(float const ori, bool force = true); - // Launches a spline to face the given object void SetFacingToObject(WorldObject const* object, bool force = true); + void SetFacingToPoint(Position const& point, bool force = true); bool IsAlive() const { return (m_deathState == ALIVE); } bool isDying() const { return (m_deathState == JUST_DIED); } diff --git a/src/server/game/Movement/Spline/MoveSpline.cpp b/src/server/game/Movement/Spline/MoveSpline.cpp index 9e6f17a4cd..660341274e 100644 --- a/src/server/game/Movement/Spline/MoveSpline.cpp +++ b/src/server/game/Movement/Spline/MoveSpline.cpp @@ -43,21 +43,22 @@ Location MoveSpline::computePosition(int32 time_point, int32 point_index) const else if (splineflags.falling) computeFallElevation(time_point, c.z); - if (splineflags.done && splineflags.isFacing()) + if (splineflags.done && facing.type != MONSTER_MOVE_NORMAL) { - if (splineflags.final_angle) + if (facing.type == MONSTER_MOVE_FACING_ANGLE) c.orientation = facing.angle; - else if (splineflags.final_point) + else if (facing.type == MONSTER_MOVE_FACING_SPOT) c.orientation = std::atan2(facing.f.y - c.y, facing.f.x - c.x); //nothing to do for MoveSplineFlag::Final_Target flag } else { - if (!splineflags.hasFlag(MoveSplineFlag::OrientationFixed | MoveSplineFlag::Falling | MoveSplineFlag::Unknown0)) + if (!splineflags.hasFlag(MoveSplineFlag::OrientationFixed | MoveSplineFlag::Falling | MoveSplineFlag::Unknown_0x8)) { Vector3 hermite; spline.evaluate_derivative(point_Idx, u, hermite); - c.orientation = std::atan2(hermite.y, hermite.x); + if (hermite.x != 0.f || hermite.y != 0.f) + c.orientation = std::atan2(hermite.y, hermite.x); } if (splineflags.backward) @@ -186,6 +187,9 @@ void MoveSpline::Initialize(MoveSplineInitArgs const& args) time_passed = 0; vertical_acceleration = 0.f; effect_start_time = 0; + anim_tier = args.animTier; + splineIsFacingOnly = args.path.size() == 2 && args.facing.type != MONSTER_MOVE_NORMAL && ((args.path[1] - args.path[0]).length() < 0.1f); + velocity = args.velocity; // Check if its a stop spline @@ -201,12 +205,16 @@ void MoveSpline::Initialize(MoveSplineInitArgs const& args) // spline initialized, duration known and i able to compute parabolic acceleration if (args.flags & (MoveSplineFlag::Parabolic | MoveSplineFlag::Animation)) { - effect_start_time = Duration() * args.time_perc; - if (args.flags.parabolic && effect_start_time < Duration()) + int32 spline_duration = Duration(); + effect_start_time = spline_duration * args.effect_start_time_percent + args.effect_start_time.count(); + if (effect_start_time > spline_duration) + effect_start_time = spline_duration; + + if (args.flags.parabolic && effect_start_time < spline_duration) { if (args.parabolic_amplitude != 0.0f) { - float f_duration = MSToSec(Duration() - effect_start_time); + float f_duration = MSToSec(spline_duration - effect_start_time); vertical_acceleration = args.parabolic_amplitude * 8.f / (f_duration * f_duration); } else if (args.vertical_acceleration != 0.0f) @@ -219,14 +227,15 @@ void MoveSpline::Initialize(MoveSplineInitArgs const& args) MoveSpline::MoveSpline() : m_Id(0), time_passed(0), vertical_acceleration(0.f), initialOrientation(0.f), effect_start_time(0), point_Idx(0), point_Idx_offset(0), velocity(0.f), - onTransport(false) + onTransport(false), splineIsFacingOnly(false) { splineflags.done = true; } MoveSplineInitArgs::MoveSplineInitArgs(size_t path_capacity /*= 16*/) : path_Idx_offset(0), velocity(0.f), - parabolic_amplitude(0.f), vertical_acceleration(0.f), time_perc(0.f), splineId(0), initialOrientation(0.f), walk(false), - HasVelocity(false), TransformForTransport(true) +parabolic_amplitude(0.f), vertical_acceleration(0.0f), effect_start_time_percent(0.f), effect_start_time(0ms), +splineId(0), initialOrientation(0.f), +walk(false), HasVelocity(false), TransformForTransport(true) { path.reserve(path_capacity); } @@ -250,35 +259,22 @@ bool MoveSplineInitArgs::Validate(Unit* unit) const } CHECK(path.size() > 1); CHECK(velocity >= 0.01f); - CHECK(time_perc >= 0.f && time_perc <= 1.f); - //CHECK(_checkPathLengths()); + CHECK(effect_start_time_percent >= 0.f && effect_start_time_percent <= 1.f); + CHECK(_checkPathLengths()); return true; #undef CHECK } -// MONSTER_MOVE packet format limitation for not CatmullRom movement: -// each vertex offset packed into 11 bytes -bool MoveSplineInitArgs::_checkPathBounds() const +// check path lengths - why are we even starting such short movement? +bool MoveSplineInitArgs::_checkPathLengths() const { - if (!(flags & MoveSplineFlag::Catmullrom) && path.size() > 2) - { - enum{ - MAX_OFFSET = (1 << 11) / 2 - }; - Vector3 middle = (path.front()+path.back()) / 2; - Vector3 offset; - for (uint32 i = 1; i < path.size()-1; ++i) - { - offset = path[i] - middle; - if (std::fabs(offset.x) >= float(MAX_OFFSET) || std::fabs(offset.y) >= float(MAX_OFFSET) || std::fabs(offset.z) >= float(MAX_OFFSET)) - { - TC_LOG_ERROR("misc", "MoveSplineInitArgs::_checkPathBounds check failed"); + if (path.size() > 2 || facing.type == MONSTER_MOVE_NORMAL) + for (uint32 i = 0; i < path.size() - 1; ++i) + if ((path[i + 1] - path[i]).length() < 0.1f) return false; - } - } - } return true; } + /// ============================================================================================ MoveSpline::UpdateResult MoveSpline::_updateState(int32& ms_time_diff) @@ -365,11 +361,11 @@ std::string MoveSpline::ToString() const str << "MoveSpline" << std::endl; str << "spline Id: " << GetId() << std::endl; str << "flags: " << splineflags.ToString() << std::endl; - if (splineflags.final_angle) + if (facing.type == MONSTER_MOVE_FACING_ANGLE) str << "facing angle: " << facing.angle; - else if (splineflags.final_target) + else if (facing.type == MONSTER_MOVE_FACING_TARGET) str << "facing target: " << facing.target.ToString(); - else if (splineflags.final_point) + else if (facing.type == MONSTER_MOVE_FACING_SPOT) str << "facing point: " << facing.f.x << " " << facing.f.y << " " << facing.f.z; str << std::endl; str << "time passed: " << time_passed << std::endl; diff --git a/src/server/game/Movement/Spline/MoveSpline.h b/src/server/game/Movement/Spline/MoveSpline.h index 1a6f8c84ae..b45f9f9f00 100644 --- a/src/server/game/Movement/Spline/MoveSpline.h +++ b/src/server/game/Movement/Spline/MoveSpline.h @@ -82,6 +82,7 @@ namespace Movement int32 point_Idx; int32 point_Idx_offset; float velocity; + Optional anim_tier; void init_spline(MoveSplineInitArgs const& args); @@ -141,10 +142,10 @@ namespace Movement int32 MaxPathIdx() const { return spline.last() - 1; } bool HasStarted() const { return time_passed > 0; } - bool HasAnimation() const { return splineflags.animation; } - AnimationTier GetAnimationTier() const { return static_cast(splineflags.animTier); } + Optional GetAnimation() const { return anim_tier; } bool onTransport; + bool splineIsFacingOnly; std::string ToString() const; }; } diff --git a/src/server/game/Movement/Spline/MoveSplineFlag.h b/src/server/game/Movement/Spline/MoveSplineFlag.h index f06442ee17..47b29d58da 100644 --- a/src/server/game/Movement/Spline/MoveSplineFlag.h +++ b/src/server/game/Movement/Spline/MoveSplineFlag.h @@ -30,13 +30,15 @@ namespace Movement enum eFlags { None = 0x00000000, - // x00-x07 used as animation Ids storage in pair with Animation flag - Unknown0 = 0x00000008, // NOT VERIFIED + Unknown_0x1 = 0x00000001, // NOT VERIFIED + Unknown_0x2 = 0x00000002, // NOT VERIFIED + Unknown_0x4 = 0x00000004, // NOT VERIFIED + Unknown_0x8 = 0x00000008, // NOT VERIFIED - does someting related to falling/fixed orientation FallingSlow = 0x00000010, Done = 0x00000020, Falling = 0x00000040, // Affects elevation computation, can't be combined with Parabolic flag No_Spline = 0x00000080, - Unknown2 = 0x00000100, // NOT VERIFIED + Unknown_0x100 = 0x00000100, // NOT VERIFIED Flying = 0x00000200, // Smooth movement(Catmullrom interpolation mode), flying animation OrientationFixed = 0x00000400, // Model orientation fixed Catmullrom = 0x00000800, // Used Catmullrom interpolation mode @@ -45,30 +47,28 @@ namespace Movement Frozen = 0x00004000, // Will never arrive TransportEnter = 0x00008000, TransportExit = 0x00010000, - Unknown3 = 0x00020000, // NOT VERIFIED - Unknown4 = 0x00040000, // NOT VERIFIED + Unknown_0x20000 = 0x00020000, // NOT VERIFIED + Unknown_0x40000 = 0x00040000, // NOT VERIFIED Backward = 0x00080000, SmoothGroundPath = 0x00100000, CanSwim = 0x00200000, UncompressedPath = 0x00400000, - Unknown6 = 0x00800000, // NOT VERIFIED + Unknown_0x800000 = 0x00800000, // NOT VERIFIED Animation = 0x01000000, // Plays animation after some time passed Parabolic = 0x02000000, // Affects elevation computation, can't be combined with Falling flag - Final_Point = 0x04000000, - Final_Target = 0x08000000, - Final_Angle = 0x10000000, - Unknown7 = 0x20000000, // NOT VERIFIED - Unknown8 = 0x40000000, // NOT VERIFIED - Unknown9 = 0x80000000, // NOT VERIFIED + FadeObject = 0x04000000, + Steering = 0x08000000, + UnlimitedSpeed = 0x10000000, + Unknown_0x20000000 = 0x20000000, // NOT VERIFIED + Unknown_0x40000000 = 0x40000000, // NOT VERIFIED + Unknown_0x80000000 = 0x80000000, // NOT VERIFIED // Masks - Mask_Final_Facing = Final_Point | Final_Target | Final_Angle, - // animation ids stored here, see AimationTier enum, used with Animation flag - Mask_Animations = 0x7, // flags that shouldn't be appended into SMSG_MONSTER_MOVE\SMSG_MONSTER_MOVE_TRANSPORT packet, should be more probably - Mask_No_Monster_Move = Mask_Final_Facing | Mask_Animations | Done, + Mask_No_Monster_Move = Done, // Unused, not suported flags - Mask_Unused = No_Spline|Frozen|Unknown0|Unknown2|Unknown3|Unknown4|Unknown6|Unknown7|Unknown8|Unknown9 + Mask_Unused = No_Spline | Enter_Cycle | Frozen | Unknown_0x8 | Unknown_0x100 | Unknown_0x20000 | Unknown_0x40000 + | Unknown_0x800000 | FadeObject | Steering | UnlimitedSpeed | Unknown_0x20000000 | Unknown_0x40000000 | Unknown_0x80000000 }; inline uint32& raw() { return (uint32&)*this; } @@ -81,7 +81,6 @@ namespace Movement bool isSmooth() const { return (raw() & Catmullrom) != 0; } bool isLinear() const { return !isSmooth(); } - bool isFacing() const { return (raw() & Mask_Final_Facing) != 0; } bool hasAllFlags(uint32 f) const { return (raw() & f) == f; } bool hasFlag(uint32 f) const { return (raw() & f) != 0; } @@ -94,24 +93,23 @@ namespace Movement void operator &= (uint32 f) { raw() &= f; } void operator |= (uint32 f) { raw() |= f; } - void EnableAnimation(uint8 anim) { raw() = (raw() & ~(Mask_Animations | Falling | Parabolic | FallingSlow)) | Animation | (anim & Mask_Animations); } - void EnableParabolic() { raw() = (raw() & ~(Mask_Animations | Falling | Animation | FallingSlow)) | Parabolic; } + void EnableAnimation() { raw() = (raw() & ~(Falling | Parabolic | FallingSlow | FadeObject)) | Animation; } + void EnableParabolic() { raw() = (raw() & ~(Falling | Animation | FallingSlow | FadeObject)) | Parabolic; } void EnableFlying() { raw() = (raw() & ~(Falling)) | Flying; } - void EnableFalling() { raw() = (raw() & ~(Mask_Animations | Parabolic | Animation | Flying)) | Falling; } + void EnableFalling() { raw() = (raw() & ~(Parabolic | Animation | Flying)) | Falling; } void EnableCatmullRom() { raw() = (raw() & ~SmoothGroundPath) | Catmullrom; } - void EnableFacingPoint() { raw() = (raw() & ~Mask_Final_Facing) | Final_Point; } - void EnableFacingAngle() { raw() = (raw() & ~Mask_Final_Facing) | Final_Angle; } - void EnableFacingTarget() { raw() = (raw() & ~Mask_Final_Facing) | Final_Target; } void EnableTransportEnter() { raw() = (raw() & ~TransportExit) | TransportEnter; } void EnableTransportExit() { raw() = (raw() & ~TransportEnter) | TransportExit; } - uint8 animTier : 3; - bool unknown0 : 1; + bool unknown0x1 : 1; + bool unknown0x2 : 1; + bool unknown0x4 : 1; + bool unknown0x8 : 1; bool fallingSlow : 1; bool done : 1; bool falling : 1; bool no_spline : 1; - bool unknown2 : 1; + bool unknown0x100 : 1; bool flying : 1; bool orientationFixed : 1; bool catmullrom : 1; @@ -120,21 +118,21 @@ namespace Movement bool frozen : 1; bool transportEnter : 1; bool transportExit : 1; - bool unknown3 : 1; - bool unknown4 : 1; + bool unknown0x20000 : 1; + bool unknown0x40000 : 1; bool backward : 1; bool smoothGroundPath : 1; bool canSwim : 1; bool uncompressedPath : 1; - bool unknown6 : 1; + bool unknown0x800000 : 1; bool animation : 1; bool parabolic : 1; - bool final_point : 1; - bool final_target : 1; - bool final_angle : 1; - bool unknown7 : 1; - bool unknown8 : 1; - bool unknown9 : 1; + bool fadeObject : 1; + bool steering : 1; + bool unlimitedSpeed : 1; + bool unknown0x20000000 : 1; + bool unknown0x40000000 : 1; + bool unknown0x80000000 : 1; }; #pragma pack(pop) } diff --git a/src/server/game/Movement/Spline/MoveSplineInit.cpp b/src/server/game/Movement/Spline/MoveSplineInit.cpp index fe2986d459..cdcae35768 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.cpp +++ b/src/server/game/Movement/Spline/MoveSplineInit.cpp @@ -62,7 +62,7 @@ namespace Movement { MoveSpline& move_spline = *unit->movespline; - bool transport = unit->GetTransGUID() != 0; + bool transport = !unit->GetTransGUID().IsEmpty(); Location real_position; // there is a big chance that current position is unknown if current state is not finalized, need compute it // this also allows calculate spline position and update map position in much greater intervals @@ -91,7 +91,7 @@ namespace Movement args.path[0] = real_position; args.initialOrientation = real_position.orientation; args.flags.enter_cycle = args.flags.cyclic; - move_spline.onTransport = (unit->GetTransGUID() != 0); + move_spline.onTransport = transport; uint32 moveFlags = unit->m_movementInfo.GetMovementFlags(); if (!args.flags.backward) @@ -99,6 +99,9 @@ namespace Movement else moveFlags = (moveFlags & ~MOVEMENTFLAG_FORWARD) | MOVEMENTFLAG_BACKWARD; + if (moveFlags & MOVEMENTFLAG_ROOT) + moveFlags &= ~MOVEMENTFLAG_MASK_MOVING; + if (!args.HasVelocity) { // If spline is initialized with SetWalk method it only means we need to select @@ -125,6 +128,7 @@ namespace Movement packet.MoverGUID = unit->GetGUID(); packet.Pos = Position(real_position.x, real_position.y, real_position.z, real_position.orientation); packet.InitializeSplineData(move_spline); + if (unit->m_movementInfo.HasExtraMovementFlag(MOVEMENTFLAG2_IS_VEHICLE_EXIT_VOLUNTARY)) packet.SplineData.Move.VehicleExitVoluntary = true; @@ -147,7 +151,7 @@ namespace Movement if (move_spline.Finalized()) return; - bool transport = unit->GetTransGUID() != 0; + bool transport = !unit->GetTransGUID().IsEmpty(); Location loc; if (move_spline.onTransport == transport) loc = move_spline.ComputePosition(); @@ -174,15 +178,7 @@ namespace Movement packet.MoverGUID = unit->GetGUID(); packet.Pos = Position(loc.x, loc.y, loc.z, loc.orientation); packet.SplineData.ID = move_spline.GetId(); - - if (unit->IsAlive()) - packet.SplineData.Move.Face = MONSTER_MOVE_STOP; - else - { - // Stopping splines for killed creatures send a normal packet with their current position as first path point - packet.SplineData.Move.Face = MONSTER_MOVE_NORMAL; - packet.SplineData.Move.Points.push_back({ loc.x, loc.y, loc.z }); - } + packet.SplineData.Move.Face = MONSTER_MOVE_STOP; if (transport) { @@ -213,13 +209,19 @@ namespace Movement args.facing.f.x = finalSpot.x; args.facing.f.y = finalSpot.y; args.facing.f.z = finalSpot.z; - args.flags.EnableFacingPoint(); + args.facing.type = MONSTER_MOVE_FACING_SPOT; + } + + void MoveSplineInit::SetFacing(float x, float y, float z) + { + SetFacing({ x, y, z }); } void MoveSplineInit::SetFacing(Unit const* target) { - args.flags.EnableFacingTarget(); + args.facing.angle = unit->GetAngle(target); args.facing.target = target->GetGUID(); + args.facing.type = MONSTER_MOVE_FACING_TARGET; } void MoveSplineInit::SetFacing(float angle) @@ -233,7 +235,7 @@ namespace Movement } args.facing.angle = G3D::wrap(angle, 0.f, (float)G3D::twoPi()); - args.flags.EnableFacingAngle(); + args.facing.type = MONSTER_MOVE_FACING_ANGLE; } void MoveSplineInit::MovebyPath(PointsArray const& controls, int32 path_offset) diff --git a/src/server/game/Movement/Spline/MoveSplineInit.h b/src/server/game/Movement/Spline/MoveSplineInit.h index 9c07be58ca..886197022b 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.h +++ b/src/server/game/Movement/Spline/MoveSplineInit.h @@ -75,7 +75,7 @@ namespace Movement /* Plays animation after movement done * can't be combined with parabolic movement */ - void SetAnimation(AnimationTier anim); + void SetAnimation(AnimationTier anim, Milliseconds transitionStartTime = 0ms); /* Adds final facing animation * sets unit's facing to specified point/angle after all path done @@ -83,6 +83,7 @@ namespace Movement */ void SetFacing(float angle); void SetFacing(Vector3 const& point); + void SetFacing(float x, float y, float z); void SetFacing(Unit const* target); /* Initializes movement by path @@ -174,7 +175,7 @@ namespace Movement inline void MoveSplineInit::SetParabolic(float amplitude, float time_shift) { - args.time_perc = time_shift; + args.effect_start_time_percent = time_shift; args.parabolic_amplitude = amplitude; args.vertical_acceleration = 0.0f; args.flags.EnableParabolic(); @@ -182,16 +183,18 @@ namespace Movement inline void MoveSplineInit::SetParabolicVerticalAcceleration(float vertical_acceleration, float time_shift) { - args.time_perc = time_shift; + args.effect_start_time_percent = time_shift; args.parabolic_amplitude = 0.0f; args.vertical_acceleration = vertical_acceleration; args.flags.EnableParabolic(); } - inline void MoveSplineInit::SetAnimation(AnimationTier anim) + inline void MoveSplineInit::SetAnimation(AnimationTier anim, Milliseconds transitionStartTime /*= 0ms*/) { - args.time_perc = 0.f; - args.flags.EnableAnimation((uint8)anim); + args.effect_start_time_percent = 0.f; + args.effect_start_time = transitionStartTime; + args.animTier = anim; + args.flags.EnableAnimation(); } inline void MoveSplineInit::DisableTransportPathTransformations() { args.TransformForTransport = false; } diff --git a/src/server/game/Movement/Spline/MoveSplineInitArgs.h b/src/server/game/Movement/Spline/MoveSplineInitArgs.h index 4e1439edf7..0cf98b48ea 100644 --- a/src/server/game/Movement/Spline/MoveSplineInitArgs.h +++ b/src/server/game/Movement/Spline/MoveSplineInitArgs.h @@ -18,12 +18,15 @@ #ifndef TRINITYSERVER_MOVESPLINEINIT_ARGS_H #define TRINITYSERVER_MOVESPLINEINIT_ARGS_H +#include "Duration.h" #include "MoveSplineFlag.h" #include "ObjectGuid.h" -#include +#include "Optional.h" class Unit; +enum class AnimationTier : uint8; + namespace Movement { typedef std::vector PointsArray; @@ -37,7 +40,9 @@ namespace Movement ObjectGuid target; float angle; - FacingInfo() : angle(0.0f) { f.x = f.y = f.z = 0.0f; } + MonsterMoveType type; + + FacingInfo() : angle(0.0f), type(MONSTER_MOVE_NORMAL) { f.x = f.y = f.z = 0.0f; } }; struct MoveSplineInitArgs @@ -53,9 +58,11 @@ namespace Movement float velocity; float parabolic_amplitude; float vertical_acceleration; - float time_perc; + float effect_start_time_percent; // fraction of total spline duration + Milliseconds effect_start_time; // absolute value uint32 splineId; float initialOrientation; + Optional animTier; bool walk; bool HasVelocity; bool TransformForTransport; @@ -64,7 +71,7 @@ namespace Movement bool Validate(Unit* unit) const; private: - bool _checkPathBounds() const; + bool _checkPathLengths() const; }; } diff --git a/src/server/game/Movement/Spline/MovementPacketBuilder.cpp b/src/server/game/Movement/Spline/MovementPacketBuilder.cpp index 4748ed4a78..d3f8d1390b 100644 --- a/src/server/game/Movement/Spline/MovementPacketBuilder.cpp +++ b/src/server/game/Movement/Spline/MovementPacketBuilder.cpp @@ -35,15 +35,18 @@ namespace Movement void PacketBuilder::WriteCreateBits(MoveSpline const& moveSpline, ByteBuffer& data) { - if (!data.WriteBit(!moveSpline.Finalized())) + + bool hasSplineMove = data.WriteBit(!moveSpline.Finalized() && !moveSpline.splineIsFacingOnly); + if (!hasSplineMove) return; data.WriteBits(uint8(moveSpline.spline.mode()), 2); data.WriteBit(moveSpline.splineflags & (MoveSplineFlag::Parabolic | MoveSplineFlag::Animation)); data.WriteBits(moveSpline.getPath().size(), 22); - switch (moveSpline.splineflags & MoveSplineFlag::Mask_Final_Facing) + + switch (moveSpline.facing.type) { - case MoveSplineFlag::Final_Target: + case MONSTER_MOVE_FACING_TARGET: { ObjectGuid targetGuid(moveSpline.facing.target); data.WriteBits(2, 2); @@ -57,10 +60,10 @@ namespace Movement data.WriteBit(targetGuid[5]); break; } - case MoveSplineFlag::Final_Angle: + case MONSTER_MOVE_FACING_ANGLE: data.WriteBits(0, 2); break; - case MoveSplineFlag::Final_Point: + case MONSTER_MOVE_FACING_SPOT: data.WriteBits(1, 2); break; default: @@ -68,13 +71,13 @@ namespace Movement break; } - data.WriteBit((moveSpline.splineflags & MoveSplineFlag::Parabolic) && moveSpline.effect_start_time < moveSpline.Duration()); + data.WriteBit((moveSpline.splineflags & MoveSplineFlag::Parabolic) != 0 && moveSpline.effect_start_time < moveSpline.Duration()); data.WriteBits(moveSpline.splineflags.raw(), 25); } void PacketBuilder::WriteCreateData(MoveSpline const& moveSpline, ByteBuffer& data) { - if (!moveSpline.Finalized()) + if (!moveSpline.Finalized() && !moveSpline.splineIsFacingOnly) { MoveSplineFlag const& splineFlags = moveSpline.splineflags; @@ -83,9 +86,9 @@ namespace Movement data << moveSpline.timePassed(); - if (splineFlags.final_angle) + if (moveSpline.facing.type == MONSTER_MOVE_FACING_ANGLE) data << moveSpline.facing.angle; - else if (splineFlags.final_target) + else if (moveSpline.facing.type == MONSTER_MOVE_FACING_TARGET) { ObjectGuid facingGuid(moveSpline.facing.target); data.WriteByteSeq(facingGuid[5]); @@ -106,7 +109,7 @@ namespace Movement data << float(moveSpline.getPath()[i].y); } - if (splineFlags.final_point) + if (moveSpline.facing.type == MONSTER_MOVE_FACING_SPOT) data << moveSpline.facing.f.x << moveSpline.facing.f.z << moveSpline.facing.f.y; data << float(1.f); // splineInfo.duration_mod_next; added in 3.1 diff --git a/src/server/game/Server/Packets/MovementPackets.cpp b/src/server/game/Server/Packets/MovementPackets.cpp index d74a2606cd..0742e452c1 100644 --- a/src/server/game/Server/Packets/MovementPackets.cpp +++ b/src/server/game/Server/Packets/MovementPackets.cpp @@ -377,31 +377,16 @@ void WorldPackets::Movement::MonsterMove::InitializeSplineData(::Movement::MoveS ::Movement::MoveSplineFlag splineFlags = moveSpline.splineflags; splineFlags.enter_cycle = moveSpline.isCyclic(); movementSpline.Flags = uint32(splineFlags & uint32(~::Movement::MoveSplineFlag::Mask_No_Monster_Move)); - - switch (moveSpline.splineflags & ::Movement::MoveSplineFlag::Mask_Final_Facing) - { - case ::Movement::MoveSplineFlag::Final_Point: - movementSpline.Face = ::Movement::MONSTER_MOVE_FACING_SPOT; - movementSpline.FaceSpot = Position(moveSpline.facing.f.x, moveSpline.facing.f.y, moveSpline.facing.f.z); - break; - case ::Movement::MoveSplineFlag::Final_Target: - movementSpline.Face = ::Movement::MONSTER_MOVE_FACING_TARGET; - movementSpline.FaceGUID = moveSpline.facing.target; - break; - case ::Movement::MoveSplineFlag::Final_Angle: - movementSpline.Face = ::Movement::MONSTER_MOVE_FACING_ANGLE; - movementSpline.FaceDirection = moveSpline.facing.angle; - break; - default: - movementSpline.Face = ::Movement::MONSTER_MOVE_NORMAL; - break; - } + movementSpline.Face = moveSpline.facing.type; + movementSpline.FaceDirection = moveSpline.facing.angle; + movementSpline.FaceGUID = moveSpline.facing.target; + movementSpline.FaceSpot = Position(moveSpline.facing.f.x, moveSpline.facing.f.y, moveSpline.facing.f.z); if (splineFlags.animation) { movementSpline.Animation.emplace(); - movementSpline.Animation->AnimTier = splineFlags.animTier; movementSpline.Animation->TierTransStartTime = moveSpline.effect_start_time; + movementSpline.Animation->AnimTier = AsUnderlyingType(*moveSpline.anim_tier); } movementSpline.MoveTime = moveSpline.Duration(); @@ -498,8 +483,6 @@ ByteBuffer& WorldPackets::operator<<(ByteBuffer& data, Movement::MovementSpline switch (movementSpline.Face) { - case ::Movement::MONSTER_MOVE_NORMAL: - break; case ::Movement::MONSTER_MOVE_FACING_SPOT: data << movementSpline.FaceSpot; break; @@ -509,8 +492,6 @@ ByteBuffer& WorldPackets::operator<<(ByteBuffer& data, Movement::MovementSpline case ::Movement::MONSTER_MOVE_FACING_ANGLE: data << float(movementSpline.FaceDirection); break; - default: - return data; } data << int32(movementSpline.Flags);