feat: paragons scale the movement clock by SpeedBuff

RunUO had no deliberate paragon movement policy: dividing by 1.2 knocked
most speeds off TransformMoveDelay's exact-equality table, so those
paragons moved at the raw divided delay (2x+ faster than their transformed
base), while 0.3/0.6 creatures landed back on the table (0.25/0.5 are
exact in IEEE) for only a ~1.33x buff. This applies the uniform 1.2x the
buff always claimed: Convert/UnConvert scale movement overrides alongside
the think clock; inheriting values stay inheriting, since they already
follow the scaled think values.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Kamron Batman 2026-08-23 09:46:27 -07:00
parent 5bf9fbefb6
commit 658735fd45
No known key found for this signature in database
GPG key ID: 7D81DF26D9A5D94A
3 changed files with 31 additions and 0 deletions

View file

@ -112,6 +112,18 @@ public class MoveSpeedTests : IDisposable
Assert.Equal(0.9, bc.PassiveMoveSpeed); // other override untouched
}
[Fact]
public void ScaleMoveSpeed_ScalesOverrides_LeavesInheritAlone()
{
var bc = NewCreature();
bc.ActiveMoveSpeed = 0.6; // passive left inheriting
bc.ScaleMoveSpeed(1.0 / 1.2);
Assert.Equal(0.5, bc.ActiveMoveSpeed);
Assert.Equal(bc.PassiveSpeed, bc.PassiveMoveSpeed); // still inheriting, not 0 * scalar
}
[Fact]
public void Migration_MatchingThinkSpeeds_AdoptTableMoveValues()
{

View file

@ -4674,6 +4674,23 @@ namespace Server.Mobiles
_passiveMoveSpeed = 0;
}
/// <summary>
/// Scales movement overrides (paragon and similar buffs). Inheriting values stay
/// inheriting — they already follow the scaled think clock.
/// </summary>
public void ScaleMoveSpeed(double scalar)
{
if (_activeMoveSpeed > 0)
{
_activeMoveSpeed *= scalar;
}
if (_passiveMoveSpeed > 0)
{
_passiveMoveSpeed *= scalar;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SetCurrentSpeedToActive() => CurrentSpeed = ActiveSpeed;

View file

@ -79,6 +79,7 @@ public static class Paragon
bc.PassiveSpeed /= SpeedBuff;
bc.ActiveSpeed /= SpeedBuff;
bc.ScaleMoveSpeed(1.0 / SpeedBuff);
bc.CurrentSpeed = bc.PassiveSpeed;
bc.DamageMin += DamageBuff;
@ -143,6 +144,7 @@ public static class Paragon
bc.PassiveSpeed *= SpeedBuff;
bc.ActiveSpeed *= SpeedBuff;
bc.ScaleMoveSpeed(SpeedBuff);
bc.CurrentSpeed = bc.PassiveSpeed;
bc.DamageMin -= DamageBuff;