Decompiled source of DynamicRagdoll v1.0.5

Mods\DynamicRagdoll.dll

Decompiled 8 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BoneLib.BoneMenu;
using EuphoriaLite;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSLZ.Marrow.PuppetMasta;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using RagdollOnHit;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(EuphoriaLiteMod), "DynamicRagdoll", "1.0.3", "skait5k", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: MelonAdditionalDependencies(new string[] { "DynamicRagdoll2" })]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("DynamicRagdoll")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("DynamicRagdoll")]
[assembly: AssemblyTitle("DynamicRagdoll")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace EuphoriaLite
{
	public class EuphoriaLiteMod : MelonMod
	{
		private sealed class Clutch
		{
			public PuppetMaster Pm;

			public SubBehaviourHealth Health;

			public Rigidbody Target;

			public Vector3 LocalPoint;

			public bool HasLocal;

			public Rigidbody LeftHand;

			public Rigidbody RightHand;

			public Rigidbody HeadBody;

			public Rigidbody LeftElbow;

			public Rigidbody RightElbow;

			public Vector3 OffsetL;

			public Vector3 OffsetR;

			public float StartedAt;

			public float Until;

			public float DelayUntil;

			public float Loosen;
		}

		private sealed class Downed
		{
			public PuppetMaster Pm;

			public SubBehaviourHealth Health;

			public Rigidbody[] Bodies;

			public float Until;

			public float NextWrithe;

			public bool BracingNow;

			public float PrevH = 99f;

			public bool Landed;

			public bool LastStand;

			public int Rolls;

			public MuscleRegion Region;

			public float NextStir;

			public float NextSfx;

			public Animator Anim;

			public float AnimSpeed = 1f;

			public bool HasAnim;
		}

		private sealed class BalanceState
		{
			public float Loss;

			public float LastTime = -100f;

			public float WindowT = -100f;

			public int WindowCount;

			public float LastWindowEnd = -100f;
		}

		private sealed class Stagger
		{
			public PuppetMaster Pm;

			public SubBehaviourHealth Health;

			public Animator TargetAnim;

			public float TargetSpeed = 1f;

			public Rigidbody[] Bodies;

			public Rigidbody Hips;

			public Rigidbody FootL;

			public Rigidbody FootR;

			public Vector3 Dir;

			public float StartedAt;

			public float HipsY0;

			public float V0;

			public float PeakDv;

			public float BornAt;

			public int Steps;

			public float BalancedSince = -1f;

			public float KickMul = 1f;

			public float Spin;

			public float StepForceMul = 1f;

			public float StepLiftMul = 1f;

			public bool Bracing;

			public MuscleRegion Region;

			public int HitMuscle;

			public float ShoveMul = 1f;

			public bool Pellet;

			public float MassScale = 1f;

			public float GunMul = 1f;

			public string GunName = "?";

			public bool Melee;

			public bool Sharp;

			public float LastDSeg;

			public float LastDrop;

			public Vector3 StartPos;

			public float OrigSpine;

			public float OrigArmL;

			public float OrigArmR;

			public bool Swinging;

			public bool SwingLeft;

			public Vector3 SwingTarget;

			public Vector3 SwingFrom;

			public float SwingStart;

			public float SwingUntil;

			public float NextStepAt;

			public float PlantUntil;

			public Rigidbody LastFoot;
		}

		private sealed class NpcWatch
		{
			public PuppetMaster Pm;

			public Rigidbody Hips;
		}

		private sealed class AnimThaw
		{
			public Animator Anim;

			public float To;

			public float Until;
		}

		private sealed class Scales
		{
			public PuppetMaster Pm;

			public float[] Original = new float[17];

			public float[] Factor = new float[17];

			public float[] Target = new float[17];

			public float[] Up = new float[17];

			public float[] Down = new float[17];

			public float[] LastSet = new float[17];

			public float[] OriginalMap = new float[17];

			public float[] FactorMap = new float[17];

			public float[] TargetMap = new float[17];

			public float[] LastSetMap = new float[17];

			public Scales(PuppetMaster pm)
			{
				Pm = pm;
				for (int i = 0; i < 17; i++)
				{
					Original[i] = float.NaN;
					LastSet[i] = float.NaN;
					Factor[i] = 1f;
					Target[i] = 1f;
					Up[i] = 2f;
					Down[i] = 4f;
					OriginalMap[i] = float.NaN;
					FactorMap[i] = 1f;
					TargetMap[i] = 1f;
					LastSetMap[i] = float.NaN;
				}
			}
		}

		private const int RootM = 0;

		private const int SpineM = 7;

		private const int AnkleL = 3;

		private const int AnkleR = 6;

		private const int ChestM = 8;

		private const int HeadM = 9;

		private const int JawM = 16;

		private const int WristL = 12;

		private const int WristR = 15;

		private const int MuscleCount = 17;

		private static readonly int[] LegMusclesL = new int[3] { 1, 2, 3 };

		private static readonly int[] LegMusclesR = new int[3] { 4, 5, 6 };

		private static readonly int[] ArmMusclesL = new int[3] { 10, 11, 12 };

		private static readonly int[] ArmMusclesR = new int[3] { 13, 14, 15 };

		private static readonly int[] TorsoMuscles = new int[4] { 7, 8, 9, 16 };

		private static readonly int[] WritheMuscles = new int[6] { 9, 8, 12, 15, 3, 6 };

		internal static MelonPreferences_Entry<bool> Enabled;

		internal static MelonPreferences_Entry<bool> BalanceEnabled;

		internal static MelonPreferences_Entry<bool> FlipDirection;

		internal static MelonPreferences_Entry<bool> VarietyEnabled;

		internal static MelonPreferences_Entry<bool> MeleeEnabled;

		internal static MelonPreferences_Entry<bool> WalkThrough;

		internal static MelonPreferences_Entry<float> ClutchSeconds;

		internal static MelonPreferences_Entry<float> ClutchAcceleration;

		internal static MelonPreferences_Entry<float> ArmLooseness;

		internal static MelonPreferences_Entry<float> ClutchDelay;

		internal static MelonPreferences_Entry<float> HeadClutchChance;

		internal static MelonPreferences_Entry<float> FallThreshold;

		internal static MelonPreferences_Entry<float> BalanceRecovery;

		internal static MelonPreferences_Entry<float> LegGiveWay;

		internal static MelonPreferences_Entry<float> FallSeconds;

		internal static MelonPreferences_Entry<float> FallShove;

		internal static MelonPreferences_Entry<float> FallArmSplay;

		internal static MelonPreferences_Entry<float> StaggerArmFling;

		internal static MelonPreferences_Entry<float> FlailForce;

		internal static MelonPreferences_Entry<float> BraceForce;

		internal static MelonPreferences_Entry<float> LimbKick;

		internal static MelonPreferences_Entry<float> WritheForce;

		internal static MelonPreferences_Entry<float> HandSpeedCap;

		internal static MelonPreferences_Entry<float> GunForce;

		internal static MelonPreferences_Entry<float> MeleeForce;

		internal static MelonPreferences_Entry<float> SharpForce;

		internal static MelonPreferences_Entry<float> SharpClutchSeconds;

		internal static MelonPreferences_Entry<float> PunchClutchMax;

		internal static MelonPreferences_Entry<float> HeavyClutchDamage;

		internal static MelonPreferences_Entry<int> LastStandMaxRolls;

		internal static MelonPreferences_Entry<float> StaggerSeconds;

		internal static MelonPreferences_Entry<float> MinStaggerSeconds;

		internal static MelonPreferences_Entry<float> UpperBodyStun;

		internal static MelonPreferences_Entry<float> RecoverStun;

		internal static MelonPreferences_Entry<float> HipsKick;

		internal static MelonPreferences_Entry<float> ChestKick;

		internal static MelonPreferences_Entry<float> HeadKick;

		internal static MelonPreferences_Entry<float> SnapSeconds;

		internal static MelonPreferences_Entry<float> StaggerWeight;

		internal static MelonPreferences_Entry<float> StaggerMapping;

		internal static MelonPreferences_Entry<float> UpperMapWeight;

		internal static MelonPreferences_Entry<float> TorsoLift;

		internal static MelonPreferences_Entry<float> ForwardBend;

		internal static MelonPreferences_Entry<float> ShoveForce;

		internal static MelonPreferences_Entry<float> ShoveSeconds;

		internal static MelonPreferences_Entry<float> TorsoStrength;

		internal static MelonPreferences_Entry<float> HeadStrength;

		internal static MelonPreferences_Entry<float> MuscleRecoverSeconds;

		internal static MelonPreferences_Entry<float> MuscleLoosenSeconds;

		internal static MelonPreferences_Entry<float> LegStrength;

		internal static MelonPreferences_Entry<float> LegMapping;

		internal static MelonPreferences_Entry<float> LegHitStrength;

		internal static MelonPreferences_Entry<float> HipAssist;

		internal static MelonPreferences_Entry<float> LimpSway;

		internal static MelonPreferences_Entry<float> OrientToFall;

		internal static MelonPreferences_Entry<float> KneeChance;

		internal static MelonPreferences_Entry<float> DeathArch;

		internal static MelonPreferences_Entry<float> LastStandHp;

		internal static MelonPreferences_Entry<float> LastStandHpAbs;

		internal static MelonPreferences_Entry<float> AnimFreezeSeconds;

		internal static MelonPreferences_Entry<float> AdvanceForce;

		internal static MelonPreferences_Entry<int> MaxSteps;

		internal static MelonPreferences_Entry<int> CfgVersion;

		internal static MelonPreferences_Entry<float> MaxStepLength;

		internal static MelonPreferences_Entry<float> SwingSeconds;

		internal static MelonPreferences_Entry<float> SwingForce;

		internal static MelonPreferences_Entry<float> LiftForce;

		internal static MelonPreferences_Entry<float> PlantForce;

		internal static MelonPreferences_Entry<float> SwingLegStrength;

		internal static MelonPreferences_Entry<float> BalanceMargin;

		internal static MelonPreferences_Entry<float> StepMargin;

		internal static MelonPreferences_Entry<float> FallDistance;

		internal static MelonPreferences_Entry<float> FallDrop;

		internal static MelonPreferences_Entry<float> AssistRampSeconds;

		private static readonly Dictionary<int, Clutch> Clutches = new Dictionary<int, Clutch>();

		private static readonly Dictionary<int, Downed> DownedMap = new Dictionary<int, Downed>();

		private static readonly Dictionary<int, NpcWatch> KnownNpcs = new Dictionary<int, NpcWatch>();

		private static int _scanFrame;

		private static int _scanLogs;

		private static readonly Dictionary<int, BalanceState> Balances = new Dictionary<int, BalanceState>();

		private static readonly Dictionary<int, Stagger> Staggers = new Dictionary<int, Stagger>();

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

		private static readonly Dictionary<int, AnimThaw> Thaws = new Dictionary<int, AnimThaw>();

		private static bool _loggedClutch;

		private static int _balanceLogs;

		private static int _staggerLogs;

		private static int _stepLogs;

		private static int _endLogs;

		private static int _styleLogs;

		private static int _strideLogs;

		private static int _rigLogs;

		private static int _meshLogs;

		private static int _clutchDbg;

		private static int _standLogs;

		private static int _peakLogs;

		private static int _floorLogs;

		private static int _floorLastTick;

		private static int _spamTick;

		private static readonly Dictionary<int, Scales> ScaleMap = new Dictionary<int, Scales>();

		private static int _propLogs;

		private static int _mapLogs;

		private static bool MeleeSharp(string attackType)
		{
			if (string.IsNullOrEmpty(attackType))
			{
				return false;
			}
			string text = attackType.ToLowerInvariant();
			if (!text.Contains("stab") && !text.Contains("slash") && !text.Contains("cut") && !text.Contains("claw") && !text.Contains("bite") && !text.Contains("whip"))
			{
				return text.Contains("chop");
			}
			return true;
		}

		private static bool MeleeAxe(string attackType)
		{
			if (string.IsNullOrEmpty(attackType))
			{
				return false;
			}
			return attackType.ToLowerInvariant().Contains("axe");
		}

		private static float MeleeVol(string attackType)
		{
			try
			{
				return MeleeSharp(attackType) ? SharpForce.Value : MeleeForce.Value;
			}
			catch
			{
				return 1f;
			}
		}

		private static bool IsMelee(string attackType)
		{
			if (string.IsNullOrEmpty(attackType))
			{
				return false;
			}
			string text = attackType.ToLowerInvariant();
			if (!text.Contains("blunt") && !text.Contains("stab") && !text.Contains("slash") && !text.Contains("punch") && !text.Contains("melee") && !text.Contains("claw") && !text.Contains("bite") && !text.Contains("cut") && !text.Contains("axe") && !text.Contains("blade") && !text.Contains("bat") && !text.Contains("whip"))
			{
				return text.Contains("chop");
			}
			return true;
		}

		private static bool PunchJab(NpcHitInfo info)
		{
			try
			{
				if (PunchClutchMax.Value <= 0f)
				{
					return false;
				}
				if (MeleeSharp(info.AttackType))
				{
					return false;
				}
				if (!IsMelee(info.AttackType))
				{
					return false;
				}
				return info.Damage >= 0f && info.Damage < PunchClutchMax.Value;
			}
			catch
			{
				return false;
			}
		}

		private static bool UsesLastStand(PuppetMaster pm, SubBehaviourHealth h)
		{
			try
			{
				if (RagdollApi.IsNullBody(pm))
				{
					return false;
				}
				if (h == null)
				{
					return false;
				}
				float num = RagdollApi.CurHp(h);
				bool num2 = LastStandHpAbs.Value > 0f && num >= 0f && num <= LastStandHpAbs.Value;
				bool flag = LastStandHp.Value > 0f && HpFraction(h) < LastStandHp.Value;
				return num2 || flag;
			}
			catch
			{
				return false;
			}
		}

		private static float CaptureAnimSpeed(Animator ta)
		{
			try
			{
				float speed = ta.speed;
				return (speed > 0.01f) ? speed : 1f;
			}
			catch
			{
				return 1f;
			}
		}

		private static void RestoreAnimSpeed(Animator ta, float stored)
		{
			try
			{
				if ((Object)(object)ta != (Object)null)
				{
					ta.speed = ((stored > 0.01f) ? stored : 1f);
				}
			}
			catch
			{
			}
		}

		private static float DownedAnimSpeed(int id, float staggerBase, Animator ta)
		{
			try
			{
				if (Thaws.TryGetValue(id, out var value) && value.To > 0.01f)
				{
					return value.To;
				}
				if (staggerBase > 0.01f)
				{
					return staggerBase;
				}
				return CaptureAnimSpeed(ta);
			}
			catch
			{
				return 1f;
			}
		}

		public override void OnInitializeMelon()
		{
			MelonPreferences_Category obj = MelonPreferences.CreateCategory("EuphoriaLite");
			Enabled = obj.CreateEntry<bool>("Enabled", true, "Euphoria layer on/off (clutch, stagger, falls)", (string)null, false, false, (ValueValidator)null, (string)null);
			ClutchSeconds = obj.CreateEntry<float>("ClutchSeconds", 0.8f, "How long the hands are pulled to the wound", (string)null, false, false, (ValueValidator)null, (string)null);
			ClutchAcceleration = obj.CreateEntry<float>("ClutchAcceleration", 60f, "Pull strength on the hands (m/s^2)", (string)null, false, false, (ValueValidator)null, (string)null);
			ArmLooseness = obj.CreateEntry<float>("ArmLooseness", 0.15f, "Arm stun level while clutching (0 = limp, 1 = normal)", (string)null, false, false, (ValueValidator)null, (string)null);
			ClutchDelay = obj.CreateEntry<float>("ClutchDelay", 0.15f, "RAGE CTaskNMShot: reach-for-wound delay 100-200ms (s)", (string)null, false, false, (ValueValidator)null, (string)null);
			HeadClutchChance = obj.CreateEntry<float>("HeadClutchChance", 0.25f, "RAGE DisableReachForWoundOnHeadShot: hands rarely reach to head (0-1)", (string)null, false, false, (ValueValidator)null, (string)null);
			BalanceEnabled = obj.CreateEntry<bool>("BalanceEnabled", true, "Legs try to hold the NPC up (off = every medium hit knocks him down)", (string)null, false, false, (ValueValidator)null, (string)null);
			VarietyEnabled = obj.CreateEntry<bool>("VarietyEnabled", true, "No two hits play out the same (kick strength, spin, clutch side)", (string)null, false, false, (ValueValidator)null, (string)null);
			FlipDirection = obj.CreateEntry<bool>("FlipDirection", false, "Set true if NPCs are pushed TOWARD you when shot", (string)null, false, false, (ValueValidator)null, (string)null);
			WalkThrough = obj.CreateEntry<bool>("WalkThrough", true, "Shot NPCs keep walking at you: legs stay game-driven, only the upper body reacts (off = full takeover)", (string)null, false, false, (ValueValidator)null, (string)null);
			FallThreshold = obj.CreateEntry<float>("FallThreshold", 1.6f, "Balance loss at which he falls outright (0 = every hit)", (string)null, false, false, (ValueValidator)null, (string)null);
			GunForce = obj.CreateEntry<float>("GunForce", 0.65f, "Global gun volume: Eder22-level. All kicks, shoves and loss scale off this", (string)null, false, false, (ValueValidator)null, (string)null);
			MeleeEnabled = obj.CreateEntry<bool>("MeleeEnabled", true, "Melee hits run the same reactions as gunshots (off = skipped, old behavior)", (string)null, false, false, (ValueValidator)null, (string)null);
			MeleeForce = obj.CreateEntry<float>("MeleeForce", 0.65f, "Blunt-melee volume (fists included: Marrow labels those Blunt, indistinguishable)", (string)null, false, false, (ValueValidator)null, (string)null);
			PunchClutchMax = obj.CreateEntry<float>("PunchClutchMax", 1.5f, "Blunt hits below this damage skip the clutch (jabs snap, don't grab). 0 = always clutch", (string)null, false, false, (ValueValidator)null, (string)null);
			HeavyClutchDamage = obj.CreateEntry<float>("HeavyClutchDamage", 3f, "Melee hits at/above this damage clutch as long as stabs (machete chops, axe). 0 = off", (string)null, false, false, (ValueValidator)null, (string)null);
			SharpForce = obj.CreateEntry<float>("SharpForce", 0.4f, "Stab/slash volume: low launch, the wound does the work via SharpClutchSeconds", (string)null, false, false, (ValueValidator)null, (string)null);
			SharpClutchSeconds = obj.CreateEntry<float>("SharpClutchSeconds", 1.6f, "How long stabs are clutched (a cut stays; ~2x the gunshot clutch)", (string)null, false, false, (ValueValidator)null, (string)null);
			BalanceRecovery = obj.CreateEntry<float>("BalanceRecovery", 1f, "Balance loss that drains per second", (string)null, false, false, (ValueValidator)null, (string)null);
			LegGiveWay = obj.CreateEntry<float>("LegGiveWay", 0.5f, "He falls if a leg's stun level is below this (leg shot)", (string)null, false, false, (ValueValidator)null, (string)null);
			FallSeconds = obj.CreateEntry<float>("FallSeconds", 3f, "How long he stays down once he falls", (string)null, false, false, (ValueValidator)null, (string)null);
			FallShove = obj.CreateEntry<float>("FallShove", 3f, "Push on the hit body part when he falls outright", (string)null, false, false, (ValueValidator)null, (string)null);
			FallArmSplay = obj.CreateEntry<float>("FallArmSplay", 3f, "How hard the arms fling out wide as he falls (m/s, 0 = off)", (string)null, false, false, (ValueValidator)null, (string)null);
			StaggerArmFling = obj.CreateEntry<float>("StaggerArmFling", 0.6f, "Startle throw of the arms on every stagger hit (m/s, 0 = off)", (string)null, false, false, (ValueValidator)null, (string)null);
			FlailForce = obj.CreateEntry<float>("FlailForce", 0f, "RAGE armsWindmillAdaptive: slow tightrope sway once clutch lets go (m/s^2, 0 = off)", (string)null, false, false, (ValueValidator)null, (string)null);
			BraceForce = obj.CreateEntry<float>("BraceForce", 45f, "Arms stiffen and reach for the ground while falling (m/s^2, 0 = off)", (string)null, false, false, (ValueValidator)null, (string)null);
			LimbKick = obj.CreateEntry<float>("LimbKick", 2.6f, "Extra yank on the exact limb that was shot (m/s, 0 = off)", (string)null, false, false, (ValueValidator)null, (string)null);
			WritheForce = obj.CreateEntry<float>("WritheForce", 1.5f, "RAGE bodyWrithe: small fast writhe, mostly back/legs not arms (m/s, 0 = off)", (string)null, false, false, (ValueValidator)null, (string)null);
			HandSpeedCap = obj.CreateEntry<float>("HandSpeedCap", 8f, "Hands can never exceed this speed (m/s): makes joint-stretching impossible", (string)null, false, false, (ValueValidator)null, (string)null);
			StaggerSeconds = obj.CreateEntry<float>("StaggerSeconds", 2.6f, "RAGE onFire staggerTime direction: longest a stagger lasts (s)", (string)null, false, false, (ValueValidator)null, (string)null);
			MinStaggerSeconds = obj.CreateEntry<float>("MinStaggerSeconds", 1.5f, "Staggers always play out at least this long (visible reaction)", (string)null, false, false, (ValueValidator)null, (string)null);
			AnimFreezeSeconds = obj.CreateEntry<float>("AnimFreezeSeconds", 0.3f, "How long the animator stays frozen on impact before running again under physics (0 = never freeze)", (string)null, false, false, (ValueValidator)null, (string)null);
			AdvanceForce = obj.CreateEntry<float>("AdvanceForce", 6f, "Stagger drive toward you: shot NPCs keep coming instead of stopping (0 = old statue)", (string)null, false, false, (ValueValidator)null, (string)null);
			StaggerWeight = obj.CreateEntry<float>("StaggerWeight", 0.7f, "RAGE skeleton 100->35: whole-body strength in a stagger (low = floppy)", (string)null, false, false, (ValueValidator)null, (string)null);
			StaggerMapping = obj.CreateEntry<float>("StaggerMapping", 0.3f, "Whole-body animation glue in a stagger (low = physics owns the pose)", (string)null, false, false, (ValueValidator)null, (string)null);
			UpperMapWeight = obj.CreateEntry<float>("UpperMapWeight", 0.1f, "How glued torso/head/arms are to the frozen pose in a stagger (low = they whip and clutch)", (string)null, false, false, (ValueValidator)null, (string)null);
			TorsoLift = obj.CreateEntry<float>("TorsoLift", 18f, "Upward force on the chest during a stagger, stops it folding (m/s^2, 0 = off)", (string)null, false, false, (ValueValidator)null, (string)null);
			ForwardBend = obj.CreateEntry<float>("ForwardBend", 8f, "RAGE staggerFall.alwaysBendForwards: crouch forward at the hip while staggering", (string)null, false, false, (ValueValidator)null, (string)null);
			ShoveForce = obj.CreateEntry<float>("ShoveForce", 12f, "Sustained push along the shot during a stagger, carries him back (m/s^2, 0 = off)", (string)null, false, false, (ValueValidator)null, (string)null);
			ShoveSeconds = obj.CreateEntry<float>("ShoveSeconds", 0.45f, "How long the sustained push lasts", (string)null, false, false, (ValueValidator)null, (string)null);
			SnapSeconds = obj.CreateEntry<float>("SnapSeconds", 0.22f, "Upper-body snap on impact before the struggle starts (0 = off)", (string)null, false, false, (ValueValidator)null, (string)null);
			UpperBodyStun = obj.CreateEntry<float>("UpperBodyStun", 0.1f, "How limp the ARMS go in a stagger (0 = limp, 1 = stiff)", (string)null, false, false, (ValueValidator)null, (string)null);
			TorsoStrength = obj.CreateEntry<float>("TorsoStrength", 0.25f, "RAGE skeleton: spine/chest strength in a stagger (0 = limp, 1 = normal)", (string)null, false, false, (ValueValidator)null, (string)null);
			HeadStrength = obj.CreateEntry<float>("HeadStrength", 0.15f, "RAGE skeleton: head/neck strength in a stagger (neck 100->35-40)", (string)null, false, false, (ValueValidator)null, (string)null);
			LegStrength = obj.CreateEntry<float>("LegStrength", 0.6f, "RAGE lowerBodyStiffness 13->14: stance-leg strength (holds him up)", (string)null, false, false, (ValueValidator)null, (string)null);
			LegHitStrength = obj.CreateEntry<float>("LegHitStrength", 0.3f, "Shot-leg strength in a stagger (limps instead of ragdolling)", (string)null, false, false, (ValueValidator)null, (string)null);
			LegMapping = obj.CreateEntry<float>("LegMapping", 0.15f, "How glued legs are to the walk animation in a stagger (low = physics owns them)", (string)null, false, false, (ValueValidator)null, (string)null);
			MuscleRecoverSeconds = obj.CreateEntry<float>("MuscleRecoverSeconds", 1.6f, "How long spine/head take to stiffen back up afterwards", (string)null, false, false, (ValueValidator)null, (string)null);
			MuscleLoosenSeconds = obj.CreateEntry<float>("MuscleLoosenSeconds", 0.5f, "How fast spine/head go limp after a hit (higher = softer, less collapse)", (string)null, false, false, (ValueValidator)null, (string)null);
			HipAssist = obj.CreateEntry<float>("HipAssist", 30f, "RAGE removed hipLeanAcc/resistAcc cheats: small hip servo back over feet (m/s^2, 0 = off)", (string)null, false, false, (ValueValidator)null, (string)null);
			LimpSway = obj.CreateEntry<float>("LimpSway", 15f, "Side-to-side sway on leg hits, forces weight shifts and limping steps (m/s^2, 0 = off)", (string)null, false, false, (ValueValidator)null, (string)null);
			OrientToFall = obj.CreateEntry<float>("OrientToFall", 6f, "RAGE highFall.orientateBodyToFallDirection: chest steers toward travel dir", (string)null, false, false, (ValueValidator)null, (string)null);
			KneeChance = obj.CreateEntry<float>("KneeChance", 0.28f, "RAGE ChanceOfFallToKnees 0.25 + GutShot 0.30: fall becomes long stagger instead", (string)null, false, false, (ValueValidator)null, (string)null);
			LastStandHp = obj.CreateEntry<float>("LastStandHp", 0.15f, "Fallback fraction gate when absolute HP is unreadable (0 = off)", (string)null, false, false, (ValueValidator)null, (string)null);
			LastStandHpAbs = obj.CreateEntry<float>("LastStandHpAbs", 5f, "Absolute HP at/below which last stand triggers even above the fraction gate (0 = off)", (string)null, false, false, (ValueValidator)null, (string)null);
			DeathArch = obj.CreateEntry<float>("DeathArch", 2f, "RAGE smartFall: brief rigid arch on death before going limp (m/s, 0 = off)", (string)null, false, false, (ValueValidator)null, (string)null);
			RecoverStun = obj.CreateEntry<float>("RecoverStun", 0.7f, "Where upper-body stiffness restarts from afterwards (higher = recovers faster)", (string)null, false, false, (ValueValidator)null, (string)null);
			HipsKick = obj.CreateEntry<float>("HipsKick", 1.8f, "Instant speed given to the hips along the push (m/s)", (string)null, false, false, (ValueValidator)null, (string)null);
			ChestKick = obj.CreateEntry<float>("ChestKick", 3f, "Instant speed given to the chest along the push (m/s)", (string)null, false, false, (ValueValidator)null, (string)null);
			HeadKick = obj.CreateEntry<float>("HeadKick", 2f, "Instant speed given to the head along the push (m/s)", (string)null, false, false, (ValueValidator)null, (string)null);
			MaxSteps = obj.CreateEntry<int>("MaxSteps", 8, "Most catch-steps before he gives up and falls", (string)null, false, false, (ValueValidator)null, (string)null);
			LastStandMaxRolls = obj.CreateEntry<int>("LastStandMaxRolls", 3, "How many times a last stand extends before he gets up anyway (0 = forever)", (string)null, false, false, (ValueValidator)null, (string)null);
			MaxStepLength = obj.CreateEntry<float>("MaxStepLength", 0.6f, "Longest single catch-step (m)", (string)null, false, false, (ValueValidator)null, (string)null);
			SwingSeconds = obj.CreateEntry<float>("SwingSeconds", 0.2f, "How long a foot swing takes", (string)null, false, false, (ValueValidator)null, (string)null);
			SwingForce = obj.CreateEntry<float>("SwingForce", 100f, "Force swinging the stepping foot (m/s^2)", (string)null, false, false, (ValueValidator)null, (string)null);
			LiftForce = obj.CreateEntry<float>("LiftForce", 55f, "Force lifting the stepping foot so steps stomp, not slide (m/s^2)", (string)null, false, false, (ValueValidator)null, (string)null);
			PlantForce = obj.CreateEntry<float>("PlantForce", 70f, "Force stomping the foot down to grip (m/s^2)", (string)null, false, false, (ValueValidator)null, (string)null);
			SwingLegStrength = obj.CreateEntry<float>("SwingLegStrength", 0.45f, "Muscle strength of the stepping leg while it swings (lower = freer)", (string)null, false, false, (ValueValidator)null, (string)null);
			BalanceMargin = obj.CreateEntry<float>("BalanceMargin", 0.12f, "Centre of mass this close to his feet counts as balanced (m)", (string)null, false, false, (ValueValidator)null, (string)null);
			StepMargin = obj.CreateEntry<float>("StepMargin", 0.05f, "Centre of mass this far out triggers a catch-step (lower = steps constantly)", (string)null, false, false, (ValueValidator)null, (string)null);
			FallDistance = obj.CreateEntry<float>("FallDistance", 0.9f, "Centre of mass this far outside his feet = he can't recover (m)", (string)null, false, false, (ValueValidator)null, (string)null);
			FallDrop = obj.CreateEntry<float>("FallDrop", 0.55f, "Hips dropping this much = he's falling (m)", (string)null, false, false, (ValueValidator)null, (string)null);
			AssistRampSeconds = obj.CreateEntry<float>("AssistRampSeconds", 1f, "Hip servo ramps up over this long (early = flies with the shot, late = caught)", (string)null, false, false, (ValueValidator)null, (string)null);
			CfgVersion = obj.CreateEntry<int>("CfgVersion", 50, "Do not edit: resets tuning when the mod updates", (string)null, false, false, (ValueValidator)null, (string)null);
			if (CfgVersion.Value < 49)
			{
				Enabled.Value = true;
				ClutchSeconds.Value = 0.8f;
				ClutchAcceleration.Value = 60f;
				ArmLooseness.Value = 0.15f;
				ClutchDelay.Value = 0.15f;
				HeadClutchChance.Value = 0.25f;
				BalanceEnabled.Value = true;
				VarietyEnabled.Value = true;
				FlipDirection.Value = false;
				FallThreshold.Value = 1.6f;
				BalanceRecovery.Value = 1f;
				LegGiveWay.Value = 0.5f;
				GunForce.Value = 0.65f;
				LastStandHp.Value = 0.15f;
				LastStandHpAbs.Value = 5f;
				FallSeconds.Value = 3f;
				FallShove.Value = 3f;
				FallArmSplay.Value = 3f;
				StaggerArmFling.Value = 0.6f;
				FlailForce.Value = 0f;
				BraceForce.Value = 45f;
				LimbKick.Value = 2.6f;
				WritheForce.Value = 1.5f;
				StaggerSeconds.Value = 2.6f;
				MinStaggerSeconds.Value = 1.5f;
				UpperBodyStun.Value = 0.1f;
				SnapSeconds.Value = 0.22f;
				StaggerWeight.Value = 0.7f;
				StaggerMapping.Value = 0.3f;
				UpperMapWeight.Value = 0.1f;
				TorsoLift.Value = 18f;
				ForwardBend.Value = 8f;
				ShoveForce.Value = 10f;
				ShoveSeconds.Value = 0.55f;
				TorsoStrength.Value = 0.25f;
				HeadStrength.Value = 0.15f;
				LegStrength.Value = 0.6f;
				LegHitStrength.Value = 0.3f;
				MuscleRecoverSeconds.Value = 1.6f;
				MuscleLoosenSeconds.Value = 0.5f;
				HipAssist.Value = 30f;
				RecoverStun.Value = 0.7f;
				OrientToFall.Value = 6f;
				KneeChance.Value = 0.28f;
				DeathArch.Value = 2f;
				HipsKick.Value = 1.8f;
				ChestKick.Value = 3.6f;
				HeadKick.Value = 2f;
				MaxSteps.Value = 8;
				MaxStepLength.Value = 0.6f;
				SwingSeconds.Value = 0.2f;
				SwingForce.Value = 100f;
				LiftForce.Value = 55f;
				PlantForce.Value = 70f;
				SwingLegStrength.Value = 0.45f;
				BalanceMargin.Value = 0.12f;
				StepMargin.Value = 0.05f;
				FallDistance.Value = 0.9f;
				FallDrop.Value = 0.55f;
				AssistRampSeconds.Value = 1f;
				CfgVersion.Value = 49;
				MelonPreferences.Save();
			}
			if (CfgVersion.Value < 50)
			{
				PunchClutchMax.Value = 1.5f;
				ShoveSeconds.Value = 0.45f;
				ChestKick.Value = 3f;
				CfgVersion.Value = 50;
				MelonPreferences.Save();
			}
			RagdollApi.AutoKnockdown = !BalanceEnabled.Value;
			RagdollApi.OnNpcHit += OnHit;
			((MelonBase)this).LoggerInstance.Msg("DynamicRagdoll 1.0.3 loaded (balance " + (BalanceEnabled.Value ? "ON" : "off") + ").");
			((MelonBase)this).LoggerInstance.Msg($"Tuning: torso={TorsoStrength.Value:F2} head={HeadStrength.Value:F2} steps={MaxSteps.Value} margin={BalanceMargin.Value:F2} fallDrop={FallDrop.Value:F2} hipAssist={HipAssist.Value:F0}");
		}

		public override void OnDeinitializeMelon()
		{
			RagdollApi.OnNpcHit -= OnHit;
			RagdollApi.AutoKnockdown = true;
		}

		public override void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
			KnownNpcs.Clear();
			Balances.Clear();
			Staggers.Clear();
			Clutches.Clear();
			DownedMap.Clear();
			ScaleMap.Clear();
			Thaws.Clear();
			Finished.Clear();
			try
			{
				MenuPage.EnsureBuilt();
			}
			catch
			{
			}
		}

		public override void OnLateUpdate()
		{
			if (DownedMap.Count == 0 && Staggers.Count == 0)
			{
				return;
			}
			foreach (KeyValuePair<int, Downed> item in DownedMap)
			{
				Downed value = item.Value;
				if ((Object)(object)value.Pm == (Object)null)
				{
					continue;
				}
				try
				{
					value.Pm.mappingWeight = 0.3f;
					value.Pm.muscleWeight = 0f;
					if (!ScaleMap.TryGetValue(item.Key, out var value2))
					{
						continue;
					}
					for (int i = 0; i < 17; i++)
					{
						Muscle val = MuscleOf(value2.Pm, i);
						if (val != null && val.props != null)
						{
							if (!float.IsNaN(value2.LastSet[i]))
							{
								val.props.muscleWeight = value2.LastSet[i];
							}
							if (!float.IsNaN(value2.LastSetMap[i]))
							{
								val.props.mappingWeight = value2.LastSetMap[i];
							}
						}
					}
				}
				catch
				{
				}
			}
			foreach (KeyValuePair<int, Stagger> stagger in Staggers)
			{
				Stagger value3 = stagger.Value;
				if ((Object)(object)value3.Pm == (Object)null)
				{
					continue;
				}
				try
				{
					value3.Pm.mappingWeight = StaggerMapping.Value;
					if (!ScaleMap.TryGetValue(stagger.Key, out var value4))
					{
						continue;
					}
					for (int j = 0; j < 17; j++)
					{
						Muscle val2 = MuscleOf(value4.Pm, j);
						if (val2 != null && val2.props != null)
						{
							if (!float.IsNaN(value4.LastSet[j]))
							{
								val2.props.muscleWeight = value4.LastSet[j];
							}
							if (!float.IsNaN(value4.LastSetMap[j]))
							{
								val2.props.mappingWeight = value4.LastSetMap[j];
							}
						}
					}
				}
				catch
				{
				}
			}
		}

		private static void OnHit(NpcHitInfo info)
		{
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: 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_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: 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_019a: 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_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Invalid comparison between Unknown and I4
			if ((Object)(object)info.Puppet == (Object)null || RagdollApi.IsExcluded(info.Puppet))
			{
				return;
			}
			try
			{
				Il2CppReferenceArray<Muscle> muscles = info.Puppet.muscles;
				if (muscles == null || ((Il2CppArrayBase<Muscle>)(object)muscles).Length != 17)
				{
					if (_rigLogs < 3)
					{
						_rigLogs++;
						string value = "?";
						try
						{
							value = ((Object)info.Puppet).name;
						}
						catch
						{
						}
						MelonLogger.Msg($"Rig gate: skipping non-humanoid '{value}' ({((Il2CppArrayBase<Muscle>)(object)muscles)?.Length ?? (-1)} muscles)");
					}
					return;
				}
			}
			catch
			{
			}
			try
			{
				int instanceID = ((Object)info.Puppet).GetInstanceID();
				if (!KnownNpcs.ContainsKey(instanceID))
				{
					if (KnownNpcs.Count > 64)
					{
						KnownNpcs.Clear();
					}
					KnownNpcs[instanceID] = new NpcWatch
					{
						Pm = info.Puppet,
						Hips = BodyOf(info.Puppet, 0)
					};
				}
			}
			catch
			{
			}
			if (info.IsDead)
			{
				try
				{
					if (DeathArch.Value > 0f && (Object)(object)info.Body != (Object)null)
					{
						Rigidbody val = BodyOf(info.Puppet, 8);
						if ((Object)(object)val != (Object)null)
						{
							Vector3 val2 = Vector3.up * 0.8f - info.Direction * 0.4f;
							val.AddForce(((Vector3)(ref val2)).normalized * DeathArch.Value, (ForceMode)2);
						}
						info.Body.AddForce(info.Direction * DeathArch.Value * 0.6f, (ForceMode)2);
					}
				}
				catch
				{
				}
				ReleaseAllNow(info.Puppet);
			}
			else if (Enabled.Value && (!IsMelee(info.AttackType) || MeleeEnabled.Value))
			{
				if (Enabled.Value && !PunchJab(info))
				{
					StartClutch(info);
				}
				if (BalanceEnabled.Value && (int)info.Tier == 1)
				{
					HandleBalance(info);
				}
			}
		}

		internal static void ReleaseAllNow(PuppetMaster pm)
		{
			int instanceID;
			try
			{
				instanceID = ((Object)pm).GetInstanceID();
			}
			catch
			{
				return;
			}
			if (!ScaleMap.TryGetValue(instanceID, out var value))
			{
				return;
			}
			try
			{
				for (int i = 0; i < 17; i++)
				{
					Muscle val = MuscleOf(pm, i);
					if (val != null)
					{
						if (!float.IsNaN(value.Original[i]))
						{
							val.props.muscleWeight = value.Original[i];
						}
						if (!float.IsNaN(value.OriginalMap[i]))
						{
							val.props.mappingWeight = value.OriginalMap[i];
						}
					}
				}
			}
			catch
			{
			}
			ScaleMap.Remove(instanceID);
		}

		private static void HandleBalance(NpcHitInfo info)
		{
			//IL_050e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0513: 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_0412: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Invalid comparison between Unknown and I4
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Invalid comparison between Unknown and I4
			//IL_043b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: Invalid comparison between Unknown and I4
			//IL_0270: Unknown result type (might be due to invalid IL or missing references)
			//IL_0276: Invalid comparison between Unknown and I4
			PuppetMaster puppet = info.Puppet;
			int instanceID = ((Object)puppet).GetInstanceID();
			float time = Time.time;
			if (!Balances.TryGetValue(instanceID, out var value))
			{
				if (Balances.Count > 256)
				{
					Balances.Clear();
				}
				value = new BalanceState();
				Balances[instanceID] = value;
			}
			float num = time - value.LastTime;
			float num2 = Impulse(info);
			bool pellet = false;
			if (num < 0.12f)
			{
				value.WindowCount++;
				num2 *= 0.3f;
				if (value.WindowCount >= 3)
				{
					pellet = true;
				}
			}
			else
			{
				if (time - value.LastWindowEnd < 0.6f && value.LastWindowEnd > 0f)
				{
					num2 *= 0.75f;
				}
				value.WindowCount = 1;
				value.WindowT = time;
			}
			value.LastWindowEnd = time;
			value.Loss = Mathf.Max(0f, value.Loss - BalanceRecovery.Value * num) + num2;
			value.LastTime = time;
			bool flag = false;
			if (info.Health != null)
			{
				float limbStun = RagdollApi.GetLimbStun(info.Health, (MuscleRegion)6);
				float limbStun2 = RagdollApi.GetLimbStun(info.Health, (MuscleRegion)7);
				if ((int)info.Region == 6 || (int)info.Region == 7)
				{
					flag = limbStun < LegGiveWay.Value * 0.5f && limbStun2 < LegGiveWay.Value * 0.5f;
				}
				else
				{
					float num3 = LegGiveWay.Value * 0.5f;
					flag = Mathf.Min(limbStun, limbStun2) < num3;
				}
			}
			bool flag2 = value.Loss >= FallThreshold.Value || flag;
			if (_balanceLogs < 15)
			{
				_balanceLogs++;
				MelonLogger.Msg($"Balance: region={info.Region} loss={value.Loss:F2}/{FallThreshold.Value:F2} legsGaveWay={flag} -> {(flag2 ? "FALL" : "STAGGER")}");
			}
			if (flag2)
			{
				if (((int)info.Region == 2 || (int)info.Region == 1) && KneeChance.Value > 0f && Random.value < KneeChance.Value)
				{
					value.Loss = FallThreshold.Value * 0.55f;
					if (_balanceLogs < 15)
					{
						_balanceLogs++;
						MelonLogger.Msg("Balance: gut-shot -> knees (long stagger instead of fall)");
					}
					StartStagger(info, instanceID, pellet);
					if (Staggers.TryGetValue(instanceID, out var value2))
					{
						value2.Steps = -2;
						value2.StartedAt -= 0.4f;
					}
					return;
				}
				value.Loss = 0f;
				if (Staggers.TryGetValue(instanceID, out var value3))
				{
					GiveBackStun(value3);
					Staggers.Remove(instanceID);
				}
				float num4 = FallSeconds.Value;
				try
				{
					if (UsesLastStand(puppet, info.Health))
					{
						num4 *= 3f;
						if (_balanceLogs < 15)
						{
							_balanceLogs++;
							MelonLogger.Msg($"Balance: last stand (long floor clutch, cur={RagdollApi.CurHp(info.Health):F0}hp)");
						}
					}
				}
				catch
				{
				}
				RagdollApi.KnockDown(puppet, info.Health, num4);
				RagdollApi.HoldLoco(puppet, num4);
				RagdollApi.HoldNav(puppet, num4);
				RagdollApi.HoldLiteLoco(puppet, num4);
				if ((Object)(object)info.Body != (Object)null && FallShove.Value > 0f)
				{
					info.Body.AddForce(info.Direction * FallShove.Value * (IsMelee(info.AttackType) ? MeleeVol(info.AttackType) : GunForce.Value), (ForceMode)2);
				}
				FlingArms(puppet, FallArmSplay.Value);
				Rigidbody[] array = ((value3 != null) ? value3.Bodies : BodiesOf(puppet));
				if (array != null)
				{
					if (DownedMap.Count > 64)
					{
						DownedMap.Clear();
					}
					bool flag3 = false;
					try
					{
						flag3 = RagdollApi.SetGetupDisabled(puppet, true);
					}
					catch
					{
					}
					bool lastStand = false;
					try
					{
						lastStand = UsesLastStand(puppet, info.Health);
					}
					catch
					{
					}
					Downed downed = new Downed
					{
						Pm = puppet,
						Health = info.Health,
						Bodies = array,
						Until = time + num4,
						NextWrithe = time + Random.Range(0.15f, 0.3f),
						PrevH = 99f,
						Landed = false,
						LastStand = lastStand,
						Region = info.Region,
						NextStir = time + Random.Range(2f, 3f)
					};
					try
					{
						Animator targetAnimator = puppet.targetAnimator;
						if ((Object)(object)targetAnimator != (Object)null)
						{
							downed.Anim = targetAnimator;
							downed.AnimSpeed = DownedAnimSpeed(instanceID, value3?.TargetSpeed ?? 0f, targetAnimator);
							downed.HasAnim = true;
						}
					}
					catch
					{
					}
					DownedMap[instanceID] = downed;
					Thaws.Remove(instanceID);
					if (_balanceLogs < 15)
					{
						_balanceLogs++;
						MelonLogger.Msg($"Downed: getup lock {(flag3 ? "HELD" : "FAILED")} for {num4:F0}s");
					}
				}
				if (Clutches.TryGetValue(instanceID, out var value4))
				{
					UpgradeClutch(value4);
					value4.Until = Mathf.Max(value4.Until, time + num4);
				}
				else
				{
					if (!Enabled.Value || !((Object)(object)info.Body != (Object)null))
					{
						return;
					}
					try
					{
						StartClutch(info, force: true);
						if (Clutches.TryGetValue(instanceID, out var value5))
						{
							value5.Until = Mathf.Max(value5.Until, time + num4);
						}
					}
					catch
					{
					}
				}
			}
			else
			{
				StartStagger(info, instanceID, pellet);
			}
		}

		private static float GunMult(string gun)
		{
			if (string.IsNullOrEmpty(gun))
			{
				return 1f;
			}
			string text = gun.ToLowerInvariant();
			if (text.Contains("eder"))
			{
				return 0.85f;
			}
			if (text.Contains("1911"))
			{
				return 1f;
			}
			if (text.Contains("mp5") || text.Contains("mp7") || text.Contains("uzi") || text.Contains("scorpion") || text.Contains("mac-"))
			{
				return 0.9f;
			}
			if (text.Contains("m4") || text.Contains("mk18") || text.Contains("m16") || text.Contains("akm") || text.Contains("scar"))
			{
				return 1.15f;
			}
			if (text.Contains("590") || text.Contains("shotgun"))
			{
				return 1f;
			}
			if (text.Contains("desert"))
			{
				return 1.25f;
			}
			if (!text.Contains("boardgun"))
			{
				text.Contains("blaster");
			}
			return 1f;
		}

		private static float VolMul(Stagger s)
		{
			try
			{
				return s.Sharp ? SharpForce.Value : (s.Melee ? MeleeForce.Value : (GunForce.Value * s.GunMul));
			}
			catch
			{
				return 1f;
			}
		}

		private static float HpFraction(SubBehaviourHealth h)
		{
			try
			{
				return RagdollApi.HpFraction(h);
			}
			catch
			{
				return 1f;
			}
		}

		private static float Impulse(NpcHitInfo info)
		{
			//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_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected I4, but got Unknown
			float num = ((info.Damage > 0f) ? info.Damage : 0.9f);
			MuscleRegion region = info.Region;
			float num2;
			switch (region - 3)
			{
			case 0:
				num2 = 1.3f;
				break;
			case 1:
			case 2:
				num2 = 0.5f;
				break;
			case 3:
			case 4:
				num2 = 0.8f;
				break;
			default:
				num2 = 1f;
				break;
			}
			float num3 = num * num2;
			if (VarietyEnabled.Value)
			{
				num3 *= Random.Range(0.85f, 1.2f);
			}
			return num3 * (IsMelee(info.AttackType) ? MeleeVol(info.AttackType) : GunForce.Value);
		}

		private static void StartStagger(NpcHitInfo info, int id, bool pellet = false)
		{
			//IL_0008: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0849: Unknown result type (might be due to invalid IL or missing references)
			//IL_0855: Unknown result type (might be due to invalid IL or missing references)
			//IL_085a: Unknown result type (might be due to invalid IL or missing references)
			//IL_085f: Unknown result type (might be due to invalid IL or missing references)
			//IL_087d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0882: Unknown result type (might be due to invalid IL or missing references)
			//IL_0341: Unknown result type (might be due to invalid IL or missing references)
			//IL_034d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0359: Unknown result type (might be due to invalid IL or missing references)
			//IL_0491: Unknown result type (might be due to invalid IL or missing references)
			//IL_0492: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0510: Unknown result type (might be due to invalid IL or missing references)
			PuppetMaster puppet = info.Puppet;
			Vector3 val = info.Direction;
			if (FlipDirection.Value)
			{
				val = -val;
			}
			val.y = 0f;
			if (((Vector3)(ref val)).sqrMagnitude < 0.01f)
			{
				return;
			}
			((Vector3)(ref val)).Normalize();
			float kickMul = 1f;
			float spin = 0f;
			if (VarietyEnabled.Value)
			{
				val = Quaternion.Euler(0f, Random.Range(-10f, 10f), 0f) * val;
				kickMul = Random.Range(0.8f, 1.3f);
				if (Random.value < 0.5f)
				{
					spin = Random.Range(-0.8f, 0.8f);
				}
			}
			float headM;
			float chestM;
			float hipsM;
			if (Staggers.TryGetValue(id, out var value))
			{
				value.Dir = val;
				value.Steps = 0;
				value.BalancedSince = -1f;
				value.KickMul = kickMul;
				value.Spin = spin;
				value.Region = info.Region;
				value.HitMuscle = info.MuscleIndex;
				KickProfile(value.HitMuscle, value.Region, out headM, out chestM, out hipsM, out var shoveM);
				value.ShoveMul = shoveM;
				if (pellet)
				{
					value.ShoveMul *= 0.5f;
					value.Pellet = true;
				}
				value.Melee = IsMelee(info.AttackType);
				value.Sharp = value.Melee && MeleeSharp(info.AttackType);
				value.GunMul = (value.Melee ? 1f : GunMult(info.Gun));
				value.GunName = (value.Melee ? ("melee:" + (info.AttackType ?? "?")) : (info.Gun ?? "?"));
				value.Bracing = false;
				value.NextStepAt = Mathf.Min(value.NextStepAt, Time.time + 0.1f);
				if (SnapSeconds.Value > 0f)
				{
					SnapUpperBody(puppet, value.Health);
				}
				Kick(value);
				FlingArms(puppet, StaggerArmFling.Value);
				RagdollApi.HoldMapping(puppet, StaggerSeconds.Value + 0.6f, StaggerMapping.Value);
				if (!WalkThrough.Value)
				{
					RagdollApi.HoldLimp(puppet, value.Health, StaggerWeight.Value, StaggerSeconds.Value + 0.6f);
				}
				if (!WalkThrough.Value)
				{
					RagdollApi.HoldLoco(puppet, StaggerSeconds.Value + 0.6f);
				}
				if (!WalkThrough.Value)
				{
					RagdollApi.HoldNav(puppet, StaggerSeconds.Value + 0.6f);
				}
				if (!WalkThrough.Value)
				{
					RagdollApi.HoldLiteLoco(puppet, StaggerSeconds.Value + 0.6f);
				}
				return;
			}
			Rigidbody[] array = (Rigidbody[])(object)new Rigidbody[17];
			for (int i = 0; i < 17; i++)
			{
				array[i] = BodyOf(puppet, i);
			}
			Rigidbody val2 = array[0];
			Rigidbody val3 = array[3];
			Rigidbody val4 = array[6];
			if ((Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null || (Object)(object)val4 == (Object)null)
			{
				return;
			}
			if (val2.position.y - Mathf.Min(val3.position.y, val4.position.y) < 0.45f)
			{
				RagdollApi.KnockDown(puppet, info.Health, FallSeconds.Value);
				RagdollApi.HoldLoco(puppet, FallSeconds.Value);
				RagdollApi.HoldNav(puppet, FallSeconds.Value);
				RagdollApi.HoldLiteLoco(puppet, FallSeconds.Value);
				try
				{
					float time = Time.time;
					int instanceID = ((Object)puppet).GetInstanceID();
					if (Clutches.TryGetValue(instanceID, out var value2))
					{
						UpgradeClutch(value2);
						value2.Until = Mathf.Max(value2.Until, time + FallSeconds.Value);
					}
					else if (Enabled.Value && (Object)(object)info.Body != (Object)null)
					{
						StartClutch(info, force: true);
						if (Clutches.TryGetValue(instanceID, out var value3))
						{
							value3.Until = Mathf.Max(value3.Until, time + FallSeconds.Value);
						}
					}
					return;
				}
				catch
				{
					return;
				}
			}
			value = new Stagger
			{
				Pm = puppet,
				Health = info.Health,
				Bodies = array,
				Hips = val2,
				FootL = val3,
				FootR = val4,
				Dir = val,
				StartedAt = Time.time,
				BornAt = Time.time,
				HipsY0 = val2.position.y,
				StartPos = val2.position,
				V0 = Vector3.Dot(val2.velocity, val),
				KickMul = kickMul,
				Spin = spin,
				Region = info.Region,
				HitMuscle = info.MuscleIndex
			};
			KickProfile(value.HitMuscle, value.Region, out hipsM, out chestM, out headM, out var shoveM2);
			value.ShoveMul = shoveM2;
			value.Melee = IsMelee(info.AttackType);
			value.Sharp = value.Melee && MeleeSharp(info.AttackType);
			value.GunMul = (value.Melee ? 1f : GunMult(info.Gun));
			value.GunName = (value.Melee ? ("melee:" + (info.AttackType ?? "?")) : (info.Gun ?? "?"));
			if (pellet)
			{
				value.ShoveMul *= 0.5f;
			}
			value.Pellet = pellet;
			try
			{
				float num = 0f;
				Rigidbody[] bodies = value.Bodies;
				foreach (Rigidbody val5 in bodies)
				{
					if ((Object)(object)val5 != (Object)null)
					{
						num += val5.mass;
					}
				}
				if (num > 1f)
				{
					value.MassScale = Mathf.Clamp(80f / num, 0.6f, 1.5f);
				}
			}
			catch
			{
			}
			if (!WalkThrough.Value)
			{
				RagdollApi.HoldLoco(puppet, StaggerSeconds.Value + 0.6f);
			}
			if (!WalkThrough.Value)
			{
				RagdollApi.HoldNav(puppet, StaggerSeconds.Value + 0.6f);
			}
			if (!WalkThrough.Value)
			{
				RagdollApi.HoldLiteLoco(puppet, StaggerSeconds.Value + 0.6f);
			}
			if (!WalkThrough.Value)
			{
				RagdollApi.HoldLimp(puppet, info.Health, StaggerWeight.Value, StaggerSeconds.Value + 0.6f);
			}
			try
			{
				Animator targetAnimator = puppet.targetAnimator;
				if ((Object)(object)targetAnimator != (Object)null && !WalkThrough.Value)
				{
					value.TargetAnim = targetAnimator;
					value.TargetSpeed = CaptureAnimSpeed(targetAnimator);
					targetAnimator.speed = 0f;
				}
			}
			catch
			{
			}
			if (info.Health != null)
			{
				value.OrigSpine = RagdollApi.GetLimbStun(info.Health, (MuscleRegion)2);
				value.OrigArmL = RagdollApi.GetLimbStun(info.Health, (MuscleRegion)4);
				value.OrigArmR = RagdollApi.GetLimbStun(info.Health, (MuscleRegion)5);
			}
			Staggers[id] = value;
			if (Thaws.TryGetValue(id, out var value4))
			{
				value.TargetSpeed = ((value4.To > 0.01f) ? value4.To : 1f);
				Thaws.Remove(id);
			}
			value.NextStepAt = Time.time + 0.12f;
			RagdollApi.HoldMapping(puppet, StaggerSeconds.Value + 0.6f, StaggerMapping.Value);
			RagdollApi.Diag(puppet);
			if (SnapSeconds.Value > 0f)
			{
				SnapUpperBody(puppet, info.Health);
			}
			Kick(value);
			FlingArms(puppet, StaggerArmFling.Value);
			if (_staggerLogs >= 8)
			{
				return;
			}
			_staggerLogs++;
			float value5 = float.NaN;
			Camera main = Camera.main;
			if ((Object)(object)main != (Object)null)
			{
				Vector3 val6 = val2.position - ((Component)main).transform.position;
				val6.y = 0f;
				if (((Vector3)(ref val6)).sqrMagnitude > 0.01f)
				{
					value5 = Vector3.Dot(((Vector3)(ref val6)).normalized, val);
				}
			}
			MelonLogger.Msg($"Stagger started: upper body limp, legs strong. direction vs 'away from you' = {value5:F2} (want about +1)");
		}

		private static void KickProfile(int hitMuscle, MuscleRegion region, out float hipsM, out float chestM, out float headM, out float shoveM)
		{
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Invalid comparison between Unknown and I4
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Invalid comparison between Unknown and I4
			switch (hitMuscle)
			{
			case 10:
			case 13:
				hipsM = 0.2f;
				chestM = 0.5f;
				headM = 0.2f;
				shoveM = 0.2f;
				return;
			case 0:
			case 7:
				hipsM = 1.3f;
				chestM = 0.6f;
				headM = 0.35f;
				shoveM = 0.8f;
				return;
			case 8:
				hipsM = 0.3f;
				chestM = 1.25f;
				headM = 0.9f;
				shoveM = 0.3f;
				return;
			case 9:
			case 16:
				hipsM = 0.35f;
				chestM = 0.7f;
				headM = 1.5f;
				shoveM = 0.35f;
				return;
			case 1:
			case 2:
			case 3:
			case 4:
			case 5:
			case 6:
				hipsM = 0.6f;
				chestM = 0.4f;
				headM = 0.3f;
				shoveM = 0.6f;
				return;
			}
			if ((int)region == 4 || (int)region == 5)
			{
				hipsM = 0.25f;
				chestM = 0.4f;
				headM = 0.25f;
				shoveM = 0.25f;
			}
			else
			{
				hipsM = 1f;
				chestM = 1f;
				headM = 1f;
				shoveM = 1f;
			}
		}

		private static void Kick(Stagger s)
		{
			//IL_001c: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Invalid comparison between Unknown and I4
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Invalid comparison between Unknown and I4
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: 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_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: 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_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0270: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Expected I4, but got Unknown
			//IL_0365: Unknown result type (might be due to invalid IL or missing references)
			//IL_036f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0374: Unknown result type (might be due to invalid IL or missing references)
			//IL_037e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0383: Unknown result type (might be due to invalid IL or missing references)
			//IL_0388: Unknown result type (might be due to invalid IL or missing references)
			//IL_038c: Unknown result type (might be due to invalid IL or missing references)
			//IL_039b: 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_03c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f0: 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_0405: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0308: Unknown result type (might be due to invalid IL or missing references)
			//IL_030a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0314: Unknown result type (might be due to invalid IL or missing references)
			//IL_0319: Unknown result type (might be due to invalid IL or missing references)
			//IL_031e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0322: Unknown result type (might be due to invalid IL or missing references)
			//IL_0331: Unknown result type (might be due to invalid IL or missing references)
			//IL_0337: Unknown result type (might be due to invalid IL or missing references)
			float num = s.KickMul * s.MassScale * VolMul(s);
			KickProfile(s.HitMuscle, s.Region, out var hipsM, out var chestM, out var headM, out var _);
			if ((Object)(object)s.Bodies[0] != (Object)null)
			{
				s.Bodies[0].AddForce(s.Dir * HipsKick.Value * hipsM * num, (ForceMode)2);
			}
			if ((Object)(object)s.Bodies[8] != (Object)null)
			{
				s.Bodies[8].AddForce(s.Dir * ChestKick.Value * chestM * num, (ForceMode)2);
			}
			if ((Object)(object)s.Bodies[9] != (Object)null)
			{
				s.Bodies[9].AddForce(s.Dir * HeadKick.Value * headM * num, (ForceMode)2);
			}
			if (s.Pellet && (Object)(object)s.Bodies[8] != (Object)null)
			{
				s.Bodies[8].AddForce(Vector3.up * 1.2f * num, (ForceMode)2);
			}
			Vector3 val2;
			if (LimbKick.Value > 0f && (s.HitMuscle == 10 || s.HitMuscle == 13))
			{
				Rigidbody val = s.Bodies[s.HitMuscle];
				if ((Object)(object)val != (Object)null)
				{
					val2 = s.Dir * 1.4f + Vector3.down * 0.2f;
					val.AddForce(((Vector3)(ref val2)).normalized * LimbKick.Value * 1.4f * num, (ForceMode)2);
				}
			}
			float num2 = (((int)s.Region == 2 || (int)s.Region == 1) ? 0.5f : 1f);
			if ((Object)(object)s.Bodies[0] != (Object)null && Mathf.Abs(s.Spin) > 0.05f)
			{
				s.Bodies[0].AddTorque(Vector3.up * s.Spin * num2, (ForceMode)2);
			}
			if (LimbKick.Value > 0f)
			{
				Vector3 val3 = Vector3.Cross(Vector3.up, s.Dir);
				if (((Vector3)(ref val3)).sqrMagnitude > 0.0001f)
				{
					((Vector3)(ref val3)).Normalize();
				}
				else
				{
					val3 = Vector3.right;
				}
				MuscleRegion region = s.Region;
				switch (region - 4)
				{
				case 2:
					if ((Object)(object)s.Bodies[3] != (Object)null)
					{
						Rigidbody obj4 = s.Bodies[3];
						val2 = -val3 + Vector3.down * 0.7f;
						obj4.AddForce(((Vector3)(ref val2)).normalized * LimbKick.Value * num, (ForceMode)2);
					}
					break;
				case 3:
					if ((Object)(object)s.Bodies[6] != (Object)null)
					{
						Rigidbody obj2 = s.Bodies[6];
						val2 = val3 + Vector3.down * 0.7f;
						obj2.AddForce(((Vector3)(ref val2)).normalized * LimbKick.Value * num, (ForceMode)2);
					}
					break;
				case 0:
					if ((Object)(object)s.Bodies[12] != (Object)null)
					{
						Rigidbody obj3 = s.Bodies[12];
						val2 = s.Dir * 1.2f + Vector3.up * 0.6f;
						obj3.AddForce(((Vector3)(ref val2)).normalized * LimbKick.Value * num, (ForceMode)2);
					}
					break;
				case 1:
					if ((Object)(object)s.Bodies[15] != (Object)null)
					{
						Rigidbody obj = s.Bodies[15];
						val2 = s.Dir * 1.2f + Vector3.up * 0.6f;
						obj.AddForce(((Vector3)(ref val2)).normalized * LimbKick.Value * num, (ForceMode)2);
					}
					break;
				}
			}
			if (_styleLogs < 12)
			{
				_styleLogs++;
				MelonLogger.Msg($"Stagger style: kick x{num:F2}, spin {s.Spin:F2}, gun {s.GunName} x{s.GunMul:F2}, adv={AdvanceForce.Value:F1}");
			}
		}

		private static void SnapUpperBody(PuppetMaster pm, SubBehaviourHealth health)
		{
			if (health != null)
			{
				RagdollApi.SetLimbStun(health, (MuscleRegion)4, 0f);
				RagdollApi.SetLimbStun(health, (MuscleRegion)5, 0f);
			}
			ScaleMuscle(pm, 7, 0.25f, 1f, 25f);
			ScaleMuscle(pm, 8, 0.25f, 1f, 25f);
			ScaleMuscle(pm, 9, 0.25f, 1f, 25f);
			ScaleMuscle(pm, 16, 0.25f, 1f, 25f);
		}

		private static void FlingArms(PuppetMaster pm, float force)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: 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)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: 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_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			if (force <= 0f)
			{
				return;
			}
			Rigidbody val = BodyOf(pm, 0);
			Rigidbody val2 = BodyOf(pm, 12);
			Rigidbody val3 = BodyOf(pm, 15);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Vector3 right = ((Component)pm).transform.right;
			if (((Vector3)(ref right)).sqrMagnitude < 0.01f)
			{
				right = Vector3.right;
			}
			Vector3 val5;
			if ((Object)(object)val2 != (Object)null)
			{
				Vector3 val4 = val2.position - val.position;
				val4.y = 0f;
				if (((Vector3)(ref val4)).sqrMagnitude < 0.01f)
				{
					val4 = -right;
				}
				val5 = ((Vector3)(ref val4)).normalized + Vector3.up;
				val2.AddForce(((Vector3)(ref val5)).normalized * force, (ForceMode)2);
			}
			if ((Object)(object)val3 != (Object)null)
			{
				Vector3 val6 = val3.position - val.position;
				val6.y = 0f;
				if (((Vector3)(ref val6)).sqrMagnitude < 0.01f)
				{
					val6 = right;
				}
				val5 = ((Vector3)(ref val6)).normalized + Vector3.up;
				val3.AddForce(((Vector3)(ref val5)).normalized * force, (ForceMode)2);
			}
		}

		private static bool UpdateStagger(Stagger s, float now)
		{
			//IL_0d23: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d25: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d31: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d3c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d41: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d46: Unknown result type (might be due to invalid IL or missing references)
			//IL_0916: Unknown result type (might be due to invalid IL or missing references)
			//IL_091b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d4a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0cc5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0cc9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0cce: Unknown result type (might be due to invalid IL or missing references)
			//IL_12aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_12b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_12b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_12ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_0cd2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0cd7: Unknown result type (might be due to invalid IL or missing references)
			//IL_118c: Unknown result type (might be due to invalid IL or missing references)
			//IL_119b: Unknown result type (might be due to invalid IL or missing references)
			//IL_11a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_12f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_12fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_12ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_12cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_09eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_09f1: Invalid comparison between Unknown and I4
			//IL_0cff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d01: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d08: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d12: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d17: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d1c: Unknown result type (might be due to invalid IL or missing references)
			//IL_1206: Unknown result type (might be due to invalid IL or missing references)
			//IL_11b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_11b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_11c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_11cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_11d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_11e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_11ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_11f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_11f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_11fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_09f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_09fa: Invalid comparison between Unknown and I4
			//IL_0dda: Unknown result type (might be due to invalid IL or missing references)
			//IL_0de0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0de5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0dea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0df7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0dfd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e02: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e07: Unknown result type (might be due to invalid IL or missing references)
			//IL_10c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_10c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_10c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_10d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_10d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_10d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_10dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_13a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_13af: Invalid comparison between Unknown and I4
			//IL_1341: Unknown result type (might be due to invalid IL or missing references)
			//IL_1337: Unknown result type (might be due to invalid IL or missing references)
			//IL_09fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a03: Invalid comparison between Unknown and I4
			//IL_10f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_1105: Unknown result type (might be due to invalid IL or missing references)
			//IL_116a: Unknown result type (might be due to invalid IL or missing references)
			//IL_116e: Unknown result type (might be due to invalid IL or missing references)
			//IL_13ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_13c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_13c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_13ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_13b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_13b8: Invalid comparison between Unknown and I4
			//IL_1346: Unknown result type (might be due to invalid IL or missing references)
			//IL_122c: Unknown result type (might be due to invalid IL or missing references)
			//IL_123c: Unknown result type (might be due to invalid IL or missing references)
			//IL_13fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_1407: Unknown result type (might be due to invalid IL or missing references)
			//IL_1416: Unknown result type (might be due to invalid IL or missing references)
			//IL_13da: Unknown result type (might be due to invalid IL or missing references)
			//IL_13df: Unknown result type (might be due to invalid IL or missing references)
			//IL_136c: Unknown result type (might be due to invalid IL or missing references)
			//IL_137b: Unknown result type (might be due to invalid IL or missing references)
			//IL_16c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_16cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_16d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_16d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_1256: Unknown result type (might be due to invalid IL or missing references)
			//IL_1260: Unknown result type (might be due to invalid IL or missing references)
			//IL_1746: Unknown result type (might be due to invalid IL or missing references)
			//IL_1751: Unknown result type (might be due to invalid IL or missing references)
			//IL_1756: Unknown result type (might be due to invalid IL or missing references)
			//IL_175b: Unknown result type (might be due to invalid IL or missing references)
			//IL_1703: Unknown result type (might be due to invalid IL or missing references)
			//IL_1708: Unknown result type (might be due to invalid IL or missing references)
			//IL_1712: Unknown result type (might be due to invalid IL or missing references)
			//IL_1717: Unknown result type (might be due to invalid IL or missing references)
			//IL_171c: Unknown result type (might be due to invalid IL or missing references)
			//IL_1720: Unknown result type (might be due to invalid IL or missing references)
			//IL_172f: Unknown result type (might be due to invalid IL or missing references)
			//IL_16f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_16f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_16fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a42: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a47: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a53: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a5f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a61: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a66: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a6b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a73: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a7b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a7d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a88: Expected O, but got Unknown
			//IL_1282: Unknown result type (might be due to invalid IL or missing references)
			//IL_128c: Unknown result type (might be due to invalid IL or missing references)
			//IL_101a: Unknown result type (might be due to invalid IL or missing references)
			//IL_101c: Unknown result type (might be due to invalid IL or missing references)
			//IL_101e: Unknown result type (might be due to invalid IL or missing references)
			//IL_1783: Unknown result type (might be due to invalid IL or missing references)
			//IL_1788: Unknown result type (might be due to invalid IL or missing references)
			//IL_1792: Unknown result type (might be due to invalid IL or missing references)
			//IL_1797: Unknown result type (might be due to invalid IL or missing references)
			//IL_179c: Unknown result type (might be due to invalid IL or missing references)
			//IL_17a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_17af: Unknown result type (might be due to invalid IL or missing references)
			//IL_1778: Unknown result type (might be due to invalid IL or missing references)
			//IL_177d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ebb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0eca: Unknown result type (might be due to invalid IL or missing references)
			//IL_14ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_14d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_14da: Unknown result type (might be due to invalid IL or missing references)
			//IL_14df: Unknown result type (might be due to invalid IL or missing references)
			//IL_1556: Unknown result type (might be due to invalid IL or missing references)
			//IL_1561: Unknown result type (might be due to invalid IL or missing references)
			//IL_1566: Unknown result type (might be due to invalid IL or missing references)
			//IL_156b: Unknown result type (might be due to invalid IL or missing references)
			//IL_150c: Unknown result type (might be due to invalid IL or missing references)
			//IL_1518: Unknown result type (might be due to invalid IL or missing references)
			//IL_151d: Unknown result type (might be due to invalid IL or missing references)
			//IL_1527: Unknown result type (might be due to invalid IL or missing references)
			//IL_152c: Unknown result type (might be due to invalid IL or missing references)
			//IL_1531: Unknown result type (might be due to invalid IL or missing references)
			//IL_1535: Unknown result type (might be due to invalid IL or missing references)
			//IL_153c: Unknown result type (might be due to invalid IL or missing references)
			//IL_14fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_1501: Unknown result type (might be due to invalid IL or missing references)
			//IL_1506: Unknown result type (might be due to invalid IL or missing references)
			//IL_035d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0363: Invalid comparison between Unknown and I4
			//IL_0f0a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f0f: Unknown result type (might be due to invalid IL or missing references)
			//IL_1593: Unknown result type (might be due to invalid IL or missing references)
			//IL_15a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_15aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_15b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_15b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_15be: Unknown result type (might be due to invalid IL or missing references)
			//IL_15c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_15c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_1588: Unknown result type (might be due to invalid IL or missing references)
			//IL_158d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f35: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f37: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f3e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f4b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f6a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0381: Unknown result type (might be due to invalid IL or missing references)
			//IL_0387: Invalid comparison between Unknown and I4
			//IL_0b8a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b91: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b96: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b9b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bd9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0be8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bf3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c05: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c0a: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0502: Unknown result type (might be due to invalid IL or missing references)
			//IL_0507: Unknown result type (might be due to invalid IL or missing references)
			//IL_0509: Unknown result type (might be due to invalid IL or missing references)
			//IL_0510: Unknown result type (might be due to invalid IL or missing references)
			//IL_0523: Unknown result type (might be due to invalid IL or missing references)
			//IL_0545: Unknown result type (might be due to invalid IL or missing references)
			//IL_054c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0557: Unknown result type (might be due to invalid IL or missing references)
			//IL_055e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0570: Unknown result type (might be due to invalid IL or missing references)
			//IL_0577: Unknown result type (might be due to invalid IL or missing references)
			//IL_0585: Unknown result type (might be due to invalid IL or missing references)
			//IL_058c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0598: Unknown result type (might be due to invalid IL or missing references)
			//IL_059a: Unknown result type (might be due to invalid IL or missing references)
			//IL_059c: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c2e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c3d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c47: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c52: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c64: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c69: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0cac: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c74: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c76: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c7a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c89: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c93: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c9e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ca3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ca8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0663: Unknown result type (might be due to invalid IL or missing references)
			//IL_0667: Unknown result type (might be due to invalid IL or missing references)
			//IL_066c: Unknown result type (might be due to invalid IL or missing references)
			//IL_067d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)s.Pm == (Object)null || !s.Pm.isAlive)
			{
				GiveBackStun(s);
				return true;
			}
			if ((Object)(object)s.TargetAnim != (Object)null)
			{
				try
				{
					float num = ((now - s.StartedAt < AnimFreezeSeconds.Value) ? 0f : s.TargetSpeed);
					float num2 = Time.fixedDeltaTime / ((num <= 0.01f) ? 0.12f : 0.4f);
					s.TargetAnim.speed = Mathf.MoveTowards(s.TargetAnim.speed, num, num2);
				}
				catch
				{
				}
			}
			float num3 = now - s.StartedAt;
			if (ShoveForce.Value > 0f && num3 < ShoveSeconds.Value && (Object)(object)s.Hips != (Object)null)
			{
				s.Hips.AddForce(s.Dir * ShoveForce.Value * s.ShoveMul * VolMul(s), (ForceMode)5);
			}
			if (!s.Bracing && (s.LastDSeg > FallDistance.Value * 0.6f || s.LastDrop > FallDrop.Value * 0.6f))
			{
				s.Bracing = true;
			}
			bool flag = false;
			try
			{
				int num4 = (((Object)(object)s.Pm != (Object)null) ? ((Object)s.Pm).GetInstanceID() : 0);
				if (num4 != 0 && Clutches.TryGetValue(num4, out var value) && now < value.Until)
				{
					flag = true;
				}
			}
			catch
			{
			}
			if (s.Health != null && !s.Bracing)
			{
				float num5 = (flag ? UpperBodyStun.Value : 0.45f);
				RagdollApi.SetLimbStunLevel(s.Health, (MuscleRegion)4, num5);
				RagdollApi.SetLimbStunLevel(s.Health, (MuscleRegion)5, num5);
			}
			float downSpeed = 1f / Mathf.Max(0.05f, MuscleLoosenSeconds.Value);
			float upSpeed = 1f / Mathf.Max(0.05f, MuscleRecoverSeconds.Value);
			float factor = (flag ? TorsoStrength.Value : Mathf.Max(TorsoStrength.Value, 0.4f));
			float factor2 = (flag ? HeadStrength.Value : Mathf.Max(HeadStrength.Value, 0.4f));
			ScaleMuscle(s.Pm, 7, factor, upSpeed, downSpeed);
			ScaleMuscle(s.Pm, 8, factor, upSpeed, downSpeed);
			ScaleMuscle(s.Pm, 9, factor2, upSpeed, downSpeed);
			ScaleMuscle(s.Pm, 16, factor2, upSpeed, downSpeed);
			int[] torsoMuscles = TorsoMuscles;
			foreach (int idx in torsoMuscles)
			{
				ScaleMapWeight(s.Pm, idx, UpperMapWeight.Value, upSpeed, downSpeed);
			}
			torsoMuscles = ArmMusclesL;
			foreach (int idx2 in torsoMuscles)
			{
				ScaleMapWeight(s.Pm, idx2, UpperMapWeight.Value, upSpeed, downSpeed);
			}
			torsoMuscles = ArmMusclesR;
			foreach (int idx3 in torsoMuscles)
			{
				ScaleMapWeight(s.Pm, idx3, UpperMapWeight.Value, upSpeed, downSpeed);
			}
			float num6 = Mathf.Max(0.6f, 1f - (float)Mathf.Max(0, s.Steps) * 0.04f);
			float factor3 = (((int)s.Region == 6) ? LegHitStrength.Value : LegStrength.Value) * num6;
			float factor4 = (((int)s.Region == 7) ? LegHitStrength.Value : LegStrength.Value) * num6;
			if (!WalkThrough.Value)
			{
				torsoMuscles = LegMusclesL;
				foreach (int idx4 in torsoMuscles)
				{
					ScaleMuscle(s.Pm, idx4, factor3, upSpeed, downSpeed);
				}
			}
			if (!WalkThrough.Value)
			{
				torsoMuscles = LegMusclesR;
				foreach (int idx5 in torsoMuscles)
				{
					ScaleMuscle(s.Pm, idx5, factor4, upSpeed, downSpeed);
				}
			}
			if (!WalkThrough.Value)
			{
				torsoMuscles = LegMusclesL;
				foreach (int idx6 in torsoMuscles)
				{
					ScaleMapWeight(s.Pm, idx6, LegMapping.Value, upSpeed, downSpeed);
				}
			}
			if (!WalkThrough.Value)
			{
				torsoMuscles = LegMusclesR;
				foreach (int idx7 in torsoMuscles)
				{
					ScaleMapWeight(s.Pm, idx7, LegMapping.Value, upSpeed, downSpeed);
				}
			}
			float num7 = Vector3.Dot(s.Hips.velocity, s.Dir) - s.V0;
			if (num3 < 0.5f && num7 > s.PeakDv)
			{
				s.PeakDv = num7;
			}
			ComputeCom(s, out var com, out var vel);
			Vector3 position = s.FootL.position;
			Vector3 position2 = s.FootR.position;
			float num8 = Mathf.Min(position.y, position2.y);
			float num9 = Mathf.Max(0.35f, com.y - num8);
			float num10 = Mathf.Sqrt(9.81f / num9);
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(com.x + vel.x / num10, com.z + vel.z / num10);
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(position.x, position.z);
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(position2.x, position2.z);
			float num11 = DistPointSegment(val, val2, val3);
			float num12 = s.HipsY0 - s.Hips.position.y;
			s.LastDSeg = num11;
			s.LastDrop = num12;
			try
			{
				if ((Object)(object)s.Hips != (Object)null)
				{
					Vector3 velocity = s.Hips.velocity;
					float y = velocity.y;
					velocity.y = 0f;
					float num13 = ((num11 <= BalanceMargin.Value) ? 8f : 3f);
					float num14 = Mathf.Max(0f, num13 - AdvanceForce.Value);
					if (WalkThrough.Value)
					{
						num14 = 0f;
					}
					float num15 = Mathf.Max(0f, 1f - num14 * Time.fixedDeltaTime);
					velocity *= num15;
					velocity.y = y;
					s.Hips.velocity = velocity;
				}
			}
			catch
			{
			}
			bool flag2 = !s.Swinging && s.Steps >= MaxSteps.Value && num11 > BalanceMargin.Value;
			if (flag2 && num12 < FallDrop.Value * 0.5f && num11 < FallDistance.Value * 0.5f && s.Steps < MaxSteps.Value + 4)
			{
				s.Steps = MaxSteps.Value - 2;
				flag2 = false;
			}
			if (num12 > FallDrop.Value || num11 > FallDistance.Value || flag2)
			{
				string text = ((num12 > FallDrop.Value) ? "hips dropping" : ((num11 > FallDistance.Value) ? "too far gone" : "out of steps"));
				LogEnd(s, "FELL (" + text + ")", num3, num11, num12);
				GiveBackStun(s);
				float num16 = FallSeconds.Value;
				try
				{
					if (UsesLastStand(s.Pm, s.Health))
					{
						num16 *= 3f;
						if (_endLogs < 14)
						{
							_endLogs++;
							MelonLogger.Msg("Stagger end: last stand (long floor clutch)");
						}
					}
				}
				catch
				{
				}
				RagdollApi.KnockDown(s.Pm, s.Health, num16);
				RagdollApi.HoldLoco(s.Pm, num16);
				RagdollApi.HoldNav(s.Pm, num16);
				RagdollApi.HoldLiteLoco(s.Pm, num16);
				try
				{
					int num17 = (((Object)(object)s.Pm != (Object)null) ? ((Object)s.Pm).GetInstanceID() : 0);
					if (num17 != 0 && s.Bodies != null)
					{
						if (DownedMap.Count > 64)
						{
							DownedMap.Clear();
						}
						bool flag3 = false;
						try
						{
							flag3 = RagdollApi.SetGetupDisabled(s.Pm, true);
						}
						catch
						{
						}
						if (_standLogs < 40)
						{
							_standLogs++;
							MelonLogger.Msg("Downed: getup lock " + (flag3 ? "HELD" : "FAILED"));
						}
						Downed downed = new Downed
						{
							Pm = s.Pm,
							Health = s.Health,
							Bodies = s.Bodies,
							Until = now + num16,
							NextWrithe = now + Random.Range(0.15f, 0.3f),
							PrevH = 99f,
							Landed = false,
							LastStand = (num16 > FallSeconds.Value * 1.5f),
							Region = s.Region,
							NextStir = now + Random.Range(2f, 3f)
						};
						try
						{
							Animator val4 = (((Object)(object)s.Pm != (Object)null) ? s.Pm.targetAnimator : null);
							if ((Object)(object)val4 != (Object)null)
							{
								downed.Anim = val4;
								downed.AnimSpeed = DownedAnimSpeed(num17, s.TargetSpeed, val4);
								downed.HasAnim = true;
							}
						}
						catch
						{
						}
						DownedMap[num17] = downed;
						Thaws.Remove(num17);
						try
						{
							if (Clutches.TryGetValue(num17, out var value2))
							{
								UpgradeClutch(value2);
								value2.Until = Mathf.Max(value2.Until, now + num16);
							}
							else if (Enabled.Value)
							{
								int num18 = (((int)s.Region == 6) ? 3 : (((int)s.Region == 7) ? 6 : (((int)s.Region != 1) ? 8 : 0)));
								Rigidbody val5 = ((s.Bodies != null && num18 >= 0 && num18 < s.Bodies.Length) ? s.Bodies[num18] : null);
								if ((Object)(object)val5 != (Object)null)
								{
									StartClutch(new NpcHitInfo
									{
										Puppet = s.Pm,
										Health = s.Health,
										Region = s.Region,
										Body = val5,
										MuscleIndex = num18,
										Tier = (HitTier)1
									}, force: true);
									if (Clutches.TryGetValue(num17, out var value3))
									{
										value3.Until = Mathf.Max(value3.Until, now + num16);
									}
								}
							}
						}
						catch
						{
						}
					}
				}
				catch
				{
				}
				return true;
			}
			Vector3 val12;
			if (s.Swinging)
			{
				Rigidbody val6 = (s.SwingLeft ? s.FootL : s.FootR);
				torsoMuscles = (s.SwingLeft ? LegMusclesL : LegMusclesR);
				foreach (int idx8 in torsoMuscles)
				{
					ScaleMuscle(s.Pm, idx8, SwingLegStrength.Value, 12f, 12f);
				}
				float factor5 = StanceGrip(s, !s.SwingLeft);
				torsoMuscles = (s.SwingLeft ? LegMusclesR : LegMusclesL);
				foreach (int idx9 in torsoMuscles)
				{
					ScaleMuscle(s.Pm, idx9, factor5, 8f, 8f);
				}
				Vector3 val7 = s.SwingTarget - val6.position;
				val7.y = 0f;
				float magnitude = ((Vector3)(ref val7)).magnitude;
				float num19 = Mathf.Clamp01((now - s.SwingStart) / Mathf.Max(0.05f, s.SwingUntil - s.SwingStart));
				Vector3 val8 = Vector3.up * LiftForce.Value * s.StepLiftMul * Mathf.Sin(num19 * (float)Math.PI);
				try
				{
					Rigidbody val9 = s.Bodies[s.SwingLeft ? 2 : 5];
					if ((Object)(object)val9 != (Object)null)
					{
						Vector3 val10 = Vector3.up * LiftForce.Value * 0.7f * s.StepLiftMul * Mathf.Sin(num19 * (float)Math.PI);
						if (magnitude > 0.04f)
						{
							val10 += val7 / magnitude * SwingForce.Value * 0.15f * s.StepForceMul;
						}
						val9.AddForce(val10, (ForceMode)5);
					}
				}
				catch
				{
				}
				if (magnitude > 0.04f)
				{
					Vector3 val11 = val7 / magnitude;
					try
					{
						float num20 = Vector3.Dot(val6.velocity, val11);
						float num21 = Mathf.Clamp(magnitude * 4f, 0.25f, 4f);
						if (num20 > num21)
						{
							val8 -= val11 * (num20 - num21) * 14f;
						}
					}
					catch
					{
					}
					val8 += val11 * SwingForce.Value * s.StepForceMul;
				}
				val6.AddForce(val8, (ForceMode)5);
				float rate = 5f + AdvanceForce.Value * 1.5f;
				if (!WalkThrough.Value)
				{
					BrakeFoot(s.SwingLeft ? s.FootR : s.FootL, rate);
				}
				if (now >= s.SwingUntil)
				{
					ReleaseLeg(s);
					s.Swinging = false;
					s.PlantUntil = now + 0.16f;
					s.NextStepAt = now + 0.05f;
					s.LastFoot = val6;
					if (_strideLogs < 8)
					{
						try
						{
							val12 = s.SwingTarget - s.SwingFrom;
							float magnitude2 = ((Vector3)(ref val12)).magnitude;
							val12 = val6.position - s.SwingFrom;
							float magnitude3 = ((Vector3)(ref val12)).magnitude;
							_strideLogs++;
							MelonLogger.Msg($"Stride {s.Steps}: wanted {magnitude2:F2}m, foot travelled {magnitude3:F2}m");
						}
						catch
						{
						}
					}
				}
			}
			else
			{
				if ((Object)(object)s.LastFoot != (Object)null && now < s.PlantUntil)
				{
					s.LastFoot.AddForce(Vector3.down * PlantForce.Value, (ForceMode)5);
					BrakeFoot(s.LastFoot, 12f + AdvanceForce.Value * 1.5f);
					try
					{
						if ((Object)(object)s.Hips != (Object)null)
						{
							Vector3 velocity2 = s.Hips.velocity;
							velocity2.y = 0f;
							float magnitude4 = ((Vector3)(ref velocity2)).magnitude;
							if (magnitude4 > 1.5f)
							{
								s.Hips.AddForce(-velocity2 / magnitude4 * (magnitude4 - 1.5f) * Mathf.Max(0f, 8f - AdvanceForce.Value), (ForceMode)5);
							}
						}
					}
					catch
					{
					}
					torsoMuscles = (((Object)(object)s.LastFoot == (Object)(object)s.FootL) ? LegMusclesL : LegMusclesR);
					foreach (int idx10 in torsoMuscles)
					{
						ScaleMuscle(s.Pm, idx10, StanceGrip(s, (Object)(object)s.LastFoot == (Object)(object)s.FootL), 8f, 8f);
					}
				}
				if (num11 > StepMargin.Value && now >= s.NextStepAt && s.Steps < MaxSteps.Value && !WalkThrough.Value)
				{
					BeginStep(s, now, val, val2, val3, num8, num11);
				}
				if (!WalkThrough.Value)
				{
					BrakeFoot(s.FootL, 5f + AdvanceForce.Value * 1.5f);
				}
				if (!WalkThrough.Value)
				{
					BrakeFoot(s.FootR, 5f + AdvanceForce.Value * 1.5f);
				}
			}
			if (!WalkThrough.Value && HipAssist.Value > 0f && num11 > 0.02f && (Object)(object)s.Hips != (Object)null)
			{
				Vector2 val13 = (val2 + val3) * 0.5f - val;
				if (((Vector2)(ref val13)).sqrMagnitude > 0.0001f)
				{
					((Vector2)(ref val13)).Normalize();
					Vector3 val14 = default(Vector3);
					((Vector3)(ref val14))..ctor(val13.x, 0f, val13.y);
					float num22 = Mathf.Min(HipAssist.Value, HipAssist.Value * num11 / Mathf.Max(0.05f, BalanceMargin.Value));
					num22 *= Mathf.Clamp01(num3 / Mathf.Max(0.05f, AssistRampSeconds.Value));
					s.Hips.AddForce(val14 * num22, (ForceMode)5);
				}
			}
			if ((Object)(object)s.Bodies[8] != (Object)null)
			{
				Vector3 val15 = Vector3.up * TorsoLift.Value;
				if (ForwardBe

Mods\DynamicRagdoll2.dll

Decompiled 8 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSLZ.Marrow.PuppetMasta;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using RagdollOnHit;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Main), "DynamicRagdoll2", "1.0.1", "skait5k", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("DynamicRagdoll2")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("DynamicRagdoll2")]
[assembly: AssemblyTitle("DynamicRagdoll2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace RagdollOnHit
{
	public enum HitTier
	{
		Light,
		Medium,
		Kill
	}
	public enum MuscleRegion
	{
		Unknown,
		Hips,
		Torso,
		Head,
		ArmL,
		ArmR,
		LegL,
		LegR
	}
	public sealed class NpcHitInfo
	{
		public PuppetMaster Puppet;

		public BehaviourPuppet Behaviour;

		public SubBehaviourHealth Health;

		public int MuscleIndex;

		public MuscleRegion Region;

		public Rigidbody Body;

		public Vector3 HitPoint;

		public bool HasHitPoint;

		public string AttackType;

		public string Gun;

		public Vector3 Direction;

		public float Damage;

		public HitTier Tier;

		public bool IsDead;
	}
	public static class RagdollApi
	{
		public static bool AutoKnockdown = true;

		public static MelonPreferences_Entry<bool> EnabledEntry;

		private static readonly Dictionary<int, object> SfxCache = new Dictionary<int, object>();

		private static readonly HashSet<int> NoSfx = new HashSet<int>();

		private static readonly string[] ExcludedTokens = new string[6] { "omni", "turret", "crablet", "skeleton", "nullrat", "cultist" };

		private static readonly Dictionary<int, bool> ExcludedCache = new Dictionary<int, bool>();

		private static int _excludeLogs;

		public static event Action<NpcHitInfo> OnNpcHit;

		public static void HoldMapping(PuppetMaster pm, float seconds)
		{
			if (!((Object)(object)pm == (Object)null))
			{
				Main.HoldMapping(pm, seconds);
			}
		}

		public static void KnockDown(PuppetMaster pm, SubBehaviourHealth health, float seconds)
		{
			if (!((Object)(object)pm == (Object)null))
			{
				Main.KnockDown(pm, health, seconds);
			}
		}

		public static void HoldLimp(PuppetMaster pm, SubBehaviourHealth health, float weight, float seconds)
		{
			if (!((Object)(object)pm == (Object)null))
			{
				Main.HoldLimp(pm, health, weight, seconds);
			}
		}

		public static void HoldMapping(PuppetMaster pm, float seconds, float weight)
		{
			if (!((Object)(object)pm == (Object)null))
			{
				Main.HoldMapping(pm, seconds, weight);
			}
		}

		public static void HoldLoco(PuppetMaster pm, float seconds)
		{
			if (!((Object)(object)pm == (Object)null))
			{
				Main.HoldLoco(pm, seconds);
			}
		}

		public static void HoldNav(PuppetMaster pm, float seconds)
		{
			if (!((Object)(object)pm == (Object)null))
			{
				Main.HoldNav(pm, seconds);
			}
		}

		public static void HoldLiteLoco(PuppetMaster pm, float seconds)
		{
			if (!((Object)(object)pm == (Object)null))
			{
				Main.HoldLiteLoco(pm, seconds);
			}
		}

		public static void ReleaseAI(PuppetMaster pm)
		{
			if (!((Object)(object)pm == (Object)null))
			{
				Main.ReleaseAI(pm);
			}
		}

		public static void Diag(PuppetMaster pm)
		{
			if (!((Object)(object)pm == (Object)null))
			{
				Main.Diag(pm);
			}
		}

		public static MuscleRegion RegionOf(int muscleIndex)
		{
			switch (muscleIndex)
			{
			case 0:
				return MuscleRegion.Hips;
			case 1:
			case 2:
			case 3:
				return MuscleRegion.LegL;
			default:
				if (muscleIndex >= 4 && muscleIndex <= 6)
				{
					return MuscleRegion.LegR;
				}
				switch (muscleIndex)
				{
				case 7:
				case 8:
					return MuscleRegion.Torso;
				case 9:
				case 16:
					return MuscleRegion.Head;
				case 10:
				case 11:
				case 12:
					return MuscleRegion.ArmL;
				default:
					if (muscleIndex >= 13 && muscleIndex <= 15)
					{
						return MuscleRegion.ArmR;
					}
					return MuscleRegion.Unknown;
				}
			}
		}

		internal static string StunFieldOf(MuscleRegion region)
		{
			return region switch
			{
				MuscleRegion.ArmL => "stun_arm_lf", 
				MuscleRegion.ArmR => "stun_arm_rt", 
				MuscleRegion.LegL => "stun_leg_lf", 
				MuscleRegion.LegR => "stun_leg_rt", 
				_ => "stun_spine", 
			};
		}

		public static float GetLimbStun(SubBehaviourHealth h, MuscleRegion region)
		{
			if (!Reflect.TryGet<float>(h, StunFieldOf(region), out var value))
			{
				return 1f;
			}
			return value;
		}

		public static void SetLimbStun(SubBehaviourHealth h, MuscleRegion region, float level)
		{
			if (h != null)
			{
				string name = StunFieldOf(region);
				if (Reflect.TryGet<float>(h, name, out var value) && level < value)
				{
					Reflect.TrySet(h, name, level);
				}
			}
		}

		public static float CurHp(SubBehaviourHealth h)
		{
			try
			{
				if (h != null && Reflect.TryGet<float>(h, "cur_hp", out var value))
				{
					return value;
				}
			}
			catch
			{
			}
			return -1f;
		}

		public static float HpFraction(SubBehaviourHealth h)
		{
			try
			{
				if (h == null)
				{
					return 1f;
				}
				float num = -1f;
				float num2 = 0f;
				if (Reflect.TryGet<float>(h, "cur_hp", out var value))
				{
					num = value;
				}
				if (Reflect.TryGet<float>(h, "maxHitPoints", out var value2))
				{
					num2 = value2;
				}
				if (num2 > 0f && num >= 0f)
				{
					return Mathf.Clamp01(num / num2);
				}
			}
			catch
			{
			}
			return 1f;
		}

		public static object FindSfx(PuppetMaster pm)
		{
			int instanceID;
			try
			{
				instanceID = ((Object)pm).GetInstanceID();
			}
			catch
			{
				return null;
			}
			if (SfxCache.TryGetValue(instanceID, out var value) && value != null)
			{
				return value;
			}
			if (NoSfx.Contains(instanceID))
			{
				return null;
			}
			try
			{
				foreach (BehaviourBase item in (Il2CppArrayBase<BehaviourBase>)(object)pm.behaviours)
				{
					if ((Object)(object)item == (Object)null)
					{
						continue;
					}
					string className;
					SubBehaviourSfx val = Reflect.FindMemberOfType<SubBehaviourSfx>(Reflect.ResolveRuntimeType((Il2CppObjectBase)(object)item, out className), out className);
					if (val != null)
					{
						if (SfxCache.Count > 512)
						{
							SfxCache.Clear();
						}
						SfxCache[instanceID] = val;
						return val;
					}
				}
			}
			catch
			{
			}
			if (NoSfx.Count > 512)
			{
				NoSfx.Clear();
			}
			NoSfx.Add(instanceID);
			return null;
		}

		public static bool SetGetupDisabled(PuppetMaster pm, bool disabled)
		{
			if ((Object)(object)pm == (Object)null)
			{
				return false;
			}
			try
			{
				if (Reflect.TrySetBool(pm, "getupDisabled", disabled) && Reflect.TryGet<bool>(pm, "getupDisabled", out var value) && value == disabled)
				{
					return true;
				}
				try
				{
					foreach (BehaviourBase item in (Il2CppArrayBase<BehaviourBase>)(object)pm.behaviours)
					{
						if (!((Object)(object)item == (Object)null))
						{
							object obj = null;
							try
							{
								obj = Reflect.ResolveRuntimeType((Il2CppObjectBase)(object)item, out var _);
							}
							catch
							{
							}
							object o = obj ?? item;
							if (Reflect.TrySetBool(o, "getupDisabled", disabled) && Reflect.TryGet<bool>(o, "getupDisabled", out var value2) && value2 == disabled)
							{
								return true;
							}
							if (Reflect.TrySetBool(o, "getUpDisabled", disabled) && Reflect.TryGet<bool>(o, "getUpDisabled", out var value3) && value3 == disabled)
							{
								return true;
							}
						}
					}
				}
				catch
				{
				}
			}
			catch
			{
			}
			return false;
		}

		public static void SetLimbStunLevel(SubBehaviourHealth h, MuscleRegion region, float level)
		{
			if (h != null)
			{
				Reflect.TrySet(h, StunFieldOf(region), Mathf.Clamp01(level));
			}
		}

		internal static void ClearNpcCache()
		{
			ExcludedCache.Clear();
		}

		private static string NormName(string s)
		{
			if (string.IsNullOrEmpty(s))
			{
				return "";
			}
			char[] array = new char[s.Length];
			int length = 0;
			foreach (char c in s)
			{
				if (c >= 'a' && c <= 'z')
				{
					array[length++] = c;
				}
				else if (c >= 'A' && c <= 'Z')
				{
					array[length++] = (char)(c + 32);
				}
				else if (c >= '0' && c <= '9')
				{
					array[length++] = c;
				}
			}
			return new string(array, 0, length);
		}

		public static bool IsExcluded(PuppetMaster pm)
		{
			int instanceID;
			try
			{
				instanceID = ((Object)pm).GetInstanceID();
			}
			catch
			{
				return true;
			}
			if (ExcludedCache.TryGetValue(instanceID, out var value))
			{
				return value;
			}
			bool flag = CheckExcluded(pm);
			if (ExcludedCache.Count > 256)
			{
				ExcludedCache.Clear();
			}
			ExcludedCache[instanceID] = flag;
			return flag;
		}

		private static bool CheckExcluded(PuppetMaster pm)
		{
			try
			{
				Transform val = ((Component)pm).transform;
				for (int i = 0; i < 6; i++)
				{
					if (!((Object)(object)val != (Object)null))
					{
						break;
					}
					string text = null;
					try
					{
						text = ((Object)val).name;
					}
					catch
					{
					}
					string text2 = NormName(text);
					if (text2.Length > 0)
					{
						string[] excludedTokens = ExcludedTokens;
						foreach (string value in excludedTokens)
						{
							if (text2.Contains(value))
							{
								if (_excludeLogs < 6)
								{
									_excludeLogs++;
									MelonLogger.Msg($"NPC gate: skipping '{text}' (matched '{value}')");
								}
								return true;
							}
						}
					}
					try
					{
						val = val.parent;
					}
					catch
					{
						break;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		public static bool IsNullBody(PuppetMaster pm)
		{
			try
			{
				Transform val = ((Component)pm).transform;
				for (int i = 0; i < 6; i++)
				{
					if (!((Object)(object)val != (Object)null))
					{
						break;
					}
					try
					{
						if (NormName(((Object)val).name).Contains("nullbodyagent"))
						{
							return true;
						}
					}
					catch
					{
					}
					try
					{
						val = val.parent;
					}
					catch
					{
						break;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		internal static void Raise(NpcHitInfo info)
		{
			Action<NpcHitInfo> onNpcHit = RagdollApi.OnNpcHit;
			if (onNpcHit == null)
			{
				return;
			}
			Delegate[] invocationList = onNpcHit.GetInvocationList();
			foreach (Delegate obj in invocationList)
			{
				try
				{
					((Action<NpcHitInfo>)obj)(info);
				}
				catch (Exception value)
				{
					MelonLogger.Error($"RagdollApi subscriber threw: {value}");
				}
			}
		}
	}
	public class Main : MelonMod
	{
		private sealed class Reaction
		{
			public float Original;

			public float Weight;

			public float HoldUntil;

			public SubBehaviourHealth Health;

			public float[] Held;
		}

		private sealed class MapHold
		{
			public float Original;

			public float Weight;

			public float Until;
		}

		private sealed class FlagHold
		{
			public object Beh;

			public bool Original;

			public float Until;
		}

		private sealed class FloatHold
		{
			public object Target;

			public float Original;

			public float Until;
		}

		private static MelonPreferences_Entry<float> GetUpDelay;

		private static MelonPreferences_Entry<float> KnockbackForce;

		private static MelonPreferences_Entry<float> KnockdownDamage;

		private static MelonPreferences_Entry<bool> UseGameStun;

		private static MelonPreferences_Entry<float> LightStunLevel;

		private static MelonPreferences_Entry<float> LightMuscleWeight;

		private static MelonPreferences_Entry<float> LightSeconds;

		private static MelonPreferences_Entry<float> RecoverSeconds;

		private static MelonPreferences_Entry<float> SlowMoScale;

		private static MelonPreferences_Entry<float> SlowMoSeconds;

		private static MelonPreferences_Entry<bool> LogHits;

		private static MelonPreferences_Entry<bool> Enabled;

		private const float ReactCooldown = 0.25f;

		private const float DropSpeed = 20f;

		private static readonly string[] StunFields = new string[5] { "stun_spine", "stun_arm_lf", "stun_arm_rt", "stun_leg_lf", "stun_leg_rt" };

		private static readonly Dictionary<int, Reaction> Reactions = new Dictionary<int, Reaction>();

		private static readonly Dictionary<int, float> LastReact = new Dictionary<int, float>();

		private static readonly Dictionary<int, SubBehaviourHealth> HealthCache = new Dictionary<int, SubBehaviourHealth>();

		private static readonly HashSet<int> NoHealth = new HashSet<int>();

		private static bool _dumpedAttack;

		private static bool _dumpedStructure;

		private static bool _loggedHealth;

		private static bool _loggedNoHealth;

		private static bool _loggedStun;

		private static bool _loggedLightDip;

		private static bool _loggedMedium;

		private static bool _loggedUnpin;

		private static bool _loggedKill;

		private static bool _slowActive;

		private static int _hitLogCount;

		private static int _locoLogs;

		private static int _originLogs;

		private static int _sourceLogs;

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

		private static readonly Dictionary<int, MapHold> MapHolds = new Dictionary<int, MapHold>();

		private static readonly Dictionary<string, FlagHold> FlagHolds = new Dictionary<string, FlagHold>();

		private static readonly Dictionary<string, FloatHold> FloatHolds = new Dictionary<string, FloatHold>();

		private static int _diagCount;

		public override void OnInitializeMelon()
		{
			MelonPreferences_Category obj = MelonPreferences.CreateCategory("RagdollOnHit");
			GetUpDelay = obj.CreateEntry<float>("GetUpDelay", 3f, "Seconds a knocked-down NPC stays limp", (string)null, false, false, (ValueValidator)null, (string)null);
			KnockbackForce = obj.CreateEntry<float>("KnockbackForce", 4f, "Shove on hit (0 = none)", (string)null, false, false, (ValueValidator)null, (string)null);
			KnockdownDamage = obj.CreateEntry<float>("KnockdownDamage", 0.5f, "Hits at/above this damage knock the NPC down (0 = every hit)", (string)null, false, false, (ValueValidator)null, (string)null);
			UseGameStun = obj.CreateEntry<bool>("UseGameStun", true, "Light hits use the game's own per-limb stun (false = whole-body muscle dip)", (string)null, false, false, (ValueValidator)null, (string)null);
			LightStunLevel = obj.CreateEntry<float>("LightStunLevel", 0.15f, "Light hits: how limp the hit limb goes (0 = fully limp, 1 = normal)", (string)null, false, false, (ValueValidator)null, (string)null);
			LightMuscleWeight = obj.CreateEntry<float>("LightMuscleWeight", 0.3f, "Fallback dip: muscle strength during a light hit (0 = limp, 1 = normal)", (string)null, false, false, (ValueValidator)null, (string)null);
			LightSeconds = obj.CreateEntry<float>("LightSeconds", 0.4f, "Fallback dip: how long a light hit lasts", (string)null, false, false, (ValueValidator)null, (string)null);
			RecoverSeconds = obj.CreateEntry<float>("RecoverSeconds", 0.8f, "How long it takes to stiffen back up afterwards", (string)null, false, false, (ValueValidator)null, (string)null);
			SlowMoScale = obj.CreateEntry<float>("SlowMoScale", 1f, "Time scale on a kill (1 = off, 0.3 = slow-mo)", (string)null, false, false, (ValueValidator)null, (string)null);
			SlowMoSeconds = obj.CreateEntry<float>("SlowMoSeconds", 1f, "Slow-mo length in real seconds", (string)null, false, false, (ValueValidator)null, (string)null);
			LogHits = obj.CreateEntry<bool>("LogHits", true, "Log the first 50 hits (damage, muscle, tier)", (string)null, false, false, (ValueValidator)null, (string)null);
			Enabled = obj.CreateEntry<bool>("Enabled", true, "Master switch: base reactions + API events on/off", (string)null, false, false, (ValueValidator)null, (string)null);
			RagdollApi.EnabledEntry = Enabled;
			((MelonBase)this).LoggerInstance.Msg("DynamicRagdoll2 1.0.1 loaded.");
			GunHook.TryInstall();
		}

		public override void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
			LastReact.Clear();
			HealthCache.Clear();
			NoHealth.Clear();
			RagdollApi.ClearNpcCache();
		}

		private static string SafeName(PuppetMaster pm)
		{
			try
			{
				return ((Object)pm).name + "#" + ((Object)pm).GetInstanceID().ToString("X8");
			}
			catch
			{
				return "?";
			}
		}

		internal static void HandleHit(MuscleCollisionBroadcaster b, object attack)
		{
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0317: Unknown result type (might be due to invalid IL or missing references)
			//IL_031c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0335: Unknown result type (might be due to invalid IL or missing references)
			//IL_0341: Unknown result type (might be due to invalid IL or missing references)
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			//IL_034b: Unknown result type (might be due to invalid IL or missing references)
			//IL_034f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0354: Unknown result type (might be due to invalid IL or missing references)
			//IL_030e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0313: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: 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_0487: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e6: Unknown result type (might be due to invalid IL or missing references)
			PuppetMaster puppetMaster = b.puppetMaster;
			if ((Object)(object)puppetMaster == (Object)null || !Enabled.Value || RagdollApi.IsExcluded(puppetMaster))
			{
				return;
			}
			if (!_dumpedAttack && attack != null)
			{
				_dumpedAttack = true;
				Reflect.LogMembers(attack, "Attack members", includeBases: false);
			}
			int muscleIndex = b.muscleIndex;
			if (!_dumpedStructure)
			{
				_dumpedStructure = true;
				DumpStructure(puppetMaster);
			}
			Rigidbody val = ((Component)b).GetComponent<Rigidbody>();
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)b).GetComponentInParent<Rigidbody>();
			}
			if (!Reflect.TryGet<float>(attack, "damage", out var value))
			{
				value = -1f;
			}
			string text = "Unknown";
			try
			{
				if (attack != null && Reflect.TryGetObj(attack, "attackType", out var value2) && value2 != null)
				{
					text = value2.ToString();
					if (_attackTypeLogs.Count < 5 && _attackTypeLogs.Add(text))
					{
						MelonLogger.Msg("AttackType seen: " + text);
					}
				}
			}
			catch
			{
			}
			if (_sourceLogs < 24)
			{
				bool flag = false;
				try
				{
					flag = !puppetMaster.isAlive || puppetMaster.isKilling;
				}
				catch
				{
				}
				if (value >= KnockdownDamage.Value || flag)
				{
					_sourceLogs++;
					string value3 = "?";
					string value4 = "?";
					try
					{
						if (attack != null && Reflect.TryGetObj(attack, "collider", out var value5) && value5 != null)
						{
							object value6 = null;
							try
							{
								Reflect.TryGetObj(value5, "name", out value6);
							}
							catch
							{
							}
							value3 = (value6 ?? value5.ToString())?.ToString() ?? "?";
						}
						if (attack != null && Reflect.TryGetObj(attack, "proxy", out var value7) && value7 != null)
						{
							value4 = value7.ToString();
						}
					}
					catch
					{
					}
					MelonLogger.Msg($"Hit source: type={text} collider={value3} proxy={value4} dmg={value:F2}");
				}
			}
			Vector3 hitPoint = Vector3.zero;
			bool flag2 = false;
			Vector3 val2;
			try
			{
				if (attack != null && Reflect.TryGet<Vector3>(attack, "origin", out var value8))
				{
					val2 = value8 - ((Component)b).transform.position;
					float magnitude = ((Vector3)(ref val2)).magnitude;
					if (magnitude < 1.5f)
					{
						hitPoint = value8;
						flag2 = true;
					}
					if (_originLogs < 5)
					{
						_originLogs++;
						MelonLogger.Msg($"[hit-origin {_originLogs}/5] origin->muscle dist={magnitude:F2}m {(flag2 ? "TRUSTED" : "rejected (muzzle?)")}");
					}
				}
			}
			catch
			{
			}
			Vector3 val3;
			if (Reflect.TryGet<Vector3>(attack, "direction", out var value9) && ((Vector3)(ref value9)).sqrMagnitude > 0.0001f)
			{
				val3 = ((Vector3)(ref value9)).normalized;
			}
			else
			{
				val3 = Vector3.up;
				Camera main = Camera.main;
				if ((Object)(object)main != (Object)null)
				{
					val2 = ((Component)b).transform.position - ((Component)main).transform.position;
					val3 = ((Vector3)(ref val2)).normalized;
				}
			}
			bool flag3 = !puppetMaster.isAlive || puppetMaster.isKilling;
			HitTier hitTier = (flag3 ? HitTier.Kill : ((!(value >= 0f) || !(value < KnockdownDamage.Value)) ? HitTier.Medium : HitTier.Light));
			MuscleRegion muscleRegion = RagdollApi.RegionOf(muscleIndex);
			if (LogHits.Value && _hitLogCount < 50)
			{
				_hitLogCount++;
				MelonLogger.Msg($"[hit {_hitLogCount}/50] muscle={muscleIndex} ({muscleRegion}) damage={value:F2} tier={hitTier} dead={flag3} npc={SafeName(puppetMaster)}");
			}
			BehaviourPuppet val4 = FindPuppet(puppetMaster);
			SubBehaviourHealth health = FindHealth(puppetMaster);
			React(puppetMaster, val4, health, hitTier, muscleRegion, val, val3);
			RagdollApi.Raise(new NpcHitInfo
			{
				Puppet = puppetMaster,
				Behaviour = val4,
				Health = health,
				MuscleIndex = muscleIndex,
				Region = muscleRegion,
				Body = val,
				HitPoint = hitPoint,
				HasHitPoint = flag2,
				AttackType = text,
				Gun = GunHook.Attribute(),
				Direction = val3,
				Damage = value,
				Tier = hitTier,
				IsDead = flag3
			});
		}

		private static BehaviourPuppet FindPuppet(PuppetMaster pm)
		{
			BehaviourPuppet componentInChildren = ((Component)pm).GetComponentInChildren<BehaviourPuppet>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				return componentInChildren;
			}
			try
			{
				Il2CppReferenceArray<BehaviourBase> behaviours = pm.behaviours;
				if (behaviours != null)
				{
					foreach (BehaviourBase item in (Il2CppArrayBase<BehaviourBase>)(object)behaviours)
					{
						if (!((Object)(object)item == (Object)null))
						{
							BehaviourPuppet val = ((Il2CppObjectBase)item).TryCast<BehaviourPuppet>();
							if ((Object)(object)val != (Object)null)
							{
								return val;
							}
						}
					}
				}
			}
			catch
			{
			}
			return null;
		}

		private static SubBehaviourHealth FindHealth(PuppetMaster pm)
		{
			int instanceID = ((Object)pm).GetInstanceID();
			if (HealthCache.TryGetValue(instanceID, out var value) && value != null)
			{
				return value;
			}
			if (NoHealth.Contains(instanceID))
			{
				return null;
			}
			try
			{
				foreach (BehaviourBase item in (Il2CppArrayBase<BehaviourBase>)(object)pm.behaviours)
				{
					if ((Object)(object)item == (Object)null)
					{
						continue;
					}
					string className;
					string memberName;
					SubBehaviourHealth val = Reflect.FindMemberOfType<SubBehaviourHealth>(Reflect.ResolveRuntimeType((Il2CppObjectBase)(object)item, out className), out memberName);
					if (val != null)
					{
						if (HealthCache.Count > 512)
						{
							HealthCache.Clear();
						}
						HealthCache[instanceID] = val;
						if (!_loggedHealth)
						{
							_loggedHealth = true;
							MelonLogger.Msg("Found SubBehaviourHealth at " + memberName);
							Reflect.LogValues(val, "SubBehaviourHealth values");
						}
						return val;
					}
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("FindHealth failed: " + ex.Message);
			}
			if (NoHealth.Count > 512)
			{
				NoHealth.Clear();
			}
			NoHealth.Add(instanceID);
			if (!_loggedNoHealth)
			{
				_loggedNoHealth = true;
				MelonLogger.Msg("No SubBehaviourHealth found on this NPC; light hits use the muscle dip instead.");
			}
			return null;
		}

		private static void React(PuppetMaster pm, BehaviourPuppet bp, SubBehaviourHealth health, HitTier tier, MuscleRegion region, Rigidbody body, Vector3 dir)
		{
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: 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)
			int instanceID = ((Object)pm).GetInstanceID();
			float time = Time.time;
			if (tier != HitTier.Kill && LastReact.TryGetValue(instanceID, out var value) && time - value < 0.25f)
			{
				return;
			}
			LastReact[instanceID] = time;
			float num = 0f;
			switch (tier)
			{
			case HitTier.Light:
				num = 0.25f;
				if (health != null && UseGameStun.Value)
				{
					RagdollApi.SetLimbStun(health, region, LightStunLevel.Value);
					if (!_loggedStun)
					{
						_loggedStun = true;
						MelonLogger.Msg($"Light hit -> limb stun on {region}");
					}
				}
				else
				{
					Dip(pm, null, LightMuscleWeight.Value, LightSeconds.Value);
					if (!_loggedLightDip)
					{
						_loggedLightDip = true;
						MelonLogger.Msg("Light hit -> muscleWeight dip");
					}
				}
				break;
			case HitTier.Medium:
				if (!RagdollApi.AutoKnockdown)
				{
					break;
				}
				num = 1f;
				if ((Object)(object)bp != (Object)null)
				{
					bp.canGetUp = true;
					bp.getUpDelay = GetUpDelay.Value;
					bp.Unpin();
					if (!_loggedUnpin)
					{
						_loggedUnpin = true;
						MelonLogger.Msg("Medium hit -> BehaviourPuppet.Unpin()");
					}
				}
				else
				{
					Dip(pm, health, 0f, GetUpDelay.Value);
					if (!_loggedMedium)
					{
						_loggedMedium = true;
						MelonLogger.Msg("Medium hit -> muscleWeight drop (limb stun frozen while down)");
					}
				}
				break;
			case HitTier.Kill:
				ReleaseNow(pm);
				num = 1.5f;
				SlowMo(SlowMoSeconds.Value, SlowMoScale.Value);
				if (!_loggedKill)
				{
					_loggedKill = true;
					Reflect.TryGet<object>(pm, "state", out var value2);
					MelonLogger.Msg($"Kill -> PuppetMaster state={value2}");
				}
				break;
			}
			if ((Object)(object)body != (Object)null && num > 0f && KnockbackForce.Value > 0f)
			{
				body.AddForce(dir * KnockbackForce.Value * num, (ForceMode)2);
			}
		}

		internal static void HoldMapping(PuppetMaster pm, float seconds)
		{
			HoldMapping(pm, seconds, 1f);
		}

		internal static void HoldMapping(PuppetMaster pm, float seconds, float weight)
		{
			int instanceID = ((Object)pm).GetInstanceID();
			float num = Time.time + seconds;
			if (MapHolds.TryGetValue(instanceID, out var value))
			{
				value.Until = Mathf.Max(value.Until, num);
				value.Weight = Mathf.Min(value.Weight, weight);
				return;
			}
			value = new MapHold
			{
				Original = pm.mappingWeight,
				Weight = weight,
				Until = num
			};
			MapHolds[instanceID] = value;
			MelonCoroutines.Start(MapRoutine(pm, instanceID, value));
		}

		private static IEnumerator MapRoutine(PuppetMaster pm, int id, MapHold h)
		{
			while ((Object)(object)pm != (Object)null && pm.isAlive && Time.time < h.Until)
			{
				pm.mappingWeight = h.Weight;
				yield return null;
			}
			if ((Object)(object)pm != (Object)null)
			{
				try
				{
					pm.mappingWeight = h.Original;
				}
				catch
				{
				}
			}
			MapHolds.Remove(id);
		}

		internal static void HoldBoolFlag(PuppetMaster pm, string field, bool value, float seconds)
		{
			string key = ((Object)pm).GetInstanceID() + ":" + field;
			float num = Time.time + seconds;
			if (FlagHolds.TryGetValue(key, out var value2))
			{
				value2.Until = Mathf.Max(value2.Until, num);
				return;
			}
			object obj = null;
			bool flag = !value;
			try
			{
				foreach (BehaviourBase item in (Il2CppArrayBase<BehaviourBase>)(object)pm.behaviours)
				{
					if (!((Object)(object)item == (Object)null))
					{
						string className;
						object obj2 = Reflect.ResolveRuntimeType((Il2CppObjectBase)(object)item, out className) ?? item;
						if (Reflect.TryGet<bool>(obj2, field, out var value3))
						{
							obj = obj2;
							flag = value3;
							break;
						}
					}
				}
			}
			catch
			{
			}
			if (obj == null)
			{
				if (_locoLogs < 8)
				{
					_locoLogs++;
					MelonLogger.Msg("HoldFlag: no " + field + " found on this NPC, nothing held");
				}
				return;
			}
			value2 = new FlagHold
			{
				Beh = obj,
				Original = flag,
				Until = num
			};
			FlagHolds[key] = value2;
			Reflect.TrySetBool(obj, field, value);
			bool value4;
			bool flag2 = Reflect.TryGet<bool>(obj, field, out value4);
			if (_locoLogs < 8)
			{
				_locoLogs++;
				MelonLogger.Msg($"HoldFlag: {field} was {flag}, now reads {(flag2 ? value4.ToString() : "?")} -> {((flag2 && value4 == value) ? "held" : "WRITE FAILED")}");
			}
			MelonCoroutines.Start(FlagRoutine(pm, key, value2, field, value));
		}

		private static IEnumerator FlagRoutine(PuppetMaster pm, string key, FlagHold h, string field, bool value)
		{
			int frame = 0;
			while (((Object)(object)pm == (Object)null || pm.isAlive) && Time.time < h.Until)
			{
				if (h.Beh != null && (frame++ & 0xF) == 0)
				{
					Reflect.TrySetBool(h.Beh, field, value);
				}
				yield return null;
			}
			if (h.Beh != null && ((Object)(object)pm == (Object)null || pm.isAlive))
			{
				Reflect.TrySetBool(h.Beh, field, h.Original);
			}
			FlagHolds.Remove(key);
		}

		internal static void HoldLoco(PuppetMaster pm, float seconds)
		{
			HoldBoolFlag(pm, "followPlayer", value: false, seconds);
		}

		internal static void HoldNav(PuppetMaster pm, float seconds)
		{
			HoldBoolFlag(pm, "_isNavAgentStopped", value: true, seconds);
		}

		internal static void HoldLiteLoco(PuppetMaster pm, float seconds)
		{
			string key = ((Object)pm).GetInstanceID() + ":liteloco.weight";
			float num = Time.time + seconds;
			if (FloatHolds.TryGetValue(key, out var value))
			{
				value.Until = Mathf.Max(value.Until, num);
				return;
			}
			object obj = null;
			float num2 = 1f;
			try
			{
				foreach (BehaviourBase item in (Il2CppArrayBase<BehaviourBase>)(object)pm.behaviours)
				{
					if (!((Object)(object)item == (Object)null) && Reflect.TryGetObj(Reflect.ResolveRuntimeType((Il2CppObjectBase)(object)item, out var _) ?? item, "_liteLoco", out var value2) && value2 != null)
					{
						obj = value2;
						break;
					}
				}
			}
			catch
			{
			}
			if (obj == null)
			{
				if (_locoLogs < 10)
				{
					_locoLogs++;
					MelonLogger.Msg("HoldLiteLoco: no _liteLoco on this NPC, nothing held");
				}
				return;
			}
			if (!Reflect.TryGet<float>(obj, "weight", out var value3))
			{
				value3 = 1f;
			}
			num2 = value3;
			value = new FloatHold
			{
				Target = obj,
				Original = num2,
				Until = num
			};
			FloatHolds[key] = value;
			Reflect.TrySet(obj, "weight", 0f);
			float value4;
			bool flag = Reflect.TryGet<float>(obj, "weight", out value4);
			if (_locoLogs < 10)
			{
				_locoLogs++;
				MelonLogger.Msg($"HoldLiteLoco: weight was {num2:F2}, now reads {(flag ? value4.ToString("F2") : "?")} -> {((flag && value4 < 0.01f) ? "held" : "WRITE FAILED")}");
			}
			MelonCoroutines.Start(FloatRoutine(pm, key, value));
		}

		private static IEnumerator FloatRoutine(PuppetMaster pm, string key, FloatHold h)
		{
			int frame = 0;
			while (((Object)(object)pm == (Object)null || pm.isAlive) && Time.time < h.Until)
			{
				if (h.Target != null && (frame++ & 0xF) == 0)
				{
					Reflect.TrySet(h.Target, "weight", 0f);
				}
				yield return null;
			}
			if (h.Target != null && ((Object)(object)pm == (Object)null || pm.isAlive))
			{
				Reflect.TrySet(h.Target, "weight", h.Original);
			}
			FloatHolds.Remove(key);
		}

		internal static void ReleaseAI(PuppetMaster pm)
		{
			int instanceID;
			try
			{
				instanceID = ((Object)pm).GetInstanceID();
			}
			catch
			{
				return;
			}
			string[] array = new string[2] { "followPlayer", "_isNavAgentStopped" };
			foreach (string text in array)
			{
				string key = instanceID + ":" + text;
				if (FlagHolds.TryGetValue(key, out var value))
				{
					value.Until = 0f;
				}
			}
			string key2 = instanceID + ":liteloco.weight";
			if (FloatHolds.TryGetValue(key2, out var value2))
			{
				value2.Until = 0f;
			}
		}

		internal static void KnockDown(PuppetMaster pm, SubBehaviourHealth health, float seconds)
		{
			Dip(pm, health, 0f, seconds);
		}

		internal static void HoldLimp(PuppetMaster pm, SubBehaviourHealth health, float weight, float seconds)
		{
			Dip(pm, health, weight, seconds);
		}

		internal static void ReleaseNow(PuppetMaster pm)
		{
			int instanceID;
			try
			{
				instanceID = ((Object)pm).GetInstanceID();
			}
			catch
			{
				return;
			}
			if (Reactions.TryGetValue(instanceID, out var value))
			{
				try
				{
					pm.muscleWeight = value.Original;
				}
				catch
				{
				}
				Reactions.Remove(instanceID);
			}
			if (MapHolds.TryGetValue(instanceID, out var value2))
			{
				try
				{
					pm.mappingWeight = value2.Original;
				}
				catch
				{
				}
				MapHolds.Remove(instanceID);
			}
		}

		internal static void Diag(PuppetMaster pm)
		{
			if ((Object)(object)pm == (Object)null || _diagCount >= 8)
			{
				return;
			}
			_diagCount++;
			try
			{
				MelonLogger.Msg($"Diag #{_diagCount}: muscleWeight={pm.muscleWeight:F2} mappingWeight={pm.mappingWeight:F2} spring={pm.muscleSpring:F2} damper={pm.muscleDamper:F2}");
				foreach (BehaviourBase item in (Il2CppArrayBase<BehaviourBase>)(object)pm.behaviours)
				{
					if ((Object)(object)item == (Object)null)
					{
						continue;
					}
					string className;
					object o = Reflect.ResolveRuntimeType((Il2CppObjectBase)(object)item, out className) ?? item;
					List<string> list = new List<string>();
					string[] array = new string[9] { "followPlayer", "_isNavAgentStopped", "engagedMode", "locoState", "mentalState", "useAiLocoController", "aggression", "_unbalancedTimer", "_dyingTime" };
					foreach (string text in array)
					{
						if (Reflect.TryGetObj(o, text, out var value))
						{
							list.Add($"{text}={value}");
						}
					}
					MelonLogger.Msg($"Diag #{_diagCount} [{className}]: {string.Join(", ", list)}");
					if (_diagCount != 1)
					{
						continue;
					}
					array = new string[2] { "aiLocoController", "_liteLoco" };
					foreach (string text2 in array)
					{
						try
						{
							if (!Reflect.TryGetObj(o, text2, out var value2))
							{
								goto IL_0281;
							}
							Il2CppObjectBase val = (Il2CppObjectBase)((value2 is Il2CppObjectBase) ? value2 : null);
							if (val == null || val == null)
							{
								goto IL_0281;
							}
							Reflect.LogMembers(Reflect.ResolveRuntimeType(val, out var className2) ?? value2, "Loco [" + className2 + "]", includeBases: false);
							goto end_IL_023b;
							IL_0281:
							MelonLogger.Msg("Loco [" + text2 + "]: null/unreadable");
							end_IL_023b:;
						}
						catch (Exception ex)
						{
							MelonLogger.Msg("Loco [" + text2 + "]: " + ex.Message);
						}
					}
				}
				try
				{
					Muscle val2 = ((Il2CppArrayBase<Muscle>)(object)pm.muscles)[1];
					if (val2 != null && val2.props != null)
					{
						Reflect.LogMembers(val2.props, "MuscleProps members", includeBases: false);
					}
					int[] array2 = new int[2] { 1, 4 };
					foreach (int num in array2)
					{
						Muscle val3 = ((Il2CppArrayBase<Muscle>)(object)pm.muscles)[num];
						if (val3 == null || val3.props == null)
						{
							continue;
						}
						List<string> list2 = new List<string>();
						string[] array = new string[4] { "muscleWeight", "pinWeight", "mappingWeight", "muscleDamper" };
						foreach (string text3 in array)
						{
							if (Reflect.TryGetObj(val3.props, text3, out var value3))
							{
								list2.Add($"{text3}={value3}");
							}
						}
						MelonLogger.Msg($"Diag #{_diagCount} muscle[{num}]: {string.Join(", ", list2)}");
					}
				}
				catch (Exception ex2)
				{
					MelonLogger.Msg($"Diag #{_diagCount} muscles: unreadable ({ex2.Message})");
				}
			}
			catch (Exception ex3)
			{
				MelonLogger.Warning("Diag failed: " + ex3.Message);
			}
		}

		private static void Dip(PuppetMaster pm, SubBehaviourHealth health, float weight, float hold)
		{
			int instanceID = ((Object)pm).GetInstanceID();
			float time = Time.time;
			if (Reactions.TryGetValue(instanceID, out var value))
			{
				bool flag = time < value.HoldUntil;
				if (!flag || !(weight > value.Weight))
				{
					value.Weight = weight;
					value.HoldUntil = (flag ? Mathf.Max(value.HoldUntil, time + hold) : (time + hold));
				}
				return;
			}
			value = new Reaction
			{
				Original = ((pm.muscleWeight > 0.01f) ? pm.muscleWeight : 1f),
				Weight = weight,
				HoldUntil = time + hold,
				Health = health,
				Held = ((health != null) ? new float[StunFields.Length] : null)
			};
			if (health != null)
			{
				ReadStun(health, value.Held);
			}
			Reactions[instanceID] = value;
			MelonCoroutines.Start(ReactionRoutine(pm, instanceID, value));
		}

		private static IEnumerator ReactionRoutine(PuppetMaster pm, int id, Reaction r)
		{
			float current = pm.muscleWeight;
			while ((Object)(object)pm != (Object)null)
			{
				if (!pm.isAlive || pm.isKilling)
				{
					try
					{
						pm.muscleWeight = r.Original;
					}
					catch
					{
					}
					Reactions.Remove(id);
					yield break;
				}
				if (Time.time < r.HoldUntil)
				{
					current = Mathf.MoveTowards(current, r.Weight, 20f * Time.deltaTime);
					if (r.Health != null)
					{
						HoldStun(r);
					}
				}
				else
				{
					if (r.Health != null)
					{
						ReadStun(r.Health, r.Held);
					}
					float num = r.Original / Mathf.Max(0.05f, RecoverSeconds.Value);
					current = Mathf.MoveTowards(current, r.Original, num * Time.deltaTime);
					if (Mathf.Approximately(current, r.Original))
					{
						break;
					}
				}
				pm.muscleWeight = current;
				HoldMapping(pm, 0.15f);
				yield return null;
			}
			if ((Object)(object)pm != (Object)null && pm.isAlive)
			{
				pm.muscleWeight = r.Original;
			}
			Reactions.Remove(id);
		}

		private static void ReadStun(SubBehaviourHealth h, float[] into)
		{
			for (int i = 0; i < StunFields.Length; i++)
			{
				into[i] = (Reflect.TryGet<float>(h, StunFields[i], out var value) ? value : 1f);
			}
		}

		private static void HoldStun(Reaction r)
		{
			for (int i = 0; i < StunFields.Length; i++)
			{
				if (Reflect.TryGet<float>(r.Health, StunFields[i], out var value))
				{
					float num = Mathf.Min(r.Held[i], value);
					r.Held[i] = num;
					if (value > num)
					{
						Reflect.TrySet(r.Health, StunFields[i], num);
					}
				}
			}
		}

		private static void SlowMo(float seconds, float scale)
		{
			if (!(seconds <= 0f) && !(scale >= 1f) && !_slowActive)
			{
				MelonCoroutines.Start(SlowRoutine(seconds, scale));
			}
		}

		private static IEnumerator SlowRoutine(float seconds, float scale)
		{
			_slowActive = true;
			float previous = Time.timeScale;
			Time.timeScale = scale;
			float t = 0f;
			while (t < seconds)
			{
				t += Time.unscaledDeltaTime;
				yield return null;
			}
			if (Mathf.Approximately(Time.timeScale, scale))
			{
				Time.timeScale = previous;
			}
			_slowActive = false;
		}

		private static void DumpStructure(PuppetMaster pm)
		{
			try
			{
				foreach (BehaviourBase item in (Il2CppArrayBase<BehaviourBase>)(object)pm.behaviours)
				{
					if (!((Object)(object)item == (Object)null))
					{
						string className;
						object obj = Reflect.ResolveRuntimeType((Il2CppObjectBase)(object)item, out className);
						MelonLogger.Msg($"Behaviour runtime class: {className} (wrapper found: {obj != null})");
						if (obj != null)
						{
							Reflect.LogMembers(obj, "Behaviour members", includeBases: true);
						}
					}
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("Structure dump failed: " + ex.Message);
			}
		}
	}
	internal static class GunHook
	{
		internal static string LastGun = "Unknown";

		internal static float LastGunTime = -100f;

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

		private static readonly string[] KnownGuns = new string[4] { "Il2CppSLZ.Marrow.Gun", "Il2CppSLZ.Bonelab.ObjectiveGun", "Il2CppSLZ.Bonelab.GunHeat", "Il2CppSLZ.Bonelab.SpawnGun" };

		private static readonly string[] KnownAssemblies = new string[4] { "Il2CppSLZ.Marrow", "Il2CppSLZ.Bonelab", "Assembly-CSharp", "Assembly-CSharp-firstpass" };

		private static Type FindGunType(string fullName)
		{
			try
			{
				string[] knownAssemblies = KnownAssemblies;
				foreach (string text in knownAssemblies)
				{
					Assembly assembly = null;
					try
					{
						Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
						foreach (Assembly assembly2 in assemblies)
						{
							string name;
							try
							{
								name = assembly2.GetName().Name;
							}
							catch
							{
								continue;
							}
							if (name == text)
							{
								assembly = assembly2;
								break;
							}
						}
					}
					catch
					{
						continue;
					}
					if (!(assembly == null) && !assembly.IsDynamic)
					{
						Type type = null;
						try
						{
							type = assembly.GetType(fullName, throwOnError: false, ignoreCase: false);
						}
						catch
						{
						}
						if (type != null)
						{
							return type;
						}
					}
				}
			}
			catch
			{
			}
			return null;
		}

		private static int PatchOnFire(Type t, Harmony harmony, HarmonyMethod post)
		{
			MethodInfo[] array = null;
			try
			{
				array = t.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			}
			catch
			{
				return 0;
			}
			int num = 0;
			MethodInfo[] array2 = array;
			foreach (MethodInfo methodInfo in array2)
			{
				if (methodInfo == null || methodInfo.Name != "OnFire")
				{
					continue;
				}
				try
				{
					harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, post, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					num++;
					try
					{
						MelonLogger.Msg("Gun hook: " + t.FullName + ".OnFire");
					}
					catch
					{
					}
				}
				catch (Exception ex)
				{
					MelonLogger.Warning("Gun hook failed on " + t.FullName + ": " + ex.Message);
				}
				if (num >= 2)
				{
					break;
				}
			}
			return num;
		}

		internal static void TryInstall()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			try
			{
				int num = 0;
				Harmony harmony = new Harmony("HitRagdoll.GunHook");
				HarmonyMethod val = null;
				try
				{
					val = new HarmonyMethod(typeof(GunHook).GetMethod("Fired", BindingFlags.Static | BindingFlags.NonPublic));
				}
				catch
				{
				}
				if (val != null)
				{
					string[] knownGuns = KnownGuns;
					foreach (string fullName in knownGuns)
					{
						Type type = null;
						try
						{
							type = FindGunType(fullName);
						}
						catch
						{
						}
						if (!(type == null))
						{
							try
							{
								num += PatchOnFire(type, harmony, val);
							}
							catch
							{
							}
							if (num >= 6)
							{
								break;
							}
						}
					}
				}
				if (num == 0)
				{
					num = LegacyScan();
				}
				MelonLogger.Msg((num > 0) ? $"Gun hook: {num} OnFire patched" : "Gun hook: no OnFire found, damage bands only");
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("Gun hook install failed: " + ex.Message);
			}
		}

		private static int LegacyScan()
		{
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Expected O, but got Unknown
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				try
				{
					if (assembly.IsDynamic)
					{
						continue;
					}
				}
				catch
				{
					continue;
				}
				string name;
				try
				{
					name = assembly.GetName().Name;
				}
				catch
				{
					continue;
				}
				if (!name.StartsWith("Il2Cpp") && !(name == "Assembly-CSharp") && !(name == "Assembly-CSharp-firstpass"))
				{
					continue;
				}
				Type[] types;
				try
				{
					types = assembly.GetTypes();
				}
				catch
				{
					continue;
				}
				Type[] array = types;
				foreach (Type type in array)
				{
					try
					{
						if (type.IsAbstract || type.IsInterface || type.IsEnum || (type.Name ?? "").IndexOf("Gun", StringComparison.OrdinalIgnoreCase) < 0)
						{
							continue;
						}
						MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
						foreach (MethodInfo methodInfo in methods)
						{
							if (methodInfo.Name != "OnFire")
							{
								continue;
							}
							try
							{
								HarmonyMethod val = new HarmonyMethod(typeof(GunHook).GetMethod("Fired", BindingFlags.Static | BindingFlags.NonPublic));
								new Harmony("HitRagdoll.GunHook").Patch((MethodBase)methodInfo, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
								num++;
								try
								{
									MelonLogger.Msg("Gun hook: " + type.FullName + ".OnFire");
								}
								catch
								{
								}
							}
							catch (Exception ex)
							{
								MelonLogger.Warning("Gun hook failed on " + type.FullName + ": " + ex.Message);
							}
							if (num >= 6)
							{
								break;
							}
						}
						goto IL_01a3;
					}
					catch
					{
						goto IL_01a3;
					}
					IL_01a3:
					if (num >= 6)
					{
						break;
					}
				}
				if (num >= 6)
				{
					break;
				}
			}
			return num;
		}

		private static void Fired(object __instance)
		{
			try
			{
				string text = null;
				try
				{
					if (__instance != null && Reflect.TryGetObj(__instance, "name", out var value) && value != null)
					{
						text = value.ToString();
					}
				}
				catch
				{
				}
				if (string.IsNullOrEmpty(text))
				{
					try
					{
						text = __instance?.GetType().Name;
					}
					catch
					{
					}
				}
				if (!string.IsNullOrEmpty(text))
				{
					LastGun = text;
					LastGunTime = Time.time;
					if (Seen.Count < 8 && Seen.Add(text))
					{
						MelonLogger.Msg("Gun seen: " + text);
					}
				}
			}
			catch
			{
			}
		}

		internal static string Attribute()
		{
			try
			{
				if (Time.time - LastGunTime < 0.6f)
				{
					return LastGun;
				}
			}
			catch
			{
			}
			return "Unknown";
		}
	}
	[HarmonyPatch(typeof(MuscleCollisionBroadcaster), "ReceiveAttack")]
	internal static class HitPatch
	{
		private static void Postfix(MuscleCollisionBroadcaster __instance, object __0)
		{
			try
			{
				Main.HandleHit(__instance, __0);
			}
			catch (Exception value)
			{
				MelonLogger.Error($"RagdollOnHit: {value}");
			}
		}
	}
	internal static class Reflect
	{
		private const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

		private static bool IsEngineNamespace(string ns)
		{
			ns = ns ?? "";
			if (!ns.StartsWith("System") && !ns.StartsWith("UnityEngine") && !ns.StartsWith("Il2CppSystem"))
			{
				return ns.StartsWith("Il2CppInterop");
			}
			return true;
		}

		internal static bool TryGetObj(object o, string name, out object value)
		{
			value = null;
			if (o == null)
			{
				return false;
			}
			try
			{
				Type type = o.GetType();
				PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (property != null && property.CanRead && property.GetIndexParameters().Length == 0)
				{
					value = property.GetValue(o);
					return true;
				}
				FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					value = field.GetValue(o);
					return true;
				}
			}
			catch
			{
			}
			return false;
		}

		internal static bool TryGet<T>(object o, string name, out T value)
		{
			value = default(T);
			if (o == null)
			{
				return false;
			}
			try
			{
				for (Type type = o.GetType(); type != null && !IsEngineNamespace(type.Namespace); type = type.BaseType)
				{
					BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
					object obj = null;
					bool flag = false;
					PropertyInfo property = type.GetProperty(name, bindingAttr);
					if (property != null && property.CanRead && property.GetIndexParameters().Length == 0)
					{
						obj = property.GetValue(o);
						flag = true;
					}
					else
					{
						FieldInfo field = type.GetField(name, bindingAttr);
						if (field == null)
						{
							continue;
						}
						obj = field.GetValue(o);
						flag = true;
					}
					if (flag)
					{
						if (obj is T val)
						{
							value = val;
							return true;
						}
						if (typeof(T) == typeof(float) && obj is IConvertible convertible)
						{
							value = (T)(object)convertible.ToSingle(null);
							return true;
						}
						return false;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		internal static bool TrySet(object o, string name, float value)
		{
			return TrySetRaw(o, name, value);
		}

		internal static bool TrySetBool(object o, string name, bool value)
		{
			return TrySetRaw(o, name, value);
		}

		private static bool TrySetRaw(object o, string name, object value)
		{
			if (o == null)
			{
				return false;
			}
			try
			{
				Type type = o.GetType();
				while (type != null && !IsEngineNamespace(type.Namespace))
				{
					BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
					PropertyInfo property = type.GetProperty(name, bindingAttr);
					if (property != null && property.CanWrite && property.GetIndexParameters().Length == 0)
					{
						property.SetValue(o, Convert.ChangeType(value, property.PropertyType));
						return true;
					}
					FieldInfo field = type.GetField(name, bindingAttr);
					if (field != null)
					{
						field.SetValue(o, Convert.ChangeType(value, field.FieldType));
						return true;
					}
					type = type.BaseType;
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("Couldn't set " + name + ": " + ex.Message);
			}
			return false;
		}

		internal static T FindMemberOfType<T>(object o, out string memberName) where T : class
		{
			memberName = null;
			if (o == null)
			{
				return null;
			}
			Type type = o.GetType();
			while (type != null && !IsEngineNamespace(type.Namespace))
			{
				BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
				PropertyInfo[] properties = type.GetProperties(bindingAttr);
				foreach (PropertyInfo propertyInfo in properties)
				{
					if (!typeof(T).IsAssignableFrom(propertyInfo.PropertyType) || !propertyInfo.CanRead || propertyInfo.GetIndexParameters().Length != 0)
					{
						continue;
					}
					try
					{
						if (propertyInfo.GetValue(o) is T result)
						{
							memberName = type.Name + "." + propertyInfo.Name;
							return result;
						}
					}
					catch
					{
					}
				}
				FieldInfo[] fields = type.GetFields(bindingAttr);
				foreach (FieldInfo fieldInfo in fields)
				{
					if (!typeof(T).IsAssignableFrom(fieldInfo.FieldType))
					{
						continue;
					}
					try
					{
						if (fieldInfo.GetValue(o) is T result2)
						{
							memberName = type.Name + "." + fieldInfo.Name;
							return result2;
						}
					}
					catch
					{
					}
				}
				type = type.BaseType;
			}
			return null;
		}

		internal static void LogMembers(object o, string label, bool includeBases)
		{
			Type type = o.GetType();
			while (type != null && !IsEngineNamespace(type.Namespace))
			{
				BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
				IEnumerable<string> values = (from p in type.GetProperties(bindingAttr)
					select p.PropertyType.Name + " " + p.Name).Concat(from f in type.GetFields(bindingAttr)
					select f.FieldType.Name + " " + f.Name);
				MelonLogger.Msg($"{label} [{type.FullName}]: {string.Join(", ", values)}");
				if (includeBases)
				{
					type = type.BaseType;
					continue;
				}
				break;
			}
		}

		internal static void LogValues(object o, string label)
		{
			if (o == null)
			{
				return;
			}
			try
			{
				List<string> list = new List<string>();
				PropertyInfo[] properties = o.GetType().GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (PropertyInfo propertyInfo in properties)
				{
					Type propertyType = propertyInfo.PropertyType;
					if ((propertyType.IsPrimitive || propertyType.IsEnum || propertyType == typeof(string)) && propertyInfo.CanRead && propertyInfo.GetIndexParameters().Length == 0)
					{
						try
						{
							list.Add($"{propertyInfo.Name}={propertyInfo.GetValue(o)}");
						}
						catch
						{
						}
					}
				}
				MelonLogger.Msg(label + ": " + string.Join(", ", list));
			}
			catch (Exception ex)
			{
				MelonLogger.Warning(label + ": dump failed (" + ex.Message + ")");
			}
		}

		internal static object ResolveRuntimeType(Il2CppObjectBase obj, out string className)
		{
			className = "?";
			try
			{
				IntPtr intPtr = IL2CPP.il2cpp_object_get_class(obj.Pointer);
				string text = Marshal.PtrToStringAnsi(IL2CPP.il2cpp_class_get_name(intPtr));
				string text2 = Marshal.PtrToStringAnsi(IL2CPP.il2cpp_class_get_namespace(intPtr));
				className = (string.IsNullOrEmpty(text2) ? text : (text2 + "." + text));
				Type type = null;
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				for (int i = 0; i < assemblies.Length; i++)
				{
					type = assemblies[i].GetType("Il2Cpp" + className);
					if (type != null)
					{
						break;
					}
				}
				if (type == null)
				{
					return null;
				}
				return typeof(Il2CppObjectBase).GetMethod("TryCast").MakeGenericMethod(type).Invoke(obj, null);
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("ResolveRuntimeType failed: " + ex.Message);
				return null;
			}
		}
	}
}