Cycle auto, semi, burst and fix burst firing

This commit is contained in:
Justin Oros
2026-09-15 19:11:10 -07:00
parent 6c9f57eae1
commit c35fed5fc7
2 changed files with 52 additions and 25 deletions
+48 -21
View File
@@ -46,18 +46,17 @@ public class FullAuto : SonsMod
private void OnUpdate() private void OnUpdate()
{ {
CheckFireInputPatch.UpdateTrigger();
if (!Enabled || !GameState.IsPlayerControllable || !CheckFireInputPatch.HoldingGun) if (!Enabled || !GameState.IsPlayerControllable || !CheckFireInputPatch.HoldingGun)
return; return;
if (Mode == FireMode.Burst && Input.GetMouseButtonDown(0))
CheckFireInputPatch.StartBurst();
if (Input.GetMouseButtonDown(2)) if (Input.GetMouseButtonDown(2))
{ {
Mode = Mode switch Mode = Mode switch
{ {
FireMode.Auto => FireMode.Burst, FireMode.Auto => FireMode.Semi,
FireMode.Burst => FireMode.Semi, FireMode.Semi => FireMode.Burst,
_ => FireMode.Auto _ => FireMode.Auto
}; };
CheckFireInputPatch.CancelBurst(); CheckFireInputPatch.CancelBurst();
@@ -122,9 +121,9 @@ public class FullAuto : SonsMod
{ {
return Mode switch return Mode switch
{ {
FireMode.Auto => "Full-Auto", FireMode.Auto => "Full-automatic",
FireMode.Burst => "3-Round Burst", FireMode.Burst => "3-Round Burst",
_ => "Semi-Automatic" _ => "Semi-automatic"
}; };
} }
@@ -179,6 +178,7 @@ internal static class CheckFireInputPatch
{ {
private const int MaxShotsPerFrame = 4; private const int MaxShotsPerFrame = 4;
private const int BurstSize = 3; private const int BurstSize = 3;
private const float ReleaseTime = 0.05f;
private static readonly HashSet<string> Guns = new() private static readonly HashSet<string> Guns = new()
{ {
@@ -189,10 +189,13 @@ internal static class CheckFireInputPatch
}; };
private static readonly Dictionary<IntPtr, bool> Allowed = new(); private static readonly Dictionary<IntPtr, bool> Allowed = new();
private static readonly Dictionary<IntPtr, float> FireDelays = new();
private static readonly HashSet<string> Reported = new(); private static readonly HashSet<string> Reported = new();
private static float _nextShot; private static float _nextShot;
private static int _burstLeft; private static int _burstLeft;
private static float _lastGunTime = -1f; private static float _lastGunTime = -1f;
private static bool _triggerDown;
private static float _releasedFor;
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;
@@ -202,7 +205,26 @@ internal static class CheckFireInputPatch
_burstLeft = 0; _burstLeft = 0;
} }
internal static void StartBurst() internal static void UpdateTrigger()
{
if (Input.GetMouseButton(0))
{
_releasedFor = 0f;
if (_triggerDown)
return;
_triggerDown = true;
if (FullAuto.Enabled && FullAuto.Mode == FireMode.Burst && HoldingGun && GameState.IsPlayerControllable)
StartBurst();
return;
}
_releasedFor += Time.unscaledDeltaTime;
if (_releasedFor >= ReleaseTime)
_triggerDown = false;
}
private static void StartBurst()
{ {
if (_burstLeft > 0) if (_burstLeft > 0)
return; return;
@@ -234,13 +256,24 @@ internal static class CheckFireInputPatch
if (FullAuto.Mode == FireMode.Semi) if (FullAuto.Mode == FireMode.Semi)
return true; return true;
var held = Input.GetMouseButton(0);
if (!GameState.IsPlayerControllable) if (!GameState.IsPlayerControllable)
{ {
CancelBurst(); CancelBurst();
return true; return !held;
} }
var held = Input.GetMouseButton(0); if (__instance._isReloading || __instance.IsReloading())
return Stop();
var weapon = __instance.GetRangedWeapon();
if (!weapon)
return Stop();
var ammo = weapon.GetAmmo();
if (ammo == null || ammo.GetRemainingAmmo() <= 0)
return Stop();
if (FullAuto.Mode == FireMode.Burst) if (FullAuto.Mode == FireMode.Burst)
{ {
@@ -252,20 +285,9 @@ internal static class CheckFireInputPatch
return true; return true;
} }
if (__instance._isReloading || __instance.IsReloading())
return Stop();
if (__instance._mustAimToFire && !__instance.IsAiming) if (__instance._mustAimToFire && !__instance.IsAiming)
return Stop(); return Stop();
var weapon = __instance.GetRangedWeapon();
if (!weapon)
return Stop();
var ammo = weapon.GetAmmo();
if (ammo == null || ammo.GetRemainingAmmo() <= 0)
return Stop();
var now = Time.time; var now = Time.time;
var interval = 60f / FullAuto.Rpm; var interval = 60f / FullAuto.Rpm;
@@ -287,6 +309,9 @@ internal static class CheckFireInputPatch
shots++; shots++;
} }
if (FireDelays.TryGetValue(__instance.Pointer, out var delay))
__instance._fireDelay = delay;
return false; return false;
} }
@@ -332,6 +357,8 @@ internal static class CheckFireInputPatch
var name = controller.GetIl2CppType().Name; var name = controller.GetIl2CppType().Name;
allowed = Guns.Contains(name); allowed = Guns.Contains(name);
Allowed[ptr] = allowed; Allowed[ptr] = allowed;
if (allowed)
FireDelays[ptr] = controller._fireDelay;
RLog.Msg($"FullAuto {name}: {(allowed ? "full-auto" : "ignored")}"); RLog.Msg($"FullAuto {name}: {(allowed ? "full-auto" : "ignored")}");
return allowed; return allowed;
} }
+4 -4
View File
@@ -47,11 +47,11 @@ With a gun equipped, click the middle mouse button to cycle fire modes:
| Mode | Behavior | | Mode | Behavior |
| --- | --- | | --- | --- |
| Full-auto | Fires while the button is held | | Full-automatic | Fires while the button is held |
| 3-round burst | Fires 3 shots per click | | Semi-automatic | Normal game behavior, one shot per click |
| Semi-auto | Normal game behavior, one shot per click | | 3-Round Burst | Fires 3 shots, then release and press again for the next 3 |
The mod starts in full-auto every time the game loads. The mod starts in full-automatic every time the game loads.
Press F1 to open the console, then use these commands: Press F1 to open the console, then use these commands: