Decompiled source of RemoveSlapCooldown v1.0.0

BepInEx/plugins/RemoveSlapCooldown/BombananaNoSlapCooldown.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using Bombanana;
using HarmonyLib;
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("BombananaNoSlapCooldown")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BombananaNoSlapCooldown")]
[assembly: AssemblyTitle("BombananaNoSlapCooldown")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BombananaNoSlapCooldown
{
	[BepInPlugin("codaaaaaa.bombanana.noslapcooldown", "Remove Slap Cooldown", "1.0.0")]
	public class Plugin : BasePlugin
	{
		public const string Guid = "codaaaaaa.bombanana.noslapcooldown";

		internal const float BypassStamp = -9999f;

		internal static ManualLogSource Logger;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<float> CooldownSeconds;

		internal static ConfigEntry<bool> Verbose;

		internal static ConfigEntry<float> WindupSpeedMultiplier;

		internal static ConfigEntry<bool> AlsoSpeedUpRecovery;

		internal static ConfigEntry<bool> RemoveImpactCooldown;

		internal const float MinPhase = 0.01f;

		internal static readonly Dictionary<int, float> LastAllowedSlap = new Dictionary<int, float>();

		private static readonly HashSet<string> LoggedKeys = new HashSet<string>();

		private static bool _loggedOriginal;

		private Harmony _harmony;

		private static float _vanillaWindup;

		private static float _vanillaTwist;

		private static float _vanillaForward;

		private static float _vanillaHold;

		private static float _vanillaReturn;

		public override void Load()
		{
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Expected O, but got Unknown
			Logger = ((BasePlugin)this).Log;
			Enabled = ((BasePlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master switch. False = vanilla slap cooldown.");
			CooldownSeconds = ((BasePlugin)this).Config.Bind<float>("General", "CooldownSeconds", 0f, "Seconds between slaps. 0 = no cooldown at all. Any value above 0 replaces the game's cooldown with your own.");
			Verbose = ((BasePlugin)this).Config.Bind<bool>("General", "Verbose", true, "Log the first time each gate is hit, so you can confirm all three are actually being bypassed. Set false once you are happy.");
			WindupSpeedMultiplier = ((BasePlugin)this).Config.Bind<float>("Windup", "WindupSpeedMultiplier", 4f, "How much faster the hand travels before the slap connects (windup + twist + forward). 1 = vanilla, 4 = four times faster, very high = practically instant. The hit registers when the hand reaches the target, so this is what removes the wind-up delay.");
			AlsoSpeedUpRecovery = ((BasePlugin)this).Config.Bind<bool>("Windup", "AlsoSpeedUpRecovery", true, "Apply the same multiplier to the post-impact phases (hold + return), so the hand snaps back too.");
			RemoveImpactCooldown = ((BasePlugin)this).Config.Bind<bool>("General", "RemoveImpactCooldown", true, "Also clear the victim-side throttle (PlayerThrowableImpactEffects.playerImpactCooldown), which otherwise swallows the reaction to rapid repeat slaps on the same player.");
			_harmony = new Harmony("codaaaaaa.bombanana.noslapcooldown");
			_harmony.PatchAll(typeof(Patch_SlapInteraction_LateUpdate));
			_harmony.PatchAll(typeof(Patch_SlapInteraction_Awake));
			_harmony.PatchAll(typeof(Patch_PlayerBase_RequestSlap));
			_harmony.PatchAll(typeof(Patch_PlayerBase_RequestSlapServerRpc));
			_harmony.PatchAll(typeof(Patch_ImpactEffects_HandleSlapImpact));
			Logger.LogInfo((object)("Patched. Enabled=" + Enabled.Value + ", CooldownSeconds=" + CooldownSeconds.Value));
			Logger.LogInfo((object)"Gate 3 (server) applies to every attacker once YOU host -- Harmony patches the method, not one instance.");
		}

		public override bool Unload()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			return ((BasePlugin)this).Unload();
		}

		internal static float TargetCooldown()
		{
			float value = CooldownSeconds.Value;
			if (!(value > 0f))
			{
				return 0f;
			}
			return value;
		}

		internal static void LogOnce(string key, string message)
		{
			if (Verbose.Value && LoggedKeys.Add(key))
			{
				Logger.LogInfo((object)message);
			}
		}

		private static float Scale(float duration, float multiplier)
		{
			if (multiplier <= 1f)
			{
				return duration;
			}
			float num = duration / multiplier;
			if (!(num < 0.01f))
			{
				return num;
			}
			return 0.01f;
		}

		internal static void ApplyTuning(PlayerSlapInteraction inst)
		{
			LogVanillaOnce(inst);
			float num = TargetCooldown();
			if (inst.slapCooldown != num)
			{
				LogOnce("gate1", "[gate 1/4] local input: slapCooldown pinned to " + num.ToString("0.###") + "s");
				inst.slapCooldown = num;
			}
			float value = WindupSpeedMultiplier.Value;
			if (!(value <= 1f))
			{
				inst.handWindupDuration = Scale(_vanillaWindup, value);
				inst.handTwistDuration = Scale(_vanillaTwist, value);
				inst.handForwardDuration = Scale(_vanillaForward, value);
				if (AlsoSpeedUpRecovery.Value)
				{
					inst.handHoldDuration = Scale(_vanillaHold, value);
					inst.handReturnDuration = Scale(_vanillaReturn, value);
				}
				LogOnce("windup", "[windup] pre-impact " + VanillaWindupTotal().ToString("0.###") + "s -> " + (Scale(_vanillaWindup, value) + Scale(_vanillaTwist, value) + Scale(_vanillaForward, value)).ToString("0.###") + "s (x" + value.ToString("0.##") + ")");
			}
		}

		internal static float VanillaWindupTotal()
		{
			return _vanillaWindup + _vanillaTwist + _vanillaForward;
		}

		private static void LogVanillaOnce(PlayerSlapInteraction inst)
		{
			if (!_loggedOriginal)
			{
				_loggedOriginal = true;
				_vanillaWindup = inst.handWindupDuration;
				_vanillaTwist = inst.handTwistDuration;
				_vanillaForward = inst.handForwardDuration;
				_vanillaHold = inst.handHoldDuration;
				_vanillaReturn = inst.handReturnDuration;
				Logger.LogInfo((object)("Vanilla slapCooldown=" + inst.slapCooldown.ToString("0.###") + "s  windup=" + _vanillaWindup.ToString("0.###") + "  twist=" + _vanillaTwist.ToString("0.###") + "  forward=" + _vanillaForward.ToString("0.###") + "  (pre-impact total " + VanillaWindupTotal().ToString("0.###") + "s)  hold=" + _vanillaHold.ToString("0.###") + "  return=" + _vanillaReturn.ToString("0.###")));
			}
		}
	}
	[HarmonyPatch(typeof(PlayerSlapInteraction), "LateUpdate")]
	internal static class Patch_SlapInteraction_LateUpdate
	{
		private static void Postfix(PlayerSlapInteraction __instance)
		{
			if (Plugin.Enabled.Value)
			{
				Plugin.ApplyTuning(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(PlayerSlapInteraction), "Awake")]
	internal static class Patch_SlapInteraction_Awake
	{
		private static void Postfix(PlayerSlapInteraction __instance)
		{
			if (Plugin.Enabled.Value)
			{
				Plugin.ApplyTuning(__instance);
				__instance.lastLocalSlapTime = -9999f;
			}
		}
	}
	[HarmonyPatch(typeof(PlayerBase), "RequestSlap")]
	internal static class Patch_PlayerBase_RequestSlap
	{
		private static bool Prefix(PlayerBase __instance)
		{
			if (!Plugin.Enabled.Value)
			{
				return true;
			}
			float value = Plugin.CooldownSeconds.Value;
			if (value > 0f)
			{
				int instanceID = ((Object)__instance).GetInstanceID();
				if (Plugin.LastAllowedSlap.TryGetValue(instanceID, out var value2) && Time.time - value2 < value)
				{
					return false;
				}
				Plugin.LastAllowedSlap[instanceID] = Time.time;
			}
			Plugin.LogOnce("gate2", "[gate 2/4] client: RequestSlap intercepted, lastClientSlapTime rewound");
			__instance.lastClientSlapTime = -9999f;
			__instance.lastServerSlapTime = -9999f;
			return true;
		}
	}
	[HarmonyPatch(typeof(PlayerThrowableImpactEffects), "HandleSlapImpact")]
	internal static class Patch_ImpactEffects_HandleSlapImpact
	{
		private static void Prefix(PlayerThrowableImpactEffects __instance)
		{
			if (Plugin.Enabled.Value && Plugin.RemoveImpactCooldown.Value)
			{
				Plugin.LogOnce("gate4", "[gate 4/4] impact: HandleSlapImpact reached us, lastPlayerImpactTime rewound");
				__instance.lastPlayerImpactTime = -9999f;
			}
		}
	}
	[HarmonyPatch(typeof(PlayerBase), "RequestSlapServerRpc")]
	internal static class Patch_PlayerBase_RequestSlapServerRpc
	{
		private static void Prefix(PlayerBase __instance)
		{
			if (Plugin.Enabled.Value)
			{
				Plugin.LogOnce("gate3", "[gate 3/4] server: RequestSlapServerRpc reached us -- we are host for this slap, lastServerSlapTime rewound");
				__instance.lastServerSlapTime = -9999f;
			}
		}
	}
}