Decompiled source of DramaticHitReactions v1.0.0

BepInEx/plugins/DramaticHitReactions/DramaticHitReactions.dll

Decompiled 12 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FistVR;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6", FrameworkDisplayName = ".NET Framework 4.6")]
[assembly: AssemblyCompany("DramaticHitReactions")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+a74d29e7e3da15aef21e8ae72c7becaf7e599ee7")]
[assembly: AssemblyProduct("DramaticHitReactions")]
[assembly: AssemblyTitle("DramaticHitReactions")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace DramaticHitReactions;

[BepInPlugin("invent60.h3vr.dramatichitreactions", "Dramatic Hit Reactions", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
	internal static ManualLogSource Log;

	private static readonly object[] NoTags = new object[0];

	internal static ConfigEntry<bool> Enabled;

	internal static ConfigEntry<float> PushChance;

	internal static ConfigEntry<float> PushSpeed;

	internal static ConfigEntry<float> ChestStandMin;

	internal static ConfigEntry<float> ChestStandMax;

	internal static ConfigEntry<float> HeadStandMin;

	internal static ConfigEntry<float> HeadStandMax;

	internal static ConfigEntry<float> DriftPerHit;

	internal static ConfigEntry<float> HeadSnap;

	internal static ConfigEntry<float> LegCrouch;

	internal static ConfigEntry<bool> FootKnocksDown;

	internal static ConfigEntry<float> ChestJolt;

	internal static ConfigEntry<float> StepBack;

	internal static ConfigEntry<float> LegStand;

	internal static ConfigEntry<float> Shove;

	internal static ConfigEntry<float> RoundRef;

	internal static ConfigEntry<float> Sway;

	internal static ConfigEntry<float> Dip;

	internal static ConfigEntry<float> FallBack;

	internal static ConfigEntry<float> LegLowTime;

	internal static ConfigEntry<float> StepBackChance;

	internal static ConfigEntry<float> JoltDist;

	internal static ConfigEntry<float> OverwhelmJ;

	internal static ConfigEntry<bool> LowHeadshotFalls;

	internal static ConfigEntry<float> TurnDeg;

	internal static ConfigEntry<float> TurnStays;

	internal static ConfigEntry<float> BackStays;

	internal static ConfigEntry<bool> DebugLog;

	private void Awake()
	{
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Expected O, but got Unknown
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Expected O, but got Unknown
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Expected O, but got Unknown
		//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ac: Expected O, but got Unknown
		//IL_030c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0316: Expected O, but got Unknown
		//IL_039d: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a7: Expected O, but got Unknown
		//IL_03f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_03fe: Expected O, but got Unknown
		//IL_0423: Unknown result type (might be due to invalid IL or missing references)
		//IL_0428: Unknown result type (might be due to invalid IL or missing references)
		//IL_044f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0464: Unknown result type (might be due to invalid IL or missing references)
		//IL_0471: Expected O, but got Unknown
		//IL_0471: Expected O, but got Unknown
		//IL_0472: Unknown result type (might be due to invalid IL or missing references)
		//IL_0499: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a7: Expected O, but got Unknown
		//IL_04a8: 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_04dd: Expected O, but got Unknown
		//IL_0504: Unknown result type (might be due to invalid IL or missing references)
		//IL_0512: Expected O, but got Unknown
		//IL_0518: Unknown result type (might be due to invalid IL or missing references)
		//IL_051d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0523: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Sosigs physically react to getting shot. false = vanilla. Example: Enabled = false");
		string text = Path.Combine(Paths.ConfigPath, "invent60.h3vr.dramatichitreactions.dev.cfg");
		ConfigFile val = new ConfigFile(text, false);
		val.SaveOnConfigSet = File.Exists(text);
		PushChance = val.Bind<float>("Hit push", "Chance", 0.6f, new ConfigDescription("Chance (0-1) that a bullet reaching flesh gives the extra push. Example: 0.6 = 6 of 10 bullets push, the rest are vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), NoTags));
		PushSpeed = val.Bind<float>("Hit push", "Push (m/s)", 1.5f, new ConfigDescription("Speed change given to the hit body part at the hit point, the same for every bullet. Example: 0.8 = subtle, 2.5 = strong.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), NoTags));
		ChestStandMin = val.Bind<float>("Chest", "Stand min (s)", 0.8f, "Shortest dazed stand before a chest-hit sosig falls. Example: 0.5");
		ChestStandMax = val.Bind<float>("Chest", "Stand max (s)", 2.4f, "Longest dazed stand before a chest-hit sosig falls. Example: 3");
		DriftPerHit = val.Bind<float>("Chest", "Drift per hit (m/s)", 0.35f, "How fast each chest hit makes the dazed sosig stumble along the bullet's direction (fades out). Example: 0 = stands in place, 1 = big stumble.");
		HeadStandMin = val.Bind<float>("Head", "Stand min (s)", 0.3f, "Shortest still stand after a headshot (head not exploded). Example: 0.2");
		HeadStandMax = val.Bind<float>("Head", "Stand max (s)", 1.5f, "Longest still stand after a headshot. Example: 2");
		HeadSnap = val.Bind<float>("Head", "Snap (m/s)", 2.5f, "How hard a headshot snaps the head back before it bounces back. Example: 1.5 = slight, 4 = strong.");
		LegCrouch = val.Bind<float>("Legs", "Crouch level", 0.35f, new ConfigDescription("Suppression level a leg hit sets (vanilla crouches above 0.2, goes prone around 0.4-0.8). Example: 0.3", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), NoTags));
		FootKnocksDown = val.Bind<bool>("Foot", "Foot hit knocks down", true, "true = a bullet in the foot (lowest segment) makes the sosig fall (pushed back first). false = the foot is like the legs: the sosig goes low. Example: Foot hit knocks down = true");
		ChestJolt = val.Bind<float>("Chest", "Jolt (m/s)", 2f, "Every bullet into the chest jolts the torso back at the hit point (on top of Hit push). Example: 1 = light, 3 = hard.");
		StepBack = val.Bind<float>("Chest", "Step back (m/s)", 0.6f, "After the jolt the sosig takes a step back the way the bullet went (legs: 60 % of it). Example: 0 = stays put.");
		LegStand = val.Bind<float>("Legs", "Push before fall (s)", 0.25f, "A leg or foot hit that drops the sosig: it is pushed back this long first, then falls. Example: 0 = falls at once.");
		Shove = val.Bind<float>("Hit push", "Shove (m/s)", 1.25f, "Every bullet that touches a sosig (flesh, armour, a ricochet) shoves the hit part at the hit point the bullet's way, so it turns. Example: 0 = off, 2 = strong.");
		RoundRef = val.Bind<float>("Hit push", "Round strength reference (J)", 1000f, "Every push, jolt, snap, shove and step back is scaled by the bullet: square root of (energy it left in the sosig / this). A hit\nleaving this much energy gets the values as set; 9 mm (~450 J) about 0.7x, 5.56 (~1500 J) about 1.2x, .50 BMG up to 3x\n(never under 0.3x). The Debug log shows each hit's energy and scale. 0 = no scaling (every round the same).\nExample: Round strength reference (J) = 1500");
		Sway = val.Bind<float>("Stumble", "Side steps", 0.6f, "How far the sosig zig-zags sideways while it staggers back, as a share of its step back speed. Example: 0 = straight back, 1 = wild.");
		Dip = val.Bind<float>("Stumble", "Dip per step (m/s)", 0.35f, "How hard the body drops on each stagger step (the up-down of stumbling). Example: 0 = level, 0.6 = heavy.");
		FallBack = val.Bind<float>("Stumble", "Fall onto back (m/s)", 1.5f, "When a staggering sosig loses its balance, its chest and head are pushed back the way it was going, so it lands on its back. Example: 0 = falls as the game drops it.");
		LegLowTime = val.Bind<float>("Legs", "Stay low (s)", 2.5f, "A leg or foot hit that would knock the sosig down keeps it low (crouched, like suppressed) this long instead. Leg hits that kill still fall. Example: Stay low (s) = 4");
		StepBackChance = val.Bind<float>("Chest", "Step back chance", 0.55f, new ConfigDescription("Chance (0-1) a hit makes the sosig step back; each step back is also a random size (60-140 % of Step back). Example: Step back chance = 1 = every hit.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), NoTags));
		JoltDist = val.Bind<float>("Hit push", "Jolt (m)", 0.15f, "Every bullet that gets into flesh knocks the body back this far in a few hundredths of a second (chest full, head half, legs 40 %),\nthen springs part of the way back with a small forward bounce (Stays back keeps the rest); the step back / stumble starts\nafter it. Scaled by the round. Example: Jolt (m) = 0.2");
		OverwhelmJ = val.Bind<float>("Armour", "Overwhelming round (J)", 3500f, "A bullet that goes through armour into flesh carrying at least this much energy (measured as it hit the armour) drops the sosig at once,\nno stand. 7.62x51 ~3300 J, .300 Win Mag ~4500 J, .50 BMG ~18000 J. The Debug log shows each armour hit's energy. 0 = off.\nExample: Overwhelming round (J) = 3000");
		LowHeadshotFalls = val.Bind<bool>("Head", "Headshot on a low sosig falls at once", true, "A sosig that is low (suppressed crouch, or a leg hit) and shot in the head drops at once, no stand. Example: false = it gets the head stand too.");
		BackStays = val.Bind<float>("Hit push", "Stays back (share)", 0.5f, new ConfigDescription("Share of each bullet's knock back (Jolt (m)) the sosig keeps: it is really moved back that far; the rest springs back with a\nsmall forward bounce. Example: Stays back (share) = 0.3", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), NoTags));
		TurnDeg = val.Bind<float>("Hit push", "Turn (deg)", 40f, "How far a bullet at the very edge of the body (seen from the shooter) turns the sosig that way; a hit in the middle turns\nit none and only pushes it back. Scaled by the round. Example: Turn (deg) = 60");
		TurnStays = val.Bind<float>("Hit push", "Stays turned (share)", 0.75f, new ConfigDescription("Share of the turn the sosig keeps after the bounce (for about a second, then it turns back to fight). Example: Stays turned (share) = 0.9", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), NoTags));
		DebugLog = val.Bind<bool>("Debug", "Log", false, "Log every decision (hit part, push, stand time). Example: true");
		Harmony val2 = new Harmony("invent60.h3vr.dramatichitreactions");
		val2.Patch((MethodBase)AccessTools.Method(typeof(SosigLink), "Damage", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches), "LinkDamagePrefix", (Type[])null), new HarmonyMethod(typeof(Patches), "LinkDamagePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		val2.Patch((MethodBase)AccessTools.Method(typeof(SosigWearable), "Damage", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches), "WearableDamagePrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		val2.Patch((MethodBase)AccessTools.Method(typeof(Sosig), "Shudder", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches), "ShudderPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		val2.Patch((MethodBase)AccessTools.Method(typeof(Sosig), "SosigDies", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches), "DiesPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		GameObject val3 = new GameObject("DramaticHitReactions.Runner");
		Object.DontDestroyOnLoad((Object)val3);
		val3.AddComponent<Runner>();
		if (DebugLog.Value)
		{
			Log.LogInfo((object)("Dramatic Hit Reactions loaded" + (val.SaveOnConfigSet ? (" (developer tuning from " + text + ").") : ".")));
		}
	}

	internal static float Scale(float kinetic)
	{
		if (RoundRef.Value <= 0f)
		{
			return 1f;
		}
		return Mathf.Clamp(Mathf.Sqrt(Mathf.Max(0f, kinetic) / RoundRef.Value), 0.3f, 3f);
	}

	internal static void Dbg(string s)
	{
		if (DebugLog.Value)
		{
			Log.LogInfo((object)s);
		}
	}
}
internal sealed class Pending
{
	public Sosig S;

	public bool IsDeath;

	public float ShudderAmount;

	public DamageClass DeathClass;

	public SosigDeathType DeathType;

	public float FallAt;

	public Vector3 Drift;

	public bool Head;

	public bool Leg;
}
internal sealed class Runner : MonoBehaviour
{
	private sealed class Stagger
	{
		public Sosig S;

		public Vector3 Back;

		public float Speed;

		public float T0;

		public float Until;

		public float Phase;

		public float Rate;

		public float LastWave;
	}

	private sealed class Hit
	{
		public Sosig S;

		public Vector3 Back;

		public float Dist;

		public float Yaw;

		public float T0;

		public float Moved;
	}

	private static readonly List<Pending> s_list = new List<Pending>();

	private static readonly List<Stagger> s_stag = new List<Stagger>();

	private static readonly List<Hit> s_hits = new List<Hit>();

	private const float HitRise = 0.03f;

	private const float SpringBack = 0.12f;

	private const float Bounce = 0.1f;

	private const float MaxOff = 0.35f;

	private const float TurnRise = 0.05f;

	private const float TurnBounce = 0.25f;

	private const float TurnHold = 1.2f;

	private const float TurnEase = 1.5f;

	private const float MaxYaw = 80f;

	private static readonly Dictionary<Sosig, float> s_low = new Dictionary<Sosig, float>();

	private static readonly FieldInfo s_supField = AccessTools.Field(typeof(Sosig), "m_suppressionLevel");

	private static readonly FieldInfo s_hobField = AccessTools.Field(typeof(Sosig), "m_isHobbled");

	private static readonly MethodInfo s_setPose = AccessTools.Method(typeof(Sosig), "SetBodyPose", (Type[])null, (Type[])null);

	private static readonly HashSet<Sosig> s_weHobbled = new HashSet<Sosig>();

	private const float HitTime = 0.1f;

	private const float BackFade = 0.22f;

	private const float SwayFade = 0.6f;

	internal static bool Releasing;

	internal static void AddHit(Sosig s, Vector3 back, float dist, float yaw)
	{
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)s == (Object)null) && (!(dist < 0.0005f) || !(Mathf.Abs(yaw) < 0.1f)))
		{
			s_hits.Add(new Hit
			{
				S = s,
				Back = back,
				Dist = dist,
				Yaw = yaw,
				T0 = Time.time
			});
		}
	}

	private static float BackCurve(float t, float keep)
	{
		if (t < 0.03f)
		{
			return Mathf.SmoothStep(0f, 1f, t / 0.03f) * 1f;
		}
		float num = t - 0.03f;
		if (!(num < 0.12f))
		{
			return Mathf.Lerp(keep - 0.1f * keep, keep, Mathf.SmoothStep(0f, 1f, (num - 0.12f) / 0.12f));
		}
		return Mathf.Lerp(1f, keep - 0.1f * keep, Mathf.SmoothStep(0f, 1f, num / 0.12f));
	}

	private static float TurnCurve(float t, float stays)
	{
		if (t < 0.05f)
		{
			return Mathf.SmoothStep(0f, 1f, t / 0.05f);
		}
		if (t < 0.3f)
		{
			return Mathf.Lerp(1f, stays, Mathf.SmoothStep(0f, 1f, (t - 0.05f) / 0.25f));
		}
		float num = t - 0.05f - 0.25f;
		if (num < 1.2f)
		{
			return stays;
		}
		return stays * (1f - Mathf.SmoothStep(0f, 1f, (num - 1.2f) / 1.5f));
	}

	private static bool HitDone(float t)
	{
		return t > Mathf.Max(0.26999998f, 3f);
	}

	internal static void KeepLow(Sosig s, float seconds)
	{
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		float num = Time.time + seconds;
		if (!s_low.TryGetValue(s, out var value) || value < num)
		{
			s_low[s] = num;
		}
		HoldLow(s);
		if ((object)s_hobField != null && !(bool)s_hobField.GetValue(s))
		{
			s_hobField.SetValue(s, true);
			s_weHobbled.Add(s);
		}
		if ((object)s_setPose != null && (int)s.BodyPose == 0)
		{
			s_setPose.Invoke(s, new object[1] { (object)(SosigBodyPose)1 });
		}
	}

	private static void EndLow(Sosig s)
	{
		if ((Object)(object)s != (Object)null && s_weHobbled.Remove(s) && (object)s_hobField != null)
		{
			s_hobField.SetValue(s, false);
		}
	}

	internal static bool IsLow(Sosig s)
	{
		if (!s_low.TryGetValue(s, out var value) || !(Time.time < value))
		{
			return s.SuppressionLevel > 0.2f;
		}
		return true;
	}

	private static void HoldLow(Sosig s)
	{
		if ((object)s_supField != null && (float)s_supField.GetValue(s) < Plugin.LegCrouch.Value)
		{
			s_supField.SetValue(s, Plugin.LegCrouch.Value);
		}
	}

	private static Stagger FindStagger(Sosig s)
	{
		for (int i = 0; i < s_stag.Count; i++)
		{
			if (s_stag[i].S == s)
			{
				return s_stag[i];
			}
		}
		return null;
	}

	internal static void StepBack(Sosig s, Vector3 v, float seconds)
	{
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)s == (Object)null) && !(((Vector3)(ref v)).sqrMagnitude < 0.0001f) && !(seconds <= 0f))
		{
			Stagger stagger = FindStagger(s);
			float num = ((Vector3)(ref v)).magnitude;
			if (stagger == null)
			{
				stagger = new Stagger
				{
					S = s,
					Phase = Random.value * 6.2832f,
					Rate = Random.Range(2.2f, 3.2f)
				};
				s_stag.Add(stagger);
			}
			else
			{
				float num2 = Time.time - stagger.T0;
				num += 0.5f * stagger.Speed * ((num2 < 0.1f) ? 1f : Mathf.Exp((0f - (num2 - 0.1f)) / 0.22f));
			}
			stagger.Back = v / ((Vector3)(ref v)).magnitude;
			stagger.Speed = num;
			stagger.T0 = Time.time;
			stagger.Until = Mathf.Max(stagger.Until, Time.time + seconds + 1.2f);
		}
	}

	internal static Vector3 BackOf(Sosig s)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		return FindStagger(s)?.Back ?? Vector3.zero;
	}

	internal static SosigLink CoreLink(Sosig s)
	{
		return Part(s, (SosigBodyPart)1);
	}

	private static SosigLink Part(Sosig s, SosigBodyPart part)
	{
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		if (s.Links == null)
		{
			return null;
		}
		for (int i = 0; i < s.Links.Count; i++)
		{
			if ((Object)(object)s.Links[i] != (Object)null && s.Links[i].BodyPart == part)
			{
				return s.Links[i];
			}
		}
		return null;
	}

	private static void Wobble(Stagger g, float dt)
	{
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: 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_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_010f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_0118: 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_0123: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0192: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
		Sosig s = g.S;
		float num = Time.time - g.T0;
		float num2 = g.Speed * ((num < 0.1f) ? 1f : Mathf.Exp((0f - (num - 0.1f)) / 0.22f));
		float num3 = Mathf.SmoothStep(0f, 1f, (num - 0.04f) / 0.16f) * Mathf.Exp((0f - num) / 0.6f);
		if (Find(s) != null)
		{
			num3 = Mathf.Max(num3, 0.4f * Mathf.SmoothStep(0f, 1f, num / 0.2f));
		}
		float num4 = Mathf.Sin((float)Math.PI * 2f * g.Rate * num + g.Phase);
		Vector3 val = Vector3.Cross(Vector3.up, g.Back);
		float num5 = g.Speed * Plugin.Sway.Value * num4 * num3;
		if ((Object)(object)s.Agent != (Object)null && ((Behaviour)s.Agent).enabled && s.Agent.isOnNavMesh)
		{
			s.Agent.Move((g.Back * num2 + val * num5) * dt);
		}
		SosigLink val2 = Part(s, (SosigBodyPart)1);
		if ((Object)(object)val2 != (Object)null && (Object)(object)val2.R != (Object)null && !val2.IsExploded)
		{
			if (Mathf.Sign(num4) != Mathf.Sign(g.LastWave) && num3 > 0.05f && Plugin.Dip.Value > 0f)
			{
				val2.R.AddForce(Vector3.down * Plugin.Dip.Value * num3, (ForceMode)2);
			}
			val2.R.AddTorque(g.Back * ((0f - num4) * num3 * 6f * dt), (ForceMode)2);
		}
		g.LastWave = num4;
	}

	internal static Pending Find(Sosig s)
	{
		for (int i = 0; i < s_list.Count; i++)
		{
			if (s_list[i].S == s)
			{
				return s_list[i];
			}
		}
		return null;
	}

	internal static void Add(Pending p)
	{
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		s_list.Add(p);
		if (((Vector3)(ref p.Drift)).sqrMagnitude > 0.0001f)
		{
			StepBack(p.S, p.Drift, Mathf.Max(0.3f, p.FallAt - Time.time));
		}
		for (int i = 0; i < p.S.Hands.Count; i++)
		{
			if (p.S.Hands[i] != null)
			{
				p.S.Hands[i].DropHeldObject();
			}
		}
		p.S.Stun(p.FallAt - Time.time + 0.2f);
		Plugin.Dbg("Dramatic Hit Reactions: " + ((Object)p.S).name + (p.Head ? " headshot" : (p.Leg ? " leg hit" : " chest hit")) + ", " + (p.IsDeath ? "death" : "fall") + " held back " + (p.FallAt - Time.time).ToString("F2") + " s, weapon dropped");
	}

	internal static void Release(Pending p, string why)
	{
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0106: Unknown result type (might be due to invalid IL or missing references)
		//IL_0111: Unknown result type (might be due to invalid IL or missing references)
		//IL_0141: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0156: Unknown result type (might be due to invalid IL or missing references)
		s_list.Remove(p);
		if ((Object)(object)p.S == (Object)null)
		{
			return;
		}
		Plugin.Dbg("Dramatic Hit Reactions: " + ((Object)p.S).name + " falls (" + why + ")");
		Vector3 val = BackOf(p.S);
		Releasing = true;
		try
		{
			if (p.IsDeath)
			{
				p.S.SosigDies(p.DeathClass, p.DeathType);
			}
			else
			{
				p.S.Shudder(p.ShudderAmount);
			}
		}
		finally
		{
			Releasing = false;
		}
		if (Plugin.FallBack.Value > 0f && ((Vector3)(ref val)).sqrMagnitude > 0.0001f)
		{
			SosigLink val2 = Part(p.S, (SosigBodyPart)1);
			SosigLink val3 = Part(p.S, (SosigBodyPart)0);
			if ((Object)(object)val2 != (Object)null && (Object)(object)val2.R != (Object)null && !val2.IsExploded)
			{
				val2.R.AddForce(val * Plugin.FallBack.Value, (ForceMode)2);
			}
			if ((Object)(object)val3 != (Object)null && (Object)(object)val3.R != (Object)null && !val3.IsExploded)
			{
				val3.R.AddForce(val * Plugin.FallBack.Value * 1.3f, (ForceMode)2);
			}
		}
	}

	private void LateUpdate()
	{
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0136: Unknown result type (might be due to invalid IL or missing references)
		//IL_013c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0143: Unknown result type (might be due to invalid IL or missing references)
		//IL_014d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0152: 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_0104: Unknown result type (might be due to invalid IL or missing references)
		//IL_0276: Unknown result type (might be due to invalid IL or missing references)
		//IL_027b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0287: Unknown result type (might be due to invalid IL or missing references)
		//IL_028c: Unknown result type (might be due to invalid IL or missing references)
		float value = Plugin.BackStays.Value;
		float value2 = Plugin.TurnStays.Value;
		for (int num = s_hits.Count - 1; num >= 0; num--)
		{
			Hit hit = s_hits[num];
			float num2 = Time.time - hit.T0;
			if ((Object)(object)hit.S == (Object)null || HitDone(num2))
			{
				s_hits.RemoveAt(num);
			}
			else
			{
				Sosig s = hit.S;
				if (((Behaviour)s).isActiveAndEnabled && (int)s.BodyState == 0 && !((Object)(object)s.CoreTarget == (Object)null))
				{
					float num3 = hit.Dist * value * Mathf.Clamp01((num2 - 0.015f) / 0.12f);
					if (num3 > hit.Moved && (Object)(object)s.Agent != (Object)null && ((Behaviour)s.Agent).enabled && s.Agent.isOnNavMesh)
					{
						s.Agent.Move(hit.Back * (num3 - hit.Moved));
						hit.Moved = num3;
					}
					float num4 = hit.Dist * BackCurve(num2, value) - hit.Moved;
					Transform coreTarget = s.CoreTarget;
					coreTarget.position += Vector3.ClampMagnitude(hit.Back * num4, 0.35f);
				}
			}
		}
		for (int i = 0; i < s_hits.Count; i++)
		{
			Sosig s2 = s_hits[i].S;
			if ((Object)(object)s2 == (Object)null || (Object)(object)s2.CoreTarget == (Object)null || (int)s2.BodyState != 0)
			{
				continue;
			}
			bool flag = true;
			for (int j = 0; j < i; j++)
			{
				if (s_hits[j].S == s2)
				{
					flag = false;
					break;
				}
			}
			if (!flag)
			{
				continue;
			}
			float num5 = 0f;
			for (int k = i; k < s_hits.Count; k++)
			{
				if (s_hits[k].S == s2)
				{
					num5 += s_hits[k].Yaw * TurnCurve(Time.time - s_hits[k].T0, value2);
				}
			}
			num5 = Mathf.Clamp(num5, -80f, 80f);
			if (Mathf.Abs(num5) > 0.01f)
			{
				s2.CoreTarget.rotation = Quaternion.AngleAxis(num5, Vector3.up) * s2.CoreTarget.rotation;
			}
		}
	}

	private void Update()
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_0180: Unknown result type (might be due to invalid IL or missing references)
		//IL_0197: Unknown result type (might be due to invalid IL or missing references)
		//IL_019d: Invalid comparison between Unknown and I4
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		float deltaTime = Time.deltaTime;
		for (int num = s_stag.Count - 1; num >= 0; num--)
		{
			Stagger stagger = s_stag[num];
			if ((Object)(object)stagger.S == (Object)null || (int)stagger.S.BodyState != 0 || (Time.time >= stagger.Until && Find(stagger.S) == null))
			{
				s_stag.RemoveAt(num);
			}
			else
			{
				Wobble(stagger, deltaTime);
			}
		}
		if (s_low.Count > 0)
		{
			List<Sosig> list = null;
			foreach (KeyValuePair<Sosig, float> item in s_low)
			{
				if ((Object)(object)item.Key == (Object)null || Time.time >= item.Value || (int)item.Key.BodyState != 0)
				{
					if (list == null)
					{
						list = new List<Sosig>();
					}
					list.Add(item.Key);
				}
				else
				{
					HoldLow(item.Key);
				}
			}
			if (list != null)
			{
				for (int i = 0; i < list.Count; i++)
				{
					s_low.Remove(list[i]);
					EndLow(list[i]);
				}
			}
		}
		for (int num2 = s_list.Count - 1; num2 >= 0; num2--)
		{
			Pending pending = s_list[num2];
			if ((Object)(object)pending.S == (Object)null)
			{
				s_list.RemoveAt(num2);
			}
			else if ((int)pending.S.BodyState != 0)
			{
				if (pending.IsDeath && (int)pending.S.BodyState != 3)
				{
					Release(pending, "dropped by something else");
				}
				else
				{
					s_list.RemoveAt(num2);
				}
			}
			else if (Time.time >= pending.FallAt)
			{
				Release(pending, "stand over");
			}
		}
	}
}
internal static class Patches
{
	private static SosigLink s_link;

