diff --git a/Source/Framework/Constants/Movement/MovementConst.cs b/Source/Framework/Constants/Movement/MovementConst.cs index cb954dbe0..78e7419c7 100644 --- a/Source/Framework/Constants/Movement/MovementConst.cs +++ b/Source/Framework/Constants/Movement/MovementConst.cs @@ -120,14 +120,6 @@ namespace Framework.Constants public const uint SmartEscortLastOCCPoint = 0xFFFFFF; } - public enum AnimType - { - ToGround = 0, // 460 = ToGround, index of AnimationData.dbc - FlyToFly = 1, // 461 = FlyToFly? - ToFly = 2, // 458 = ToFly - FlyToGround = 3 // 463 = FlyToGround - } - public enum RotateDirection { Left, diff --git a/Source/Framework/Constants/UnitConst.cs b/Source/Framework/Constants/UnitConst.cs index e10d39851..24e2fceba 100644 --- a/Source/Framework/Constants/UnitConst.cs +++ b/Source/Framework/Constants/UnitConst.cs @@ -277,13 +277,13 @@ namespace Framework.Constants All = 0xFF } - public enum UnitBytes1Flags + public enum AnimTier { - None = 0x00, - AlwaysStand = 0x01, - Hover = 0x02, - Unk3 = 0x04, - All = 0xFF + Ground = 0, // plays ground tier animations + Swim = 1, // falls back to ground tier animations, not handled by the client, should never appear in sniffs, will prevent tier change animations from playing correctly if used + Hover = 2, // plays flying tier animations or falls back to ground tier animations, automatically enables hover clientside when entering visibility with this value + Fly = 3, // plays flying tier animations + Submerged = 4 } public enum UnitPVPStateFlags diff --git a/Source/Game/AI/SmartScripts/SmartScript.cs b/Source/Game/AI/SmartScripts/SmartScript.cs index a8f46da50..ed1ac06b8 100644 --- a/Source/Game/AI/SmartScripts/SmartScript.cs +++ b/Source/Game/AI/SmartScripts/SmartScript.cs @@ -1841,9 +1841,7 @@ namespace Game.AI target.ToUnit().AddVisFlags((UnitVisFlags)e.Action.setunitByte.byte1); break; case 3: - // this is totally wrong to maintain compatibility with existing scripts - // TODO: fix with animtier overhaul - target.ToUnit().SetAnimTier((UnitBytes1Flags)(target.ToUnit().m_unitData.AnimTier | e.Action.setunitByte.byte1), false); + target.ToUnit().SetAnimTier((AnimTier)e.Action.setunitByte.byte1); break; } } @@ -1868,7 +1866,7 @@ namespace Game.AI target.ToUnit().RemoveVisFlags((UnitVisFlags)e.Action.setunitByte.byte1); break; case 3: - target.ToUnit().SetAnimTier((UnitBytes1Flags)(target.ToUnit().m_unitData.AnimTier & ~e.Action.setunitByte.byte1), false); + target.ToUnit().SetAnimTier(AnimTier.Ground); break; } } diff --git a/Source/Game/Entities/Creature/Creature.cs b/Source/Game/Entities/Creature/Creature.cs index ffdd272cf..323bbf57f 100644 --- a/Source/Game/Entities/Creature/Creature.cs +++ b/Source/Game/Entities/Creature/Creature.cs @@ -1807,6 +1807,7 @@ namespace Game.Entities uint scalingMode = WorldConfig.GetUIntValue(WorldCfg.RespawnDynamicMode); if (scalingMode != 0) GetMap().ApplyDynamicModeRespawnScaling(this, m_spawnId, ref respawnDelay, scalingMode); + // @todo remove the boss respawn time hack in a dynspawn follow-up once we have creature groups in instances if (m_respawnCompatibilityMode) { @@ -1841,8 +1842,9 @@ namespace Game.Entities if (m_formation != null && m_formation.GetLeader() == this) m_formation.FormationReset(true); - bool needsFalling = IsFlying() || IsHovering(); - SetHover(false); + bool needsFalling = (IsFlying() || IsHovering()) && !IsUnderWater(); + SetHover(false, false); + SetDisableGravity(false, false); if (needsFalling) GetMotionMaster().MoveFall(); @@ -2374,7 +2376,7 @@ namespace Game.Entities SetStandState((UnitStandStateType)(cainfo.bytes1 & 0xFF)); SetVisFlags((UnitVisFlags)((cainfo.bytes1 >> 16) & 0xFF)); - SetAnimTier((UnitBytes1Flags)((cainfo.bytes1 >> 24) & 0xFF), false); + SetAnimTier((AnimTier)((cainfo.bytes1 >> 24) & 0xFF), false); //! Suspected correlation between UNIT_FIELD_BYTES_1, offset 3, value 0x2: //! If no inhabittype_fly (if no MovementFlag_DisableGravity or MovementFlag_CanFly flag found in sniffs) diff --git a/Source/Game/Entities/Player/Player.cs b/Source/Game/Entities/Player/Player.cs index a7feb2134..8e8c4fbae 100644 --- a/Source/Game/Entities/Player/Player.cs +++ b/Source/Game/Entities/Player/Player.cs @@ -4149,9 +4149,6 @@ namespace Game.Entities StopMirrorTimers(); //disable timers(bars) - // set and clear other - SetAnimTier(UnitBytes1Flags.AlwaysStand, false); - // OnPlayerRepop hook Global.ScriptMgr.OnPlayerRepop(this); } @@ -4358,7 +4355,6 @@ namespace Game.Entities // speed change, land walk // remove death flag + set aura - SetAnimTier(UnitBytes1Flags.None, false); RemovePlayerFlag(PlayerFlags.IsOutOfBounds); // This must be called always even on Players with race != RACE_NIGHTELF in case of faction change diff --git a/Source/Game/Entities/Unit/Unit.Movement.cs b/Source/Game/Entities/Unit/Unit.Movement.cs index bb3ce35e0..ab5ff2221 100644 --- a/Source/Game/Entities/Unit/Unit.Movement.cs +++ b/Source/Game/Entities/Unit/Unit.Movement.cs @@ -659,7 +659,7 @@ namespace Game.Entities return IsInDist(obj, objBoundaryRadius); } - public bool SetDisableGravity(bool disable) + public bool SetDisableGravity(bool disable, bool updateAnimationTier = true) { if (disable == IsGravityDisabled()) return false; @@ -692,6 +692,16 @@ namespace Game.Entities SendMessageToSet(packet, true); } + if (IsCreature() && updateAnimationTier && IsAlive() && !HasUnitState(UnitState.Root) && !ToCreature().GetMovementTemplate().IsRooted()) + { + if (IsGravityDisabled()) + SetAnimTier(AnimTier.Fly); + else if (IsHovering()) + SetAnimTier(AnimTier.Hover); + else + SetAnimTier(AnimTier.Ground); + } + return true; } @@ -1011,7 +1021,7 @@ namespace Game.Entities return true; } - public bool SetHover(bool enable) + public bool SetHover(bool enable, bool updateAnimationTier = true) { if (enable == HasUnitMovementFlag(MovementFlag.Hover)) return false; @@ -1056,6 +1066,17 @@ namespace Game.Entities packet.MoverGUID = GetGUID(); SendMessageToSet(packet, true); } + + if (IsCreature() && updateAnimationTier && IsAlive() && !HasUnitState(UnitState.Root) && !ToCreature().GetMovementTemplate().IsRooted()) + { + if (IsGravityDisabled()) + SetAnimTier(AnimTier.Fly); + else if (IsHovering()) + SetAnimTier(AnimTier.Hover); + else + SetAnimTier(AnimTier.Ground); + } + return true; } @@ -1723,10 +1744,17 @@ namespace Game.Entities } if (arrived) + { DisableSpline(); + AnimTier? animTier = MoveSpline.GetAnimation(); + if (animTier.HasValue) + SetAnimTier(animTier.Value); + } + UpdateSplinePosition(); } + void UpdateSplinePosition() { Vector4 loc = MoveSpline.ComputePosition(); diff --git a/Source/Game/Entities/Unit/Unit.cs b/Source/Game/Entities/Unit/Unit.cs index 71bd602a6..106a077c9 100644 --- a/Source/Game/Entities/Unit/Unit.cs +++ b/Source/Game/Entities/Unit/Unit.cs @@ -2154,7 +2154,9 @@ namespace Game.Entities } } - public void SetAnimTier(UnitBytes1Flags animTier, bool notifyClient) + public AnimTier GetAnimTier() { return (AnimTier)(byte)m_unitData.AnimTier; } + + public void SetAnimTier(AnimTier animTier, bool notifyClient = true) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.AnimTier), (byte)animTier); diff --git a/Source/Game/Movement/Generators/WaypointMovement.cs b/Source/Game/Movement/Generators/WaypointMovement.cs index ce84cb1d3..fc00108dd 100644 --- a/Source/Game/Movement/Generators/WaypointMovement.cs +++ b/Source/Game/Movement/Generators/WaypointMovement.cs @@ -358,10 +358,10 @@ namespace Game.Movement switch (waypoint.moveType) { case WaypointMoveType.Land: - init.SetAnimation(AnimType.ToGround); + init.SetAnimation(AnimTier.Ground); break; case WaypointMoveType.Takeoff: - init.SetAnimation(AnimType.ToFly); + init.SetAnimation(AnimTier.Hover); break; case WaypointMoveType.Run: init.SetWalk(false); diff --git a/Source/Game/Movement/MotionMaster.cs b/Source/Game/Movement/MotionMaster.cs index 3879b0fef..2c05017a1 100644 --- a/Source/Game/Movement/MotionMaster.cs +++ b/Source/Game/Movement/MotionMaster.cs @@ -625,7 +625,7 @@ namespace Game.Movement { MoveSplineInit init = new(_owner); init.MoveTo(pos, false); - init.SetAnimation(AnimType.ToGround); + init.SetAnimation(AnimTier.Ground); Add(new GenericMovementGenerator(init, MovementGeneratorType.Effect, id)); } @@ -633,7 +633,7 @@ namespace Game.Movement { MoveSplineInit init = new(_owner); init.MoveTo(pos); - init.SetAnimation(AnimType.ToFly); + init.SetAnimation(AnimTier.Hover); Add(new GenericMovementGenerator(init, MovementGeneratorType.Effect, id)); } @@ -820,7 +820,7 @@ namespace Game.Movement { init.SetFly(); init.SetCyclic(); - init.SetAnimation(AnimType.ToFly); + init.SetAnimation(AnimTier.Hover); } else { diff --git a/Source/Game/Movement/MoveSpline.cs b/Source/Game/Movement/MoveSpline.cs index b9c6ef9c7..8e74d4106 100644 --- a/Source/Game/Movement/MoveSpline.cs +++ b/Source/Game/Movement/MoveSpline.cs @@ -347,6 +347,8 @@ namespace Game.Movement public Vector3 FinalDestination() { return Initialized() ? spline.GetPoint(spline.Last()) : Vector3.Zero; } public Vector3 CurrentDestination() { return Initialized() ? spline.GetPoint(point_Idx + 1) : Vector3.Zero; } + public AnimTier? GetAnimation() { return anim_tier != null ? (AnimTier)anim_tier.AnimTier : null; } + #region Fields public MoveSplineInitArgs InitArgs; public Spline spline = new(); diff --git a/Source/Game/Movement/MoveSplineInit.cs b/Source/Game/Movement/MoveSplineInit.cs index 913111064..10f4bb0fb 100644 --- a/Source/Game/Movement/MoveSplineInit.cs +++ b/Source/Game/Movement/MoveSplineInit.cs @@ -310,7 +310,7 @@ namespace Game.Movement args.flags.EnableParabolic(); } - public void SetAnimation(AnimType anim) + public void SetAnimation(AnimTier anim) { args.time_perc = 0.0f; args.animTier = new();