From f91230ae338669cbe495c34b17f7f0f77a888e85 Mon Sep 17 00:00:00 2001 From: hondacrx Date: Wed, 15 Jun 2022 15:48:07 -0400 Subject: [PATCH] Core/Movement: Delay creating MoveSplineInit objects used by GenericMovementGenerator to spline launch time Port From (https://github.com/TrinityCore/TrinityCore/commit/36dde87249e87c5693162a6e890875d828f93d6d) --- Source/Game/Entities/Unit/Unit.Movement.cs | 10 +- Source/Game/Entities/Unit/Unit.cs | 20 +- Source/Game/Entities/Vehicle.cs | 16 +- Source/Game/Handlers/MovementHandler.cs | 5 +- .../Generators/GenericMovementGenerator.cs | 11 +- Source/Game/Movement/MotionMaster.cs | 206 ++++++++++-------- Source/Scripts/World/NpcSpecial.cs | 13 +- 7 files changed, 154 insertions(+), 127 deletions(-) diff --git a/Source/Game/Entities/Unit/Unit.Movement.cs b/Source/Game/Entities/Unit/Unit.Movement.cs index 01a09012a..871aaa60c 100644 --- a/Source/Game/Entities/Unit/Unit.Movement.cs +++ b/Source/Game/Entities/Unit/Unit.Movement.cs @@ -234,10 +234,12 @@ namespace Game.Entities public void MonsterMoveWithSpeed(float x, float y, float z, float speed, bool generatePath = false, bool forceDestination = false) { - MoveSplineInit init = new(this); - init.MoveTo(x, y, z, generatePath, forceDestination); - init.SetVelocity(speed); - GetMotionMaster().LaunchMoveSpline(init, 0, MovementGeneratorPriority.Normal, MovementGeneratorType.Point); + var initializer = (MoveSplineInit init) => + { + init.MoveTo(x, y, z, generatePath, forceDestination); + init.SetVelocity(speed); + }; + GetMotionMaster().LaunchMoveSpline(initializer, 0, MovementGeneratorPriority.Normal, MovementGeneratorType.Point); } public void KnockbackFrom(Position origin, float speedXY, float speedZ, SpellEffectExtraData spellEffectExtraData = null) diff --git a/Source/Game/Entities/Unit/Unit.cs b/Source/Game/Entities/Unit/Unit.cs index 0398e4083..af6437e96 100644 --- a/Source/Game/Entities/Unit/Unit.cs +++ b/Source/Game/Entities/Unit/Unit.cs @@ -1108,18 +1108,20 @@ namespace Game.Entities } } - float height = pos.GetPositionZ() + vehicle.GetBase().GetCollisionHeight(); + var initializer = (MoveSplineInit init) => + { + float height = pos.GetPositionZ() + vehicle.GetBase().GetCollisionHeight(); - MoveSplineInit init = new(this); + // Creatures without inhabit type air should begin falling after exiting the vehicle + if (IsTypeId(TypeId.Unit) && !CanFly() && height > GetMap().GetWaterOrGroundLevel(GetPhaseShift(), pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ() + vehicle.GetBase().GetCollisionHeight(), ref height)) + init.SetFall(); - // Creatures without inhabit type air should begin falling after exiting the vehicle - if (IsTypeId(TypeId.Unit) && !ToCreature().CanFly() && height > GetMap().GetWaterOrGroundLevel(GetPhaseShift(), pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ() + vehicle.GetBase().GetCollisionHeight(), ref height)) - init.SetFall(); + init.MoveTo(pos.GetPositionX(), pos.GetPositionY(), height, false); + init.SetFacing(pos.GetOrientation()); + init.SetTransportExit(); + }; - init.MoveTo(pos.GetPositionX(), pos.GetPositionY(), height, false); - init.SetFacing(pos.GetOrientation()); - init.SetTransportExit(); - GetMotionMaster().LaunchMoveSpline(init, EventId.VehicleExit, MovementGeneratorPriority.Highest); + GetMotionMaster().LaunchMoveSpline(initializer, EventId.VehicleExit, MovementGeneratorPriority.Highest); if (player != null) player.ResummonPetTemporaryUnSummonedIfAny(); diff --git a/Source/Game/Entities/Vehicle.cs b/Source/Game/Entities/Vehicle.cs index 114030709..33ec24204 100644 --- a/Source/Game/Entities/Vehicle.cs +++ b/Source/Game/Entities/Vehicle.cs @@ -718,14 +718,16 @@ namespace Game.Entities Passenger.SendClearTarget(); // SMSG_BREAK_TARGET Passenger.SetControlled(true, UnitState.Root); // SMSG_FORCE_ROOT - In some cases we send SMSG_SPLINE_MOVE_ROOT here (for creatures) - // also adds MOVEMENTFLAG_ROOT + // also adds MOVEMENTFLAG_ROOT - MoveSplineInit init = new(Passenger); - init.DisableTransportPathTransformations(); - init.MoveTo(x, y, z, false, true); - init.SetFacing(o); - init.SetTransportEnter(); - Passenger.GetMotionMaster().LaunchMoveSpline(init, EventId.VehicleBoard, MovementGeneratorPriority.Highest); + var initializer = (MoveSplineInit init) => + { + init.DisableTransportPathTransformations(); + init.MoveTo(x, y, z, false, true); + init.SetFacing(o); + init.SetTransportEnter(); + }; + Passenger.GetMotionMaster().LaunchMoveSpline(initializer, EventId.VehicleBoard, MovementGeneratorPriority.Highest); foreach (var (_, threatRef) in Passenger.GetThreatManager().GetThreatenedByMeList()) threatRef.GetOwner().GetThreatManager().AddThreat(Target.GetBase(), threatRef.GetThreat(), null, true, true); diff --git a/Source/Game/Handlers/MovementHandler.cs b/Source/Game/Handlers/MovementHandler.cs index 9a9efedf5..0b53ceaf2 100644 --- a/Source/Game/Handlers/MovementHandler.cs +++ b/Source/Game/Handlers/MovementHandler.cs @@ -81,11 +81,10 @@ namespace Game Log.outError(LogFilter.Network, "HandleMovementOpcodes: guid error"); return; } + if (!movementInfo.Pos.IsPositionValid()) - { - Log.outError(LogFilter.Network, "HandleMovementOpcodes: Invalid Position"); return; - } + if (!mover.MoveSpline.Finalized()) return; diff --git a/Source/Game/Movement/Generators/GenericMovementGenerator.cs b/Source/Game/Movement/Generators/GenericMovementGenerator.cs index 55729be64..e045847e6 100644 --- a/Source/Game/Movement/Generators/GenericMovementGenerator.cs +++ b/Source/Game/Movement/Generators/GenericMovementGenerator.cs @@ -17,12 +17,13 @@ using Framework.Constants; using Game.Entities; +using System; namespace Game.Movement { class GenericMovementGenerator : MovementGenerator { - MoveSplineInit _splineInit; + Action _splineInit; MovementGeneratorType _type; uint _pointId; TimeTracker _duration; @@ -30,9 +31,9 @@ namespace Game.Movement uint _arrivalSpellId; ObjectGuid _arrivalSpellTargetGuid; - public GenericMovementGenerator(MoveSplineInit splineInit, MovementGeneratorType type, uint id, uint arrivalSpellId = 0, ObjectGuid arrivalSpellTargetGuid = default) + public GenericMovementGenerator(Action initializer, MovementGeneratorType type, uint id, uint arrivalSpellId = 0, ObjectGuid arrivalSpellTargetGuid = default) { - _splineInit = splineInit; + _splineInit = initializer; _type = type; _pointId = id; _duration = new(); @@ -57,7 +58,9 @@ namespace Game.Movement RemoveFlag(MovementGeneratorFlags.InitializationPending | MovementGeneratorFlags.Deactivated); AddFlag(MovementGeneratorFlags.Initialized); - _duration.Reset((uint)_splineInit.Launch()); + MoveSplineInit init = new(owner); + _splineInit(init); + _duration.Reset((uint)init.Launch()); } public override void Reset(Unit owner) diff --git a/Source/Game/Movement/MotionMaster.cs b/Source/Game/Movement/MotionMaster.cs index 6ce149a94..ad23d1c61 100644 --- a/Source/Game/Movement/MotionMaster.cs +++ b/Source/Game/Movement/MotionMaster.cs @@ -637,33 +637,41 @@ namespace Game.Movement else { // We are already close enough. We just need to turn toward the target without changing position. - MoveSplineInit init = new(_owner); - init.MoveTo(_owner.GetPositionX(), _owner.GetPositionY(), _owner.GetPositionZ()); - init.SetFacing(target); - Add(new GenericMovementGenerator(init, MovementGeneratorType.Effect, id)); + var initializer = (MoveSplineInit init) => + { + init.MoveTo(_owner.GetPositionX(), _owner.GetPositionY(), _owner.GetPositionZ()); + Unit refreshedTarget = Global.ObjAccessor.GetUnit(_owner, target.GetGUID()); + if (refreshedTarget != null) + init.SetFacing(refreshedTarget); + }; + Add(new GenericMovementGenerator(initializer, MovementGeneratorType.Effect, id)); } } public void MoveLand(uint id, Position pos, float? velocity = null) { - MoveSplineInit init = new(_owner); - init.MoveTo(pos, false); - init.SetAnimation(AnimTier.Ground); - if (velocity.HasValue) - init.SetVelocity(velocity.Value); + var initializer = (MoveSplineInit init) => + { + init.MoveTo(pos, false); + init.SetAnimation(AnimTier.Ground); + if (velocity.HasValue) + init.SetVelocity(velocity.Value); + }; - Add(new GenericMovementGenerator(init, MovementGeneratorType.Effect, id)); + Add(new GenericMovementGenerator(initializer, MovementGeneratorType.Effect, id)); } public void MoveTakeoff(uint id, Position pos, float? velocity = null) { - MoveSplineInit init = new(_owner); - init.MoveTo(pos, false); - init.SetAnimation(AnimTier.Hover); - if (velocity.HasValue) - init.SetVelocity(velocity.Value); + var initializer = (MoveSplineInit init) => + { + init.MoveTo(pos, false); + init.SetAnimation(AnimTier.Hover); + if (velocity.HasValue) + init.SetVelocity(velocity.Value); + }; - Add(new GenericMovementGenerator(init, MovementGeneratorType.Effect, id)); + Add(new GenericMovementGenerator(initializer, MovementGeneratorType.Effect, id)); } public void MoveCharge(float x, float y, float z, float speed = SPEED_CHARGE, uint id = EventId.Charge, bool generatePath = false, Unit target = null, SpellEffectExtraData spellEffectExtraData = null) @@ -723,15 +731,17 @@ namespace Game.Movement // Use a mmap raycast to get a valid destination. _owner.MovePositionToFirstCollision(dest, dist, _owner.GetRelativeAngle(origin) + MathF.PI); - MoveSplineInit init = new(_owner); - init.MoveTo(dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ(), false); - init.SetParabolic(max_height, 0); - init.SetOrientationFixed(true); - init.SetVelocity(speedXY); - if (spellEffectExtraData != null) - init.SetSpellEffectExtraData(spellEffectExtraData); + var initializer = (MoveSplineInit init) => + { + init.MoveTo(dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ(), false); + init.SetParabolic(max_height, 0); + init.SetOrientationFixed(true); + init.SetVelocity(speedXY); + if (spellEffectExtraData != null) + init.SetSpellEffectExtraData(spellEffectExtraData); + }; - GenericMovementGenerator movement = new(init, MovementGeneratorType.Effect, 0); + GenericMovementGenerator movement = new(initializer, MovementGeneratorType.Effect, 0); movement.Priority = MovementGeneratorPriority.Highest; movement.AddFlag(MovementGeneratorFlags.PersistOnDeath); Add(movement); @@ -765,14 +775,16 @@ namespace Game.Movement float moveTimeHalf = (float)(speedZ / gravity); float max_height = -MoveSpline.ComputeFallElevation(moveTimeHalf, false, -speedZ); - MoveSplineInit init = new(_owner); - init.MoveTo(x, y, z, false); - init.SetParabolic(max_height, 0); - init.SetVelocity(speedXY); - if (hasOrientation) - init.SetFacing(o); - if (spellEffectExtraData != null) - init.SetSpellEffectExtraData(spellEffectExtraData); + var initializer = (MoveSplineInit init) => + { + init.MoveTo(x, y, z, false); + init.SetParabolic(max_height, 0); + init.SetVelocity(speedXY); + if (hasOrientation) + init.SetFacing(o); + if (spellEffectExtraData != null) + init.SetSpellEffectExtraData(spellEffectExtraData); + }; uint arrivalSpellId = 0; ObjectGuid arrivalSpellTargetGuid = ObjectGuid.Empty; @@ -782,7 +794,7 @@ namespace Game.Movement arrivalSpellTargetGuid = arrivalCast.Target; } - GenericMovementGenerator movement = new(init, MovementGeneratorType.Effect, id, arrivalSpellId, arrivalSpellTargetGuid); + GenericMovementGenerator movement = new(initializer, MovementGeneratorType.Effect, id, arrivalSpellId, arrivalSpellTargetGuid); movement.Priority = MovementGeneratorPriority.Highest; movement.BaseUnitState = UnitState.Jumping; Add(movement); @@ -794,17 +806,17 @@ namespace Game.Movement if (speedXY < 0.01f) return; - MoveSplineInit init = new(_owner); - init.MoveTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), false); - init.SetParabolicVerticalAcceleration(gravity, 0); - init.SetUncompressed(); - init.SetVelocity(speedXY); - - if (hasOrientation) - init.SetFacing(pos.GetOrientation()); - - if (spellEffectExtraData != null) - init.SetSpellEffectExtraData(spellEffectExtraData); + var initializer = (MoveSplineInit init) => + { + init.MoveTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), false); + init.SetParabolicVerticalAcceleration(gravity, 0); + init.SetUncompressed(); + init.SetVelocity(speedXY); + if (hasOrientation) + init.SetFacing(pos.GetOrientation()); + if (spellEffectExtraData != null) + init.SetSpellEffectExtraData(spellEffectExtraData); + }; uint arrivalSpellId = 0; ObjectGuid arrivalSpellTargetGuid = default; @@ -814,7 +826,7 @@ namespace Game.Movement arrivalSpellTargetGuid = arrivalCast.Target; } - GenericMovementGenerator movement = new GenericMovementGenerator(init, MovementGeneratorType.Effect, id, arrivalSpellId, arrivalSpellTargetGuid); + GenericMovementGenerator movement = new GenericMovementGenerator(initializer, MovementGeneratorType.Effect, id, arrivalSpellId, arrivalSpellTargetGuid); movement.Priority = MovementGeneratorPriority.Highest; movement.BaseUnitState = UnitState.Jumping; movement.AddFlag(MovementGeneratorFlags.PersistOnDeath); @@ -823,61 +835,63 @@ namespace Game.Movement public void MoveCirclePath(float x, float y, float z, float radius, bool clockwise, byte stepCount) { - float step = 2 * MathFunctions.PI / stepCount * (clockwise ? -1.0f : 1.0f); - Position pos = new(x, y, z, 0.0f); - float angle = pos.GetAbsoluteAngle(_owner.GetPositionX(), _owner.GetPositionY()); - - MoveSplineInit init = new(_owner); - - // add the owner's current position as starting point as it gets removed after entering the cycle - init.Path().Add(new Vector3(_owner.GetPositionX(), _owner.GetPositionY(), _owner.GetPositionZ())); - - for (byte i = 0; i < stepCount; angle += step, ++i) + var initializer = (MoveSplineInit init) => { - Vector3 point = new(); - point.X = (float)(x + radius * Math.Cos(angle)); - point.Y = (float)(y + radius * Math.Sin(angle)); + float step = 2 * MathFunctions.PI / stepCount * (clockwise ? -1.0f : 1.0f); + Position pos = new(x, y, z, 0.0f); + float angle = pos.GetAbsoluteAngle(_owner.GetPositionX(), _owner.GetPositionY()); + + // add the owner's current position as starting point as it gets removed after entering the cycle + init.Path().Add(new Vector3(_owner.GetPositionX(), _owner.GetPositionY(), _owner.GetPositionZ())); + + for (byte i = 0; i < stepCount; angle += step, ++i) + { + Vector3 point = new(); + point.X = (float)(x + radius * Math.Cos(angle)); + point.Y = (float)(y + radius * Math.Sin(angle)); + + if (_owner.IsFlying()) + point.Z = z; + else + point.Z = _owner.GetMapHeight(point.X, point.Y, z) + _owner.GetHoverOffset(); + + init.Path().Add(point); + } if (_owner.IsFlying()) - point.Z = z; + { + init.SetFly(); + init.SetCyclic(); + init.SetAnimation(AnimTier.Hover); + } else - point.Z = _owner.GetMapHeight(point.X, point.Y, z) + _owner.GetHoverOffset(); + { + init.SetWalk(true); + init.SetCyclic(); + } + }; - init.Path().Add(point); - } - - if (_owner.IsFlying()) - { - init.SetFly(); - init.SetCyclic(); - init.SetAnimation(AnimTier.Hover); - } - else - { - init.SetWalk(true); - init.SetCyclic(); - } - - Add(new GenericMovementGenerator(init, MovementGeneratorType.Effect, 0)); + Add(new GenericMovementGenerator(initializer, MovementGeneratorType.Effect, 0)); } void MoveSmoothPath(uint pointId, Vector3[] pathPoints, int pathSize, bool walk = false, bool fly = false) { - MoveSplineInit init = new(_owner); - if (fly) + var initializer = (MoveSplineInit init) => { - init.SetFly(); - init.SetUncompressed(); - init.SetSmooth(); - } - - init.MovebyPath(pathPoints); - init.SetWalk(walk); + init.MovebyPath(pathPoints); + init.SetWalk(walk); + if (fly) + { + init.SetFly(); + init.SetUncompressed(); + init.SetSmooth(); + } + }; // This code is not correct // GenericMovementGenerator does not affect UNIT_STATE_ROAMING_MOVE // need to call PointMovementGenerator with various pointIds - Add(new GenericMovementGenerator(init, MovementGeneratorType.Effect, pointId)); + Add(new GenericMovementGenerator(initializer, MovementGeneratorType.Effect, pointId)); } public void MoveAlongSplineChain(uint pointId, uint dbChainId, bool walk) @@ -925,8 +939,8 @@ namespace Game.Movement return; // rooted units don't move (also setting falling+root flag causes client freezes) - if (_owner.HasUnitState(UnitState.Root | UnitState.Stunned)) - return; + if (_owner.HasUnitState(UnitState.Root | UnitState.Stunned)) + return; _owner.SetFall(true); @@ -937,11 +951,13 @@ namespace Game.Movement return; } - MoveSplineInit init = new(_owner); - init.MoveTo(_owner.GetPositionX(), _owner.GetPositionY(), tz + _owner.GetHoverOffset(), false); - init.SetFall(); + var initializer = (MoveSplineInit init) => + { + init.MoveTo(_owner.GetPositionX(), _owner.GetPositionY(), tz + _owner.GetHoverOffset(), false); + init.SetFall(); + }; - GenericMovementGenerator movement = new(init, MovementGeneratorType.Effect, id); + GenericMovementGenerator movement = new(initializer, MovementGeneratorType.Effect, id); movement.Priority = MovementGeneratorPriority.Highest; Add(movement); } @@ -1031,7 +1047,7 @@ namespace Game.Movement Add(new FormationMovementGenerator(leader, range, angle, point1, point2), MovementSlot.Default); } - public void LaunchMoveSpline(MoveSplineInit init, uint id = 0, MovementGeneratorPriority priority = MovementGeneratorPriority.Normal, MovementGeneratorType type = MovementGeneratorType.Effect) + public void LaunchMoveSpline(Action initializer, uint id = 0, MovementGeneratorPriority priority = MovementGeneratorPriority.Normal, MovementGeneratorType type = MovementGeneratorType.Effect) { if (IsInvalidMovementGeneratorType(type)) { @@ -1039,7 +1055,7 @@ namespace Game.Movement return; } - GenericMovementGenerator movement = new(init, type, id); + GenericMovementGenerator movement = new(initializer, type, id); movement.Priority = priority; Add(movement); } @@ -1262,7 +1278,7 @@ namespace Game.Movement public uint? ProgressCurveId; public uint? ParabolicCurveId; } - + public struct ChaseRange { // this contains info that informs how we should path! diff --git a/Source/Scripts/World/NpcSpecial.cs b/Source/Scripts/World/NpcSpecial.cs index 5e67e2c25..992864095 100644 --- a/Source/Scripts/World/NpcSpecial.cs +++ b/Source/Scripts/World/NpcSpecial.cs @@ -2039,11 +2039,14 @@ namespace Scripts.World.NpcSpecial break; } - MoveSplineInit init = new(who); - init.DisableTransportPathTransformations(); - init.MoveTo(x, y, z, false); - init.SetFacing(o); - who.GetMotionMaster().LaunchMoveSpline(init, EventId.VehicleBoard, MovementGeneratorPriority.Highest); + var initializer = (MoveSplineInit init) => + { + init.DisableTransportPathTransformations(); + init.MoveTo(x, y, z, false); + init.SetFacing(o); + }; + + who.GetMotionMaster().LaunchMoveSpline(initializer, EventId.VehicleBoard, MovementGeneratorPriority.Highest); who.m_Events.AddEvent(new CastFoodSpell(who, SpellIds.ChairSpells[who.GetEntry()]), who.m_Events.CalculateTime(TimeSpan.FromSeconds(1))); Creature creature = who.ToCreature(); if (creature)