Skip to content

Commit

Permalink
feat: Introduce color-coded stam bar
Browse files Browse the repository at this point in the history
Cancel stam regen if sprint detoggled above threshold

Fix bug with directional input at stam threshold that caused character to stutter step

Update README
  • Loading branch information
afilbert committed Dec 27, 2023
1 parent a71ad12 commit 3d9ec08
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 17 deletions.
Binary file added Libs/Unity.TextMeshPro.dll
Binary file not shown.
Binary file added Libs/UnityEngine.UI.dll
Binary file not shown.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,15 @@ v0.0.3 introduced the ability to equip/switch weapons during auto-run while spri
Configuration allows:

* **Enable**, Enable the mod, default: true
* **OverrideGameAutorun**, This overrides the new auto-run config setting that functions as a sprint toggle, default: true
* **SprintToggle**, Sprint works like a toggle, default: true
* **SprintToggleAlternate**, Sprint is toggled through use of another key/button, default: false
* **SprintToggleAlternateKey**, Used in conjunction with SprintToggleAlternate. This is the key used to toggle sprint on/off, default: T
* **AutorunToggle**, Fixes auto-run to follow look, default: true
* **AutorunFreelookKey**, Overrides look direction in auto-run while pressed, default: CapsLock
* **AutorunStrafe**, Enable strafing while in auto-run/crouch, default: true
* **AutorunStrafeForwardDisables**, Disable autorun if Forward key/button pressed while AutorunStrafe enabled, default: true
* **AutorunInMap**, Keep running while viewing map, default: true
* **ReequipWeaponAfterSwimming**, Any weapon stowed in order to swim will reequip once out of swimming state, default: true
* **RunToCrouchToggle**, Go from run to crouch with the click of a button, default: true
* **StopSneakOnNoStam**, Stops sneak movement if no stamina available, default: true
Expand All @@ -91,6 +93,7 @@ Configuration allows:
* **SprintHealthOverridePercentValue**, Percentage of health to detoggle sprint so stamina can start to recover, default: 30%
* **TrackElapsedZeroStamToggle**, Automatically toggle off sprint after elapsed time spent at zero stamina, default: true
* **TrackElapsedZeroStamTime**, Seconds to wait at zero stamina before toggling off sprint, default: 5 seconds
* **ChangeStamColorOnSprint**, Changes stamina bar color to orange when draining and sprint enabled, and blue when stam regenerating. Flashes empty bar if stam drained fully while sprinting, default: true

