Decompiled source of PunchingRevised Patch6 v1.1.0

Mods/PunchingRevised_Patch6.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BoneLib;
using BoneLib.BoneMenu;
using BoneLib.BoneMenu.UI;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSLZ.Marrow;
using Il2CppSLZ.Marrow.Audio;
using Il2CppSLZ.Marrow.Combat;
using Il2CppSLZ.Marrow.Data;
using Il2CppSLZ.VRMK;
using Il2CppSystem;
using Il2CppTMPro;
using LabFusion.Entities;
using LabFusion.Network;
using LabFusion.Player;
using LabFusion.Senders;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using PunchingRevised;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(PunchingRevisedMod), "PunchingRevised", "2.7.7", "PunchingRevised", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: MelonPriority(-750)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("PunchingRevised")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyCopyright("PunchingRevised")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("PunchingRevised")]
[assembly: AssemblyTitle("PunchingRevised_Patch6")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 PunchingRevised
{
	public class PunchingRevisedMod : MelonMod
	{
		internal struct PoisonHit
		{
			public HandSFX HandSfx;

			public Collider EnemyCollider;

			public Rigidbody EnemyRigidbody;

			public Collider SelfCollider;

			public ImpactProperties ImpactProps;

			public Vector3 ContactPoint;

			public Vector3 ContactNormal;

			public bool IsFusionPlayer;

			public byte FusionTargetId;
		}

		internal class PoisonTarget
		{
			public readonly Queue<PoisonHit> Queue = new Queue<PoisonHit>();

			public int FrameCounter = 0;

			public bool Dead = false;

			public bool LethalityActive = false;

			public int LethalityCounter = 0;

			public float LethalityMultiplier = 1f;
		}

		internal class PunchSequence
		{
			public HandSFX HandSfx;

			public Collider EnemyCollider;

			public Rigidbody EnemyRigidbody;

			public Collider SelfCollider;

			public ImpactProperties ImpactProps;

			public Vector3 ContactPoint;

			public Vector3 ContactNormal;

			public int HitsRemaining;

			public int FrameCounter;

			public bool IsFusionPlayer;

			public byte FusionTargetId;
		}

		private static MelonPreferences_Category _prefCategory;

		private static MelonPreferences_Entry<bool> _enabledPref;

		private static MelonPreferences_Entry<bool> _rapidFirePref;

		private static MelonPreferences_Entry<bool> _ultraRapidFirePref;

		private static MelonPreferences_Entry<bool> _poisonFistPref;

		private static MelonPreferences_Entry<bool> _fistGesturePref;

		private static MelonPreferences_Entry<bool> _moreThanHandsPref;

		private static MelonPreferences_Entry<bool> _punchWhileGrabbingPref;

		private static MelonPreferences_Entry<bool> _speedScalingPref;

		private static MelonPreferences_Entry<bool> _speedRequirementPref;

		private static MelonPreferences_Entry<bool> _punchSfxPref;

		internal const float SpeedScalingThreshold = 2.5f;

		internal const float SpeedScalingDoubleStep = 2.5f;

		internal const float SpeedScalingMin = 0.1f;

		internal const float SpeedScalingMax = 128f;

		internal static bool _proxyCached = false;

		internal static float _proxyMassArm;

		internal static float _proxyMassTotal;

		internal static float _proxyMassChest;

		internal static float _proxyMassPelvis;

		internal static float _proxyMassHead;

		internal static float _proxyMassLeg;

		internal static float _proxyStrUpper;

		internal static float _proxyStrLower;

		internal static float _proxyStrGrip;

		internal static float _proxyHandMassL = -1f;

		internal static float _proxyUpperArmMassL = -1f;

		internal static float _proxyLowerArmMassL = -1f;

		internal static float _proxyHandMassR = -1f;

		internal static float _proxyUpperArmMassR = -1f;

		internal static float _proxyLowerArmMassR = -1f;

		internal static float LastForcedPunchTimeLeft = 0f;

		internal static float LastForcedPunchTimeRight = 0f;

		internal static float LastBodyHitTime = 0f;

		internal const float ForcedPunchCooldown = 0.15f;

		internal const float GripThreshold = 0.5f;

		internal const int UltraHitFrameDelay = 5;

		internal const int PoisonHitFrameDelay = 20;

		internal const int PoisonQueueMax = 50;

		internal const int PoisonHitsPerPunch = 8;

		internal const int LethalityThreshold = 5;

		internal static readonly Dictionary<int, PoisonTarget> PoisonTargets = new Dictionary<int, PoisonTarget>();

		private static readonly List<int> _poisonRemoveList = new List<int>();

		internal static readonly List<PunchSequence> ActiveSequences = new List<PunchSequence>();

		internal static AudioClip _sfxLow;

		internal static AudioClip _sfxAverage;

		internal static AudioClip _sfxHigh;

		private static bool _sfxLoaded = false;

		private const string SfxResourceLow = "PunchingRevised.Audio.PunchLow.wav";

		private const string SfxResourceAverage = "PunchingRevised.Audio.PunchAverage.wav";

		private const string SfxResourceHigh = "PunchingRevised.Audio.PunchHigh.wav";

		private static Page _page;

		private static Page _explanationPage;

		private static GameObject _navContainer;

		private static Sprite _fillSprite;

		private static Sprite _borderSprite;

		private static ScrollRect _cachedScrollRect;

		private static bool _scrollOverrideActive;

		private static readonly List<int> _explanationGroupSizes = new List<int>();

		private static int _explanationPendingDelay;

		private static int _explanationPendingFrames;

		private static bool _pendingScrollToTop;

		private static readonly List<(TextMeshProUGUI tmp, bool origAutoSize, TextOverflowModes origOverflow, bool origWrap)> _modifiedTmps = new List<(TextMeshProUGUI, bool, TextOverflowModes, bool)>();

		private static readonly List<(Image img, Color origColor)> _modifiedImages = new List<(Image, Color)>();

		private const int ExplanationCharsPerLine = 18;

		private const int ExplanationLinesPerButton = 3;

		public static bool Enabled => _enabledPref.Value;

		public static bool RapidFire => _rapidFirePref.Value;

		public static bool UltraRapidFire => _ultraRapidFirePref.Value;

		public static bool PoisonFist => _poisonFistPref.Value;

		public static bool AnyRapidFire => _rapidFirePref.Value || _ultraRapidFirePref.Value;

		public static bool FistGesture => _fistGesturePref.Value;

		public static bool MoreThanHands => _moreThanHandsPref.Value;

		public static bool PunchWhileGrabbing => _punchWhileGrabbingPref.Value;

		public static bool SpeedScaling => _speedScalingPref.Value;

		public static bool SpeedRequirement => _speedRequirementPref.Value;

		public static bool PunchSFX => _punchSfxPref.Value;

		internal static void CacheAvatarProxy()
		{
			try
			{
				RigManager rigManager = Player.RigManager;
				Avatar val = ((rigManager != null) ? rigManager.avatar : null);
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				_proxyMassArm = val._massArm;
				_proxyMassTotal = val._massTotal;
				_proxyMassChest = val._massChest;
				_proxyMassPelvis = val._massPelvis;
				_proxyMassHead = val._massHead;
				_proxyMassLeg = val._massLeg;
				_proxyStrUpper = val._strengthUpper;
				_proxyStrLower = val._strengthLower;
				_proxyStrGrip = val._strengthGrip;
				PhysicsRig physicsRig = Player.PhysicsRig;
				if ((Object)(object)physicsRig != (Object)null)
				{
					Hand leftHand = physicsRig.leftHand;
					PhysHand val2 = ((leftHand != null) ? leftHand.physHand : null);
					if ((Object)(object)val2 != (Object)null)
					{
						if ((Object)(object)val2._handRb != (Object)null)
						{
							_proxyHandMassL = val2._handRb.mass;
						}
						if ((Object)(object)val2._upperArmRb != (Object)null)
						{
							_proxyUpperArmMassL = val2._upperArmRb.mass;
						}
						if ((Object)(object)val2._lowerArmRb != (Object)null)
						{
							_proxyLowerArmMassL = val2._lowerArmRb.mass;
						}
					}
					Hand rightHand = physicsRig.rightHand;
					PhysHand val3 = ((rightHand != null) ? rightHand.physHand : null);
					if ((Object)(object)val3 != (Object)null)
					{
						if ((Object)(object)val3._handRb != (Object)null)
						{
							_proxyHandMassR = val3._handRb.mass;
						}
						if ((Object)(object)val3._upperArmRb != (Object)null)
						{
							_proxyUpperArmMassR = val3._upperArmRb.mass;
						}
						if ((Object)(object)val3._lowerArmRb != (Object)null)
						{
							_proxyLowerArmMassR = val3._lowerArmRb.mass;
						}
					}
				}
				_proxyCached = true;
			}
			catch
			{
			}
		}

		internal static void ApplyScale(float scale, bool isLeft)
		{
			try
			{
				RigManager rigManager = Player.RigManager;
				Avatar val = ((rigManager != null) ? rigManager.avatar : null);
				if ((Object)(object)val != (Object)null)
				{
					val._massArm = _proxyMassArm * scale;
					val._massTotal = _proxyMassTotal * scale;
					val._massChest = _proxyMassChest * scale;
					val._massPelvis = _proxyMassPelvis * scale;
					val._massHead = _proxyMassHead * scale;
					val._massLeg = _proxyMassLeg * scale;
					val._strengthUpper = _proxyStrUpper * scale;
					val._strengthLower = _proxyStrLower * scale;
					val._strengthGrip = _proxyStrGrip * scale;
				}
				float num = (isLeft ? _proxyHandMassL : _proxyHandMassR);
				float num2 = (isLeft ? _proxyUpperArmMassL : _proxyUpperArmMassR);
				float num3 = (isLeft ? _proxyLowerArmMassL : _proxyLowerArmMassR);
				PhysicsRig physicsRig = Player.PhysicsRig;
				object obj;
				if (!isLeft)
				{
					if (physicsRig == null)
					{
						obj = null;
					}
					else
					{
						Hand rightHand = physicsRig.rightHand;
						obj = ((rightHand != null) ? rightHand.physHand : null);
					}
				}
				else if (physicsRig == null)
				{
					obj = null;
				}
				else
				{
					Hand leftHand = physicsRig.leftHand;
					obj = ((leftHand != null) ? leftHand.physHand : null);
				}
				PhysHand val2 = (PhysHand)obj;
				if ((Object)(object)val2 != (Object)null)
				{
					if ((Object)(object)val2._handRb != (Object)null && num > 0f)
					{
						val2._handRb.mass = num * scale;
					}
					if ((Object)(object)val2._upperArmRb != (Object)null && num2 > 0f)
					{
						val2._upperArmRb.mass = num2 * scale;
					}
					if ((Object)(object)val2._lowerArmRb != (Object)null && num3 > 0f)
					{
						val2._lowerArmRb.mass = num3 * scale;
					}
				}
			}
			catch
			{
			}
		}

		internal static void RestoreProxy(bool isLeft)
		{
			try
			{
				RigManager rigManager = Player.RigManager;
				Avatar val = ((rigManager != null) ? rigManager.avatar : null);
				if ((Object)(object)val != (Object)null)
				{
					val._massArm = _proxyMassArm;
					val._massTotal = _proxyMassTotal;
					val._massChest = _proxyMassChest;
					val._massPelvis = _proxyMassPelvis;
					val._massHead = _proxyMassHead;
					val._massLeg = _proxyMassLeg;
					val._strengthUpper = _proxyStrUpper;
					val._strengthLower = _proxyStrLower;
					val._strengthGrip = _proxyStrGrip;
				}
				float num = (isLeft ? _proxyHandMassL : _proxyHandMassR);
				float num2 = (isLeft ? _proxyUpperArmMassL : _proxyUpperArmMassR);
				float num3 = (isLeft ? _proxyLowerArmMassL : _proxyLowerArmMassR);
				PhysicsRig physicsRig = Player.PhysicsRig;
				object obj;
				if (!isLeft)
				{
					if (physicsRig == null)
					{
						obj = null;
					}
					else
					{
						Hand rightHand = physicsRig.rightHand;
						obj = ((rightHand != null) ? rightHand.physHand : null);
					}
				}
				else if (physicsRig == null)
				{
					obj = null;
				}
				else
				{
					Hand leftHand = physicsRig.leftHand;
					obj = ((leftHand != null) ? leftHand.physHand : null);
				}
				PhysHand val2 = (PhysHand)obj;
				if ((Object)(object)val2 != (Object)null)
				{
					if ((Object)(object)val2._handRb != (Object)null && num > 0f)
					{
						val2._handRb.mass = num;
					}
					if ((Object)(object)val2._upperArmRb != (Object)null && num2 > 0f)
					{
						val2._upperArmRb.mass = num2;
					}
					if ((Object)(object)val2._lowerArmRb != (Object)null && num3 > 0f)
					{
						val2._lowerArmRb.mass = num3;
					}
				}
			}
			catch
			{
			}
		}

		public override void OnInitializeMelon()
		{
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0242: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: Unknown result type (might be due to invalid IL or missing references)
			//IL_0321: Unknown result type (might be due to invalid IL or missing references)
			_prefCategory = MelonPreferences.CreateCategory("PunchingRevised");
			_enabledPref = _prefCategory.CreateEntry<bool>("Enabled", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_rapidFirePref = _prefCategory.CreateEntry<bool>("RapidFire", false, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_ultraRapidFirePref = _prefCategory.CreateEntry<bool>("UltraRapidFire", false, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_poisonFistPref = _prefCategory.CreateEntry<bool>("PoisonFist", false, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_fistGesturePref = _prefCategory.CreateEntry<bool>("FistGesture", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_moreThanHandsPref = _prefCategory.CreateEntry<bool>("MoreThanHands", false, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_punchWhileGrabbingPref = _prefCategory.CreateEntry<bool>("PunchWhileGrabbing", false, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_speedScalingPref = _prefCategory.CreateEntry<bool>("SpeedScaling", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_speedRequirementPref = _prefCategory.CreateEntry<bool>("SpeedRequirement", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_punchSfxPref = _prefCategory.CreateEntry<bool>("PunchSFX", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			Page val2 = (_page = Page.Root.CreatePage(BuildGradientText("PunchingRevised", Color.cyan, Color.magenta), Color.white, 0, true));
			Menu.OnPageOpened += OnPageOpened;
			BoolElement boolEnabled = val2.CreateBool("Punching Revised", Color.magenta, Enabled, (Action<bool>)delegate(bool val)
			{
				_enabledPref.Value = val;
				_prefCategory.SaveToFile(true);
				((MelonBase)this).LoggerInstance.Msg($"[Toggle] PunchingRevised = {val}");
			});
			BoolElement boolRapidFire = val2.CreateBool("Rapid Fire", Color.red, RapidFire, (Action<bool>)delegate(bool val)
			{
				_rapidFirePref.Value = val;
				_prefCategory.SaveToFile(true);
				((MelonBase)this).LoggerInstance.Msg($"[Toggle] RapidFire = {val}");
			});
			BoolElement boolUltraRapidFire = val2.CreateBool("Ultra Rapid Fire", Color.red, UltraRapidFire, (Action<bool>)delegate(bool val)
			{
				_ultraRapidFirePref.Value = val;
				_prefCategory.SaveToFile(true);
				((MelonBase)this).LoggerInstance.Msg($"[Toggle] UltraRapidFire = {val}");
			});
			BoolElement boolPoisonFist = val2.CreateBool("Poison Fist", Color.green, PoisonFist, (Action<bool>)delegate(bool val)
			{
				_poisonFistPref.Value = val;
				_prefCategory.SaveToFile(true);
				((MelonBase)this).LoggerInstance.Msg($"[Toggle] PoisonFist = {val}");
				if (!val)
				{
					PoisonTargets.Clear();
				}
			});
			BoolElement boolFistGesture = val2.CreateBool("Fist Gesture", Color.yellow, FistGesture, (Action<bool>)delegate(bool val)
			{
				_fistGesturePref.Value = val;
				_prefCategory.SaveToFile(true);
				((MelonBase)this).LoggerInstance.Msg($"[Toggle] FistGesture = {val}");
			});
			BoolElement boolMoreThanHands = val2.CreateBool("More Than Hands", Color.yellow, MoreThanHands, (Action<bool>)delegate(bool val)
			{
				_moreThanHandsPref.Value = val;
				_prefCategory.SaveToFile(true);
				((MelonBase)this).LoggerInstance.Msg($"[Toggle] MoreThanHands = {val}");
			});
			BoolElement boolPunchWhileGrabbing = val2.CreateBool("Punch While Grabbing", Color.yellow, PunchWhileGrabbing, (Action<bool>)delegate(bool val)
			{
				_punchWhileGrabbingPref.Value = val;
				_prefCategory.SaveToFile(true);
				((MelonBase)this).LoggerInstance.Msg($"[Toggle] PunchWhileGrabbing = {val}");
			});
			BoolElement boolSpeedScaling = val2.CreateBool("Speed Scaling", Color.yellow, SpeedScaling, (Action<bool>)delegate(bool val)
			{
				_speedScalingPref.Value = val;
				_prefCategory.SaveToFile(true);
				((MelonBase)this).LoggerInstance.Msg($"[Toggle] SpeedScaling = {val}");
			});
			BoolElement boolSpeedRequirement = val2.CreateBool("Speed Requirement", Color.yellow, SpeedRequirement, (Action<bool>)delegate(bool val)
			{
				_speedRequirementPref.Value = val;
				_prefCategory.SaveToFile(true);
				((MelonBase)this).LoggerInstance.Msg($"[Toggle] SpeedRequirement = {val}");
			});
			BoolElement boolPunchSfx = val2.CreateBool("Punch SFX", Color.yellow, PunchSFX, (Action<bool>)delegate(bool val)
			{
				_punchSfxPref.Value = val;
				_prefCategory.SaveToFile(true);
				((MelonBase)this).LoggerInstance.Msg($"[Toggle] PunchSFX = {val}");
			});
			val2.CreateFunction("Reset Toggles", Color.red, (Action)delegate
			{
				_enabledPref.Value = true;
				_rapidFirePref.Value = false;
				_ultraRapidFirePref.Value = false;
				_poisonFistPref.Value = false;
				_fistGesturePref.Value = true;
				_moreThanHandsPref.Value = false;
				_punchWhileGrabbingPref.Value = false;
				_speedScalingPref.Value = true;
				_speedRequirementPref.Value = true;
				_punchSfxPref.Value = true;
				_prefCategory.SaveToFile(true);
				boolEnabled.Value = true;
				boolRapidFire.Value = false;
				boolUltraRapidFire.Value = false;
				boolPoisonFist.Value = false;
				boolFistGesture.Value = true;
				boolMoreThanHands.Value = false;
				boolPunchWhileGrabbing.Value = false;
				boolSpeedScaling.Value = true;
				boolSpeedRequirement.Value = true;
				boolPunchSfx.Value = true;
				((MelonBase)this).LoggerInstance.Msg("[Toggle] All toggles reset to defaults");
			});
			_explanationPage = val2.CreatePage("Explanation", Color.white, 0, true);
			AddExplanation(_explanationPage, "FF00FF", "Punching Revised", "This toggle enables or disables the entire PunchingRevised mod. When off, all patches are inactive and the game's default punching behavior is restored.");
			AddExplanation(_explanationPage, "FF0000", "Rapid Fire", "This toggle removes the cooldown between punches, allowing you to land hits as fast as your hands can collide. Native impact cooldowns are also killed so every swing connects.");
			AddExplanation(_explanationPage, "FF0000", "Ultra Rapid Fire", "This toggle makes each punch land 3 times total. After the initial hit, 2 follow-up hits fire automatically with a short delay between each, multiplying your damage output per swing.");
			AddExplanation(_explanationPage, "00FF00", "Poison Fist", "This toggle queues up to 8 delayed hits per punch on each target, stacking up to 50 queued hits. Each hit uses a base 0.3x damage multiplier and processes one at a time with a short delay between each. Once the queue fills, a lethality system activates that doubles the multiplier every 5 hits, so damage scales exponentially. On physics-based NPCs, the hit force also scales exponentially, launching them with extreme momentum.");
			AddExplanation(_explanationPage, "FFFF00", "Fist Gesture", "This toggle requires you to hold grip or trigger on your controller to punch. Prevents accidental hits when your hands are open or relaxed.");
			AddExplanation(_explanationPage, "FFFF00", "More Than Hands", "This toggle lets additional body parts deal punch damage. The head, chest, pelvis, legs, and feet all trigger hits on contact, routed through the punch system with the same damage scaling as normal punches.");
			AddExplanation(_explanationPage, "FFFF00", "Punch While Grabbing", "This toggle allows you to land punches even while holding an object in that hand. Normally, holding something blocks punch detection.");
			AddExplanation(_explanationPage, "FFFF00", "Speed Scaling", "This toggle scales damage with the world-space speed of the striking hand or body part. Below 2.5 meters per second the scale is linear, so slow taps deal proportionally less damage. At 2.5 meters per second you get normal damage. Above 2.5 meters per second the scale doubles every 2.5 meters per second, so 5 is 2x, 7.5 is 4x, 10 is 8x, 12.5 is 16x, 15 is 32x, 17.5 is 64x, 20 is 128x. Output is clamped between 0.1x and 128x. Because the speed is world-space, running while punching stacks your body's velocity onto your swing.");
			AddExplanation(_explanationPage, "FFFF00", "Speed Requirement", "This toggle blocks hits from registering unless the striking hand or body part is moving at 2.5 meters per second or faster in world space. Swings slower than that simply do not land and no damage is dealt. Useful when paired with Speed Scaling so gentle bumps cannot tick NPCs down at all. Since the speed is world-space, you can meet the requirement by running into an enemy even if your hand is still.");
			AddExplanation(_explanationPage, "FFFF00", "Punch SFX", "When on, plays a custom impact sound the moment a punch lands on something that takes damage (physics-based NPC, destructible object, other player). Three tiers picked from the effective damage scale: low under 1x, average 1x to 2x, high 3x and above. Only the initial colliding hand or body-part hit plays the sound; Ultra Rapid Fire and Poison Fist follow-up hits are silent so the SFX does not stutter. Real audio clips embedded under Audio/PunchLow.wav, PunchAverage.wav, PunchHigh.wav; built-in synthesized thuds are used as fallbacks for any tier whose file is missing.");
			AddExplanation(_explanationPage, "FF0000", "Reset Toggles", "This button resets all toggles back to their default values. Punching Revised, Fist Gesture, Speed Scaling, and Speed Requirement turn on, everything else turns off.");
			((MelonBase)this).LoggerInstance.Msg("PunchingRevised v2.7.7 loaded!");
		}

		public override void OnUpdate()
		{
			ClampScrollVelocity();
			CheckPendingExplanationProcess();
		}

		public override void OnFixedUpdate()
		{
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Expected O, but got Unknown
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0406: Expected O, but got Unknown
			//IL_0444: Unknown result type (might be due to invalid IL or missing references)
			//IL_044e: Unknown result type (might be due to invalid IL or missing references)
			//IL_045b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0465: Unknown result type (might be due to invalid IL or missing references)
			//IL_0474: Unknown result type (might be due to invalid IL or missing references)
			//IL_0483: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c8: Unknown result type (might be due to invalid IL or missing references)
			if (!Enabled)
			{
				return;
			}
			if (PunchAttackPatch._needsRestore)
			{
				PunchAttackPatch._needsRestore = false;
				if (_proxyCached)
				{
					RestoreProxy(PunchAttackPatch._restoreIsLeft);
				}
			}
			if (PoisonTargets.Count > 0)
			{
				_poisonRemoveList.Clear();
				foreach (KeyValuePair<int, PoisonTarget> poisonTarget in PoisonTargets)
				{
					int key = poisonTarget.Key;
					PoisonTarget value = poisonTarget.Value;
					if (value.Queue.Count == 0)
					{
						_poisonRemoveList.Add(key);
						continue;
					}
					if (value.Dead)
					{
						value.Queue.Dequeue();
						if (value.Queue.Count == 0)
						{
							_poisonRemoveList.Add(key);
						}
						continue;
					}
					value.FrameCounter++;
					if (value.FrameCounter < 20)
					{
						continue;
					}
					value.FrameCounter = 0;
					PoisonHit poisonHit = value.Queue.Dequeue();
					bool flag = false;
					try
					{
						flag = ((Component)((Component)poisonHit.EnemyCollider).transform.root).gameObject.activeInHierarchy;
					}
					catch
					{
					}
					if (!flag)
					{
						value.Dead = true;
						continue;
					}
					float num = 0.3f * value.LethalityMultiplier;
					bool isLeft = IsLeftHand(poisonHit.HandSfx);
					if (_proxyCached)
					{
						ApplyScale(num, isLeft);
					}
					HandSFXCollisionPatch._isForcedCall = true;
					HandSFXCollisionPatch._isPoisonFollowUp = true;
					try
					{
						poisonHit.HandSfx._nextImpactTime = 0f;
						poisonHit.HandSfx._lastImpulse = 0f;
						poisonHit.HandSfx._lastHandChestVelSqMg = 100f;
						poisonHit.HandSfx._fixedRan = true;
						RelevantCollision val = new RelevantCollision();
						val.collider = poisonHit.EnemyCollider;
						val.colliderSelf = poisonHit.SelfCollider;
						val.rigidbody = poisonHit.EnemyRigidbody;
						val.iP = poisonHit.ImpactProps;
						val.relativeVelocity = Vector3.forward * 10f;
						val.totalImpulse = Vector3.forward * 50f;
						val.point = poisonHit.ContactPoint;
						val.normal = poisonHit.ContactNormal;
						poisonHit.HandSfx.PunchAttack(val, 10f, 100f);
						if (poisonHit.IsFusionPlayer)
						{
							SendFusionDamage(poisonHit.FusionTargetId, 10f * num, val.relativeVelocity);
						}
					}
					catch
					{
					}
					if (_proxyCached)
					{
						RestoreProxy(isLeft);
					}
					if (value.Queue.Count == 0)
					{
						_poisonRemoveList.Add(key);
					}
				}
				for (int i = 0; i < _poisonRemoveList.Count; i++)
				{
					PoisonTargets.Remove(_poisonRemoveList[i]);
				}
			}
			if (ActiveSequences.Count == 0)
			{
				return;
			}
			for (int num2 = ActiveSequences.Count - 1; num2 >= 0; num2--)
			{
				PunchSequence punchSequence = ActiveSequences[num2];
				punchSequence.FrameCounter++;
				if (punchSequence.FrameCounter >= 5)
				{
					punchSequence.FrameCounter = 0;
					try
					{
						punchSequence.HandSfx._nextImpactTime = 0f;
						punchSequence.HandSfx._lastImpulse = 0f;
						punchSequence.HandSfx._lastHandChestVelSqMg = 100f;
						punchSequence.HandSfx._fixedRan = true;
						RelevantCollision val2 = new RelevantCollision();
						val2.collider = punchSequence.EnemyCollider;
						val2.colliderSelf = punchSequence.SelfCollider;
						val2.rigidbody = punchSequence.EnemyRigidbody;
						val2.iP = punchSequence.ImpactProps;
						val2.relativeVelocity = Vector3.forward * 10f;
						val2.totalImpulse = Vector3.forward * 50f;
						val2.point = punchSequence.ContactPoint;
						val2.normal = punchSequence.ContactNormal;
						HandSFXCollisionPatch._isForcedCall = true;
						punchSequence.HandSfx.PunchAttack(val2, 10f, 100f);
						if (punchSequence.IsFusionPlayer)
						{
							SendFusionDamage(punchSequence.FusionTargetId, 10f, val2.relativeVelocity);
						}
					}
					catch
					{
					}
					punchSequence.HitsRemaining--;
					if (punchSequence.HitsRemaining <= 0)
					{
						ActiveSequences.RemoveAt(num2);
					}
				}
			}
		}

		public override void OnLateInitializeMelon()
		{
			Hooking.OnSwitchAvatarPostfix += OnAvatarSwitched;
			Hooking.OnLevelUnloaded += InvalidateSfx;
		}

		private void OnAvatarSwitched(Avatar avatar)
		{
			CacheAvatarProxy();
		}

		internal static bool IsLeftHand(HandSFX instance)
		{
			try
			{
				PhysicsRig physicsRig = Player.PhysicsRig;
				object obj;
				if (physicsRig == null)
				{
					obj = null;
				}
				else
				{
					Hand leftHand = physicsRig.leftHand;
					obj = ((leftHand != null) ? leftHand.physHand : null);
				}
				PhysHand val = (PhysHand)obj;
				if ((Object)(object)val == (Object)null || (Object)(object)instance._physHand == (Object)null)
				{
					return true;
				}
				return ((Il2CppObjectBase)instance._physHand).Pointer == ((Il2CppObjectBase)val).Pointer;
			}
			catch
			{
				return true;
			}
		}

		internal static bool IsHandGripping(bool isLeft)
		{
			try
			{
				BaseController val = (isLeft ? Player.LeftController : Player.RightController);
				if ((Object)(object)val == (Object)null)
				{
					return false;
				}
				float secondaryInteractionButtonAxis = val.GetSecondaryInteractionButtonAxis();
				float primaryInteractionButtonAxis = val.GetPrimaryInteractionButtonAxis();
				return secondaryInteractionButtonAxis > 0.5f || primaryInteractionButtonAxis > 0.5f;
			}
			catch
			{
				return false;
			}
		}

		internal static float GetHandSpeed(HandSFX instance)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				PhysHand val = ((instance != null) ? instance._physHand : null);
				if ((Object)(object)val != (Object)null && (Object)(object)val._handRb != (Object)null)
				{
					Vector3 velocity = val._handRb.velocity;
					return ((Vector3)(ref velocity)).magnitude;
				}
			}
			catch
			{
			}
			return 0f;
		}

		internal static float GetBodyPartSpeed(CollisionSFX instance, RelevantCollision c)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Rigidbody val = null;
				if (c != null && (Object)(object)c.colliderSelf != (Object)null)
				{
					val = c.colliderSelf.attachedRigidbody;
				}
				if ((Object)(object)val == (Object)null)
				{
					val = ((Component)instance).GetComponent<Rigidbody>();
				}
				if ((Object)(object)val == (Object)null)
				{
					val = ((Component)instance).GetComponentInParent<Rigidbody>();
				}
				if ((Object)(object)val != (Object)null)
				{
					Vector3 velocity = val.velocity;
					return ((Vector3)(ref velocity)).magnitude;
				}
			}
			catch
			{
			}
			return 0f;
		}

		internal static float ComputeSpeedScale(float speed)
		{
			float num = ((!(speed <= 2.5f)) ? Mathf.Pow(2f, (speed - 2.5f) / 2.5f) : (speed / 2.5f));
			return Mathf.Clamp(num, 0.1f, 128f);
		}

		internal static void InvalidateSfx()
		{
			_sfxLoaded = false;
			_sfxLow = null;
			_sfxAverage = null;
			_sfxHigh = null;
		}

		internal static void EnsureSfxLoaded()
		{
			if (_sfxLoaded && (Object)(object)_sfxLow != (Object)null && (Object)(object)_sfxAverage != (Object)null && (Object)(object)_sfxHigh != (Object)null)
			{
				return;
			}
			_sfxLoaded = true;
			try
			{
				_sfxLow = LoadEmbeddedWav("PunchingRevised.Audio.PunchLow.wav", "PunchSFX_Low") ?? SynthThud("PunchSFX_Low_Placeholder", 90f, 0.08f, 0.45f);
				_sfxAverage = LoadEmbeddedWav("PunchingRevised.Audio.PunchAverage.wav", "PunchSFX_Average") ?? SynthThud("PunchSFX_Average_Placeholder", 180f, 0.12f, 0.7f);
				_sfxHigh = LoadEmbeddedWav("PunchingRevised.Audio.PunchHigh.wav", "PunchSFX_High") ?? SynthThud("PunchSFX_High_Placeholder", 70f, 0.2f, 1f);
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("PunchSFX clip load failed: " + ex.Message);
			}
		}

		private static AudioClip LoadEmbeddedWav(string resourceName, string clipName)
		{
			try
			{
				Assembly executingAssembly = Assembly.GetExecutingAssembly();
				using Stream stream = executingAssembly.GetManifestResourceStream(resourceName);
				if (stream == null)
				{
					return null;
				}
				return DecodeWav(stream, clipName);
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("PunchSFX failed to decode '" + resourceName + "': " + ex.Message);
				return null;
			}
		}

		private static AudioClip DecodeWav(Stream stream, string clipName)
		{
			using BinaryReader binaryReader = new BinaryReader(stream);
			if (new string(binaryReader.ReadChars(4)) != "RIFF")
			{
				throw new Exception("not a RIFF file");
			}
			binaryReader.ReadInt32();
			if (new string(binaryReader.ReadChars(4)) != "WAVE")
			{
				throw new Exception("not a WAVE file");
			}
			int num = 1;
			int num2 = 44100;
			int num3 = 16;
			int num4 = 0;
			long num5 = -1L;
			while (stream.Position + 8 <= stream.Length)
			{
				string text = new string(binaryReader.ReadChars(4));
				int num6 = binaryReader.ReadInt32();
				if (text == "fmt ")
				{
					binaryReader.ReadInt16();
					num = binaryReader.ReadInt16();
					num2 = binaryReader.ReadInt32();
					binaryReader.ReadInt32();
					binaryReader.ReadInt16();
					num3 = binaryReader.ReadInt16();
					if (num6 > 16)
					{
						binaryReader.ReadBytes(num6 - 16);
					}
				}
				else
				{
					if (text == "data")
					{
						num5 = stream.Position;
						num4 = num6;
						break;
					}
					binaryReader.ReadBytes(num6);
				}
			}
			if (num5 < 0)
			{
				throw new Exception("no data chunk found");
			}
			stream.Position = num5;
			int num7 = num3 / 8;
			int num8 = num4 / num7 / num;
			float[] array = new float[num8 * num];
			switch (num3)
			{
			case 8:
			{
				for (int j = 0; j < array.Length; j++)
				{
					array[j] = (float)(binaryReader.ReadByte() - 128) / 128f;
				}
				break;
			}
			case 16:
			{
				for (int k = 0; k < array.Length; k++)
				{
					array[k] = (float)binaryReader.ReadInt16() / 32768f;
				}
				break;
			}
			case 24:
			{
				for (int i = 0; i < array.Length; i++)
				{
					int num9 = binaryReader.ReadByte();
					int num10 = binaryReader.ReadByte();
					int num11 = binaryReader.ReadByte();
					int num12 = (num11 << 16) | (num10 << 8) | num9;
					if (((uint)num12 & 0x800000u) != 0)
					{
						num12 |= -16777216;
					}
					array[i] = (float)num12 / 8388608f;
				}
				break;
			}
			default:
				throw new Exception($"unsupported bit depth: {num3}");
			}
			AudioClip val = AudioClip.Create(clipName, num8, num, num2, false);
			val.SetData(Il2CppStructArray<float>.op_Implicit(array), 0);
			return val;
		}

		private static AudioClip SynthThud(string clipName, float frequency, float duration, float amplitude)
		{
			int num = Mathf.Max(1, (int)(44100f * duration));
			float[] array = new float[num];
			int num2 = Mathf.Max(1, 220);
			int num3 = Mathf.Max(1, num - num2);
			float num4 = (float)Math.PI * 2f * frequency / 44100f;
			float num5 = (float)Math.PI * 2f * (frequency * 2f) / 44100f;
			for (int i = 0; i < num; i++)
			{
				float num6 = ((i < num2) ? ((float)i / (float)num2) : Mathf.Pow(1f - (float)(i - num2) / (float)num3, 2.5f));
				float num7 = Mathf.Sin(num4 * (float)i) + 0.3f * Mathf.Sin(num5 * (float)i);
				array[i] = Mathf.Clamp(num7 * amplitude * num6, -1f, 1f);
			}
			AudioClip val = AudioClip.Create(clipName, num, 1, 44100, false);
			val.SetData(Il2CppStructArray<float>.op_Implicit(array), 0);
			return val;
		}

		internal static float ComputeEffectiveDamageScale(HandSFX hand, float overrideSpeed)
		{
			if (!SpeedScaling)
			{
				return 1f;
			}
			float speed = ((overrideSpeed >= 0f) ? overrideSpeed : GetHandSpeed(hand));
			return ComputeSpeedScale(speed);
		}

		private static AudioClip PickClipForScale(float scale)
		{
			if (scale < 1f)
			{
				return _sfxLow;
			}
			if (scale < 3f)
			{
				return _sfxAverage;
			}
			return _sfxHigh;
		}

		internal static void PlayPunchSFX(HandSFX hand, Vector3 position, float overrideSpeed = -1f)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			if (!PunchSFX)
			{
				return;
			}
			EnsureSfxLoaded();
			float scale = ComputeEffectiveDamageScale(hand, overrideSpeed);
			AudioClip val = PickClipForScale(scale);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			try
			{
				Audio3dManager.PlayAtPoint(val, position, Audio3dManager.impact, 2f, 1f, new Nullable<float>(0.05f), new Nullable<float>(1f), new Nullable<float>(1f));
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("[PunchSFX] PlayAtPoint threw: " + ex.GetType().Name + ": " + ex.Message);
			}
		}

		internal static HandSFX GetPlayerHandSFX()
		{
			try
			{
				PhysicsRig physicsRig = Player.PhysicsRig;
				if ((Object)(object)physicsRig == (Object)null)
				{
					return null;
				}
				Hand leftHand = physicsRig.leftHand;
				if ((Object)(object)leftHand == (Object)null)
				{
					return null;
				}
				return ((Component)leftHand).GetComponentInChildren<HandSFX>();
			}
			catch
			{
				return null;
			}
		}

		internal static bool IsHandHoldingSomething(bool isLeft)
		{
			try
			{
				object obj;
				if (!isLeft)
				{
					PhysicsRig physicsRig = Player.PhysicsRig;
					obj = ((physicsRig != null) ? physicsRig.rightHand : null);
				}
				else
				{
					PhysicsRig physicsRig2 = Player.PhysicsRig;
					obj = ((physicsRig2 != null) ? physicsRig2.leftHand : null);
				}
				Hand val = (Hand)obj;
				if ((Object)(object)val == (Object)null)
				{
					return false;
				}
				return (Object)(object)val.m_CurrentAttachedGO != (Object)null;
			}
			catch
			{
				return false;
			}
		}

		internal static bool IsPlayerBody(CollisionSFX instance)
		{
			try
			{
				RigManager rigManager = Player.RigManager;
				if ((Object)(object)rigManager == (Object)null)
				{
					return false;
				}
				return ((Component)instance).transform.IsChildOf(((Component)rigManager).transform);
			}
			catch
			{
				return false;
			}
		}

		internal static bool IsLocalPlayerRig(Component instance)
		{
			try
			{
				RigManager rigManager = Player.RigManager;
				if ((Object)(object)rigManager == (Object)null)
				{
					return false;
				}
				return instance.transform.IsChildOf(((Component)rigManager).transform);
			}
			catch
			{
				return false;
			}
		}

		internal static bool TryGetFusionTarget(Collider col, out byte targetId)
		{
			targetId = 0;
			try
			{
				if (!NetworkInfo.HasServer)
				{
					return false;
				}
				Transform root = ((Component)col).transform.root;
				RigManager componentInChildren = ((Component)root).GetComponentInChildren<RigManager>();
				if ((Object)(object)componentInChildren == (Object)null)
				{
					return false;
				}
				RigManager rigManager = Player.RigManager;
				if ((Object)(object)rigManager != (Object)null && ((Il2CppObjectBase)componentInChildren).Pointer == ((Il2CppObjectBase)rigManager).Pointer)
				{
					return false;
				}
				NetworkPlayer val = default(NetworkPlayer);
				if (NetworkPlayerManager.TryGetPlayer(componentInChildren, ref val))
				{
					targetId = PlayerID.op_Implicit(val.PlayerID);
					return true;
				}
			}
			catch
			{
			}
			return false;
		}

		internal static void SendFusionDamage(byte targetId, float damage, Vector3 direction)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Attack val = new Attack();
				val.damage = damage;
				val.attackType = (AttackType)2;
				val.direction = direction;
				val.backFacing = false;
				PlayerSender.SendPlayerDamage(targetId, val);
			}
			catch
			{
			}
		}

		private static string BuildGradientText(string text, Color startColor, Color endColor)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(text))
			{
				return text;
			}
			StringBuilder stringBuilder = new StringBuilder(text.Length * 22);
			int length = text.Length;
			for (int i = 0; i < length; i++)
			{
				float num = ((length > 1) ? ((float)i / (float)(length - 1)) : 0f);
				Color val = Color.Lerp(startColor, endColor, num);
				int num2 = Mathf.Clamp((int)(val.r * 255f), 0, 255);
				int num3 = Mathf.Clamp((int)(val.g * 255f), 0, 255);
				int num4 = Mathf.Clamp((int)(val.b * 255f), 0, 255);
				stringBuilder.Append("<color=#").Append(num2.ToString("X2")).Append(num3.ToString("X2"))
					.Append(num4.ToString("X2"))
					.Append('>')
					.Append(text[i])
					.Append("</color>");
			}
			return stringBuilder.ToString();
		}

		private static List<string> WrapText(string text, int maxChars)
		{
			List<string> list = new List<string>();
			if (string.IsNullOrEmpty(text))
			{
				return list;
			}
			string[] array = text.Split(' ');
			StringBuilder stringBuilder = new StringBuilder();
			string[] array2 = array;
			foreach (string text2 in array2)
			{
				if (!string.IsNullOrEmpty(text2))
				{
					if (stringBuilder.Length == 0)
					{
						stringBuilder.Append(text2);
					}
					else if (stringBuilder.Length + 1 + text2.Length <= maxChars)
					{
						stringBuilder.Append(' ');
						stringBuilder.Append(text2);
					}
					else
					{
						list.Add(stringBuilder.ToString());
						stringBuilder.Clear();
						stringBuilder.Append(text2);
					}
				}
			}
			if (stringBuilder.Length > 0)
			{
				list.Add(stringBuilder.ToString());
			}
			return list;
		}

		private static void AddExplanation(Page page, string colorHex, string title, string description)
		{
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			List<string> list = WrapText(description, 18);
			int num = 0;
			int num2 = 0;
			int num3 = Math.Min(2, list.Count);
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("<color=#").Append(colorHex).Append('>')
				.Append(title)
				.Append("</color>");
			for (int i = 0; i < num3; i++)
			{
				stringBuilder.Append('\n').Append(list[i]);
			}
			page.CreateFunction(stringBuilder.ToString(), Color.white, (Action)delegate
			{
			});
			num2 += num3;
			num++;
			while (num2 < list.Count)
			{
				stringBuilder.Clear();
				int num4 = Math.Min(3, list.Count - num2);
				for (int j = 0; j < num4; j++)
				{
					if (j > 0)
					{
						stringBuilder.Append('\n');
					}
					stringBuilder.Append(list[num2 + j]);
				}
				page.CreateFunction(stringBuilder.ToString(), Color.white, (Action)delegate
				{
				});
				num2 += num4;
				num++;
			}
			_explanationGroupSizes.Add(num);
		}

		private static void OnPageOpened(Page page)
		{
			bool flag = page == _page;
			bool flag2 = page == _explanationPage;
			if (flag || flag2)
			{
				if ((Object)(object)_navContainer == (Object)null)
				{
					CreateNavButtons();
				}
				if ((Object)(object)_navContainer != (Object)null)
				{
					_navContainer.SetActive(true);
				}
				_scrollOverrideActive = true;
				CacheScrollRect();
			}
			else
			{
				if ((Object)(object)_navContainer != (Object)null)
				{
					_navContainer.SetActive(false);
				}
				_scrollOverrideActive = false;
			}
			if (flag2)
			{
				_explanationPendingDelay = 5;
				_explanationPendingFrames = 30;
				_pendingScrollToTop = true;
			}
			else
			{
				_explanationPendingDelay = 0;
				_explanationPendingFrames = 0;
				_pendingScrollToTop = false;
				RestoreExplanationButtons();
			}
		}

		internal static void CheckPendingExplanationProcess()
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			if (_explanationPendingFrames <= 0)
			{
				return;
			}
			if (_explanationPendingDelay > 0)
			{
				_explanationPendingDelay--;
				return;
			}
			if (_pendingScrollToTop)
			{
				_pendingScrollToTop = false;
				CacheScrollRect();
				if ((Object)(object)_cachedScrollRect != (Object)null)
				{
					try
					{
						_cachedScrollRect.verticalNormalizedPosition = 1f;
						_cachedScrollRect.velocity = Vector2.zero;
					}
					catch
					{
					}
				}
			}
			_explanationPendingFrames--;
			ProcessExplanationButtons();
		}

		private static void ProcessExplanationButtons()
		{
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				GUIMenu instance = GUIMenu.Instance;
				if ((Object)(object)instance == (Object)null)
				{
					return;
				}
				Transform activeView = instance.ActiveView;
				if ((Object)(object)activeView == (Object)null)
				{
					return;
				}
				int childCount = activeView.childCount;
				for (int i = 0; i < childCount; i++)
				{
					Transform child;
					try
					{
						child = activeView.GetChild(i);
					}
					catch
					{
						continue;
					}
					if ((Object)(object)child == (Object)null || !((Component)child).gameObject.activeSelf)
					{
						continue;
					}
					TextMeshProUGUI componentInChildren = ((Component)child).GetComponentInChildren<TextMeshProUGUI>();
					if ((Object)(object)componentInChildren == (Object)null)
					{
						continue;
					}
					bool flag = false;
					for (int j = 0; j < _modifiedTmps.Count; j++)
					{
						if ((Object)(object)_modifiedTmps[j].tmp == (Object)(object)componentInChildren)
						{
							flag = true;
							break;
						}
					}
					if (!flag)
					{
						_modifiedTmps.Add((componentInChildren, ((TMP_Text)componentInChildren).enableAutoSizing, ((TMP_Text)componentInChildren).overflowMode, ((TMP_Text)componentInChildren).enableWordWrapping));
					}
					((TMP_Text)componentInChildren).enableAutoSizing = false;
					((TMP_Text)componentInChildren).enableWordWrapping = false;
					((TMP_Text)componentInChildren).overflowMode = (TextOverflowModes)0;
					Il2CppArrayBase<Image> componentsInChildren = ((Component)child).GetComponentsInChildren<Image>(true);
					if (componentsInChildren == null)
					{
						continue;
					}
					foreach (Image item in componentsInChildren)
					{
						if ((Object)(object)item == (Object)null)
						{
							continue;
						}
						bool flag2 = false;
						for (int k = 0; k < _modifiedImages.Count; k++)
						{
							if ((Object)(object)_modifiedImages[k].img == (Object)(object)item)
							{
								flag2 = true;
								break;
							}
						}
						if (!flag2)
						{
							_modifiedImages.Add((item, ((Graphic)item).color));
							((Graphic)item).color = Color.clear;
						}
					}
				}
			}
			catch
			{
			}
		}

		private static void RestoreExplanationButtons()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				foreach (var (val, enableAutoSizing, overflowMode, enableWordWrapping) in _modifiedTmps)
				{
					if (!((Object)(object)val == (Object)null))
					{
						((TMP_Text)val).enableAutoSizing = enableAutoSizing;
						((TMP_Text)val).overflowMode = overflowMode;
						((TMP_Text)val).enableWordWrapping = enableWordWrapping;
					}
				}
				foreach (var (val2, color) in _modifiedImages)
				{
					if (!((Object)(object)val2 == (Object)null))
					{
						((Graphic)val2).color = color;
					}
				}
			}
			catch
			{
			}
			_modifiedTmps.Clear();
			_modifiedImages.Clear();
		}

		private static void CacheScrollRect()
		{
			if ((Object)(object)_cachedScrollRect != (Object)null)
			{
				return;
			}
			try
			{
				GUIMenu instance = GUIMenu.Instance;
				if (!((Object)(object)instance == (Object)null))
				{
					Transform val = ((Component)instance).transform.Find("Page/Content/Viewport");
					if ((Object)(object)val != (Object)null)
					{
						_cachedScrollRect = ((Component)val).GetComponent<ScrollRect>();
					}
				}
			}
			catch
			{
			}
		}

		public static void ClampScrollVelocity()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			if (!_scrollOverrideActive || (Object)(object)_cachedScrollRect == (Object)null)
			{
				return;
			}
			try
			{
				Vector2 velocity = _cachedScrollRect.velocity;
				if (Mathf.Abs(velocity.y) > 1250f)
				{
					_cachedScrollRect.velocity = new Vector2(velocity.x, Mathf.Sign(velocity.y) * 1250f);
				}
			}
			catch
			{
			}
		}

		private static void CreateNavButtons()
		{
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Expected O, but got Unknown
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_033a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0397: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_0403: Unknown result type (might be due to invalid IL or missing references)
			//IL_0408: Unknown result type (might be due to invalid IL or missing references)
			//IL_0420: Unknown result type (might be due to invalid IL or missing references)
			//IL_0441: Unknown result type (might be due to invalid IL or missing references)
			//IL_0462: Unknown result type (might be due to invalid IL or missing references)
			//IL_0483: Unknown result type (might be due to invalid IL or missing references)
			//IL_04aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_054f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0556: Expected O, but got Unknown
			//IL_0576: Unknown result type (might be due to invalid IL or missing references)
			//IL_0583: Unknown result type (might be due to invalid IL or missing references)
			//IL_0590: Unknown result type (might be due to invalid IL or missing references)
			//IL_059d: Unknown result type (might be due to invalid IL or missing references)
			//IL_05dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_05fc: Expected O, but got Unknown
			//IL_061c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0629: Unknown result type (might be due to invalid IL or missing references)
			//IL_0636: Unknown result type (might be due to invalid IL or missing references)
			//IL_0643: Unknown result type (might be due to invalid IL or missing references)
			//IL_0670: Unknown result type (might be due to invalid IL or missing references)
			//IL_0535: Unknown result type (might be due to invalid IL or missing references)
			GUIMenu instance = GUIMenu.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			Transform val = ((Component)instance).transform.Find("Page/Content");
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Transform val2 = val.Find("Interaction");
			if ((Object)(object)val2 == (Object)null)
			{
				return;
			}
			Transform val3 = val2.Find("ScrollUp");
			Transform val4 = val2.Find("ScrollDown");
			if ((Object)(object)val3 == (Object)null || (Object)(object)val4 == (Object)null)
			{
				return;
			}
			Transform val5 = val.Find("Viewport");
			ScrollRect scrollRect = (((Object)(object)val5 != (Object)null) ? ((Component)val5).GetComponent<ScrollRect>() : null);
			if ((Object)(object)scrollRect == (Object)null)
			{
				return;
			}
			TMP_FontAsset val6 = null;
			TextMeshProUGUI componentInChildren = ((Component)val).GetComponentInChildren<TextMeshProUGUI>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				val6 = ((TMP_Text)componentInChildren).font;
			}
			RectTransform component = ((Component)val3).GetComponent<RectTransform>();
			RectTransform component2 = ((Component)val4).GetComponent<RectTransform>();
			float y = component.anchoredPosition.y;
			float y2 = component2.anchoredPosition.y;
			float num = component.sizeDelta.y;
			float num2 = component.sizeDelta.x;
			if (num2 < 1f)
			{
				num2 = 40f;
			}
			if (num < 1f)
			{
				num = 40f;
			}
			EnsureSprites();
			float num3 = (y + y2) / 2f;
			float num4 = y - num * component.pivot.y;
			float num5 = y2 + num * (1f - component2.pivot.y);
			float num6 = Mathf.Abs(num4 - num5);
			float num7 = 2f;
			float num8 = num2 * 6f;
			_navContainer = new GameObject("PunchingRevised_NavButtons");
			_navContainer.transform.SetParent(val2, false);
			RectTransform val7 = _navContainer.AddComponent<RectTransform>();
			val7.anchorMin = component.anchorMin;
			val7.anchorMax = component.anchorMax;
			val7.pivot = new Vector2(0.5f, 0.5f);
			val7.anchoredPosition = new Vector2(component.anchoredPosition.x, num3);
			val7.sizeDelta = new Vector2(num8, num6);
			VerticalLayoutGroup val8 = _navContainer.AddComponent<VerticalLayoutGroup>();
			((LayoutGroup)val8).childAlignment = (TextAnchor)4;
			((HorizontalOrVerticalLayoutGroup)val8).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)val8).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)val8).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)val8).childForceExpandHeight = true;
			((HorizontalOrVerticalLayoutGroup)val8).spacing = num7;
			string[] array = new string[5] { "Top", "Upper", "Middle", "Lower", "Bottom" };
			float[] array2 = new float[5] { 0f, 0.25f, 0.5f, 0.75f, 1f };
			GameObject gameObject = ((Component)val3).gameObject;
			for (int i = 0; i < 5; i++)
			{
				float frac = array2[i];
				string text = array[i];
				GameObject val9 = Object.Instantiate<GameObject>(gameObject, _navContainer.transform);
				((Object)val9).name = text;
				val9.transform.localRotation = Quaternion.identity;
				LayoutElement component3 = val9.GetComponent<LayoutElement>();
				if ((Object)(object)component3 != (Object)null)
				{
					Object.Destroy((Object)(object)component3);
				}
				BoxCollider component4 = val9.GetComponent<BoxCollider>();
				if ((Object)(object)component4 != (Object)null)
				{
					float num9 = (num6 - num7 * 4f) / 5f;
					component4.size = new Vector3(num8, num9, component4.size.z);
					component4.center = Vector3.zero;
				}
				Button component5 = val9.GetComponent<Button>();
				if ((Object)(object)component5 != (Object)null)
				{
					((UnityEventBase)component5.onClick).RemoveAllListeners();
					((UnityEvent)component5.onClick).AddListener(UnityAction.op_Implicit((Action)delegate
					{
						//IL_001d: 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)
						scrollRect.normalizedPosition = new Vector2(0f, 1f - frac);
						scrollRect.velocity = Vector2.zero;
					}));
					ColorBlock colors = ((Selectable)component5).colors;
					((ColorBlock)(ref colors)).normalColor = new Color(1f, 1f, 1f, 0.06f);
					((ColorBlock)(ref colors)).highlightedColor = new Color(1f, 1f, 1f, 0.25f);
					((ColorBlock)(ref colors)).pressedColor = new Color(1f, 1f, 1f, 1f);
					((ColorBlock)(ref colors)).selectedColor = new Color(1f, 1f, 1f, 0.06f);
					((ColorBlock)(ref colors)).colorMultiplier = 1f;
					((ColorBlock)(ref colors)).fadeDuration = 0.08f;
					((Selectable)component5).colors = colors;
				}
				for (int num10 = val9.transform.childCount - 1; num10 >= 0; num10--)
				{
					Object.Destroy((Object)(object)((Component)val9.transform.GetChild(num10)).gameObject);
				}
				Image component6 = val9.GetComponent<Image>();
				if ((Object)(object)component6 != (Object)null)
				{
					if ((Object)(object)_fillSprite != (Object)null)
					{
						component6.sprite = _fillSprite;
						component6.type = (Type)1;
					}
					((Graphic)component6).color = Color.white;
					((Graphic)component6).raycastTarget = true;
				}
				GameObject val10 = new GameObject("Border");
				val10.transform.SetParent(val9.transform, false);
				RectTransform val11 = val10.AddComponent<RectTransform>();
				val11.anchorMin = Vector2.zero;
				val11.anchorMax = Vector2.one;
				val11.sizeDelta = Vector2.zero;
				val11.anchoredPosition = Vector2.zero;
				Image val12 = val10.AddComponent<Image>();
				if ((Object)(object)_borderSprite != (Object)null)
				{
					val12.sprite = _borderSprite;
					val12.type = (Type)1;
				}
				((Graphic)val12).color = Color.white;
				((Graphic)val12).raycastTarget = false;
				GameObject val13 = new GameObject("Text");
				val13.transform.SetParent(val9.transform, false);
				RectTransform val14 = val13.AddComponent<RectTransform>();
				val14.anchorMin = Vector2.zero;
				val14.anchorMax = Vector2.one;
				val14.sizeDelta = Vector2.zero;
				val14.anchoredPosition = Vector2.zero;
				TextMeshProUGUI val15 = val13.AddComponent<TextMeshProUGUI>();
				((TMP_Text)val15).text = text;
				((TMP_Text)val15).alignment = (TextAlignmentOptions)514;
				((Graphic)val15).color = Color.white;
				((TMP_Text)val15).enableAutoSizing = true;
				((TMP_Text)val15).fontSizeMin = 6f;
				((TMP_Text)val15).fontSizeMax = 42f;
				if ((Object)(object)val6 != (Object)null)
				{
					((TMP_Text)val15).font = val6;
				}
			}
		}

		private static void EnsureSprites()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_fillSprite != (Object)null)
			{
				return;
			}
			int num = 64;
			int num2 = 12;
			int num3 = 3;
			Texture2D val = new Texture2D(num, num, (TextureFormat)4, false);
			((Texture)val).filterMode = (FilterMode)1;
			Texture2D val2 = new Texture2D(num, num, (TextureFormat)4, false);
			((Texture)val2).filterMode = (FilterMode)1;
			for (int i = 0; i < num; i++)
			{
				for (int j = 0; j < num; j++)
				{
					float num4 = RoundedRectSDF(j, i, num, num, num2);
					bool flag = num4 <= 0f;
					bool flag2 = flag && num4 > (float)(-num3);
					val.SetPixel(j, i, flag ? Color.white : Color.clear);
					val2.SetPixel(j, i, flag2 ? Color.white : Color.clear);
				}
			}
			val.Apply();
			val2.Apply();
			float num5 = (float)num2 + 1f;
			Vector4 val3 = default(Vector4);
			((Vector4)(ref val3))..ctor(num5, num5, num5, num5);
			_fillSprite = Sprite.Create(val, new Rect(0f, 0f, (float)num, (float)num), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, val3);
			_borderSprite = Sprite.Create(val2, new Rect(0f, 0f, (float)num, (float)num), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, val3);
		}

		private static float RoundedRectSDF(int px, int py, int w, int h, int r)
		{
			bool flag = px < r || px > w - r - 1;
			bool flag2 = py < r || py > h - r - 1;
			if (flag && flag2)
			{
				float num = ((px < r) ? r : (w - r - 1));
				float num2 = ((py < r) ? r : (h - r - 1));
				float num3 = (float)px - num;
				float num4 = (float)py - num2;
				return Mathf.Sqrt(num3 * num3 + num4 * num4) - (float)r;
			}
			float num5 = px;
			float num6 = w - 1 - px;
			float num7 = py;
			float num8 = h - 1 - py;
			return 0f - Mathf.Min(Mathf.Min(num5, num6), Mathf.Min(num7, num8));
		}
	}
	[HarmonyPatch(typeof(CollisionCollector), "ProcessCollisionHaul", new Type[] { typeof(float) })]
	public static class CollisionHaulPatch
	{
		public static void Prefix(CollisionCollector __instance)
		{
			if (PunchingRevisedMod.Enabled && PunchingRevisedMod.IsLocalPlayerRig((Component)(object)__instance))
			{
				__instance.impactVelocityThresh = 0f;
			}
		}
	}
	[HarmonyPatch(typeof(CollisionCollector), "ProcessCollisionHaul", new Type[]
	{
		typeof(float),
		typeof(float)
	})]
	public static class CollisionHaulNewtonsPatch
	{
		public static void Prefix(CollisionCollector __instance, ref float divByNewtons)
		{
			if (PunchingRevisedMod.Enabled && PunchingRevisedMod.IsLocalPlayerRig((Component)(object)__instance))
			{
				__instance.impactVelocityThresh = 0f;
				divByNewtons = Mathf.Min(divByNewtons, 1f);
			}
		}
	}
	[HarmonyPatch(typeof(HandSFX), "OnSignificantCollisionEnter")]
	public static class HandSFXCollisionPatch
	{
		[ThreadStatic]
		internal static bool _isForcedCall;

		[ThreadStatic]
		internal static bool _isPoisonFollowUp;

		public static void Postfix(HandSFX __instance, RelevantCollision c)
		{
			//IL_047f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0488: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_0421: Unknown result type (might be due to invalid IL or missing references)
			//IL_0426: Unknown result type (might be due to invalid IL or missing references)
			//IL_042e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0433: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			if (!PunchingRevisedMod.Enabled || c == null || !PunchingRevisedMod.IsLocalPlayerRig((Component)(object)__instance))
			{
				return;
			}
			try
			{
				if ((Object)(object)c.collider == (Object)null)
				{
					return;
				}
				RigManager rigManager = Player.RigManager;
				if ((Object)(object)rigManager != (Object)null && ((Component)c.collider).transform.IsChildOf(((Component)rigManager).transform))
				{
					return;
				}
			}
			catch
			{
				return;
			}
			bool flag = PunchingRevisedMod.IsLeftHand(__instance);
			if ((PunchingRevisedMod.FistGesture && !PunchingRevisedMod.IsHandGripping(flag)) || (!PunchingRevisedMod.PunchWhileGrabbing && PunchingRevisedMod.IsHandHoldingSomething(flag)) || (PunchingRevisedMod.SpeedRequirement && PunchingRevisedMod.GetHandSpeed(__instance) < 2.5f))
			{
				return;
			}
			if (!PunchingRevisedMod.AnyRapidFire)
			{
				float num = (flag ? PunchingRevisedMod.LastForcedPunchTimeLeft : PunchingRevisedMod.LastForcedPunchTimeRight);
				if (Time.time - num < 0.15f)
				{
					return;
				}
			}
			float nextImpactTime = __instance._nextImpactTime;
			float lastImpulse = __instance._lastImpulse;
			float lastHandChestVelSqMg = __instance._lastHandChestVelSqMg;
			bool fixedRan = __instance._fixedRan;
			Vector3 relativeVelocity = c.relativeVelocity;
			Vector3 totalImpulse = c.totalImpulse;
			__instance._nextImpactTime = 0f;
			__instance._lastImpulse = 0f;
			__instance._lastHandChestVelSqMg = 100f;
			__instance._fixedRan = true;
			c.relativeVelocity = ((((Vector3)(ref relativeVelocity)).sqrMagnitude > 0.5f) ? (((Vector3)(ref relativeVelocity)).normalized * 10f) : (Vector3.forward * 10f));
			c.totalImpulse = ((((Vector3)(ref totalImpulse)).sqrMagnitude > 0.5f) ? (((Vector3)(ref totalImpulse)).normalized * 50f) : (Vector3.forward * 50f));
			bool isFusionPlayer = false;
			byte targetId = 0;
			try
			{
				isFusionPlayer = PunchingRevisedMod.TryGetFusionTarget(c.collider, out targetId);
			}
			catch
			{
			}
			_isForcedCall = true;
			bool flag2 = __instance.PunchAttack(c, 10f, 100f);
			_isForcedCall = false;
			if (PunchingRevisedMod.UltraRapidFire && flag2)
			{
				try
				{
					PunchingRevisedMod.ActiveSequences.Add(new PunchingRevisedMod.PunchSequence
					{
						HandSfx = __instance,
						EnemyCollider = c.collider,
						EnemyRigidbody = c.rigidbody,
						SelfCollider = c.colliderSelf,
						ImpactProps = c.iP,
						ContactPoint = c.point,
						ContactNormal = c.normal,
						HitsRemaining = 2,
						FrameCounter = 0,
						IsFusionPlayer = isFusionPlayer,
						FusionTargetId = targetId
					});
				}
				catch
				{
				}
			}
			if (PunchingRevisedMod.PoisonFist && flag2)
			{
				try
				{
					int instanceID = ((Object)((Component)((Component)c.collider).transform.root).gameObject).GetInstanceID();
					if (!PunchingRevisedMod.PoisonTargets.TryGetValue(instanceID, out var value))
					{
						value = new PunchingRevisedMod.PoisonTarget();
						PunchingRevisedMod.PoisonTargets[instanceID] = value;
					}
					int count = value.Queue.Count;
					int num2 = Mathf.Min(8, 50 - count);
					bool flag3 = false;
					if (!value.LethalityActive && count + 8 >= 50)
					{
						value.LethalityActive = true;
						flag3 = true;
					}
					if (value.LethalityActive && !flag3)
					{
						value.LethalityCounter++;
						if (value.LethalityCounter >= 5)
						{
							value.LethalityCounter = 0;
							value.LethalityMultiplier *= 2f;
						}
					}
					if (num2 > 0)
					{
						PunchingRevisedMod.PoisonHit poisonHit = default(PunchingRevisedMod.PoisonHit);
						poisonHit.HandSfx = __instance;
						poisonHit.EnemyCollider = c.collider;
						poisonHit.EnemyRigidbody = c.rigidbody;
						poisonHit.SelfCollider = c.colliderSelf;
						poisonHit.ImpactProps = c.iP;
						poisonHit.ContactPoint = c.point;
						poisonHit.ContactNormal = c.normal;
						poisonHit.IsFusionPlayer = isFusionPlayer;
						poisonHit.FusionTargetId = targetId;
						PunchingRevisedMod.PoisonHit item = poisonHit;
						for (int i = 0; i < num2; i++)
						{
							value.Queue.Enqueue(item);
						}
					}
				}
				catch
				{
				}
			}
			c.relativeVelocity = relativeVelocity;
			c.totalImpulse = totalImpulse;
			if (flag2)
			{
				if (flag)
				{
					PunchingRevisedMod.LastForcedPunchTimeLeft = Time.time;
				}
				else
				{
					PunchingRevisedMod.LastForcedPunchTimeRight = Time.time;
				}
				__instance._nextImpactTime = Time.time + 0.15f;
				PunchingRevisedMod.PlayPunchSFX(__instance, c.point);
			}
			else
			{
				__instance._nextImpactTime = nextImpactTime;
				__instance._lastImpulse = lastImpulse;
				__instance._lastHandChestVelSqMg = lastHandChestVelSqMg;
				__instance._fixedRan = fixedRan;
			}
		}
	}
	[HarmonyPatch(typeof(HandSFX), "PunchAttack")]
	public static class PunchAttackPatch
	{
		internal static bool _needsRestore = false;

		internal static bool _restoreIsLeft = false;

		internal static float _overrideSpeed = -1f;

		public static bool Prefix(HandSFX __instance, ref float impulse, ref float relVelSqr)
		{
			if (!PunchingRevisedMod.Enabled)
			{
				return true;
			}
			if (!PunchingRevisedMod.IsLocalPlayerRig((Component)(object)__instance))
			{
				return true;
			}
			bool isForcedCall = HandSFXCollisionPatch._isForcedCall;
			bool isPoisonFollowUp = HandSFXCollisionPatch._isPoisonFollowUp;
			HandSFXCollisionPatch._isForcedCall = false;
			HandSFXCollisionPatch._isPoisonFollowUp = false;
			if (!isForcedCall)
			{
				return false;
			}
			relVelSqr = Mathf.Max(relVelSqr, 100f);
			impulse = Mathf.Max(impulse, 10f);
			if (PunchingRevisedMod.AnyRapidFire)
			{
				__instance._nextImpactTime = 0f;
				__instance._lastImpulse = 0f;
			}
			_needsRestore = false;
			if (!isPoisonFollowUp && PunchingRevisedMod.SpeedScaling && PunchingRevisedMod._proxyCached)
			{
				_restoreIsLeft = PunchingRevisedMod.IsLeftHand(__instance);
				float speed = ((_overrideSpeed >= 0f) ? _overrideSpeed : PunchingRevisedMod.GetHandSpeed(__instance));
				float scale = PunchingRevisedMod.ComputeSpeedScale(speed);
				PunchingRevisedMod.ApplyScale(scale, _restoreIsLeft);
				_needsRestore = true;
			}
			_overrideSpeed = -1f;
			return true;
		}

		public static void Postfix(HandSFX __instance)
		{
			if (_needsRestore)
			{
				_needsRestore = false;
				PunchingRevisedMod.RestoreProxy(_restoreIsLeft);
			}
		}
	}
	[HarmonyPatch(typeof(CollisionSFX), "OnSignificantCollisionEnter")]
	public static class BodyCollisionPatch
	{
		public static void Postfix(CollisionSFX __instance, RelevantCollision c)
		{
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			if (!PunchingRevisedMod.Enabled || !PunchingRevisedMod.MoreThanHands || c == null || (Object)(object)c.collider == (Object)null)
			{
				return;
			}
			try
			{
				if (!PunchingRevisedMod.IsPlayerBody(__instance))
				{
					return;
				}
				RigManager rigManager = Player.RigManager;
				if (((Object)(object)rigManager != (Object)null && ((Component)c.collider).transform.IsChildOf(((Component)rigManager).transform)) || (!PunchingRevisedMod.AnyRapidFire && Time.time - PunchingRevisedMod.LastBodyHitTime < 0.15f))
				{
					return;
				}
				float bodyPartSpeed = PunchingRevisedMod.GetBodyPartSpeed(__instance, c);
				if (PunchingRevisedMod.SpeedRequirement && bodyPartSpeed < 2.5f)
				{
					return;
				}
				HandSFX playerHandSFX = PunchingRevisedMod.GetPlayerHandSFX();
				if (!((Object)(object)playerHandSFX == (Object)null))
				{
					float nextImpactTime = playerHandSFX._nextImpactTime;
					float lastImpulse = playerHandSFX._lastImpulse;
					float lastHandChestVelSqMg = playerHandSFX._lastHandChestVelSqMg;
					bool fixedRan = playerHandSFX._fixedRan;
					playerHandSFX._nextImpactTime = 0f;
					playerHandSFX._lastImpulse = 0f;
					playerHandSFX._lastHandChestVelSqMg = 100f;
					playerHandSFX._fixedRan = true;
					Vector3 relativeVelocity = c.relativeVelocity;
					Vector3 totalImpulse = c.totalImpulse;
					c.relativeVelocity = ((((Vector3)(ref relativeVelocity)).sqrMagnitude > 0.5f) ? (((Vector3)(ref relativeVelocity)).normalized * 10f) : (Vector3.forward * 10f));
					c.totalImpulse = ((((Vector3)(ref totalImpulse)).sqrMagnitude > 0.5f) ? (((Vector3)(ref totalImpulse)).normalized * 50f) : (Vector3.forward * 50f));
					PunchAttackPatch._overrideSpeed = bodyPartSpeed;
					HandSFXCollisionPatch._isForcedCall = true;
					bool flag = playerHandSFX.PunchAttack(c, 10f, 100f);
					HandSFXCollisionPatch._isForcedCall = false;
					PunchAttackPatch._overrideSpeed = -1f;
					c.relativeVelocity = relativeVelocity;
					c.totalImpulse = totalImpulse;
					if (flag)
					{
						PunchingRevisedMod.LastBodyHitTime = Time.time;
						PunchingRevisedMod.PlayPunchSFX(playerHandSFX, c.point, bodyPartSpeed);
						return;
					}
					playerHandSFX._nextImpactTime = nextImpactTime;
					playerHandSFX._lastImpulse = lastImpulse;
					playerHandSFX._lastHandChestVelSqMg = lastHandChestVelSqMg;
					playerHandSFX._fixedRan = fixedRan;
				}
			}
			catch
			{
			}
		}
	}
}