Core/Movement: Implement MoveSplineFlag::Enter_Cycle
Port From (https://github.com/TrinityCore/TrinityCore/commit/61f3d51143b51b04169bd1c2ff0393d2b9be7c33)
This commit is contained in:
@@ -41,7 +41,7 @@ namespace Game.Entities
|
||||
public MoveSpline MoveSpline { get; set; }
|
||||
MotionMaster i_motionMaster;
|
||||
public uint m_movementCounter; //< Incrementing counter used in movement packets
|
||||
TimeTrackerSmall movesplineTimer;
|
||||
TimeTrackerSmall splineSyncTimer;
|
||||
MovementForces _movementForces;
|
||||
PositionUpdateInfo _positionUpdateInfo;
|
||||
protected Unit m_unitMovedByMe; // only ever set for players, and only for direct client control
|
||||
|
||||
@@ -1700,20 +1700,30 @@ namespace Game.Entities
|
||||
|
||||
void UpdateSplineMovement(uint diff)
|
||||
{
|
||||
int positionUpdateDelay = 400;
|
||||
|
||||
if (MoveSpline.Finalized())
|
||||
return;
|
||||
|
||||
MoveSpline.UpdateState((int)diff);
|
||||
bool arrived = MoveSpline.Finalized();
|
||||
|
||||
if (MoveSpline.IsCyclic())
|
||||
{
|
||||
splineSyncTimer.Update((int)diff);
|
||||
if (splineSyncTimer.Passed())
|
||||
{
|
||||
splineSyncTimer.Reset(5000); // Retail value, do not change
|
||||
|
||||
FlightSplineSync flightSplineSync = new();
|
||||
flightSplineSync.Guid = GetGUID();
|
||||
flightSplineSync.SplineDist = MoveSpline.TimePassed() / MoveSpline.Duration();
|
||||
SendMessageToSet(flightSplineSync, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (arrived)
|
||||
DisableSpline();
|
||||
|
||||
movesplineTimer.Update((int)diff);
|
||||
if (movesplineTimer.Passed() || arrived)
|
||||
UpdateSplinePosition();
|
||||
UpdateSplinePosition();
|
||||
}
|
||||
void UpdateSplinePosition()
|
||||
{
|
||||
|
||||
@@ -87,7 +87,7 @@ namespace Game.Entities
|
||||
|
||||
m_serverSideVisibility.SetValue(ServerSideVisibilityType.Ghost, GhostVisibilityType.Alive);
|
||||
|
||||
movesplineTimer = new TimeTrackerSmall();
|
||||
splineSyncTimer = new TimeTrackerSmall();
|
||||
|
||||
m_unitData = new UnitData();
|
||||
}
|
||||
|
||||
@@ -797,8 +797,12 @@ namespace Game.Movement
|
||||
float angle = pos.GetAbsoluteAngle(_owner.GetPositionX(), _owner.GetPositionY());
|
||||
|
||||
MoveSplineInit init = new(_owner);
|
||||
init.args.path = new Vector3[stepCount];
|
||||
for (byte i = 0; i < stepCount; angle += step, ++i)
|
||||
|
||||
init.args.path = new Vector3[stepCount + 1];
|
||||
|
||||
// add the owner's current position as starting point as it gets removed after entering the cycle
|
||||
init.args.path[0] = new Vector3(_owner.GetPositionX(), _owner.GetPositionY(), _owner.GetPositionZ());
|
||||
for (byte i = 1; i < stepCount; angle += step, ++i)
|
||||
{
|
||||
Vector3 point = new();
|
||||
point.X = (float)(x + radius * Math.Cos(angle));
|
||||
|
||||
@@ -88,7 +88,10 @@ namespace Game.Movement
|
||||
Spline.EvaluationMode[] modes = new Spline.EvaluationMode[2] { Spline.EvaluationMode.Linear, Spline.EvaluationMode.Catmullrom };
|
||||
if (args.flags.HasFlag(SplineFlag.Cyclic))
|
||||
{
|
||||
spline.InitCyclicSpline(args.path, args.path.Length, modes[Convert.ToInt32(args.flags.IsSmooth())], 0, args.initialOrientation);
|
||||
int cyclic_point = 0;
|
||||
if (splineflags.HasFlag(SplineFlag.EnterCycle))
|
||||
cyclic_point = 1; // shouldn't be modified, came from client
|
||||
spline.InitCyclicSpline(args.path, args.path.Length, modes[Convert.ToInt32(args.flags.IsSmooth())], cyclic_point, args.initialOrientation);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -288,6 +291,40 @@ namespace Game.Movement
|
||||
point_Idx = spline.First();
|
||||
time_passed %= Duration();
|
||||
result = UpdateResult.NextCycle;
|
||||
// Remove first point from the path after one full cycle.
|
||||
// That point was the position of the unit prior to entering the cycle and it shouldn't be repeated with continuous cycles.
|
||||
if (splineflags.HasFlag(SplineFlag.EnterCycle))
|
||||
{
|
||||
splineflags.SetUnsetFlag(SplineFlag.EnterCycle, false);
|
||||
|
||||
MoveSplineInitArgs args = new(spline.GetPointCount());
|
||||
args.path = spline.GetPoints().AsSpan().Slice(spline.First() + 1, spline.Last()).ToArray();
|
||||
args.facing = facing;
|
||||
args.flags = splineflags;
|
||||
args.path_Idx_offset = point_Idx_offset;
|
||||
// MoveSplineFlag::Parabolic | MoveSplineFlag::Animation not supported currently
|
||||
//args.parabolic_amplitude = ?;
|
||||
//args.time_perc = ?;
|
||||
args.splineId = m_Id;
|
||||
args.initialOrientation = initialOrientation;
|
||||
args.velocity = 1.0f; // Calculated below
|
||||
args.HasVelocity = true;
|
||||
args.TransformForTransport = onTransport;
|
||||
if (args.Validate(null))
|
||||
{
|
||||
// New cycle should preserve previous cycle's duration for some weird reason, even though
|
||||
// the path is really different now. Blizzard is weird. Or this was just a simple oversight.
|
||||
// Since our splines precalculate length with velocity in mind, if we want to find the desired
|
||||
// velocity, we have to make a fake spline, calculate its duration and then compare it to the
|
||||
// desired duration, thus finding out how much the velocity has to be increased for them to match.
|
||||
MoveSpline tempSpline = new();
|
||||
tempSpline.Initialize(args);
|
||||
args.velocity = (float)tempSpline.Duration() / Duration();
|
||||
|
||||
if (args.Validate(null))
|
||||
InitSpline(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -100,7 +100,8 @@ namespace Game.Movement
|
||||
// correct first vertex
|
||||
args.path[0] = new Vector3(real_position.X, real_position.Y, real_position.Z);
|
||||
args.initialOrientation = real_position.W;
|
||||
move_spline.onTransport = !unit.GetTransGUID().IsEmpty();
|
||||
args.flags.SetUnsetFlag(SplineFlag.EnterCycle, args.flags.HasFlag(SplineFlag.Cyclic));
|
||||
move_spline.onTransport = transport;
|
||||
|
||||
MovementFlag moveFlags = unit.m_movementInfo.GetMovementFlags();
|
||||
if (!args.flags.HasFlag(SplineFlag.Backward))
|
||||
|
||||
@@ -454,6 +454,20 @@ namespace Game.Networking.Packets
|
||||
public Vector3 Pos;
|
||||
}
|
||||
|
||||
class FlightSplineSync : ServerPacket
|
||||
{
|
||||
public FlightSplineSync() : base(ServerOpcodes.FlightSplineSync, ConnectionType.Instance) { }
|
||||
|
||||
public override void Write()
|
||||
{
|
||||
_worldPacket.WritePackedGuid(Guid);
|
||||
_worldPacket.WriteFloat(SplineDist);
|
||||
}
|
||||
|
||||
public ObjectGuid Guid;
|
||||
public float SplineDist;
|
||||
}
|
||||
|
||||
public class MoveSplineSetSpeed : ServerPacket
|
||||
{
|
||||
public MoveSplineSetSpeed(ServerOpcodes opcode) : base(opcode, ConnectionType.Instance) { }
|
||||
|
||||
Reference in New Issue
Block a user