using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using EWC.API;
using EWC.CustomWeapon;
using FireRateFPSFix.Dependencies;
using FireRateFPSFix.FireState;
using GTFO.API;
using Gear;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using Microsoft.CodeAnalysis;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("FireRateFPSFix")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+812ef155cdf91c26ab928dabc22270514d5e446e")]
[assembly: AssemblyProduct("FireRateFPSFix")]
[assembly: AssemblyTitle("FireRateFPSFix")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
}
namespace FireRateFPSFix
{
internal static class DinoLogger
{
private static ManualLogSource logger = Logger.CreateLogSource("FireRateFPSFix");
public static void Log(string format, params object[] args)
{
Log(string.Format(format, args));
}
public static void Log(string str)
{
if (logger != null)
{
logger.Log((LogLevel)8, (object)str);
}
}
public static void Warning(string format, params object[] args)
{
Warning(string.Format(format, args));
}
public static void Warning(string str)
{
if (logger != null)
{
logger.Log((LogLevel)4, (object)str);
}
}
public static void Error(string format, params object[] args)
{
Error(string.Format(format, args));
}
public static void Error(string str)
{
if (logger != null)
{
logger.Log((LogLevel)2, (object)str);
}
}
public static void Debug(string format, params object[] args)
{
Debug(string.Format(format, args));
}
public static void Debug(string str)
{
if (logger != null)
{
logger.Log((LogLevel)32, (object)str);
}
}
}
[BepInPlugin("Dinorush.FireRateFPSFix", "FireRateFPSFix", "1.0.8")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
internal sealed class EntryPoint : BasePlugin
{
public const string MODNAME = "FireRateFPSFix";
public override void Load()
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
new Harmony("FireRateFPSFix").PatchAll();
LevelAPI.OnEnterLevel += LevelAPI_OnEnterLevel;
((BasePlugin)this).Log.LogMessage((object)"Loaded FireRateFPSFix");
}
private void LevelAPI_OnEnterLevel()
{
FireStateManager.Cleanup();
}
}
}
namespace FireRateFPSFix.Patches
{
[HarmonyPatch]
internal static class WeaponFirePatch
{
[HarmonyPatch(typeof(BulletWeaponArchetype), "PostFireCheck")]
[HarmonyWrapSafe]
[HarmonyPrefix]
private static void PrePostFireCallback(BulletWeaponArchetype __instance)
{
FireStateUpdater updater = FireStateManager.GetUpdater(__instance.m_weapon);
if (__instance.m_firing)
{
updater.UpdateFired();
}
}
[HarmonyPatch(typeof(BulletWeaponArchetype), "PostFireCheck")]
[HarmonyWrapSafe]
[HarmonyPostfix]
[HarmonyAfter(new string[] { "Dinorush.ExtraWeaponCustomization" })]
private static void PostFireCallback_AfterEWC(BulletWeaponArchetype __instance)
{
FireStateManager.GetUpdater(__instance.m_weapon).OnPostFireCheck();
}
[HarmonyPatch(typeof(BWA_Auto), "OnStopFiring")]
[HarmonyWrapSafe]
[HarmonyPostfix]
private static void PostStopFiringCallback(BulletWeaponArchetype __instance)
{
FireStateManager.GetUpdater(__instance.m_weapon).OnStopFiring();
}
}
}
namespace FireRateFPSFix.FireState
{
public static class FireStateManager
{
private static readonly Dictionary<IntPtr, FireStateUpdater> _updaters = new Dictionary<IntPtr, FireStateUpdater>();
public static FireStateUpdater GetUpdater(BulletWeapon weapon)
{
if (_updaters.TryGetValue(((Il2CppObjectBase)weapon).Pointer, out FireStateUpdater value))
{
return value;
}
return _updaters[((Il2CppObjectBase)weapon).Pointer] = new FireStateUpdater(weapon);
}
public static void Cleanup()
{
KeyValuePair<IntPtr, FireStateUpdater>[] array = _updaters.Where<KeyValuePair<IntPtr, FireStateUpdater>>((KeyValuePair<IntPtr, FireStateUpdater> kv) => !kv.Value.IsValid).ToList().ToArray();
foreach (KeyValuePair<IntPtr, FireStateUpdater> keyValuePair in array)
{
_updaters.Remove(keyValuePair.Key);
}
}
}
public sealed class FireStateUpdater
{
private readonly BulletWeapon _weapon;
private float _shotDelay;
private float _burstDelay;
private float _cooldownDelay;
private bool _hasCooldown;
private float _timeBuffer;
private float _lastFireTime;
private float _nextShotTimeBase;
private float _nextShotTime;
private bool _inCooldown = true;
public bool IsValid => (Object)(object)_weapon != (Object)null;
public FireStateUpdater(BulletWeapon weapon)
{
_weapon = weapon;
BulletWeaponArchetype archeType = _weapon.m_archeType;
if (!EWCWrapper.GetDelays(_weapon, out _shotDelay, out _burstDelay, out _cooldownDelay))
{
_shotDelay = archeType.ShotDelay();
_burstDelay = archeType.BurstDelay();
_cooldownDelay = archeType.CooldownDelay();
}
_hasCooldown = archeType.HasCooldown;
}
private void SetNextShotTime(float time)
{
_nextShotTimeBase = time;
_nextShotTime = Math.Max(time - _timeBuffer, Clock.Time);
}
private float GetCooldown(bool includeShotDelay = false)
{
float num = (_hasCooldown ? _cooldownDelay : _burstDelay);
if (includeShotDelay)
{
return Math.Max(_shotDelay, num);
}
return num;
}
public void EWCOnCooldownSet(float shotDelay, float burstDelay, float cooldownDelay)
{
_shotDelay = shotDelay;
_burstDelay = burstDelay;
_cooldownDelay = cooldownDelay;
_hasCooldown = _weapon.m_archeType.HasCooldown;
SetNextShotTime(Math.Max(Clock.Time, _lastFireTime + (_inCooldown ? _shotDelay : GetCooldown(includeShotDelay: true))));
}
public void UpdateFired()
{
float time = Clock.Time;
if (_nextShotTime + Clock.Delta >= time)
{
_timeBuffer += time - _nextShotTimeBase;
}
else
{
_timeBuffer = 0f;
}
_inCooldown = false;
_lastFireTime = time;
}
public void OnPostFireCheck()
{
BulletWeaponArchetype archeType = _weapon.m_archeType;
float time = Clock.Time;
if (archeType.m_firing)
{
SetNextShotTime(archeType.m_nextShotTimer);
archeType.m_nextShotTimer = _nextShotTime;
return;
}
_inCooldown = true;
SetNextShotTime(time + Math.Max(_shotDelay, GetCooldown()));
archeType.m_nextBurstTimer = Math.Max(time, time + GetCooldown() - _timeBuffer);
archeType.m_nextShotTimer = Math.Max(time, time + _shotDelay - _timeBuffer);
}
public void OnStopFiring()
{
_inCooldown = true;
SetNextShotTime(_lastFireTime + _shotDelay);
}
}
}
namespace FireRateFPSFix.Dependencies
{
internal static class EWCWrapper
{
[Serializable]
[CompilerGenerated]
private sealed class <>c
{
public static readonly <>c <>9 = new <>c();
public static CooldownSetCallback <>9__3_0;
internal void <AddFireRateChangeCallback>b__3_0(BulletWeapon weapon, float shotDelay, float burstDelay, float cooldownDelay)
{
FireStateManager.GetUpdater(weapon).EWCOnCooldownSet(shotDelay, burstDelay, cooldownDelay);
}
}
public const string PLUGIN_GUID = "Dinorush.ExtraWeaponCustomization";
public static readonly bool hasEWC;
static EWCWrapper()
{
hasEWC = ((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.ContainsKey("Dinorush.ExtraWeaponCustomization");
if (hasEWC)
{
AddFireRateChangeCallback();
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static void AddFireRateChangeCallback()
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Expected O, but got Unknown
object obj = <>c.<>9__3_0;
if (obj == null)
{
CooldownSetCallback val = delegate(BulletWeapon weapon, float shotDelay, float burstDelay, float cooldownDelay)
{
FireStateManager.GetUpdater(weapon).EWCOnCooldownSet(shotDelay, burstDelay, cooldownDelay);
};
<>c.<>9__3_0 = val;
obj = (object)val;
}
FireRateAPI.CooldownSet += (CooldownSetCallback)obj;
}
public static bool GetDelays(BulletWeapon weapon, out float shotDelay, out float burstDelay, out float cooldownDelay)
{
if (!hasEWC)
{
shotDelay = 0f;
burstDelay = 0f;
cooldownDelay = 0f;
return false;
}
return GetDelays_Internal(weapon, out shotDelay, out burstDelay, out cooldownDelay);
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static bool GetDelays_Internal(BulletWeapon weapon, out float shotDelay, out float burstDelay, out float cooldownDelay)
{
CustomWeaponComponent component = ((Component)weapon).GetComponent<CustomWeaponComponent>();
if ((Object)(object)component == (Object)null)
{
shotDelay = 0f;
burstDelay = 0f;
cooldownDelay = 0f;
return false;
}
shotDelay = 1f / component.CurrentFireRate;
burstDelay = component.CurrentBurstDelay;
cooldownDelay = component.CurrentCooldownDelay;
return true;
}
}
}