Auto reload presses the reload key so the game plays its reload animation

This commit is contained in:
Justin Oros
2026-09-20 23:24:34 -07:00
parent 9f67baf307
commit 6defa601d5
3 changed files with 77 additions and 42 deletions
+71 -36
View File
@@ -39,6 +39,7 @@ public class FullAuto : SonsMod
internal static bool FastReload; internal static bool FastReload;
internal static bool AutoReload; internal static bool AutoReload;
internal static KeyCode FlashlightKey = KeyCode.F; internal static KeyCode FlashlightKey = KeyCode.F;
internal static string ReloadKey = "r";
internal static bool Verbose; internal static bool Verbose;
private static string _configPath; private static string _configPath;
@@ -60,6 +61,7 @@ public class FullAuto : SonsMod
private void OnUpdate() private void OnUpdate()
{ {
CheckFireInputPatch.UpdateTrigger(); CheckFireInputPatch.UpdateTrigger();
CheckFireInputPatch.UpdateReloadKey();
if (!CheckFireInputPatch.HoldingGun) if (!CheckFireInputPatch.HoldingGun)
CheckFireInputPatch.RestoreReloadSpeed(); CheckFireInputPatch.RestoreReloadSpeed();
@@ -205,6 +207,8 @@ public class FullAuto : SonsMod
FastReload = fast; FastReload = fast;
else if (key == "autoreload" && bool.TryParse(val, out var auto)) else if (key == "autoreload" && bool.TryParse(val, out var auto))
AutoReload = auto; AutoReload = auto;
else if (key == "reloadkey" && val.Length > 0)
ReloadKey = val.ToLowerInvariant();
else if (key == "flashlightkey" && Enum.TryParse<KeyCode>(val, true, out var flashKey)) else if (key == "flashlightkey" && Enum.TryParse<KeyCode>(val, true, out var flashKey))
FlashlightKey = flashKey; FlashlightKey = flashKey;
else if (key.StartsWith("mode.") && Enum.TryParse<FireMode>(val, true, out var gunMode)) else if (key.StartsWith("mode.") && Enum.TryParse<FireMode>(val, true, out var gunMode))
@@ -226,6 +230,7 @@ public class FullAuto : SonsMod
sb.Append($"fastreload={FastReload.ToString().ToLowerInvariant()}\n"); sb.Append($"fastreload={FastReload.ToString().ToLowerInvariant()}\n");
sb.Append($"autoreload={AutoReload.ToString().ToLowerInvariant()}\n"); sb.Append($"autoreload={AutoReload.ToString().ToLowerInvariant()}\n");
sb.Append($"flashlightkey={FlashlightKey}\n"); sb.Append($"flashlightkey={FlashlightKey}\n");
sb.Append($"reloadkey={ReloadKey}\n");
foreach (var gun in CheckFireInputPatch.GunKeys) foreach (var gun in CheckFireInputPatch.GunKeys)
{ {
var mode = Modes.TryGetValue(gun, out var m) ? m : FireMode.Auto; var mode = Modes.TryGetValue(gun, out var m) ? m : FireMode.Auto;
@@ -247,8 +252,6 @@ internal static class CheckFireInputPatch
private const int BurstSize = 3; private const int BurstSize = 3;
private const float ReleaseTime = 0.15f; private const float ReleaseTime = 0.15f;
private const float AutoReloadDelay = 0.2f; private const float AutoReloadDelay = 0.2f;
private const float AutoReloadNextDelay = 0.05f;
private const float AutoReloadRoundTime = 0.9f;
private static readonly Dictionary<string, string> Guns = new() private static readonly Dictionary<string, string> Guns = new()
{ {
@@ -285,10 +288,11 @@ internal static class CheckFireInputPatch
private static readonly List<Light> Lights = new(); private static readonly List<Light> Lights = new();
private static float _emptySince = -1f; private static float _emptySince = -1f;
private static float _nextReloadTry; private static float _nextReloadTry;
private static bool _autoReloading; private static UnityEngine.InputSystem.Controls.KeyControl _reloadControl;
private static IntPtr _autoReloadGun = IntPtr.Zero; private static string _reloadControlKey;
private static float _lastReloadCall = -10f; private static UnityEngine.InputSystem.Controls.KeyControl _pressedKey;
private static bool _sawReloading; private static int _releaseFrame = -1;
private static bool _keySimFailed;
private static bool _loggedHook; private static bool _loggedHook;
internal static bool HoldingGun => _lastGunTime >= 0f && Time.time - _lastGunTime < 0.25f; internal static bool HoldingGun => _lastGunTime >= 0f && Time.time - _lastGunTime < 0.25f;
@@ -356,13 +360,11 @@ internal static class CheckFireInputPatch
if (!FullAuto.AutoReload || !InGame) if (!FullAuto.AutoReload || !InGame)
{ {
_emptySince = -1f; _emptySince = -1f;
_autoReloading = false;
return; return;
} }
if (controller._isReloading || controller.IsReloading() || controller.IsReloadQueued()) if (controller._isReloading || controller.IsReloading() || controller.IsReloadQueued())
{ {
_sawReloading = true;
_emptySince = -1f; _emptySince = -1f;
return; return;
} }
@@ -372,20 +374,7 @@ internal static class CheckFireInputPatch
return; return;
var ammo = weapon.GetAmmo(); var ammo = weapon.GetAmmo();
if (ammo == null) if (ammo == null || !ammo.IsEmpty() || FirePressed())
return;
if (_autoReloading && (_autoReloadGun != controller.Pointer || ammo.IsFull()))
_autoReloading = false;
if (FirePressed())
{
_autoReloading = false;
_emptySince = -1f;
return;
}
if (!ammo.IsEmpty() && !_autoReloading)
{ {
_emptySince = -1f; _emptySince = -1f;
return; return;
@@ -398,30 +387,76 @@ internal static class CheckFireInputPatch
return; return;
} }
var wait = _autoReloading ? AutoReloadNextDelay : AutoReloadDelay; if (now - _emptySince < AutoReloadDelay || now < _nextReloadTry)
if (now - _emptySince < wait || now < _nextReloadTry)
return; return;
var roundTime = FullAuto.FastReload ? AutoReloadRoundTime / FullAuto.ReloadMultiplier : AutoReloadRoundTime; _nextReloadTry = now + 2f;
if (_autoReloading && !_sawReloading && now - _lastReloadCall < roundTime)
return;
_nextReloadTry = now + 0.3f;
if (!controller.CanReload()) if (!controller.CanReload())
return;
if (PressReloadKey())
{ {
_autoReloading = false; if (FullAuto.Verbose)
RLog.Msg($"FullAuto auto reload pressed {FullAuto.ReloadKey} on {controller.GetIl2CppType().Name}");
return; return;
} }
controller.Reload(); controller._reloadQueued = true;
_autoReloading = true;
_autoReloadGun = controller.Pointer;
_lastReloadCall = now;
_sawReloading = false;
if (FullAuto.Verbose) if (FullAuto.Verbose)
RLog.Msg($"FullAuto auto reload {controller.GetIl2CppType().Name}, ammo {ammo.GetRemainingAmmo()}/{ammo.GetCapacity()}"); RLog.Msg($"FullAuto auto reload queued on {controller.GetIl2CppType().Name}");
}
private static bool PressReloadKey()
{
if (_keySimFailed || _pressedKey != null)
return false;
try
{
if (_reloadControl == null || _reloadControlKey != FullAuto.ReloadKey)
{
_reloadControlKey = FullAuto.ReloadKey;
var control = UnityEngine.InputSystem.InputSystem.FindControl($"<Keyboard>/{FullAuto.ReloadKey}");
_reloadControl = control?.TryCast<UnityEngine.InputSystem.Controls.KeyControl>();
}
if (_reloadControl == null)
{
_keySimFailed = true;
RLog.Warning($"FullAuto could not find reload key {FullAuto.ReloadKey}");
return false;
}
UnityEngine.InputSystem.InputControlExtensions.QueueValueChange<float>(_reloadControl, 1f, -1d);
_pressedKey = _reloadControl;
_releaseFrame = Time.frameCount + 3;
return true;
}
catch (Exception e)
{
_keySimFailed = true;
RLog.Warning($"FullAuto could not press reload key: {e.Message}");
return false;
}
}
internal static void UpdateReloadKey()
{
if (_pressedKey == null || Time.frameCount < _releaseFrame)
return;
try
{
UnityEngine.InputSystem.InputControlExtensions.QueueValueChange<float>(_pressedKey, 0f, -1d);
}
catch (Exception e)
{
RLog.Warning($"FullAuto could not release reload key: {e.Message}");
}
_pressedKey = null;
} }
internal static void CancelBurst() internal static void CancelBurst()
+3 -3
View File
@@ -79,13 +79,13 @@ Press F1 to open the console, then use these commands:
| `fullauto off` | Disable until the game restarts | | `fullauto off` | Disable until the game restarts |
| `fullauto rpm 1200` | Set the fire rate, 60 to 3000 rounds per minute | | `fullauto rpm 1200` | Set the fire rate, 60 to 3000 rounds per minute |
| `fullauto fastreload on` | Reload guns twice as fast, `off` to turn it back off | | `fullauto fastreload on` | Reload guns twice as fast, `off` to turn it back off |
| `fullauto autoreload on` | Reload automatically when the gun is empty, `off` to turn it back off | | `fullauto autoreload on` | Reload automatically when the gun is empty, `off` to turn it back off. It presses your reload key for you, so if you changed it from R in the game settings, set `reloadkey=` in `FullAuto.txt` to match |
| `fullauto debug` | Log every shot to `_RedLoader\Latest.log` | | `fullauto debug` | Log every shot to `_RedLoader\Latest.log` |
The default is 900 rpm. The rpm also sets how fast burst shots fire. The default is 900 rpm. The rpm also sets how fast burst shots fire.
The rpm, fast reload, auto reload, flashlight key and each gun's fire mode are The rpm, fast reload, auto reload, flashlight key, reload key and each gun's fire
saved to mode are saved to
`UserData\FullAuto.txt` in your game folder. `UserData\FullAuto.txt` in your game folder.
## Supported weapons ## Supported weapons
+1 -1
View File
@@ -3,7 +3,7 @@
"id": "FullAuto", "id": "FullAuto",
"name": "FullAuto", "name": "FullAuto",
"author": "JustinOros", "author": "JustinOros",
"version": "1.5.3", "version": "1.5.4",
"description": "Full-auto, semi-auto and 3-round burst for guns, with fast reload and a flashlight toggle", "description": "Full-auto, semi-auto and 3-round burst for guns, with fast reload and a flashlight toggle",
"gameVersion": "1.0.0", "gameVersion": "1.0.0",
"platform": "Client", "platform": "Client",