fix: snap speeds to table values after paragon unconvert
Scaling down then back up drifts some values by an ulp (0.45 and 0.9 do not survive /1.2 then *1.2 in IEEE doubles; the think values currently do only by luck of the mantissas). Drifted speeds would read as hand-tuned - notably by the planned skip-serializing-table-conformant values optimization, which would then persist every former paragon forever. UnConvert now snaps both clocks back to exact table values when within rounding distance (1e-4, the existing speed epsilon); genuinely tuned speeds are nowhere near it and keep. Also removes MoveSpeedMod: never read, never written, never serialized. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
658735fd45
commit
41ae2d8ffe
3 changed files with 53 additions and 3 deletions
|
|
@ -124,6 +124,29 @@ public class MoveSpeedTests : IDisposable
|
|||
Assert.Equal(bc.PassiveSpeed, bc.PassiveMoveSpeed); // still inheriting, not 0 * scalar
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SnapSpeedsToTable_UndoesScalingDrift_KeepsTunedValues()
|
||||
{
|
||||
var bc = NewCreature();
|
||||
bc.TableActiveMove = 0.45;
|
||||
bc.TablePassiveMove = 0.9;
|
||||
bc.SetMoveSpeed(0.45, 0.9);
|
||||
|
||||
// 0.45 and 0.9 do not survive /1.2 then *1.2 bit-exactly.
|
||||
bc.ScaleMoveSpeed(1.0 / 1.2);
|
||||
bc.ScaleMoveSpeed(1.2);
|
||||
Assert.NotEqual(0.45, bc.ActiveMoveSpeed);
|
||||
|
||||
bc.SnapSpeedsToTable();
|
||||
Assert.Equal(0.45, bc.ActiveMoveSpeed);
|
||||
Assert.Equal(0.9, bc.PassiveMoveSpeed);
|
||||
|
||||
// A hand-tuned value is nowhere near the epsilon and must keep.
|
||||
bc.SetMoveSpeed(0.7, 0.9);
|
||||
bc.SnapSpeedsToTable();
|
||||
Assert.Equal(0.7, bc.ActiveMoveSpeed);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Migration_MatchingThinkSpeeds_AdoptTableMoveValues()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -773,9 +773,6 @@ namespace Server.Mobiles
|
|||
}
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public double MoveSpeedMod { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public Point3D Home
|
||||
{
|
||||
|
|
@ -4691,6 +4688,35 @@ namespace Server.Mobiles
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Snaps speeds within rounding distance of the creature's table values back to
|
||||
/// exact. A scaling buff that divides then multiplies can drift by an ulp (e.g.
|
||||
/// 0.9 and 0.45 through 1.2), which would read as hand-tuned; call after undoing
|
||||
/// such a buff. Genuinely tuned speeds are nowhere near the epsilon and keep.
|
||||
/// </summary>
|
||||
public void SnapSpeedsToTable()
|
||||
{
|
||||
GetSpeeds(out var activeSpeed, out var passiveSpeed);
|
||||
|
||||
if (Math.Abs(_activeSpeed - activeSpeed) < 0.0001 && Math.Abs(_passiveSpeed - passiveSpeed) < 0.0001)
|
||||
{
|
||||
_activeSpeed = activeSpeed;
|
||||
_passiveSpeed = passiveSpeed;
|
||||
}
|
||||
|
||||
GetMoveSpeeds(out var activeMoveSpeed, out var passiveMoveSpeed);
|
||||
|
||||
if (activeMoveSpeed > 0 && Math.Abs(_activeMoveSpeed - activeMoveSpeed) < 0.0001)
|
||||
{
|
||||
_activeMoveSpeed = activeMoveSpeed;
|
||||
}
|
||||
|
||||
if (passiveMoveSpeed > 0 && Math.Abs(_passiveMoveSpeed - passiveMoveSpeed) < 0.0001)
|
||||
{
|
||||
_passiveMoveSpeed = passiveMoveSpeed;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void SetCurrentSpeedToActive() => CurrentSpeed = ActiveSpeed;
|
||||
|
||||
|
|
|
|||
|
|
@ -145,6 +145,7 @@ public static class Paragon
|
|||
bc.PassiveSpeed *= SpeedBuff;
|
||||
bc.ActiveSpeed *= SpeedBuff;
|
||||
bc.ScaleMoveSpeed(SpeedBuff);
|
||||
bc.SnapSpeedsToTable(); // an ulp of scaling drift must not read as hand-tuned
|
||||
bc.CurrentSpeed = bc.PassiveSpeed;
|
||||
|
||||
bc.DamageMin -= DamageBuff;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue