Interkarma / daggerfall-unity

Open source recreation of Daggerfall in the Unity engine
http://www.dfworkshop.net
MIT License
2.67k stars 326 forks source link

You can run at full speed while crouched #2670

Open petchema opened 1 month ago

petchema commented 1 month ago

Describe the issue

If you press the run key while crouched, you'll move at full running speed, same as if you were standing.

To Reproduce

Steps to reproduce the behavior:

  1. Crouch
  2. Walk forward. Notice the speed
  3. Press your run toggle key
  4. Notice the huge speed boost

Expected behavior

In classic, crouching + running seems faster than crouching alone, but much slower than running alone. I suspect running applies the same speed multiplier whether you're standing or crouched, but I haven't measured to be sure.

Desktop (please complete the following information):

petchema commented 1 month ago

PlayerMotor.UpdateSpeed() calls PlayerSpeedChanger.GetBaseSpeed(), then PlayerSpeedChanger.ApplyInputSpeedAdjustment(). The latter totally overrides GetBaseSpeed() computations in the case you're running (l.120):

            if (isRunning)
            {
                speed = RefreshRunSpeed();

P.S.: I just noticed that PlayerSpeedChanger.baseSpeed works as a covert channel between GetBaseSpeed() and GetRunSpeed(), but is only when you're riding, so my analysis still holds when you're crouching? That code is so convoluted...

petchema commented 1 month ago

A simple but cowardly fix would be to consider that when you're crouching you can't be running. Not great, does not match classic, but less surprising than what we have now.

index 0ea93e535..8e7bc9a38 100644
--- a/Assets/Scripts/Game/Player/PlayerSpeedChanger.cs
+++ b/Assets/Scripts/Game/Player/PlayerSpeedChanger.cs
@@ -107,7 +107,7 @@ namespace DaggerfallWorkshop.Game
         {
             if (playerMotor.IsGrounded)
             {
-                isRunning = CanRun() && runningMode;
+                isRunning = CanRun() && runningMode && !playerMotor.IsCrouching;
                 isSneaking = !isRunning && sneakingMode;
             }
             else
KABoissonneault commented 1 month ago

I'm thinking we might just be able to apply the crouch speed to the run function.

        public float GetRunSpeed()
        {
            Entity.PlayerEntity player = GameManager.Instance.PlayerEntity;
-           float baseRunSpeed = playerMotor.IsRiding ? baseSpeed : (player.Stats.LiveSpeed + dfWalkBase) / classicToUnitySpeedUnitRatio;
+           float baseRunSpeed;
+           if (playerMotor.IsRiding)
+               baseRunSpeed = baseSpeed;
+           else if (playerMotor.IsCrouching && !levitateMotor.IsSwimming)
+               baseRunSpeed = (player.Stats.LiveSpeed + dfCrouchBase) / classicToUnitySpeedUnitRatio;
+           else
+               baseRunSpeed = (player.Stats.LiveSpeed + dfWalkBase) / classicToUnitySpeedUnitRatio;
            return baseRunSpeed * (1.35f + (player.Skills.GetLiveSkillValue(DFCareer.Skills.Running) / 200f));
        }