Built with [BepInEx](https://valheim.thunderstore.io/package/denikson/BepInExPack_Valheim/)

Expand All @@ -100,6 +103,13 @@ Built with [BepInEx](https://valheim.thunderstore.io/package/denikson/BepInExPac

Releases in github repo are packaged for Thunderstore Mod Manager.

* 1.0.0 Major version release adds color-coded stamina bar
* Stamina bar will be orange when sprint toggled, else it will appear blue when regenerating, else it will be its normal yellow
* Stamina bar will repeatedly flash while empty if sprint toggled and regen is overridden by directional input
* Detoggling sprint while stamina is regenerating will cause stam regen to cancel as well. Stam regen otherwise reenables below the threshold as expected. This comes in handy while fighting without Rested buff, or with debuffs like Cold and Wet
* Fixes bug that caused stam regen loop when holding directional keys while regenerating at stam regen threshold. The bug caused the character to stutter step
* 0.1.4 Add config to override in-game auto-run toggle setting. This allows mod settings and behavior (like sneak to run) to work again
* Adds new config that allows character to keep auto-running while in map
* 0.1.3 Fix nil bomb caused by patch 0.217.38. Fixes broken menu translations when loading the game
* Drop requirement for [Official BepInEx ConfigurationManager](https://valheim.thunderstore.io/package/Azumatt/Official_BepInEx_ConfigurationManager/) from Thunderstore manifest.json to allow flexibility
* 0.1.2 Fix bug that disabled vanilla autorun when AutorunToggle was disabled in config
Expand Down
74 changes: 57 additions & 17 deletions ToggleMovementMod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;
using TMPro;

namespace ValheimMovementMods
{
Expand All @@ -15,7 +17,7 @@ public class ToggleMovementMod : BaseUnityPlugin
{
const string pluginGUID = "afilbert.ValheimToggleMovementMod";
const string pluginName = "Valheim - Toggle Movement Mod";
const string pluginVersion = "0.1.3";
const string pluginVersion = "1.0.0";
public static ManualLogSource logger;

private readonly Harmony _harmony = new Harmony(pluginGUID);
Expand All @@ -40,6 +42,9 @@ public class ToggleMovementMod : BaseUnityPlugin
public static ConfigEntry<float> SprintHealthOverride;
public static ConfigEntry<bool> TrackElapsedZeroStamToggle;
public static ConfigEntry<float> TrackElapsedZeroStamTime;
public static ConfigEntry<bool> OverrideAutoRunSetting;
public static ConfigEntry<bool> AllowAutoRunWhileInMap;
public static ConfigEntry<bool> VisuallyIndicateSprintState;

public static bool StaminaRefilling = false, SprintSet = false, AutorunSet = false;
public static bool RunToCrouch = false, Crouching = false;
Expand All @@ -53,13 +58,15 @@ void Awake()
_plugin = this;
logger = Logger;
EnableToggle = Config.Bind<bool>("Mod Config", "Enable", true, "Enable this mod");
OverrideAutoRunSetting = Config.Bind<bool>("Mod Config", "OverrideGameAutorun", true, "This overrides the new auto-run config setting that functions as a sprint toggle");
SprintToggle = Config.Bind<bool>("Sprint", "SprintToggle", true, "Sprint works like a toggle when true");
SprintToggleAlternate = Config.Bind<bool>("SprintAlternate", "SprintToggleAlternate", false, "Sprint is toggled through use of another key/button");
SprintToggleAlternateKey = Config.Bind<string>("SprintAlternate", "SprintToggleAlternateKey", "T", "Used in conjunction with SprintToggleAlternate. This is the key used to toggle sprint on/off");
AutorunOverride = Config.Bind<bool>("Auto-run", "AutorunToggle", true, "Fixes auto-run to follow look direction");
AutorunFreelookKey = Config.Bind<string>("Auto-run", "AutorunFreelookKey", "CapsLock", "Overrides look direction in auto-run while pressed");
AutorunStrafe = Config.Bind<bool>("Auto-run", "AutorunStrafe", true, "Enable strafing while in auto-run/crouch");
AutorunStrafeForwardDisables = Config.Bind<bool>("Auto-run", "AutorunStrafeForwardDisables", false, "Disable autorun if Forward key/button pressed while AutorunStrafe enabled");
AllowAutoRunWhileInMap = Config.Bind<bool>("Auto-run", "AutorunInMap", true, "Keep running while viewing map");
ReequipWeaponAfterSwimming = Config.Bind<bool>("Swim", "ReequipWeaponAfterSwimming", true, "Any weapon stowed in order to swim will reequip once out of swimming state");
RunToCrouchToggle = Config.Bind<bool>("Auto-sneak", "RunToCrouchToggle", true, "Allows going from full run to crouch with a click of the crouch button (and vice versa)");
StopSneakMovementToggle = Config.Bind<bool>("Auto-sneak", "StopSneakOnNoStam", true, "Stops sneak movement if no stamina available. Stock behavior is to pop out of sneak into walk");
Expand All @@ -71,22 +78,22 @@ void Awake()
SprintHealthThreshold = SprintHealthOverride.Value / 100f;
TrackElapsedZeroStamToggle = Config.Bind<bool>("Stamina", "TrackElapsedZeroStamToggle", true, "Automatically toggle off sprint after elapsed time spent at zero stamina");
TrackElapsedZeroStamTime = Config.Bind<float>("Stamina", "TrackElapsedZeroStamTime", 5f, "Seconds to wait at zero stamina before toggling off sprint");
VisuallyIndicateSprintState = Config.Bind<bool>("Stamina", "ChangeStamColorOnSprint", true, "Changes stamina bar color to orange when draining and sprint enabled, and blue when stam regenerating. Flashes empty bar if stam drained fully while sprinting");

_harmony.PatchAll();
}

[HarmonyPatch(typeof(Player), "SetControls")]
private class ToggleMovement
{
private static void Prefix(ref Player __instance, ref Vector3 movedir, ref bool run, ref bool autoRun, ref bool crouch, ref Vector3 ___m_lookDir, ref Vector3 ___m_moveDir, ref bool ___m_autoRun, ref bool ___m_crouchToggled, ref string ___m_actionAnimation, ref List<Player.MinorActionData> ___m_actionQueue)
private static void Prefix(ref Player __instance, ref Vector3 movedir, ref bool run, ref bool crouch, ref Vector3 ___m_lookDir, ref Vector3 ___m_moveDir, ref bool ___m_autoRun, ref bool ___m_crouchToggled, ref string ___m_actionAnimation, ref List<Player.MinorActionData> ___m_actionQueue)
{
if (!EnableToggle.Value)
{
return;
}
if (!__instance || _plugin.IsInMenu())
{
autoRun = false;
___m_autoRun = false;
AutorunSet = false;
return;
Expand All @@ -95,6 +102,15 @@ private static void Prefix(ref Player __instance, ref Vector3 movedir, ref bool
{
Started = true;
}
if (!SprintSet)
{
StaminaRefilling = false;
}

if (OverrideAutoRunSetting.Value)
{
run = ZInput.GetButton("Run") || ZInput.GetButton("JoyRun");
}

bool forwardDown = ZInput.GetButton("Forward") || ZInput.GetButton("JoyForward");
bool backwardDown = ZInput.GetButton("Backward") || ZInput.GetButton("JoyBackward");
Expand Down Expand Up @@ -129,8 +145,7 @@ private static void Prefix(ref Player __instance, ref Vector3 movedir, ref bool

bool isWeaponLoaded = true;
if (AutorunOverride.Value)
{
autoRun = false;
{
___m_autoRun = false;
}

Expand Down Expand Up @@ -176,7 +191,7 @@ private static void Prefix(ref Player __instance, ref Vector3 movedir, ref bool
___m_moveDir.Normalize();
}
}
if (__instance.GetStaminaPercentage() < StamRefillThreshold)
if (__instance.GetStaminaPercentage() < StamRefillThreshold && !directionalDown)
{
StaminaRefilling = true;
}
Expand All @@ -191,7 +206,6 @@ private static void Prefix(ref Player __instance, ref Vector3 movedir, ref bool
crouch = false;
if (StaminaRefilling && AutorunSet && StopSneakMovementToggle.Value)
{
autoRun = false;
___m_autoRun = false;
}
}
Expand All @@ -207,16 +221,16 @@ private static void Prefix(ref Player __instance, ref Vector3 movedir, ref bool
crouch = false;
}
}
if (SprintSet && __instance.GetStaminaPercentage() == 0)
{
ElapsedTimeAtZeroStam += Time.deltaTime;
}
else
{
ElapsedTimeAtZeroStam = 0f;
}
if (TrackElapsedZeroStamToggle.Value)
{
if (SprintSet && __instance.GetStaminaPercentage() == 0)
{
ElapsedTimeAtZeroStam += Time.deltaTime;
}
else
{
ElapsedTimeAtZeroStam = 0f;
}
if (SprintSet && ElapsedTimeAtZeroStam > TrackElapsedZeroStamTime.Value)
{
SprintSet = false;
Expand Down Expand Up @@ -248,14 +262,39 @@ private static void Postfix()
}
}

[HarmonyPatch(typeof(Hud), "UpdateStamina")]
private class Hud_UpdateStamina
{
private static void Postfix(Hud __instance, ref Player player, ref TMP_Text ___m_staminaText, ref RectTransform ___m_staminaBar2Root, ref GuiBar ___m_staminaBar2Slow, ref GuiBar ___m_staminaBar2Fast)
{
if (EnableToggle.Value && VisuallyIndicateSprintState.Value && SprintToggle.Value && SprintSet)
{
___m_staminaBar2Fast.SetColor(new Color(1.0f, 0.64f, 0.0f));

if (StaminaRefilling)
{
___m_staminaBar2Fast.SetColor(Color.blue);
}
if (ElapsedTimeAtZeroStam > 1)
{
__instance.StaminaBarEmptyFlash();
}
}
else
{
___m_staminaBar2Fast.SetColor(Color.yellow);
}
}
}

private void OnDestroy()
{
_harmony.UnpatchSelf();
}

private bool IsInMenu()
{
return ZInput.GetButtonDown("Esc") || ZInput.GetButtonDown("JoyMenu") || InventoryGui.IsVisible() || Minimap.IsOpen() || Console.IsVisible() || TextInput.IsVisible() || ZNet.instance.InPasswordDialog() || StoreGui.IsVisible() || Hud.IsPieceSelectionVisible() || UnifiedPopup.IsVisible();
return ZInput.GetButtonDown("Esc") || ZInput.GetButtonDown("JoyMenu") || InventoryGui.IsVisible() || (!AllowAutoRunWhileInMap.Value && Minimap.IsOpen()) || Console.IsVisible() || TextInput.IsVisible() || ZNet.instance.InPasswordDialog() || StoreGui.IsVisible() || Hud.IsPieceSelectionVisible() || UnifiedPopup.IsVisible();
}

private void Update()
Expand All @@ -271,6 +310,7 @@ private void Update()
{
run = ZInput.GetButtonUp("Run") || ZInput.GetButtonUp("JoyRun");
}

bool crouch = ZInput.GetButtonDown("Crouch") || ZInput.GetButtonDown("JoyCrouch");
bool autoRun = ZInput.GetButtonDown("AutoRun");

Expand All @@ -280,7 +320,7 @@ private void Update()
{
AutorunSet = false;
}
if(!RunToCrouchToggle.Value)
if (!RunToCrouchToggle.Value)
{
RunToCrouch = false;
}
Expand Down
6 changes: 6 additions & 0 deletions ToggleMovementMod.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@
<Reference Include="Unity.InputSystem">
<HintPath>Libs\Unity.InputSystem.dll</HintPath>
</Reference>
<Reference Include="Unity.TextMeshPro">
<HintPath>Libs\Unity.TextMeshPro.dll</HintPath>
</Reference>
<Reference Include="UnityEngine, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>Libs\UnityEngine.dll</HintPath>
Expand All @@ -71,6 +74,9 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>Libs\UnityEngine.CoreModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.UI">
<HintPath>Libs\UnityEngine.UI.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="ToggleMovementMod.cs" />
Expand Down

0 comments on commit 3d9ec08

Please sign in to comment.