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;
}
}
}
}