	private static Damage s_dam;

	private static float s_kin;

	private static bool s_pierced;

	private static bool s_instant;

	private static string s_instantWhy;

	private static Sosig s_armSosig;

	private static Vector3 s_armSrc;

	private static float s_armKin;

	private static int s_armFrame = -10;

	private const float BodyHalfWidth = 0.25f;

	internal static void LinkDamagePrefix(SosigLink __instance, Damage d)
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Invalid comparison between Unknown and I4
		//IL_0143: Unknown result type (might be due to invalid IL or missing references)
		//IL_0149: Invalid comparison between Unknown and I4
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: 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)
		if (!Plugin.Enabled.Value || d == null || (int)d.Class != 1)
		{
			return;
		}
		s_link = __instance;
		s_dam = d;
		s_kin = d.Dam_TotalKinetic;
		s_pierced = d.Dam_Piercing > 0f;
		s_instant = false;
		Sosig s = __instance.S;
		if (s_pierced && (Object)(object)s != (Object)null && !Runner.Releasing)
		{
			if (s_armSosig == s && Time.frameCount - s_armFrame <= 1)
			{
				Vector3 val = d.Source_Point - s_armSrc;
				if (((Vector3)(ref val)).sqrMagnitude < 0.0001f && Plugin.OverwhelmJ.Value > 0f && Mathf.Max(s_armKin, s_kin) >= Plugin.OverwhelmJ.Value)
				{
					s_instant = true;
					s_instantWhy = "through armour at " + s_armKin.ToString("0") + " J";
					goto IL_012c;
				}
			}
			if ((int)__instance.BodyPart == 0 && Plugin.LowHeadshotFalls.Value && Runner.IsLow(s))
			{
				s_instant = true;
				s_instantWhy = "headshot while low";
			}
		}
		goto IL_012c;
		IL_012c:
		Pending pending = Runner.Find(__instance.S);
		if (pending != null && !Runner.Releasing && (int)__instance.BodyPart != 1)
		{
			Runner.Release(pending, "hit again");
		}
	}

	internal static void WearableDamagePrefix(SosigWearable __instance, Damage d)
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Invalid comparison between Unknown and I4
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		if (Plugin.Enabled.Value && d != null && (int)d.Class == 1 && !((Object)(object)__instance == (Object)null))
		{
			SosigLink l = __instance.L;
			if (!((Object)(object)l == (Object)null) && !((Object)(object)l.R == (Object)null) && !l.IsExploded)
			{
				s_armSosig = l.S;
				s_armSrc = d.Source_Point;
				s_armKin = d.Dam_TotalKinetic;
				s_armFrame = Time.frameCount;
				Plugin.Dbg("Dramatic Hit Reactions: " + (((Object)(object)l.S != (Object)null) ? ((Object)l.S).name : "?") + " " + ((object)Unsafe.As<SosigBodyPart, SosigBodyPart>(ref l.BodyPart)/*cast due to .constrained prefix*/).ToString() + " armour hit, " + d.Dam_TotalKinetic.ToString("0") + " J");
				Shove(l, d, Plugin.Scale(d.Dam_TotalKinetic));
			}
		}
	}

	private static void Shove(SosigLink l, Damage d, float k)
	{
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		if (!(Plugin.Shove.Value <= 0f))
		{
			Vector3 val = ((((Vector3)(ref d.strikeDir)).sqrMagnitude > 0.0001f) ? ((Vector3)(ref d.strikeDir)).normalized : ((Component)l).transform.forward);
			l.R.AddForceAtPosition(val * Plugin.Shove.Value * k * l.R.mass, d.point, (ForceMode)1);
		}
	}

	internal unsafe static void LinkDamagePostfix(SosigLink __instance, Damage d)
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: 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_043a: Unknown result type (might be due to invalid IL or missing references)
		//IL_043c: Invalid comparison between Unknown and I4
		//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_025a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0265: Unknown result type (might be due to invalid IL or missing references)
		//IL_026b: Unknown result type (might be due to invalid IL or missing references)
		//IL_027b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0281: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b3: Invalid comparison between Unknown and I4
		//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cb: Invalid comparison between Unknown and I4
		//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0213: 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_0229: Unknown result type (might be due to invalid IL or missing references)
		//IL_022f: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b7: Invalid comparison between Unknown and I4
		//IL_044c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0457: Unknown result type (might be due to invalid IL or missing references)
		//IL_045d: Unknown result type (might be due to invalid IL or missing references)
		//IL_046d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0473: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0483: Unknown result type (might be due to invalid IL or missing references)
		//IL_0484: Unknown result type (might be due to invalid IL or missing references)
		//IL_0493: Unknown result type (might be due to invalid IL or missing references)
		//IL_0499: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c6: 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_04d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_04dc: 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)
		//IL_04ed: 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_0305: Unknown result type (might be due to invalid IL or missing references)
		//IL_0532: Unknown result type (might be due to invalid IL or missing references)
		//IL_0318: Unknown result type (might be due to invalid IL or missing references)
		//IL_031a: Unknown result type (might be due to invalid IL or missing references)
		//IL_031f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0321: Unknown result type (might be due to invalid IL or missing references)
		//IL_0326: Unknown result type (might be due to invalid IL or missing references)
		//IL_0329: Unknown result type (might be due to invalid IL or missing references)
		//IL_032e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0330: 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_0378: Unknown result type (might be due to invalid IL or missing references)
		//IL_0576: Unknown result type (might be due to invalid IL or missing references)
		//IL_057e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0580: Invalid comparison between Unknown and I4
		//IL_0543: Unknown result type (might be due to invalid IL or missing references)
		//IL_054e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0554: Unknown result type (might be due to invalid IL or missing references)
		//IL_0564: Unknown result type (might be due to invalid IL or missing references)
		//IL_056a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0582: Unknown result type (might be due to invalid IL or missing references)
		//IL_0584: Invalid comparison between Unknown and I4
		//IL_05ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_05f1: Invalid comparison between Unknown and I4
		//IL_06a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_06a6: Invalid comparison between Unknown and I4
		//IL_06b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_06b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_06c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_06cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0674: Unknown result type (might be due to invalid IL or missing references)
		//IL_0675: Unknown result type (might be due to invalid IL or missing references)
		//IL_0684: Unknown result type (might be due to invalid IL or missing references)
		//IL_068a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0694: Unknown result type (might be due to invalid IL or missing references)
		//IL_0699: Unknown result type (might be due to invalid IL or missing references)
		if (s_link != __instance)
		{
			return;
		}
		s_link = null;
		s_dam = null;
		Sosig s = __instance.S;
		if ((Object)(object)s == (Object)null || (Object)(object)__instance.R == (Object)null)
		{
			return;
		}
		SosigBodyPart bodyPart = __instance.BodyPart;
		Vector3 val = ((((Vector3)(ref d.strikeDir)).sqrMagnitude > 0.0001f) ? ((Vector3)(ref d.strikeDir)).normalized : ((Component)__instance).transform.forward);
		float num = Plugin.Scale(s_kin);
		if (!__instance.IsExploded)
		{
			Shove(__instance, d, num);
		}
		if (!s_pierced)
		{
			Plugin.Dbg("Dramatic Hit Reactions: " + ((Object)s).name + " " + ((object)(*(SosigBodyPart*)(&bodyPart))/*cast due to .constrained prefix*/).ToString() + " glancing hit (no piercing, " + s_kin.ToString("0") + " J, x" + num.ToString("0.00") + "): shove only");
			return;
		}
		Plugin.Dbg("Dramatic Hit Reactions: " + ((Object)s).name + " " + ((object)(*(SosigBodyPart*)(&bodyPart))/*cast due to .constrained prefix*/).ToString() + " hit into flesh, " + s_kin.ToString("0") + " J, x" + num.ToString("0.00"));
		if (s_instant)
		{
			s_instant = false;
			Pending pending = Runner.Find(s);
			if (pending != null)
			{
				Runner.Release(pending, s_instantWhy);
			}
			else if ((int)s.BodyState == 0)
			{
				Plugin.Dbg("Dramatic Hit Reactions: " + ((Object)s).name + " falls at once (" + s_instantWhy + ")");
				Runner.Releasing = true;
				try
				{
					s.Shudder(1f);
				}
				finally
				{
					Runner.Releasing = false;
				}
			}
			if (!__instance.IsExploded)
			{
				__instance.R.AddForceAtPosition(val * Mathf.Max(Plugin.PushSpeed.Value, Plugin.ChestJolt.Value) * num * __instance.R.mass, d.point, (ForceMode)1);
			}
			return;
		}
		if (Random.value < Plugin.PushChance.Value && !__instance.IsExploded)
		{
			__instance.R.AddForceAtPosition(val * Plugin.PushSpeed.Value * num * __instance.R.mass, d.point, (ForceMode)1);
			Plugin.Dbg("Dramatic Hit Reactions: push on " + ((Object)s).name + " " + ((object)(*(SosigBodyPart*)(&bodyPart))/*cast due to .constrained prefix*/).ToString());
		}
		if (!__instance.IsExploded && (int)s.BodyState == 0)
		{
			float num2 = (((int)bodyPart == 1) ? 1f : (((int)bodyPart == 0) ? 0.5f : 0.4f));
			Vector3 val2 = Flat(val);
			SosigLink val3 = Runner.CoreLink(s);
			Vector3 val4 = (((Object)(object)val3 != (Object)null) ? ((Component)val3).transform.position : ((Component)s).transform.position);
			Vector3 val5 = Vector3.Cross(Vector3.up, val2);
			float num3 = Mathf.Clamp(Vector3.Dot(d.point - val4, val5) / 0.25f, -1f, 1f);
			float yaw = (0f - num3) * Plugin.TurnDeg.Value * num * Mathf.Lerp(0.5f, 1f, num2);
			Runner.AddHit(s, val2, Plugin.JoltDist.Value * num * num2, yaw);
			Plugin.Dbg("Dramatic Hit Reactions: " + ((Object)s).name + " knocked back " + (Plugin.JoltDist.Value * num * num2 * 100f).ToString("0") + " cm, hit " + num3.ToString("+0.00;-0.00") + " off the middle (shooter's view) -> turns " + yaw.ToString("0") + " deg");
		}
		bool flag = Random.value < Plugin.StepBackChance.Value;
		float num4 = Random.Range(0.6f, 1.4f);
		if ((int)bodyPart == 1 && !__instance.IsExploded)
		{
			__instance.R.AddForceAtPosition(val * Plugin.ChestJolt.Value * num * __instance.R.mass, d.point, (ForceMode)1);
			if (flag)
			{
				Runner.StepBack(s, Flat(val) * Plugin.StepBack.Value * num * num4, 0.35f);
			}
		}
		else if (((int)bodyPart == 2 || (int)bodyPart == 3) && !__instance.IsExploded && flag)
		{
			Runner.StepBack(s, Flat(val) * Plugin.StepBack.Value * num * 0.6f * num4, 0.25f);
		}
		Plugin.Dbg("Dramatic Hit Reactions: " + ((Object)s).name + (flag ? (" steps back x" + num4.ToString("0.00")) : " no step back"));
		if ((int)bodyPart == 0 && !__instance.IsExploded)
		{
			__instance.R.AddForceAtPosition(val * Plugin.HeadSnap.Value * num * __instance.R.mass, d.point, (ForceMode)1);
		}
		if ((int)s.BodyState != 0)
		{
			return;
		}
		if ((int)bodyPart == 2 || ((int)bodyPart == 3 && !Plugin.FootKnocksDown.Value))
		{
			Runner.KeepLow(s, Plugin.LegLowTime.Value);
			Plugin.Dbg("Dramatic Hit Reactions: leg hit on " + ((Object)s).name + ", stays low " + Plugin.LegLowTime.Value.ToString("0.0") + " s");
		}
		else if ((int)bodyPart == 3 && Runner.Find(s) == null)
		{
			Plugin.Dbg("Dramatic Hit Reactions: foot hit on " + ((Object)s).name + ", pushed back, then falls");
			if (Plugin.LegStand.Value <= 0f)
			{
				s.Shudder(1f);
				return;
			}
			Runner.Add(new Pending
			{
				S = s,
				IsDeath = false,
				ShudderAmount = 1f,
				Leg = true,
				FallAt = Time.time + Plugin.LegStand.Value,
				Drift = Flat(val) * Plugin.StepBack.Value * num * 0.6f
			});
		}
		else if ((int)bodyPart == 1)
		{
			Pending pending2 = Runner.Find(s);
			if (pending2 != null)
			{
				Runner.StepBack(s, Flat(val) * Plugin.DriftPerHit.Value * num, Mathf.Max(0.3f, pending2.FallAt - Time.time));
			}
		}
	}

	private static Vector3 Flat(Vector3 v)
	{
		//IL_0022: 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)
		v.y = 0f;
		if (!(((Vector3)(ref v)).sqrMagnitude > 0.0001f))
		{
			return Vector3.zero;
		}
		return ((Vector3)(ref v)).normalized;
	}

	private static bool Dramatic(Sosig s, out bool head)
	{
		bool leg;
		return Dramatic(s, out head, out leg);
	}

	private static bool Dramatic(Sosig s, out bool head, out bool leg)
	{
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Invalid comparison between Unknown and I4
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Invalid comparison between Unknown and I4
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Invalid comparison between Unknown and I4
		head = false;
		leg = false;
		if (Runner.Releasing || (Object)(object)s_link == (Object)null || s_link.S != s)
		{
			return false;
		}
		if ((int)s.BodyState != 0)
		{
			return false;
		}
		if (s_link.IsExploded || s_instant)
		{
			return false;
		}
		if ((int)s_link.BodyPart == 1)
		{
			return true;
		}
		if ((int)s_link.BodyPart == 0)
		{
			head = true;
			return true;
		}
		if ((Plugin.LegStand.Value > 0f || LegGoesLow()) && ((int)s_link.BodyPart == 2 || (int)s_link.BodyPart == 3))
		{
			leg = true;
			return true;
		}
		return false;
	}

	internal static bool ShudderPrefix(Sosig __instance, float amount)
	{
		//IL_00f1: 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_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: 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_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		if (!Plugin.Enabled.Value || Runner.Releasing)
		{
			return true;
		}
		Pending pending = Runner.Find(__instance);
		if (pending != null)
		{
			pending.ShudderAmount = Mathf.Max(pending.ShudderAmount, amount);
			return false;
		}
		if (!Dramatic(__instance, out var head, out var leg))
		{
			return true;
		}
		if (leg && LegGoesLow())
		{
			Plugin.Dbg("Dramatic Hit Reactions: " + ((Object)__instance).name + " leg knock-down turned into going low");
			return false;
		}
		Runner.Add(new Pending
		{
			S = __instance,
			IsDeath = false,
			ShudderAmount = amount,
			Head = head,
			Leg = leg,
			FallAt = Time.time + (leg ? Plugin.LegStand.Value : Stand(head)),
			Drift = (head ? Vector3.zero : (Flat((s_dam != null) ? s_dam.strikeDir : Vector3.zero) * Plugin.DriftPerHit.Value * Plugin.Scale(s_kin)))
		});
		return false;
	}

	internal static bool DiesPrefix(Sosig __instance, DamageClass damClass, SosigDeathType deathType)
	{
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: 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_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: 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_00b3: 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_00b8: 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)
		if (!Plugin.Enabled.Value || Runner.Releasing)
		{
			return true;
		}
		Pending pending = Runner.Find(__instance);
		if (pending != null)
		{
			if (!pending.IsDeath)
			{
				pending.IsDeath = true;
				pending.DeathClass = damClass;
				pending.DeathType = deathType;
			}
			return false;
		}
		if (!Dramatic(__instance, out var head, out var leg))
		{
			return true;
		}
		Runner.Add(new Pending
		{
			S = __instance,
			IsDeath = true,
			DeathClass = damClass,
			DeathType = deathType,
			Head = head,
			Leg = leg,
			FallAt = Time.time + (leg ? Plugin.LegStand.Value : Stand(head)),
			Drift = (head ? Vector3.zero : (Flat((s_dam != null) ? s_dam.strikeDir : Vector3.zero) * Plugin.DriftPerHit.Value * Plugin.Scale(s_kin)))
		});
		return false;
	}

	private static bool LegGoesLow()
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Invalid comparison between Unknown and I4
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Invalid comparison between Unknown and I4
		if ((Object)(object)s_link != (Object)null)
		{
			if ((int)s_link.BodyPart != 2)
			{
				if ((int)s_link.BodyPart == 3)
				{
					return !Plugin.FootKnocksDown.Value;
				}
				return false;
			}
			return true;
		}
		return false;
	}

	private static float Stand(bool head)
	{
		if (!head)
		{
			return Random.Range(Plugin.ChestStandMin.Value, Plugin.ChestStandMax.Value);
		}
		return Random.Range(Plugin.HeadStandMin.Value, Plugin.HeadStandMax.Value);
	}
}