Core/Movement: Change default spline flags - Steering replaces SmoothGroundPath

Port From (https://github.com/TrinityCore/TrinityCore/commit/3af5cafec782ab4d5d5d8478927caae0e6258174)
This commit is contained in:
Hondacrx
2024-08-18 22:08:08 -04:00
parent 46377f0716
commit 116cfcdcf9
7 changed files with 61 additions and 67 deletions
@@ -14,10 +14,9 @@ namespace Framework.Constants
}
[Flags]
public enum SplineFlag : uint
public enum MoveSplineFlagEnum : uint
{
None = 0x00,
// x00-x07 used as animation Ids storage in pair with Animation flag
Unknown_0x1 = 0x00000001, // NOT VERIFIED
Unknown_0x2 = 0x00000002, // NOT VERIFIED
Unknown_0x4 = 0x00000004, // NOT VERIFIED
@@ -51,12 +50,10 @@ namespace Framework.Constants
Unknown_0x40000000 = 0x40000000, // NOT VERIFIED
Unknown_0x80000000 = 0x80000000, // NOT VERIFIED
// animation ids stored here, see AnimType enum, used with Animation flag
MaskAnimations = 0x7,
// flags that shouldn't be appended into SMSG_MONSTER_MOVE\SMSG_MONSTER_MOVE_TRANSPORT packet, should be more probably
MaskNoMonsterMove = Done,
// Unused, not suported flags
MaskUnused = NoSpline | EnterCycle | Frozen | Unknown_0x8 | Unknown_0x100 | Unknown_0x20000 | Unknown_0x40000
| Unknown_0x800000 | FastSteering | FadeObject | UnlimitedSpeed | Unknown_0x40000000 | Unknown_0x80000000
| Unknown_0x800000 | FadeObject | UnlimitedSpeed | Unknown_0x40000000 | Unknown_0x80000000
}
}
@@ -437,10 +437,6 @@ namespace Game.Movement
MoveSplineInit init = new(owner);
// because steering flag can cause position on client to not be perfectly accurate, dont do it in combat
if (!owner.IsInCombat())
init.SetSteering();
//! If creature is on transport, we assume waypoints set in DB are already transport offsets
if (transportPath)
init.DisableTransportPathTransformations();
@@ -494,6 +490,7 @@ namespace Game.Movement
if (!IsExactSplinePath()
&& duration > 2 * SEND_NEXT_POINT_EARLY_DELTA
&& lastWaypointForSegment.Delay == TimeSpan.Zero
&& _path.Nodes.Count > 2
// don't cut movement short at ends of path if its not a looping path or if it can be traversed backwards
&& ((_currentNode != 0 && _currentNode != _path.Nodes.Count - 1) || (!IsFollowingPathBackwardsFromEndToStart() && _repeating)))
duration -= SEND_NEXT_POINT_EARLY_DELTA;
+19 -19
View File
@@ -22,7 +22,7 @@ namespace Game.Movement
point_Idx_offset = 0;
onTransport = false;
splineIsFacingOnly = false;
splineflags.Flags = SplineFlag.Done;
splineflags.Flags = MoveSplineFlagEnum.Done;
}
public void Initialize(MoveSplineInitArgs args)
@@ -43,7 +43,7 @@ namespace Game.Movement
velocity = args.velocity;
// Check if its a stop spline
if (args.flags.HasFlag(SplineFlag.Done))
if (args.flags.HasFlag(MoveSplineFlagEnum.Done))
{
spline.Clear();
return;
@@ -53,14 +53,14 @@ namespace Game.Movement
// init parabolic / animation
// spline initialized, duration known and i able to compute parabolic acceleration
if (args.flags.HasFlag(SplineFlag.Parabolic | SplineFlag.Animation | SplineFlag.FadeObject))
if (args.flags.HasFlag(MoveSplineFlagEnum.Parabolic | MoveSplineFlagEnum.Animation | MoveSplineFlagEnum.FadeObject))
{
int spline_duration = Duration();
effect_start_time = (int)(spline_duration * args.effect_start_time_percent + args.effect_start_time.TotalMilliseconds);
if (effect_start_time > spline_duration)
effect_start_time = spline_duration;
if (args.flags.HasFlag(SplineFlag.Parabolic) && effect_start_time < spline_duration)
if (args.flags.HasFlag(MoveSplineFlagEnum.Parabolic) && effect_start_time < spline_duration)
{
if (args.parabolic_amplitude != 0.0f)
{
@@ -78,10 +78,10 @@ namespace Game.Movement
void InitSpline(MoveSplineInitArgs args)
{
EvaluationMode[] modes = new EvaluationMode[2] { EvaluationMode.Linear, EvaluationMode.Catmullrom };
if (args.flags.HasFlag(SplineFlag.Cyclic))
if (args.flags.HasFlag(MoveSplineFlagEnum.Cyclic))
{
int cyclic_point = 0;
if (splineflags.HasFlag(SplineFlag.EnterCycle))
if (splineflags.HasFlag(MoveSplineFlagEnum.EnterCycle))
cyclic_point = 1; // shouldn't be modified, came from client
spline.InitCyclicSpline(args.path.ToArray(), args.path.Count, modes[Convert.ToInt32(args.flags.IsSmooth())], cyclic_point, args.initialOrientation);
}
@@ -91,7 +91,7 @@ namespace Game.Movement
}
// init spline timestamps
if (splineflags.HasFlag(SplineFlag.Falling))
if (splineflags.HasFlag(MoveSplineFlagEnum.Falling))
{
FallInitializer init = new(spline.GetPoint(spline.First()).Z);
spline.InitLengths(init);
@@ -126,10 +126,10 @@ namespace Game.Movement
public int Duration() { return spline.Length(); }
public int CurrentSplineIdx() { return point_Idx; }
public uint GetId() { return m_Id; }
public bool Finalized() { return splineflags.HasFlag(SplineFlag.Done); }
public bool Finalized() { return splineflags.HasFlag(MoveSplineFlagEnum.Done); }
void _Finalize()
{
splineflags.SetUnsetFlag(SplineFlag.Done);
splineflags.SetUnsetFlag(MoveSplineFlagEnum.Done);
point_Idx = spline.Last() - 1;
time_passed = Duration();
}
@@ -144,12 +144,12 @@ namespace Game.Movement
float orientation = initialOrientation;
spline.Evaluate_Percent(point_index, u, out c);
if (splineflags.HasFlag(SplineFlag.Parabolic))
if (splineflags.HasFlag(MoveSplineFlagEnum.Parabolic))
ComputeParabolicElevation(time_point, ref c.Z);
else if (splineflags.HasFlag(SplineFlag.Falling))
else if (splineflags.HasFlag(MoveSplineFlagEnum.Falling))
ComputeFallElevation(time_point, ref c.Z);
if (splineflags.HasFlag(SplineFlag.Done) && facing.type != MonsterMoveType.Normal)
if (splineflags.HasFlag(MoveSplineFlagEnum.Done) && facing.type != MonsterMoveType.Normal)
{
if (facing.type == MonsterMoveType.FacingAngle)
orientation = facing.angle;
@@ -159,7 +159,7 @@ namespace Game.Movement
}
else
{
if (!splineflags.HasFlag(SplineFlag.OrientationFixed | SplineFlag.Falling | SplineFlag.Unknown_0x8))
if (!splineflags.HasFlag(MoveSplineFlagEnum.OrientationFixed | MoveSplineFlagEnum.Falling | MoveSplineFlagEnum.Unknown_0x8))
{
Vector3 hermite;
spline.Evaluate_Derivative(point_Idx, u, out hermite);
@@ -167,7 +167,7 @@ namespace Game.Movement
orientation = MathF.Atan2(hermite.Y, hermite.X);
}
if (splineflags.HasFlag(SplineFlag.Backward))
if (splineflags.HasFlag(MoveSplineFlagEnum.Backward))
orientation -= MathF.PI;
}
@@ -250,7 +250,7 @@ namespace Game.Movement
return time_passed > 0;
}
public void Interrupt() { splineflags.SetUnsetFlag(SplineFlag.Done); }
public void Interrupt() { splineflags.SetUnsetFlag(MoveSplineFlagEnum.Done); }
public void UpdateState(int difftime)
{
do
@@ -287,9 +287,9 @@ namespace Game.Movement
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))
if (splineflags.HasFlag(MoveSplineFlagEnum.EnterCycle))
{
splineflags.SetUnsetFlag(SplineFlag.EnterCycle, false);
splineflags.SetUnsetFlag(MoveSplineFlagEnum.EnterCycle, false);
MoveSplineInitArgs args = new(spline.GetPointCount());
args.path.AddRange(spline.GetPoints().AsSpan().Slice(spline.First() + 1, spline.Last()).ToArray());
@@ -333,8 +333,8 @@ namespace Game.Movement
}
int NextTimestamp() { return spline.Length(point_Idx + 1); }
int SegmentTimeElapsed() { return NextTimestamp() - time_passed; }
public bool IsCyclic() { return splineflags.HasFlag(SplineFlag.Cyclic); }
public bool IsFalling() { return splineflags.HasFlag(SplineFlag.Falling); }
public bool IsCyclic() { return splineflags.HasFlag(MoveSplineFlagEnum.Cyclic); }
public bool IsFalling() { return splineflags.HasFlag(MoveSplineFlagEnum.Falling); }
public bool Initialized() { return !spline.Empty(); }
public Vector3 FinalDestination() { return Initialized() ? spline.GetPoint(spline.Last()) : Vector3.Zero; }
public Vector3 CurrentDestination() { return Initialized() ? spline.GetPoint(point_Idx + 1) : Vector3.Zero; }
+14 -14
View File
@@ -9,16 +9,16 @@ namespace Game.Movement
public class MoveSplineFlag
{
public MoveSplineFlag() { }
public MoveSplineFlag(SplineFlag f) { Flags = f; }
public MoveSplineFlag(MoveSplineFlagEnum f) { Flags = f; }
public MoveSplineFlag(MoveSplineFlag f) { Flags = f.Flags; }
public bool IsSmooth() { return Flags.HasAnyFlag(SplineFlag.Catmullrom); }
public bool IsSmooth() { return Flags.HasAnyFlag(MoveSplineFlagEnum.Catmullrom); }
public bool IsLinear() { return !IsSmooth(); }
public bool HasAllFlags(SplineFlag f) { return (Flags & f) == f; }
public bool HasFlag(SplineFlag f) { return (Flags & f) != 0; }
public bool HasAllFlags(MoveSplineFlagEnum f) { return (Flags & f) == f; }
public bool HasFlag(MoveSplineFlagEnum f) { return (Flags & f) != 0; }
public void SetUnsetFlag(SplineFlag f, bool Set = true)
public void SetUnsetFlag(MoveSplineFlagEnum f, bool Set = true)
{
if (Set)
Flags |= f;
@@ -26,16 +26,16 @@ namespace Game.Movement
Flags &= ~f;
}
public void EnableAnimation() { Flags = (Flags & ~(SplineFlag.Falling | SplineFlag.Parabolic | SplineFlag.FallingSlow | SplineFlag.FadeObject)) | SplineFlag.Animation; }
public void EnableParabolic() { Flags = (Flags & ~(SplineFlag.Falling | SplineFlag.Animation | SplineFlag.FallingSlow | SplineFlag.FadeObject)) | SplineFlag.Parabolic; }
public void EnableFlying() { Flags = (Flags & ~SplineFlag.Falling) | SplineFlag.Flying; }
public void EnableFalling() { Flags = (Flags & ~(SplineFlag.Parabolic | SplineFlag.Animation | SplineFlag.Flying)) | SplineFlag.Falling; }
public void EnableCatmullRom() { Flags = (Flags & ~SplineFlag.SmoothGroundPath) | SplineFlag.Catmullrom; }
public void EnableTransportEnter() { Flags = (Flags & ~SplineFlag.TransportExit) | SplineFlag.TransportEnter; }
public void EnableTransportExit() { Flags = (Flags & ~SplineFlag.TransportEnter) | SplineFlag.TransportExit; }
public void EnableSteering() { Flags = (Flags & ~SplineFlag.SmoothGroundPath) | SplineFlag.Steering; }
public void EnableAnimation() { Flags = (Flags & ~(MoveSplineFlagEnum.Falling | MoveSplineFlagEnum.Parabolic | MoveSplineFlagEnum.FallingSlow | MoveSplineFlagEnum.FadeObject)) | MoveSplineFlagEnum.Animation; }
public void EnableParabolic() { Flags = (Flags & ~(MoveSplineFlagEnum.Falling | MoveSplineFlagEnum.Animation | MoveSplineFlagEnum.FallingSlow | MoveSplineFlagEnum.FadeObject)) | MoveSplineFlagEnum.Parabolic; }
public void EnableFlying() { Flags = (Flags & ~MoveSplineFlagEnum.Falling) | MoveSplineFlagEnum.Flying; }
public void EnableFalling() { Flags = (Flags & ~(MoveSplineFlagEnum.Parabolic | MoveSplineFlagEnum.Animation | MoveSplineFlagEnum.Flying)) | MoveSplineFlagEnum.Falling; }
public void EnableCatmullRom() { Flags = (Flags & ~MoveSplineFlagEnum.SmoothGroundPath) | MoveSplineFlagEnum.Catmullrom; }
public void EnableTransportEnter() { Flags = (Flags & ~MoveSplineFlagEnum.TransportExit) | MoveSplineFlagEnum.TransportEnter; }
public void EnableTransportExit() { Flags = (Flags & ~MoveSplineFlagEnum.TransportEnter) | MoveSplineFlagEnum.TransportExit; }
public void EnableSteering() { Flags = (Flags & ~MoveSplineFlagEnum.SmoothGroundPath) | MoveSplineFlagEnum.Steering; }
public SplineFlag Flags;
public MoveSplineFlagEnum Flags;
public byte animTier;
}
}
+15 -15
View File
@@ -20,11 +20,11 @@ namespace Game.Movement
// Elevators also use MOVEMENTFLAG_ONTRANSPORT but we do not keep track of their position changes
args.TransformForTransport = !unit.GetTransGUID().IsEmpty();
// mix existing state into new
args.flags.SetUnsetFlag(SplineFlag.CanSwim, unit.CanSwim());
args.flags.SetUnsetFlag(MoveSplineFlagEnum.CanSwim, unit.CanSwim());
args.walk = unit.HasUnitMovementFlag(MovementFlag.Walking);
args.flags.SetUnsetFlag(SplineFlag.Flying, unit.HasUnitMovementFlag(MovementFlag.CanFly | MovementFlag.DisableGravity));
args.flags.SetUnsetFlag(SplineFlag.Steering, unit.HasNpcFlag2(NPCFlags2.Steering));
args.flags.SetUnsetFlag(SplineFlag.SmoothGroundPath, !args.flags.HasFlag(SplineFlag.Flying) && !args.flags.HasFlag(SplineFlag.Steering)); // enabled by default, CatmullRom mode or client config "pathSmoothing" will disable this
args.flags.SetUnsetFlag(MoveSplineFlagEnum.Flying, unit.HasUnitMovementFlag(MovementFlag.CanFly | MovementFlag.DisableGravity));
args.flags.SetUnsetFlag(MoveSplineFlagEnum.FastSteering, true);
args.flags.SetUnsetFlag(MoveSplineFlagEnum.Steering, unit.HasNpcFlag2(NPCFlags2.Steering) || !unit.IsInCombat());
}
UnitMoveType SelectSpeedType(MovementFlag moveFlags)
@@ -87,11 +87,11 @@ 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;
args.flags.SetUnsetFlag(SplineFlag.EnterCycle, args.flags.HasFlag(SplineFlag.Cyclic));
args.flags.SetUnsetFlag(MoveSplineFlagEnum.EnterCycle, args.flags.HasFlag(MoveSplineFlagEnum.Cyclic));
move_spline.onTransport = transport;
MovementFlag moveFlags = unit.m_movementInfo.GetMovementFlags();
if (!args.flags.HasFlag(SplineFlag.Backward))
if (!args.flags.HasFlag(MoveSplineFlagEnum.Backward))
moveFlags = (moveFlags & ~MovementFlag.Backward) | MovementFlag.Forward;
else
moveFlags = (moveFlags & ~MovementFlag.Forward) | MovementFlag.Backward;
@@ -119,10 +119,10 @@ namespace Game.Movement
// limit the speed in the same way the client does
float speedLimit()
{
if (args.flags.HasFlag(SplineFlag.UnlimitedSpeed))
if (args.flags.HasFlag(MoveSplineFlagEnum.UnlimitedSpeed))
return float.MaxValue;
if (args.flags.HasFlag(SplineFlag.Falling) || args.flags.HasFlag(SplineFlag.Catmullrom) || args.flags.HasFlag(SplineFlag.Flying) || args.flags.HasFlag(SplineFlag.Parabolic))
if (args.flags.HasFlag(MoveSplineFlagEnum.Falling) || args.flags.HasFlag(MoveSplineFlagEnum.Catmullrom) || args.flags.HasFlag(MoveSplineFlagEnum.Flying) || args.flags.HasFlag(MoveSplineFlagEnum.Parabolic))
return 50.0f;
return Math.Max(28.0f, unit.GetSpeed(UnitMoveType.Run) * 4.0f);
@@ -176,7 +176,7 @@ namespace Game.Movement
loc.W = unit.GetOrientation();
}
args.flags.Flags = SplineFlag.Done;
args.flags.Flags = MoveSplineFlagEnum.Done;
unit.m_movementInfo.RemoveMovementFlag(MovementFlag.Forward);
move_spline.onTransport = transport;
move_spline.Initialize(args);
@@ -257,7 +257,7 @@ namespace Game.Movement
public void SetFall()
{
args.flags.EnableFalling();
args.flags.SetUnsetFlag(SplineFlag.FallingSlow, unit.HasUnitMovementFlag(MovementFlag.FallingSlow));
args.flags.SetUnsetFlag(MoveSplineFlagEnum.FallingSlow, unit.HasUnitMovementFlag(MovementFlag.FallingSlow));
}
public void SetFirstPointId(int pointId) { args.path_Idx_offset = pointId; }
@@ -268,23 +268,23 @@ namespace Game.Movement
public void SetSmooth() { args.flags.EnableCatmullRom(); }
public void SetUncompressed() { args.flags.SetUnsetFlag(SplineFlag.UncompressedPath); }
public void SetUncompressed() { args.flags.SetUnsetFlag(MoveSplineFlagEnum.UncompressedPath); }
public void SetCyclic() { args.flags.SetUnsetFlag(SplineFlag.Cyclic); }
public void SetCyclic() { args.flags.SetUnsetFlag(MoveSplineFlagEnum.Cyclic); }
public void SetVelocity(float vel) { args.velocity = vel; args.HasVelocity = true; }
void SetBackward() { args.flags.SetUnsetFlag(SplineFlag.Backward); }
void SetBackward() { args.flags.SetUnsetFlag(MoveSplineFlagEnum.Backward); }
public void SetTransportEnter() { args.flags.EnableTransportEnter(); }
public void SetTransportExit() { args.flags.EnableTransportExit(); }
public void SetOrientationFixed(bool enable) { args.flags.SetUnsetFlag(SplineFlag.OrientationFixed, enable); }
public void SetOrientationFixed(bool enable) { args.flags.SetUnsetFlag(MoveSplineFlagEnum.OrientationFixed, enable); }
public void SetSteering() { args.flags.EnableSteering(); }
public void SetUnlimitedSpeed() { args.flags.SetUnsetFlag(SplineFlag.UnlimitedSpeed, true); }
public void SetUnlimitedSpeed() { args.flags.SetUnsetFlag(MoveSplineFlagEnum.UnlimitedSpeed, true); }
public void MovebyPath(Vector3[] controls, int path_offset = 0)
{
+2 -2
View File
@@ -97,11 +97,11 @@ namespace Game.Movement
return false;
// when compression is enabled, each point coord is packed into 11 bits (10 for Z)
if (!flags.HasFlag(SplineFlag.UncompressedPath))
if (!flags.HasFlag(MoveSplineFlagEnum.UncompressedPath))
if (!isValidPackedXYOffset(MathF.Abs(path[i].X - middle.X))
|| !isValidPackedXYOffset(MathF.Abs(path[i].Y - middle.Y))
|| !isValidPackedZOffset(MathF.Abs(path[i].Z - middle.Z)))
flags.SetUnsetFlag(SplineFlag.UncompressedPath, true);
flags.SetUnsetFlag(MoveSplineFlagEnum.UncompressedPath, true);
}
}
return true;
@@ -235,11 +235,11 @@ namespace Game.Networking.Packets
data.WriteFloat(1.0f); // DurationModifier
data.WriteFloat(1.0f); // NextDurationModifier
data.WriteBits((byte)moveSpline.facing.type, 2); // Face
bool hasFadeObjectTime = data.WriteBit(moveSpline.splineflags.HasFlag(SplineFlag.FadeObject) && moveSpline.effect_start_time < moveSpline.Duration());
bool hasFadeObjectTime = data.WriteBit(moveSpline.splineflags.HasFlag(MoveSplineFlagEnum.FadeObject) && moveSpline.effect_start_time < moveSpline.Duration());
data.WriteBits(moveSpline.GetPath().Length, 16);
data.WriteBit(false); // HasSplineFilter
data.WriteBit(moveSpline.spell_effect_extra != null); // HasSpellEffectExtraData
bool hasJumpExtraData = data.WriteBit(moveSpline.splineflags.HasFlag(SplineFlag.Parabolic) && (moveSpline.spell_effect_extra == null || moveSpline.effect_start_time != 0));
bool hasJumpExtraData = data.WriteBit(moveSpline.splineflags.HasFlag(MoveSplineFlagEnum.Parabolic) && (moveSpline.spell_effect_extra == null || moveSpline.effect_start_time != 0));
data.WriteBit(moveSpline.anim_tier != null); // HasAnimTierTransition
data.WriteBit(false); // HasUnknown901
data.FlushBits();
@@ -396,7 +396,7 @@ namespace Game.Networking.Packets
MovementSpline movementSpline = SplineData.Move;
MoveSplineFlag splineFlags = moveSpline.splineflags;
movementSpline.Flags = (uint)(splineFlags.Flags & ~SplineFlag.MaskNoMonsterMove);
movementSpline.Flags = (uint)(splineFlags.Flags & ~MoveSplineFlagEnum.MaskNoMonsterMove);
movementSpline.Face = moveSpline.facing.type;
movementSpline.FaceDirection = moveSpline.facing.angle;
movementSpline.FaceGUID = moveSpline.facing.target;
@@ -413,7 +413,7 @@ namespace Game.Networking.Packets
movementSpline.MoveTime = (uint)moveSpline.Duration();
if (splineFlags.HasFlag(SplineFlag.Parabolic) && (moveSpline.spell_effect_extra == null || moveSpline.effect_start_time != 0))
if (splineFlags.HasFlag(MoveSplineFlagEnum.Parabolic) && (moveSpline.spell_effect_extra == null || moveSpline.effect_start_time != 0))
{
MonsterSplineJumpExtraData jumpExtraData = new();
jumpExtraData.JumpGravity = moveSpline.vertical_acceleration;
@@ -421,7 +421,7 @@ namespace Game.Networking.Packets
movementSpline.JumpExtraData = jumpExtraData;
}
if (splineFlags.HasFlag(SplineFlag.FadeObject))
if (splineFlags.HasFlag(MoveSplineFlagEnum.FadeObject))
movementSpline.FadeObjectTime = (uint)moveSpline.effect_start_time;
if (moveSpline.spell_effect_extra != null)
@@ -438,15 +438,15 @@ namespace Game.Networking.Packets
var spline = moveSpline.spline;
Vector3[] array = spline.GetPoints();
if (splineFlags.HasFlag(SplineFlag.UncompressedPath))
if (splineFlags.HasFlag(MoveSplineFlagEnum.UncompressedPath))
{
int count = spline.GetPointCount() - (splineFlags.HasFlag(SplineFlag.Cyclic) ? 4 : 3);
int count = spline.GetPointCount() - (splineFlags.HasFlag(MoveSplineFlagEnum.Cyclic) ? 4 : 3);
for (int i = 0; i < count; ++i)
movementSpline.Points.Add(new Vector3(array[i + 2].X, array[i + 2].Y, array[i + 2].Z));
}
else
{
int lastIdx = spline.GetPointCount() - (splineFlags.HasFlag(SplineFlag.Cyclic) ? 4 : 3);
int lastIdx = spline.GetPointCount() - (splineFlags.HasFlag(MoveSplineFlagEnum.Cyclic) ? 4 : 3);
Vector3[] realPath = array[1..];
movementSpline.Points.Add(realPath[lastIdx]);