using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using HarmonyLib;
using PluginConfig.API;
using PluginConfig.API.Fields;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("KnucklBlasterParry")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("KnucklBlasterParry")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("0047c3d5-622e-4056-975b-9789adcc5271")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
[BepInPlugin("KnuckleblasterParry", "Knuckleblaster Parry", "1.0.1")]
public class Plugin : BaseUnityPlugin
{
public static Plugin Instance;
private Harmony harmony;
public static BoolField EnableParry;
private static FieldInfo ccField;
private static FieldInfo camObjField;
private static FieldInfo ppzField;
private static FieldInfo boostedProjectileField;
private static FieldInfo hitCoinField;
private static FieldInfo enemyIdentifierField;
private static FieldInfo currentPunchField;
private static FieldInfo animatorField;
private static MethodInfo tryParryProjectileMethod;
private static MethodInfo parryProjectileMethod;
private static MethodInfo delayedPunchflectionMethod;
private void Awake()
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Expected O, but got Unknown
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Expected O, but got Unknown
Instance = this;
harmony = new Harmony("knuckleblasterparry");
PluginConfigurator val = PluginConfigurator.Create("Knuckleblaster Parry", "KnuckleblasterParryDfcfg");
string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
string iconWithURL = "file:///" + Path.Combine(directoryName, "icon.png").Replace("\\", "/");
val.SetIconWithURL(iconWithURL);
EnableParry = new BoolField(val.rootPanel, "Enable Parry", "Enable_parry", true);
CacheMembers();
harmony.PatchAll();
((BaseUnityPlugin)this).Logger.LogInfo((object)"Knuckleblaster Parry loaded");
}
private void CacheMembers()
{
ccField = AccessTools.Field(typeof(Punch), "cc");
camObjField = AccessTools.Field(typeof(Punch), "camObj");
ppzField = AccessTools.Field(typeof(Punch), "ppz");
boostedProjectileField = AccessTools.Field(typeof(Punch), "alreadyBoostedProjectile");
hitCoinField = AccessTools.Field(typeof(Punch), "alreadyHitCoin");
enemyIdentifierField = AccessTools.Field(typeof(Enemy), "eid");
currentPunchField = AccessTools.Field(typeof(FistControl), "currentPunch");
animatorField = AccessTools.Field(typeof(Punch), "anim");
tryParryProjectileMethod = AccessTools.Method(typeof(Punch), "TryParryProjectile", (Type[])null, (Type[])null);
parryProjectileMethod = AccessTools.Method(typeof(Punch), "ParryProjectile", (Type[])null, (Type[])null);
delayedPunchflectionMethod = AccessTools.Method(typeof(Coin), "DelayedPunchflection", (Type[])null, (Type[])null);
}
public static CameraController GetCameraController(Punch punch)
{
object? value = ccField.GetValue(punch);
return (CameraController)((value is CameraController) ? value : null);
}
public static GameObject GetCameraObject(Punch punch)
{
object? value = camObjField.GetValue(punch);
return (GameObject)((value is GameObject) ? value : null);
}
public static bool TryParry(Punch punch, Transform target, bool firstFrame)
{
if (IsChainsawTarget(target))
{
return false;
}
if (IsParriedProjectileTarget(target))
{
return false;
}
return (bool)tryParryProjectileMethod.Invoke(punch, new object[2] { target, firstFrame });
}
public static void ParryProjectile(Punch punch, Projectile projectile)
{
parryProjectileMethod.Invoke(punch, new object[1] { projectile });
}
public static void PunchflectCoin(Coin coin)
{
delayedPunchflectionMethod.Invoke(coin, null);
}
public static void RestoreAnimation(Punch punch)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Invalid comparison between Unknown and I4
if (!((Object)(object)punch == (Object)null) && (int)punch.type == 1)
{
object? value = animatorField.GetValue(punch);
Animator val = (Animator)((value is Animator) ? value : null);
if (!((Object)(object)val == (Object)null))
{
val.ResetTrigger("Hook");
val.SetTrigger("Punch");
}
}
}
public static ProjectileParryZone GetParryZone(Punch punch)
{
object? value = ppzField.GetValue(punch);
ProjectileParryZone val = (ProjectileParryZone)((value is ProjectileParryZone) ? value : null);
if ((Object)(object)val != (Object)null)
{
return val;
}
val = ((Component)((Component)punch).transform.parent).GetComponentInChildren<ProjectileParryZone>();
ppzField.SetValue(punch, val);
return val;
}
public static bool CanBoostProjectile(Punch punch, bool firstFrame)
{
return !(bool)boostedProjectileField.GetValue(punch) && firstFrame;
}
public static bool AlreadyHitCoin(Punch punch)
{
return (bool)hitCoinField.GetValue(punch);
}
public static void SetCoinHit(Punch punch)
{
hitCoinField.SetValue(punch, true);
}
public static EnemyIdentifier GetEnemyIdentifier(Enemy enemy)
{
object? value = enemyIdentifierField.GetValue(enemy);
return (EnemyIdentifier)((value is EnemyIdentifier) ? value : null);
}
public static Punch GetCurrentPunch()
{
FistControl instance = MonoSingleton<FistControl>.Instance;
if ((Object)(object)instance == (Object)null)
{
return null;
}
object? value = currentPunchField.GetValue(instance);
return (Punch)((value is Punch) ? value : null);
}
public static bool IsChainsawTarget(Transform target)
{
if ((Object)(object)target == (Object)null)
{
return false;
}
Chainsaw val = default(Chainsaw);
if (((Component)target).TryGetComponent<Chainsaw>(ref val))
{
return true;
}
ParryHelper val2 = default(ParryHelper);
if (((Component)target).TryGetComponent<ParryHelper>(ref val2) && (Object)(object)val2.target != (Object)null && ((Component)val2.target).TryGetComponent<Chainsaw>(ref val))
{
return true;
}
return false;
}
public static bool IsParriedProjectileTarget(Transform target)
{
if ((Object)(object)target == (Object)null)
{
return false;
}
Projectile val = default(Projectile);
if (((Component)target).TryGetComponent<Projectile>(ref val) && val.parried)
{
return true;
}
ParryHelper val2 = default(ParryHelper);
Projectile val3 = default(Projectile);
if (((Component)target).TryGetComponent<ParryHelper>(ref val2) && (Object)(object)val2.target != (Object)null && ((Component)val2.target).TryGetComponent<Projectile>(ref val3) && val3.parried)
{
return true;
}
return false;
}
}
[HarmonyPatch(typeof(LeaderboardController))]
public static class LeaderboardBlocker
{
[HarmonyPatch("SubmitLevelScore")]
[HarmonyPrefix]
private static bool BlockLevelScores()
{
MonoSingleton<HudMessageReceiver>.Instance.SendHudMessage("Leaderboards disabled - Knuckleblaster Parry.", "", "", 0, false, false, true);
return false;
}
[HarmonyPatch("SubmitCyberGrindScore")]
[HarmonyPrefix]
private static bool BlockCyberGrindScores()
{
MonoSingleton<HudMessageReceiver>.Instance.SendHudMessage("Leaderboards disabled = Knuckleblaster Parry.", "", "", 0, false, false, true);
return false;
}
}
[HarmonyPatch(typeof(Punch), "ActiveFrame")]
public class HeavyParryPatch
{
private const int ParryMask = 16384;
private const float ParryRange = 4f;
private static void Prefix(Punch __instance, bool firstFrame)
{
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Invalid comparison between Unknown and I4
if ((Object)(object)__instance == (Object)null || !Plugin.EnableParry.value || (int)__instance.type != 1 || __instance.parriedSomething)
{
return;
}
CameraController cameraController = Plugin.GetCameraController(__instance);
GameObject cameraObject = Plugin.GetCameraObject(__instance);
if (!((Object)(object)cameraController == (Object)null) && !((Object)(object)cameraObject == (Object)null))
{
HashSet<Transform> checkedTargets = new HashSet<Transform>();
if (!TryParryOverlaps(__instance, cameraController, checkedTargets, firstFrame) && !TryParryRaycast(__instance, cameraController, cameraObject, checkedTargets, firstFrame) && !TryParryZoneProjectile(__instance, checkedTargets, firstFrame))
{
TryPunchflectCoin(__instance, cameraController, cameraObject);
}
}
}
private static bool TryParryOverlaps(Punch punch, CameraController cc, HashSet<Transform> checkedTargets, bool firstFrame)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
Collider[] array = Physics.OverlapSphere(cc.GetDefaultPos(), 0.01f, 16384, (QueryTriggerInteraction)2);
foreach (Collider val in array)
{
Transform val2 = (((Object)(object)val.attachedRigidbody != (Object)null) ? ((Component)val.attachedRigidbody).transform : ((Component)val).transform);
checkedTargets.Add(val2);
checkedTargets.Add(((Component)val).transform);
if (Plugin.TryParry(punch, val2, firstFrame))
{
return true;
}
}
return false;
}
private static bool TryParryRaycast(Punch punch, CameraController cc, GameObject camObj, HashSet<Transform> checkedTargets, bool firstFrame)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
RaycastHit val = default(RaycastHit);
bool flag = Physics.Raycast(cc.GetDefaultPos(), camObj.transform.forward, ref val, 4f, 16384);
if (!flag)
{
flag = Physics.BoxCast(cc.GetDefaultPos(), Vector3.one * 0.3f, camObj.transform.forward, ref val, camObj.transform.rotation, 4f, 16384);
}
if (!flag)
{
return false;
}
if (checkedTargets.Contains(((RaycastHit)(ref val)).transform))
{
return false;
}
checkedTargets.Add(((RaycastHit)(ref val)).transform);
return Plugin.TryParry(punch, ((RaycastHit)(ref val)).transform, firstFrame);
}
private static bool TryParryZoneProjectile(Punch punch, HashSet<Transform> checkedTargets, bool firstFrame)
{
ProjectileParryZone parryZone = Plugin.GetParryZone(punch);
if ((Object)(object)parryZone == (Object)null)
{
return false;
}
Projectile val = parryZone.CheckParryZone();
if ((Object)(object)val == (Object)null)
{
return false;
}
if (checkedTargets.Contains(((Component)val).transform))
{
return false;
}
if (val.parried || val.unparryable)
{
return false;
}
if (!Plugin.CanBoostProjectile(punch, firstFrame) && val.playerBullet)
{
return false;
}
Plugin.ParryProjectile(punch, val);
punch.parriedSomething = true;
punch.hitSomething = true;
return true;
}
private static void TryPunchflectCoin(Punch punch, CameraController cc, GameObject camObj)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
if (Plugin.AlreadyHitCoin(punch))
{
return;
}
RaycastHit[] array = Physics.SphereCastAll(new Ray(cc.GetDefaultPos(), camObj.transform.forward), 0.35f, 4f, -1, (QueryTriggerInteraction)2);
Coin val = null;
float num = float.PositiveInfinity;
for (int i = 0; i < array.Length; i++)
{
RaycastHit val2 = array[i];
Coin val3 = (((Object)(object)((RaycastHit)(ref val2)).collider != (Object)null) ? ((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent<Coin>() : null);
if (!((Object)(object)val3 == (Object)null) && !(((RaycastHit)(ref val2)).distance >= num))
{
val = val3;
num = ((RaycastHit)(ref val2)).distance;
}
}
if (!((Object)(object)val == (Object)null))
{
Plugin.PunchflectCoin(val);
Plugin.SetCoinHit(punch);
punch.hitSomething = true;
}
}
}
[HarmonyPatch(typeof(Enemy), "HandleParrying")]
public class EnemyParryPatch
{
private static void Prefix(Enemy __instance, ref string __state)
{
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Invalid comparison between Unknown and I4
if (!Plugin.EnableParry.value)
{
return;
}
__state = null;
EnemyIdentifier enemyIdentifier = Plugin.GetEnemyIdentifier(__instance);
if (!((Object)(object)enemyIdentifier == (Object)null) && !(enemyIdentifier.hitter != "heavypunch"))
{
Punch currentPunch = Plugin.GetCurrentPunch();
if (!((Object)(object)currentPunch == (Object)null) && (int)currentPunch.type == 1 && currentPunch.activeFrames > 0)
{
__state = enemyIdentifier.hitter;
enemyIdentifier.hitter = "punch";
}
}
}
private static void Postfix(Enemy __instance, string __state)
{
RestoreHitter(__instance, __state);
}
private static void Finalizer(Enemy __instance, string __state)
{
RestoreHitter(__instance, __state);
}
private static void RestoreHitter(Enemy enemy, string oldHitter)
{
if (oldHitter != null)
{
EnemyIdentifier enemyIdentifier = Plugin.GetEnemyIdentifier(enemy);
if ((Object)(object)enemyIdentifier != (Object)null)
{
enemyIdentifier.hitter = oldHitter;
}
}
}
}
[HarmonyPatch(typeof(Punch), "Parry")]
public class HeavyParryAnimationPatch
{
private static void Postfix(Punch __instance)
{
Plugin.RestoreAnimation(__instance);
}
}
[HarmonyPatch(typeof(Punch), "ParryProjectile")]
public class ProjectileParryAnimationPatch
{
private static void Postfix(Punch __instance)
{
Plugin.RestoreAnimation(__instance);
}
}
[HarmonyPatch(typeof(Punch), "TryParryProjectile")]
public class TryParryAnimationPatch
{
private static void Postfix(Punch __instance, bool __result)
{
if (__result)
{
Plugin.RestoreAnimation(__instance);
}
}
}