Decompiled source of RE4Enemies v1.8.1

BepInEx/plugins/RE4Ganados/RE4Ganados.dll

Decompiled 8 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Numerics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using TMPro;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.LowLevel;
using UnityEngine.PlayerLoop;
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("RE4Ganados")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.8.1.0")]
[assembly: AssemblyInformationalVersion("1.8.1")]
[assembly: AssemblyProduct("RE4Ganados")]
[assembly: AssemblyTitle("RE4Ganados")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.8.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 RE4Ganados
{
	public sealed class ModelInfo
	{
		public string[] textures = Array.Empty<string>();
	}
	public static class Assets
	{
		private sealed class ModelData
		{
			public int[] Ids = Array.Empty<int>();

			public int[] Parents = Array.Empty<int>();

			public Vector3[] Rest = Array.Empty<Vector3>();

			public Mesh Mesh;

			public Material[] Materials = Array.Empty<Material>();
		}

		private static readonly Dictionary<string, Texture2D> textures = new Dictionary<string, Texture2D>();

		private static readonly Dictionary<string, Material> materials = new Dictionary<string, Material>();

		private static readonly Dictionary<string, ModelData> models = new Dictionary<string, ModelData>();

		private static Material Material(string reference)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Expected O, but got Unknown
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			if (materials.TryGetValue(reference, out Material value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			if (!textures.TryGetValue(reference, out Texture2D value2) || (Object)(object)value2 == (Object)null)
			{
				value2 = new Texture2D(2, 2, (TextureFormat)4, true);
				ImageConversion.LoadImage(value2, File.ReadAllBytes(Path.Combine(Plugin.AssetPath, "textures", reference + ".png")));
				((Texture)value2).wrapMode = (TextureWrapMode)0;
				((Texture)value2).filterMode = (FilterMode)2;
				Object.DontDestroyOnLoad((Object)(object)value2);
				textures[reference] = value2;
			}
			Shader obj = Shader.Find("HDRP/Lit") ?? Shader.Find("Standard");
			Material val = new Material(obj);
			val.mainTexture = (Texture)(object)value2;
			if (val.HasProperty("_BaseColorMap"))
			{
				val.SetTexture("_BaseColorMap", (Texture)(object)value2);
			}
			if (val.HasProperty("_BaseColor"))
			{
				val.SetColor("_BaseColor", Color.white);
			}
			if (val.HasProperty("_Color"))
			{
				val.SetColor("_Color", Color.white);
			}
			if (val.HasProperty("_Metallic"))
			{
				val.SetFloat("_Metallic", 0f);
			}
			if (val.HasProperty("_Smoothness"))
			{
				val.SetFloat("_Smoothness", 0.15f);
			}
			if (((Object)obj).name.StartsWith("HDRP/"))
			{
				HDMaterial.ValidateMaterial(val);
			}
			Object.DontDestroyOnLoad((Object)(object)val);
			materials[reference] = val;
			return val;
		}

		public static GameObject Model(string name)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			//IL_0098: 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_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			if (!models.TryGetValue(name, out ModelData value) || (Object)(object)value.Mesh == (Object)null || value.Materials.Any((Material m) => (Object)(object)m == (Object)null))
			{
				value = ReadModel(name);
				models[name] = value;
			}
			GameObject val = new GameObject(name);
			try
			{
				Transform[] array = (Transform[])(object)new Transform[value.Ids.Length];
				Dictionary<int, int> dictionary = new Dictionary<int, int>();
				for (int num = 0; num < array.Length; num++)
				{
					Transform transform = new GameObject("bone_" + value.Ids[num]).transform;
					transform.SetParent(val.transform, false);
					transform.localPosition = value.Rest[num];
					array[num] = transform;
					dictionary[value.Ids[num]] = num;
				}
				for (int num2 = 0; num2 < array.Length; num2++)
				{
					if (dictionary.TryGetValue(value.Parents[num2], out var value2) && value2 != num2)
					{
						array[num2].SetParent(array[value2], false);
					}
				}
				SkinnedMeshRenderer obj = val.AddComponent<SkinnedMeshRenderer>();
				obj.sharedMesh = value.Mesh;
				((Renderer)obj).sharedMaterials = value.Materials;
				obj.bones = array;
				obj.rootBone = array[0];
				obj.updateWhenOffscreen = true;
				((Renderer)obj).localBounds = new Bounds(Vector3.up, Vector3.one * 6f);
				Re4Rig re4Rig = val.AddComponent<Re4Rig>();
				re4Rig.Bones = array;
				re4Rig.Ids = (int[])value.Ids.Clone();
				re4Rig.NativeScaleCompensate = name.StartsWith("plaga_", StringComparison.Ordinal);
				return val;
			}
			catch
			{
				Object.Destroy((Object)(object)val);
				throw;
			}
		}

		public static void PreloadParasites()
		{
			string[] array = new string[5] { "plaga_blade", "plaga_biter", "plaga_spider", "plaga_tendril", "plaga_spider_tendril" };
			foreach (string text in array)
			{
				if (!models.ContainsKey(text))
				{
					models.Add(text, ReadModel(text));
				}
			}
		}

		private static ModelData ReadModel(string name)
		{
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Expected O, but got Unknown
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: 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_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: 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_030f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0320: Unknown result type (might be due to invalid IL or missing references)
			//IL_0327: Unknown result type (might be due to invalid IL or missing references)
			//IL_032f: 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)
			//IL_033f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0347: Unknown result type (might be due to invalid IL or missing references)
			//IL_0350: Expected O, but got Unknown
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
			BinaryReader r = new BinaryReader(File.OpenRead(Path.Combine(Plugin.AssetPath, "models", name + ".r4m")));
			try
			{
				if (new string(r.ReadChars(4)) != "R4M1")
				{
					throw new InvalidDataException("Invalid Ganado model");
				}
				int num = r.ReadInt32();
				int num2 = r.ReadInt32();
				int num3 = r.ReadInt32();
				if (num < 1 || num > 1000000 || num2 < 1 || num2 > 512 || num3 < 1 || num3 > 256)
				{
					throw new InvalidDataException("Invalid Ganado model dimensions");
				}
				GameObject root = new GameObject(name);
				Transform[] array = (Transform[])(object)new Transform[num2];
				int[] array2 = new int[num2];
				int[] array3 = new int[num2];
				Dictionary<int, int> dictionary = new Dictionary<int, int>();
				for (int i = 0; i < num2; i++)
				{
					array2[i] = r.ReadInt32();
					array3[i] = r.ReadInt32();
					Transform transform = new GameObject("bone_" + array2[i]).transform;
					transform.SetParent(root.transform, false);
					transform.localPosition = ReadVector();
					array[i] = transform;
					dictionary[array2[i]] = i;
				}
				for (int j = 0; j < num2; j++)
				{
					if (dictionary.TryGetValue(array3[j], out var value) && value != j)
					{
						array[j].SetParent(array[value], false);
					}
				}
				Vector3[] array4 = (Vector3[])(object)new Vector3[num];
				Vector3[] array5 = (Vector3[])(object)new Vector3[num];
				Vector2[] array6 = (Vector2[])(object)new Vector2[num];
				BoneWeight[] array7 = (BoneWeight[])(object)new BoneWeight[num];
				for (int k = 0; k < num; k++)
				{
					array4[k] = ReadVector();
					int num4 = k;
					Vector3 val = ReadVector();
					array5[num4] = ((Vector3)(ref val)).normalized;
					array6[k] = new Vector2(r.ReadSingle(), r.ReadSingle());
					int key = r.ReadInt32();
					int key2 = r.ReadInt32();
					int key3 = r.ReadInt32();
					float num5 = r.ReadSingle();
					float num6 = r.ReadSingle();
					float num7 = r.ReadSingle();
					float num8 = num5 + num6 + num7;
					if (num8 < 0.001f)
					{
						num5 = 1f;
						num8 = 1f;
					}
					int num9 = k;
					BoneWeight val2 = default(BoneWeight);
					((BoneWeight)(ref val2)).boneIndex0 = (dictionary.TryGetValue(key, out var value2) ? value2 : 0);
					((BoneWeight)(ref val2)).boneIndex1 = (dictionary.TryGetValue(key2, out var value3) ? value3 : 0);
					((BoneWeight)(ref val2)).boneIndex2 = (dictionary.TryGetValue(key3, out var value4) ? value4 : 0);
					((BoneWeight)(ref val2)).weight0 = num5 / num8;
					((BoneWeight)(ref val2)).weight1 = num6 / num8;
					((BoneWeight)(ref val2)).weight2 = num7 / num8;
					array7[num9] = val2;
				}
				Mesh val3 = new Mesh
				{
					name = "Original RE4 Ganado " + name,
					indexFormat = (IndexFormat)1,
					vertices = array4,
					normals = array5,
					uv = array6,
					boneWeights = array7,
					subMeshCount = num3
				};
				val3.bindposes = array.Select((Transform b) => b.worldToLocalMatrix * root.transform.localToWorldMatrix).ToArray();
				ModelInfo modelInfo = JsonConvert.DeserializeObject<ModelInfo>(File.ReadAllText(Path.Combine(Plugin.AssetPath, "models", name + ".json")));
				Material[] array8 = (Material[])(object)new Material[num3];
				for (int num10 = 0; num10 < num3; num10++)
				{
					int num11 = r.ReadInt32();
					int num12 = r.ReadInt32();
					if (num11 < 0 || num11 >= modelInfo.textures.Length || num12 < 0 || num12 > 3000000)
					{
						throw new InvalidDataException("Invalid Ganado material");
					}
					int[] array9 = new int[num12];
					for (int num13 = 0; num13 < num12; num13++)
					{
						array9[num13] = r.ReadInt32();
					}
					val3.SetTriangles(array9, num10);
					array8[num10] = Material(modelInfo.textures[num11]);
				}
				val3.RecalculateBounds();
				Object.DontDestroyOnLoad((Object)(object)val3);
				ModelData result = new ModelData
				{
					Ids = array2,
					Parents = array3,
					Rest = array.Select((Transform b) => b.localPosition).ToArray(),
					Mesh = val3,
					Materials = array8
				};
				Object.Destroy((Object)(object)root);
				return result;
			}
			finally
			{
				if (r != null)
				{
					((IDisposable)r).Dispose();
				}
			}
			Vector3 ReadVector()
			{
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				return new Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle());
			}
		}

		public static void HandPose(GameObject root, GanadoState state, bool armed, VillageWeapon kind = VillageWeapon.Hatchet)
		{
			bool flag = armed && kind == VillageWeapon.Hoe;
			bool flag2 = state == GanadoState.Alert && !armed;
			Transform obj = root.transform.Find("ganado_right_hand");
			if (obj != null)
			{
				((Component)obj).gameObject.SetActive(!armed);
			}
			Transform obj2 = root.transform.Find("ganado_right_hand_grip");
			if (obj2 != null)
			{
				((Component)obj2).gameObject.SetActive(armed);
			}
			Transform obj3 = root.transform.Find("ganado_right_hand_point");
			if (obj3 != null)
			{
				((Component)obj3).gameObject.SetActive(false);
			}
			Transform obj4 = root.transform.Find("ganado_left_hand");
			if (obj4 != null)
			{
				((Component)obj4).gameObject.SetActive(!flag2 && !flag);
			}
			Transform obj5 = root.transform.Find("ganado_left_hand_grip");
			if (obj5 != null)
			{
				((Component)obj5).gameObject.SetActive(flag);
			}
			Transform obj6 = root.transform.Find("ganado_left_hand_point");
			if (obj6 != null)
			{
				((Component)obj6).gameObject.SetActive(flag2);
			}
		}

		public static GameObject Hatchet(Re4Rig rig)
		{
			return Weapon(rig, VillageWeapon.Hatchet);
		}

		public static GameObject Weapon(Re4Rig rig, VillageWeapon kind)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = Model("ganado_" + VillageRules.Model(kind));
			((Object)obj).name = "Original RE4 " + VillageRules.Model(kind);
			obj.transform.SetParent(rig.Bone(10), false);
			obj.transform.localPosition = (Vector3)(kind switch
			{
				VillageWeapon.Bucket => new Vector3(-0.08f, -0.035f, 0.01f), 
				VillageWeapon.Hoe => new Vector3(-0.84358f, 0.00581f, -0.86687f), 
				_ => new Vector3(-0.31385f, -0.0212f, -0.10221f), 
			});
			obj.transform.localRotation = Quaternion.AngleAxis(kind switch
			{
				VillageWeapon.Bucket => MathF.PI * 2f / 3f, 
				VillageWeapon.Hoe => 0.7166758f, 
				_ => 1.0402162f, 
			} * 57.29578f, Vector3.up);
			return obj;
		}

		public static GameObject Ganado(float height, int appearance)
		{
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_029e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
			string text = VillageRules.Body(appearance);
			GameObject root = Model(text);
			Re4Rig master = root.GetComponent<Re4Rig>();
			Dictionary<int, Transform> map = master.Ids.Select((int id, int i) => (id: id, i: i)).ToDictionary(((int id, int i) p) => p.id, ((int id, int i) p) => master.Bones[p.i]);
			string[] array = new string[8]
			{
				text + "_head",
				text + "_stump",
				"ganado_right_hand",
				"ganado_right_hand_grip",
				"ganado_right_hand_point",
				"ganado_left_hand",
				"ganado_left_hand_point",
				"ganado_left_hand_grip"
			};
			foreach (string text2 in array)
			{
				GameObject val = Model(text2);
				val.transform.SetParent(root.transform, false);
				Re4Rig component = val.GetComponent<Re4Rig>();
				SkinnedMeshRenderer component2 = val.GetComponent<SkinnedMeshRenderer>();
				Transform[] array2 = component.Ids.Select((int id) => map[id]).ToArray();
				component2.sharedMesh = Object.Instantiate<Mesh>(component2.sharedMesh);
				component2.sharedMesh.bindposes = array2.Select((Transform b) => b.worldToLocalMatrix * root.transform.localToWorldMatrix).ToArray();
				component2.bones = array2;
				component2.rootBone = master.Bones[0];
				component.SharedRig = master;
				if (text2.EndsWith("_stump", StringComparison.Ordinal) || text2.EndsWith("_hand_grip", StringComparison.Ordinal) || text2.EndsWith("_hand_point", StringComparison.Ordinal))
				{
					val.SetActive(false);
				}
			}
			SkinnedMeshRenderer[] componentsInChildren = root.GetComponentsInChildren<SkinnedMeshRenderer>();
			Bounds bounds = componentsInChildren[0].sharedMesh.bounds;
			SkinnedMeshRenderer[] array3 = componentsInChildren;
			foreach (SkinnedMeshRenderer val2 in array3)
			{
				((Bounds)(ref bounds)).Encapsulate(val2.sharedMesh.bounds);
			}
			float num2 = height / ((Bounds)(ref bounds)).size.y;
			root.transform.localScale = Vector3.one * num2;
			root.transform.localPosition = Vector3.up * ((0f - ((Bounds)(ref bounds)).min.y) * num2);
			root.transform.localRotation = Quaternion.Euler(0f, 180f, 0f);
			return root;
		}
	}
	[HarmonyPatch(typeof(StartOfRound), "Update")]
	public static class GanadoRoundFrame
	{
		private static void Postfix()
		{
			LoopBridge.GameUpdate();
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")]
	public static class GanadoPlayerFrame
	{
		private static void Postfix(PlayerControllerB __instance)
		{
			if (((NetworkBehaviour)__instance).IsOwner)
			{
				LoopBridge.GameLateUpdate();
			}
		}
	}
	public static class DamageReactionRules
	{
		public static bool Falling(GanadoState s)
		{
			switch (s)
			{
			case GanadoState.Knockdown:
			case GanadoState.LegCollapse:
			case GanadoState.RunTrip:
			case GanadoState.KneeFall:
			case GanadoState.ForwardKnockdown:
			case GanadoState.GrabEscape:
				return true;
			default:
				return false;
			}
		}

		public static bool GettingUp(GanadoState s)
		{
			if (s == GanadoState.GetUp || s == GanadoState.GetUpFront)
			{
				return true;
			}
			return false;
		}

		public static bool DownHit(GanadoState s)
		{
			if (s - 29 <= GanadoState.Alert)
			{
				return true;
			}
			return false;
		}

		public static bool UsesFrontRecovery(GanadoState s)
		{
			switch (s)
			{
			case GanadoState.LegCollapse:
			case GanadoState.KneeFall:
			case GanadoState.GetUpFront:
			case GanadoState.DownHitFront:
			case GanadoState.ForwardKnockdown:
			case GanadoState.GrabEscape:
				return true;
			default:
				return false;
			}
		}

		public static bool IsReaction(GanadoState s)
		{
			bool flag = Falling(s) || GettingUp(s) || DownHit(s) || GanadoRules.IsOpening(s);
			if (!flag)
			{
				bool flag2;
				switch (s)
				{
				case GanadoState.Flinch:
				case GanadoState.LegFlinch:
				case GanadoState.LegPain:
				case GanadoState.RunStumble:
				case GanadoState.BackFlinch:
				case GanadoState.Disarm:
					flag2 = true;
					break;
				default:
					flag2 = false;
					break;
				}
				flag = flag2;
			}
			return flag;
		}

		public static double Guard(GanadoState s)
		{
			if ((s != GanadoState.HeadStagger && s != GanadoState.FlashStagger) || 1 == 0)
			{
				return 1.0 / 3.0;
			}
			return 0.5;
		}

		public static float DownWait(int variant)
		{
			return 2f + (float)(Math.Abs(variant / 3) % 61) / 30f;
		}

		public static GanadoState? Select(GanadoState current, HitRegion region, bool ankle, int roll, bool blocked, bool prone, bool kneeling, bool kick, ImpactKind kind = ImpactKind.Bullet, bool fromFront = true, bool armed = false)
		{
			if (kick)
			{
				return fromFront ? GanadoState.Knockdown : GanadoState.ForwardKnockdown;
			}
			if (blocked || (Falling(current) && !prone))
			{
				return null;
			}
			if (prone)
			{
				return UsesFrontRecovery(current) ? GanadoState.DownHitFront : GanadoState.DownHitBack;
			}
			if ((uint)(kind - 1) <= 2u)
			{
				return fromFront ? GanadoState.Knockdown : GanadoState.ForwardKnockdown;
			}
			if (armed && region == HitRegion.RightArm)
			{
				return GanadoState.Disarm;
			}
			if (current == GanadoState.LegStagger && kneeling)
			{
				return GanadoState.KneeFall;
			}
			if (region == HitRegion.Head)
			{
				return GanadoState.HeadStagger;
			}
			if (current == GanadoState.Run)
			{
				return (region == HitRegion.Leg) ? GanadoState.RunTrip : GanadoState.RunStumble;
			}
			return (region == HitRegion.Leg) ? GanadoRules.LegReaction(roll, ankle) : (fromFront ? GanadoState.Flinch : GanadoState.BackFlinch);
		}
	}
	public sealed class MotionPhase
	{
		private string role = "";

		private double began = double.NaN;

		public bool Enter(string next, double started, bool locomotion)
		{
			bool result = next != role || (!locomotion && started != began);
			role = next;
			began = started;
			return result;
		}
	}
	internal static class DawnCompat
	{
		private const string Guid = "com.github.teamxiaolan.dawnlib";

		private static readonly HashSet<EnemyType> registered = new HashSet<EnemyType>();

		private static MethodInfo? define;

		private static MethodInfo? from;

		private static MethodInfo? hasInfo;

		private static MethodInfo? addTag;

		private static object? external;

		public static void Initialize()
		{
			if (!Chainloader.PluginInfos.TryGetValue("com.github.teamxiaolan.dawnlib", out var value))
			{
				return;
			}
			try
			{
				Assembly assembly = ((object)value.Instance).GetType().Assembly;
				Type type = assembly.GetType("Dawn.DawnEnemyInfo", throwOnError: true);
				Type type2 = assembly.GetType("Dawn.EnemyInfoBuilder", throwOnError: true);
				Type type3 = assembly.GetType("Dawn.NamespacedKey`1", throwOnError: true).MakeGenericType(type);
				from = type3.GetMethod("From", new Type[2]
				{
					typeof(string),
					typeof(string)
				}) ?? throw new MissingMethodException("Dawn NamespacedKey.From");
				define = assembly.GetType("Dawn.DawnLib", throwOnError: true).GetMethod("DefineEnemy", new Type[3]
				{
					type3,
					typeof(EnemyType),
					typeof(Action<>).MakeGenericType(type2)
				}) ?? throw new MissingMethodException("Dawn DefineEnemy");
				Type type4 = assembly.GetType("Dawn.NamespacedKey", throwOnError: true);
				addTag = type2.GetMethod("AddTag", new Type[1] { type4 }) ?? throw new MissingMethodException("Dawn AddTag");
				external = assembly.GetType("Dawn.DawnLibTags", throwOnError: true).GetField("IsExternal", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).GetValue(null);
				hasInfo = assembly.GetType("Dawn.EnemyTypeExtensions", throwOnError: true).GetMethod("HasDawnInfo", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(EnemyType) }, null) ?? throw new MissingMethodException("Dawn HasDawnInfo");
				ParameterExpression parameterExpression = Expression.Parameter(type2, "builder");
				MethodCallExpression body = Expression.Call(typeof(DawnCompat).GetMethod("Configure", BindingFlags.Static | BindingFlags.NonPublic), Expression.Convert(parameterExpression, typeof(object)));
				Delegate obj = Expression.Lambda(typeof(Action<>).MakeGenericType(type2), body, parameterExpression).Compile();
				GanadoPool[] array = new GanadoPool[5]
				{
					GanadoPool.Day,
					GanadoPool.Night,
					GanadoPool.Mob,
					GanadoPool.Parasite,
					GanadoPool.IndoorParasite
				};
				for (int i = 0; i < array.Length; i++)
				{
					GanadoPool pool = array[i];
					EnemyType val = GanadoPrefab.TypeFor(pool);
					if (!registered.Contains(val))
					{
						object obj2 = hasInfo?.Invoke(null, new object[1] { val });
						if (obj2 is bool && (bool)obj2)
						{
							registered.Add(val);
							continue;
						}
						object obj3 = from.Invoke(null, new object[2]
						{
							"re4enemies",
							"ganado_" + pool.ToString().ToLowerInvariant()
						});
						define.Invoke(null, new object[3] { obj3, val, obj });
						registered.Add(val);
					}
				}
				Plugin.Log("DawnLib: registered Day/Night/Mob Ganados and outdoor/indoor Plagas as externally managed content; RE4 spawning retained.");
			}
			catch (Exception ex)
			{
				Plugin.Warn("Optional DawnLib registration failed: " + (ex.InnerException ?? ex).Message);
			}
		}

		private static void Configure(object builder)
		{
			addTag.Invoke(builder, new object[1] { external });
		}
	}
	public static class EncounterDifficulty
	{
		public static readonly string[] Ratings = new string[6] { "D", "C", "B", "A", "S", "S+" };

		public static readonly int[] Defaults = new int[6] { 5, 7, 9, 11, 13, 15 };

		public static int Index(string? rating)
		{
			string text = (rating ?? "").Trim().ToUpperInvariant().Replace(" ", "");
			if (text.StartsWith("RISKLEVEL:"))
			{
				text = text.Substring(10);
			}
			return text switch
			{
				"D" => 0, 
				"C" => 1, 
				"B" => 2, 
				"A" => 3, 
				"S" => 4, 
				"S+" => 5, 
				_ => -1, 
			};
		}

		public static int Count(string? rating, int[] configured, int fallback)
		{
			int num = Index(rating);
			return Math.Clamp((num >= 0 && configured.Length == 6) ? configured[num] : fallback, 0, 64);
		}
	}
	public static class EncounterRules
	{
		public const float ProjectileRadius = 0.12f;

		public static bool CanRetrieve(bool armed, bool flying, bool lost, float playerDistance, double now, double ready)
		{
			if (!armed && !flying && !lost && playerDistance > 2.5f)
			{
				return now >= ready;
			}
			return false;
		}

		public static (string Kind, int Count) Reward(int roll, int amount, bool needsHealth)
		{
			roll = Math.Clamp(roll, 0, 99);
			if (roll < (needsHealth ? 35 : 20))
			{
				return (Kind: "Green herb", Count: 1);
			}
			if (roll < 50)
			{
				return (Kind: "Handgun ammo", Count: 10);
			}
			if (roll < 60)
			{
				return (Kind: "Shotgun shells", Count: 5);
			}
			if (roll < 65)
			{
				return (Kind: "TMP ammo", Count: 25);
			}
			if (roll < 70)
			{
				return (Kind: "Rifle ammo", Count: 5);
			}
			return (Kind: "Pesetas", Count: 300 * (1 + Math.Clamp(amount, 0, 2)));
		}
	}
	public sealed class DeathLootLedger
	{
		private readonly HashSet<ulong> claimed = new HashSet<ulong>();

		public bool TryClaim(ulong id)
		{
			return claimed.Add(id);
		}

		public void Clear()
		{
			claimed.Clear();
		}
	}
	public sealed class EnemyScan
	{
		private readonly ScanNodeProperties node;

		private readonly SphereCollider collider;

		private PlagaForm previous = (PlagaForm)255;

		public EnemyScan(GanadoEnemy enemy)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			GameObject val = new GameObject("RE4 enemy scan node");
			val.layer = 22;
			val.transform.SetParent(((Component)enemy).transform, false);
			collider = val.AddComponent<SphereCollider>();
			collider.radius = 0.45f;
			((Collider)collider).isTrigger = true;
			node = val.AddComponent<ScanNodeProperties>();
			node.nodeType = 1;
			node.creatureScanID = -1;
			node.minRange = 0;
			node.maxRange = 30;
			node.requiresLineOfSight = true;
			node.scrapValue = 0;
			Present(SpawnRules.Crawler(enemy.Pool) ? PlagaForm.Crawler : PlagaForm.None, dead: false);
		}

		public void Present(PlagaForm form, bool dead)
		{
			//IL_00a3: 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)
			((Collider)collider).enabled = !dead;
			if (previous != form)
			{
				previous = form;
				ScanNodeProperties val = node;
				val.headerText = form switch
				{
					PlagaForm.Blade => "Ganado (Blade Plaga)", 
					PlagaForm.Biter => "Ganado (Head Biter Plaga)", 
					PlagaForm.Spider => "Ganado (Spider Plaga)", 
					PlagaForm.Crawler => "Spider Plaga", 
					_ => "Ganado", 
				};
				node.subText = ((form == PlagaForm.Crawler) ? "Independent parasite" : (PlagaRules.Exposed(form) ? "Exposed parasite" : "Hostile villager"));
				((Component)node).transform.localPosition = Vector3.up * ((form == PlagaForm.Crawler) ? 0.35f : (PlagaRules.Exposed(form) ? 1.9f : 1.4f));
			}
		}
	}
	public sealed class EnemyHostSettings
	{
		public bool Enabled;

		public bool Mobs;

		public bool Loot;

		public bool ScaleDifficulty;

		public int DayCount;

		public int NightCount;

		public int MobPercent;

		public int IndoorSpiderWeight;

		public int Health;

		public int GrabDamage;

		public int AxeDamage;

		public bool Valid
		{
			get
			{
				if (IndoorSpiderWeight >= 0 && IndoorSpiderWeight <= 1000 && DayCount >= 0 && DayCount <= 8 && NightCount >= 0 && NightCount <= 8 && MobPercent >= 0 && MobPercent <= 100 && Health >= 1 && Health <= 30 && GrabDamage >= 1 && GrabDamage <= 50 && AxeDamage >= 1)
				{
					return AxeDamage <= 80;
				}
				return false;
			}
		}

		public void Write(ref FastBufferWriter w)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: 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_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: 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_00e1: Unknown result type (might be due to invalid IL or missing references)
			((FastBufferWriter)(ref w)).WriteValueSafe<bool>(ref ScaleDifficulty, default(ForPrimitives));
			((FastBufferWriter)(ref w)).WriteValueSafe<bool>(ref Enabled, default(ForPrimitives));
			((FastBufferWriter)(ref w)).WriteValueSafe<bool>(ref Mobs, default(ForPrimitives));
			((FastBufferWriter)(ref w)).WriteValueSafe<int>(ref DayCount, default(ForPrimitives));
			((FastBufferWriter)(ref w)).WriteValueSafe<int>(ref NightCount, default(ForPrimitives));
			((FastBufferWriter)(ref w)).WriteValueSafe<int>(ref MobPercent, default(ForPrimitives));
			((FastBufferWriter)(ref w)).WriteValueSafe<int>(ref IndoorSpiderWeight, default(ForPrimitives));
			((FastBufferWriter)(ref w)).WriteValueSafe<int>(ref Health, default(ForPrimitives));
			((FastBufferWriter)(ref w)).WriteValueSafe<int>(ref GrabDamage, default(ForPrimitives));
			((FastBufferWriter)(ref w)).WriteValueSafe<int>(ref AxeDamage, default(ForPrimitives));
			((FastBufferWriter)(ref w)).WriteValueSafe<bool>(ref Loot, default(ForPrimitives));
		}

		public static EnemyHostSettings Read(ref FastBufferReader r)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: 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_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: 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_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			EnemyHostSettings enemyHostSettings = new EnemyHostSettings();
			((FastBufferReader)(ref r)).ReadValueSafe<bool>(ref enemyHostSettings.ScaleDifficulty, default(ForPrimitives));
			((FastBufferReader)(ref r)).ReadValueSafe<bool>(ref enemyHostSettings.Enabled, default(ForPrimitives));
			((FastBufferReader)(ref r)).ReadValueSafe<bool>(ref enemyHostSettings.Mobs, default(ForPrimitives));
			((FastBufferReader)(ref r)).ReadValueSafe<int>(ref enemyHostSettings.DayCount, default(ForPrimitives));
			((FastBufferReader)(ref r)).ReadValueSafe<int>(ref enemyHostSettings.NightCount, default(ForPrimitives));
			((FastBufferReader)(ref r)).ReadValueSafe<int>(ref enemyHostSettings.MobPercent, default(ForPrimitives));
			((FastBufferReader)(ref r)).ReadValueSafe<int>(ref enemyHostSettings.IndoorSpiderWeight, default(ForPrimitives));
			((FastBufferReader)(ref r)).ReadValueSafe<int>(ref enemyHostSettings.Health, default(ForPrimitives));
			((FastBufferReader)(ref r)).ReadValueSafe<int>(ref enemyHostSettings.GrabDamage, default(ForPrimitives));
			((FastBufferReader)(ref r)).ReadValueSafe<int>(ref enemyHostSettings.AxeDamage, default(ForPrimitives));
			((FastBufferReader)(ref r)).ReadValueSafe<bool>(ref enemyHostSettings.Loot, default(ForPrimitives));
			return enemyHostSettings;
		}
	}
	internal static class EnemySettings
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static HandleNamedMessageDelegate <0>__Receive;
		}

		private const string Channel = "RE4Enemies.settings.v4";

		private static NetworkManager? owner;

		private static EnemyHostSettings? remote;

		private static float next;

		private static string sent = "";

		public static bool Synchronized
		{
			get
			{
				if (!((Object)(object)owner == (Object)null) && !owner.IsHost)
				{
					return remote != null;
				}
				return true;
			}
		}

		public static EnemyHostSettings Current
		{
			get
			{
				if (!((Object)(object)owner != (Object)null) || owner.IsHost || remote == null)
				{
					return Plugin.Instance.LocalSettings;
				}
				return remote;
			}
		}

		public static void Register(NetworkManager network)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			owner = network;
			CustomMessagingManager customMessagingManager = network.CustomMessagingManager;
			object obj = <>O.<0>__Receive;
			if (obj == null)
			{
				HandleNamedMessageDelegate val = Receive;
				<>O.<0>__Receive = val;
				obj = (object)val;
			}
			customMessagingManager.RegisterNamedMessageHandler("RE4Enemies.settings.v4", (HandleNamedMessageDelegate)obj);
		}

		private static void Receive(ulong sender, FastBufferReader reader)
		{
			if (!((Object)(object)owner == (Object)null) && !owner.IsHost && sender == 0L && ((FastBufferReader)(ref reader)).Length - ((FastBufferReader)(ref reader)).Position == 32)
			{
				EnemyHostSettings enemyHostSettings = EnemyHostSettings.Read(ref reader);
				if (enemyHostSettings.Valid)
				{
					remote = enemyHostSettings;
				}
			}
		}

		public static void Send(ulong client)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)owner == (Object)null || !owner.IsHost)
			{
				return;
			}
			EnemyHostSettings localSettings = Plugin.Instance.LocalSettings;
			FastBufferWriter w = default(FastBufferWriter);
			((FastBufferWriter)(ref w))..ctor(64, (Allocator)2, -1);
			try
			{
				localSettings.Write(ref w);
				owner.CustomMessagingManager.SendNamedMessage("RE4Enemies.settings.v4", client, w, (NetworkDelivery)3);
			}
			finally
			{
				((FastBufferWriter)(ref w)).Dispose();
			}
		}

		public static void Tick()
		{
			if ((Object)(object)owner == (Object)null || !owner.IsHost || Time.unscaledTime < next)
			{
				return;
			}
			next = Time.unscaledTime + 1f;
			EnemyHostSettings localSettings = Plugin.Instance.LocalSettings;
			string text = $"{localSettings.ScaleDifficulty}/{localSettings.Enabled}/{localSettings.Mobs}/{localSettings.DayCount}/{localSettings.NightCount}/{localSettings.MobPercent}/{localSettings.IndoorSpiderWeight}/{localSettings.Health}/{localSettings.GrabDamage}/{localSettings.AxeDamage}/{localSettings.Loot}";
			if (text == sent)
			{
				return;
			}
			sent = text;
			foreach (ulong connectedClientsId in owner.ConnectedClientsIds)
			{
				if (connectedClientsId != owner.LocalClientId)
				{
					Send(connectedClientsId);
				}
			}
		}

		public static void Clear()
		{
			if ((Object)(object)owner != (Object)null)
			{
				CustomMessagingManager customMessagingManager = owner.CustomMessagingManager;
				if (customMessagingManager != null)
				{
					customMessagingManager.UnregisterNamedMessageHandler("RE4Enemies.settings.v4");
				}
			}
			owner = null;
			remote = null;
			next = 0f;
			sent = "";
		}
	}
	public sealed class FcvClip
	{
		public sealed class Axis
		{
			public ushort[] Frames = Array.Empty<ushort>();

			public float[] Values = Array.Empty<float>();

			public float[] In = Array.Empty<float>();

			public float[] Out = Array.Empty<float>();

			public float At(float frame)
			{
				if (Frames.Length == 0)
				{
					return 0f;
				}
				if (frame <= (float)(int)Frames[0])
				{
					return Values[0];
				}
				int num = Frames.Length - 1;
				if (frame >= (float)(int)Frames[num])
				{
					return Values[num];
				}
				int i = Array.BinarySearch(Frames, (ushort)frame);
				if (i < 0)
				{
					i = ~i - 1;
				}
				for (; i < num && frame >= (float)(int)Frames[i + 1]; i++)
				{
				}
				if (i >= num)
				{
					return Values[num];
				}
				float num2 = (frame - (float)(int)Frames[i]) / (float)Math.Max(1, Frames[i + 1] - Frames[i]);
				float num3 = num2 * num2;
				float num4 = num3 * num2;
				return (2f * num4 - 3f * num3 + 1f) * Values[i] + (num4 - 2f * num3 + num2) * Out[i] + (-2f * num4 + 3f * num3) * Values[i + 1] + (num4 - num3) * In[i + 1];
			}
		}

		public sealed class Track
		{
			public int Kind;

			public int Part;

			public int Channel;

			public Axis[] Axes = Array.Empty<Axis>();
		}

		public readonly int MaxFrame;

		public readonly Track[] Tracks;

		public float RootDistance
		{
			get
			{
				Track[] tracks = Tracks;
				foreach (Track track in tracks)
				{
					if (track.Kind == 1)
					{
						double num = 0.0;
						Axis[] axes = track.Axes;
						foreach (Axis axis in axes)
						{
							float num2 = axis.At(MaxFrame) - axis.At(0f);
							num += (double)(num2 * num2);
						}
						return (float)Math.Sqrt(num) * 0.001f;
					}
				}
				return 0f;
			}
		}

		public FcvClip(byte[] data)
		{
			BinaryReader r = new BinaryReader(new MemoryStream(data));
			try
			{
				MaxFrame = r.ReadUInt16() & 0x3FFF;
				int num = r.ReadByte();
				if (num < 1 || num > 128 || MaxFrame > 10000)
				{
					throw new InvalidDataException("Invalid FCV header");
				}
				ushort[] array = new ushort[num];
				for (int i = 0; i < num; i++)
				{
					array[i] = r.ReadUInt16();
				}
				byte[] array2 = r.ReadBytes(num);
				r.BaseStream.Position = (3 + 3 * num + 3) & -4;
				r.ReadUInt32();
				uint[] array3 = new uint[num];
				for (int j = 0; j < num; j++)
				{
					array3[j] = r.ReadUInt32();
				}
				Tracks = new Track[num];
				for (int k = 0; k < num; k++)
				{
					int num2 = array[k] >> 12;
					int num3 = num2 / 4;
					int num4 = num2 % 4;
					if (num2 != 15 && (num3 > 2 || num4 > 2))
					{
						throw new InvalidDataException("Invalid FCV compression");
					}
					if (array3[k] >= data.Length)
					{
						throw new InvalidDataException("FCV track outside file");
					}
					r.BaseStream.Position = array3[k];
					Track track = new Track
					{
						Kind = (array[k] & 0xFF),
						Part = array2[k],
						Channel = ((array[k] >> 8) & 0xF),
						Axes = new Axis[3]
					};
					Tracks[k] = track;
					for (int l = 0; l < 3; l++)
					{
						int num5 = r.ReadUInt16();
						if (num5 < 1 || num5 > 10001)
						{
							throw new InvalidDataException("Invalid FCV key count");
						}
						Axis axis = new Axis
						{
							Frames = new ushort[num5],
							Values = new float[num5],
							In = new float[num5],
							Out = new float[num5]
						};
						track.Axes[l] = axis;
						for (int m = 0; m < num5; m++)
						{
							axis.Frames[m] = r.ReadUInt16();
							if (axis.Frames[m] > MaxFrame || (m > 0 && axis.Frames[m] < axis.Frames[m - 1]))
							{
								throw new InvalidDataException("Invalid FCV key times");
							}
						}
						for (int n = 0; n < num5; n++)
						{
							axis.Values[n] = Value((num2 != 15) ? num3 : 0);
							if (num2 != 15)
							{
								axis.In[n] = Value(num4);
								axis.Out[n] = Value(num4);
							}
							if (float.IsNaN(axis.Values[n]) || float.IsInfinity(axis.Values[n]))
							{
								throw new InvalidDataException("Invalid FCV value");
							}
						}
					}
				}
			}
			finally
			{
				if (r != null)
				{
					((IDisposable)r).Dispose();
				}
			}
			float Value(int format)
			{
				return format switch
				{
					0 => r.ReadSingle(), 
					1 => (float)r.ReadInt16() * 0.0001f, 
					2 => (float)r.ReadSByte() * 0.0001f, 
					_ => throw new InvalidDataException("Invalid FCV value format"), 
				};
			}
		}
	}
	public sealed class FrameGate
	{
		private int lastFrame = -1;

		public bool Enter(int frame)
		{
			if (lastFrame == frame)
			{
				return false;
			}
			lastFrame = frame;
			return true;
		}
	}
	public static class GameplayBridge
	{
		private static MethodInfo? origin;

		private static MethodInfo? addLoot;

		private static MethodInfo? damageHit;

		private static MethodInfo? impactKind;

		private static MethodInfo? kickPressed;

		private static MethodInfo? kickLabel;

		private static MethodInfo? presentationGet;

		private static FieldInfo? poseAiming;

		private static FieldInfo? poseLoaded;

		private static FieldInfo? poseDirection;

		private static int gunMultiplier = 1;

		private static PropertyInfo? currentShot;

		private static FieldInfo? shotWeapon;

		private static FieldInfo? shotLevel;

		private static FieldInfo? shotId;

		private static FieldInfo? shotOrigin;

		private static FieldInfo? shotImpact;

		private static readonly ShotHitLedger originalHits = new ShotHitLedger();

		private static float conversion = 0.25f;

		private static FieldInfo? nativeWindows;

		private static FieldInfo? directorInstance;

		private static FieldInfo? worldField;

		private static FieldInfo? lootField;

		private static MethodInfo? lootInventory;

		public static bool BreakFreePressed
		{
			get
			{
				if (!(kickPressed != null))
				{
					Keyboard current = Keyboard.current;
					if (current == null)
					{
						return false;
					}
					return ((ButtonControl)current.qKey).wasPressedThisFrame;
				}
				return (bool)kickPressed.Invoke(null, new object[1] { "Kick" });
			}
		}

		public static string BreakFreeLabel => (kickLabel?.Invoke(null, new object[1] { "Kick" }) as string) ?? "Q";

		public static float HealthScale
		{
			get
			{
				if (!(damageHit != null))
				{
					return 1f;
				}
				return conversion;
			}
		}

		public static float HealthMultiplier => GanadoBalance.HealthMultiplier(damageHit != null, gunMultiplier, conversion);

		public static bool PlagaClipAvailable { get; private set; }

		public static bool HeadAimed(PlayerControllerB player, Vector3 head, float scale)
		{
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: 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_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: 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_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			if (presentationGet == null)
			{
				Type type = AccessTools.TypeByName("RE4Company.Presentation");
				presentationGet = ((type != null) ? AccessTools.Method(type, "Get", (Type[])null, (Type[])null) : null);
				Type type2 = AccessTools.TypeByName("RE4Company.ActorPose");
				poseAiming = type2?.GetField("Aiming");
				poseLoaded = type2?.GetField("Loaded");
				poseDirection = type2?.GetField("Direction");
			}
			object obj = presentationGet?.Invoke(null, new object[1] { player.actualClientId });
			if (obj != null)
			{
				object obj2 = poseAiming?.GetValue(obj);
				if (obj2 is bool && (bool)obj2 && poseLoaded?.GetValue(obj) is int num && num > 0)
				{
					Vector3 val = originAvailable(player);
					Vector3 val2 = ((poseDirection?.GetValue(obj) is Vector3 val3) ? val3 : ((Component)player.gameplayCamera).transform.forward);
					Vector3 val4 = head - val;
					float num2 = Vector3.Dot(val4, ((Vector3)(ref val2)).normalized);
					if (num2 > 0f && num2 <= 8f * scale)
					{
						Vector3 val5 = val4 - ((Vector3)(ref val2)).normalized * num2;
						return ((Vector3)(ref val5)).sqrMagnitude <= 0.09f * scale * scale;
					}
					return false;
				}
			}
			return false;
		}

		public static bool UnderAim(PlayerControllerB player, Vector3 head, float scale)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: 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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: 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_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			HeadAimed(player, head, scale);
			object obj = presentationGet?.Invoke(null, new object[1] { player.actualClientId });
			if (obj != null)
			{
				object obj2 = poseAiming?.GetValue(obj);
				if (obj2 is bool && (bool)obj2)
				{
					Vector3 val = ((poseDirection?.GetValue(obj) is Vector3 val2) ? val2 : ((Component)player.gameplayCamera).transform.forward);
					Vector3 val3 = head - originAvailable(player);
					float num = Vector3.Dot(val3, ((Vector3)(ref val)).normalized);
					if (num > 0f && num < 13f * scale)
					{
						Vector3 val4 = val3 - ((Vector3)(ref val)).normalized * num;
						return ((Vector3)(ref val4)).sqrMagnitude < 1.5625f * scale * scale;
					}
					return false;
				}
			}
			return false;
		}

		private static Vector3 originAvailable(PlayerControllerB player)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: 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_0027: Unknown result type (might be due to invalid IL or missing references)
			if (!(origin != null))
			{
				return ((Component)player).transform.position + Vector3.up * 1.6f;
			}
			return Origin(player);
		}

		private static void InstallPlagaPlayerMotion()
		{
			Type type = AccessTools.TypeByName("RE4Company.OriginalMotion");
			Type type2 = AccessTools.TypeByName("RE4Company.FcvClip");
			IDictionary dictionary = type?.GetField("clips", BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null) as IDictionary;
			ConstructorInfo constructorInfo = type2?.GetConstructor(new Type[1] { typeof(byte[]) });
			if (dictionary != null && !(constructorInfo == null))
			{
				dictionary["plaga_spider_player_hold"] = constructorInfo.Invoke(new object[1] { File.ReadAllBytes(Path.Combine(Plugin.AssetPath, "motions", "em10_plaga_spider_player_hold.fcv")) });
				PlagaClipAvailable = true;
			}
		}

		public static void Install(Harmony harmony)
		{
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Expected O, but got Unknown
			//IL_0485: Unknown result type (might be due to invalid IL or missing references)
			//IL_0493: Expected O, but got Unknown
			//IL_0696: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a2: Expected O, but got Unknown
			//IL_06b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c4: Expected O, but got Unknown
			//IL_06d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e6: Expected O, but got Unknown
			//IL_06fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0708: Expected O, but got Unknown
			Type type = AccessTools.TypeByName("RE4Company.ModBindings");
			kickPressed = ((type != null) ? AccessTools.Method(type, "Pressed", (Type[])null, (Type[])null) : null);
			kickLabel = ((type != null) ? AccessTools.Method(type, "Label", (Type[])null, (Type[])null) : null);
			Type type2 = AccessTools.TypeByName("RE4Company.Director");
			if (type2 == null)
			{
				Plugin.Log("RE4 Gameplay absent: native hit forwarding remains available; supply drops unavailable.");
				return;
			}
			InstallPlagaPlayerMotion();
			if (AccessTools.TypeByName("RE4Company.EnemySupport") == null)
			{
				Plugin.Log("Original loot outcomes require RE4 Gameplay 0.24.2 or newer; update the companion mod to enable rewards.");
			}
			Type type3 = AccessTools.TypeByName("RE4Company.DamageScale");
			damageHit = ((type3 != null) ? AccessTools.Method(type3, "Hit", new Type[4]
			{
				typeof(ulong),
				typeof(EnemyAI),
				typeof(int),
				typeof(Vector3)
			}, (Type[])null) : null);
			gunMultiplier = ((!(type3?.GetField("GunMultiplier", BindingFlags.Static | BindingFlags.Public)?.GetValue(null) is int num)) ? 1 : num);
			if (type3?.GetField("DamageDivisor", BindingFlags.Static | BindingFlags.Public)?.GetValue(null) is int num2 && num2 > 0)
			{
				conversion = 1f / (float)num2;
			}
			if (damageHit != null)
			{
				harmony.Patch((MethodBase)damageHit, new HarmonyMethod(typeof(GameplayBridge), "GenericDamage", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			Type type4 = AccessTools.TypeByName("RE4Company.CombatImpact");
			type4?.GetField("Consumable")?.SetValue(null, new Func<ulong, EnemyAI, int, Vector3, bool>(Consumable));
			type4?.GetField("CaptureCamera")?.SetValue(null, (Func<ulong, Vector3[]>)((ulong client) => Plugin.Instance.CaptureView(client)));
			type4?.GetField("CaptureClip")?.SetValue(null, (Func<ulong, string>)((ulong client) => Plugin.Instance.CapturedClip(client)));
			type4?.GetField("Override")?.SetValue(null, new Func<ulong, EnemyAI, int, Vector3, Vector3, string, bool>(Impact));
			type4?.GetField("HoldAge")?.SetValue(null, (Func<ulong, float>)((ulong client) => Plugin.Instance.HoldAge(client)));
			type4?.GetField("Escaping")?.SetValue(null, (Func<ulong, bool>)((ulong client) => Plugin.Instance.Escaping(client)));
			impactKind = ((type4 != null) ? AccessTools.Method(type4, "Kind", (Type[])null, (Type[])null) : null);
			Type type5 = AccessTools.TypeByName("RE4Company.WeaponShot");
			currentShot = AccessTools.TypeByName("RE4Company.WeaponShots")?.GetProperty("Current", BindingFlags.Static | BindingFlags.Public);
			if (type5 != null && currentShot != null)
			{
				FieldInfo fieldInfo = type4?.GetField("WeaponOverride");
				if ((object)fieldInfo != null)
				{
					shotWeapon = type5.GetField("Weapon");
					shotLevel = type5.GetField("PowerLevel");
					shotId = type5.GetField("Id");
					shotOrigin = type5.GetField("Origin");
					shotImpact = type5.GetField("ImpactOrigin");
					if (shotWeapon == null || shotLevel == null || shotId == null || shotOrigin == null || shotImpact == null)
					{
						throw new MissingFieldException("Firing-time weapon identity schema missing");
					}
					fieldInfo.SetValue(null, new Func<ulong, EnemyAI, object, Vector3, Vector3, string, bool>(OriginalImpact));
					Plugin.Log("Retail RE4 Ganado damage enabled: owned UHD tables, native upgrades, head/critical/range rules; native-enemy damage unchanged.");
					goto IL_0467;
				}
			}
			Plugin.Log("Legacy Gameplay build: original weapon damage requires RE4 Gameplay 0.23.0 or newer; preserving legacy hit adapter.");
			goto IL_0467;
			IL_0467:
			harmony.Patch((MethodBase)AccessTools.Method(type2, "Stagger", (Type[])null, (Type[])null), new HarmonyMethod(typeof(GameplayBridge), "NativeStagger", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			nativeWindows = AccessTools.Field(type2, "nativeStaggers");
			directorInstance = AccessTools.Field(type2, "Instance");
			worldField = AccessTools.Field(type2, "World");
			lootField = ((worldField != null) ? AccessTools.Field(worldField.FieldType, "Loot") : null);
			addLoot = AccessTools.Method(type2, "AddLoot", new Type[3]
			{
				typeof(string),
				typeof(int),
				typeof(Vector3)
			}, (Type[])null);
			origin = AccessTools.Method(AccessTools.TypeByName("RE4Company.Controller"), "CombatOrigin", (Type[])null, (Type[])null);
			MethodInfo methodInfo = AccessTools.Method(type2, "Shoot", new Type[6]
			{
				typeof(ulong),
				typeof(Vector3),
				typeof(Vector3),
				typeof(float),
				typeof(int),
				typeof(bool)
			}, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(type2, "Melee", new Type[4]
			{
				typeof(ulong),
				typeof(PlayerControllerB),
				typeof(Vector3),
				typeof(bool)
			}, (Type[])null);
			MethodInfo methodInfo3 = AccessTools.Method(type2, "CanKick", new Type[1] { typeof(PlayerControllerB) }, (Type[])null);
			if (methodInfo == null || methodInfo2 == null || methodInfo3 == null || origin == null || addLoot == null)
			{
				throw new MissingMethodException("RE4 Gameplay optional combat API is incompatible");
			}
			MethodInfo methodInfo4 = AccessTools.Method(AccessTools.TypeByName("RE4Company.Controller"), "SendCombat", (Type[])null, (Type[])null);
			if (methodInfo4 == null)
			{
				throw new MissingMethodException("RE4 Gameplay aim request method missing");
			}
			harmony.Patch((MethodBase)methodInfo4, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(GameplayBridge), "AimTranspiler", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(GameplayBridge), "Shoot", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(GameplayBridge), "Melee", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, new HarmonyMethod(typeof(GameplayBridge), "CanKick", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			Plugin.Log("Optional RE4 Gameplay hit-region, kick and stagger-prompt integration installed.");
		}

		public static float ScaleDamage(EnemyAI enemy, int force)
		{
			return (float)force * HealthScale;
		}

		public static bool GenericDamage(ulong __0, EnemyAI __1, int __2, Vector3 __3)
		{
			if (!Plugin.Instance.IsHost || !(__1 is GanadoEnemy enemy) || !Plugin.IsGanado(enemy))
			{
				return true;
			}
			PlayerControllerB player = ((IEnumerable<PlayerControllerB>)StartOfRound.Instance.allPlayerScripts).FirstOrDefault((Func<PlayerControllerB, bool>)((PlayerControllerB p) => (Object)(object)p != (Object)null && p.isPlayerControlled && p.actualClientId == __0));
			Plugin.Instance.PrecisionHit(enemy, ScaleDamage((EnemyAI)(object)enemy, __2) * (float)gunMultiplier, player, HitRegion.Body);
			return false;
		}

		public static void Dispose()
		{
			Type type = AccessTools.TypeByName("RE4Company.CombatImpact");
			string[] array = new string[7] { "Override", "HoldAge", "Escaping", "WeaponOverride", "CaptureClip", "CaptureCamera", "Consumable" };
			foreach (string name in array)
			{
				type?.GetField(name)?.SetValue(null, null);
			}
			originalHits.Clear();
		}

		public static bool NativeStagger(EnemyAI __0)
		{
			if (__0 is GanadoEnemy enemy)
			{
				return !Plugin.IsGanado(enemy);
			}
			return true;
		}

		private static ImpactKind Kind(string kind, float distance)
		{
			switch (kind)
			{
			case "shotgun":
				if (distance <= 6f)
				{
					return ImpactKind.Shotgun;
				}
				goto default;
			default:
				return ImpactKind.Bullet;
			case "heavy":
				return ImpactKind.Heavy;
			case "blast":
				return ImpactKind.Blast;
			}
		}

		public static bool Impact(ulong client, EnemyAI native, int force, Vector3 direction, Vector3 point, string kind)
		{
			//IL_0058: 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_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: 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_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.Instance.IsHost)
			{
				GanadoEnemy enemy = native as GanadoEnemy;
				if (enemy != null && Plugin.IsGanado(enemy))
				{
					PlayerControllerB val = ((IEnumerable<PlayerControllerB>)StartOfRound.Instance.allPlayerScripts).FirstOrDefault((Func<PlayerControllerB, bool>)((PlayerControllerB p) => (Object)(object)p != (Object)null && p.isPlayerControlled && p.actualClientId == client));
					RaycastHit val2 = ((IEnumerable<RaycastHit>)(from h in Physics.RaycastAll(point - ((Vector3)(ref direction)).normalized * 0.08f, direction, 0.16f, -1, (QueryTriggerInteraction)2)
						orderby ((RaycastHit)(ref h)).distance
						select h)).FirstOrDefault((Func<RaycastHit, bool>)((RaycastHit h) => (Object)(object)((Component)((RaycastHit)(ref h)).collider).GetComponentInParent<EnemyAI>() == (Object)(object)enemy));
					if (kind != "blast")
					{
						Collider collider = ((RaycastHit)(ref val2)).collider;
						if ((Object)(object)((collider != null) ? ((Component)collider).GetComponent<GanadoWeaponHit>() : null) != (Object)null && Plugin.Instance.ShootWeapon(enemy))
						{
							return true;
						}
					}
					int num;
					if (!(kind == "blast"))
					{
						Collider collider2 = ((RaycastHit)(ref val2)).collider;
						num = (int)(((collider2 == null) ? ((HitRegion?)null) : ((Component)collider2).GetComponent<GanadoHurtRegion>()?.Region) ?? Plugin.Instance.Region(enemy, point));
					}
					else
					{
						num = 0;
					}
					HitRegion hitRegion = (HitRegion)num;
					Vector3 val3 = ((kind == "blast") ? (point - ((Vector3)(ref direction)).normalized) : (((Object)(object)val != (Object)null) ? Origin(val) : (point - ((Vector3)(ref direction)).normalized)));
					float num2 = Vector3.Distance(val3, point);
					Plugin.Instance.PrecisionHit(enemy, ScaleDamage((EnemyAI)(object)enemy, force + ((hitRegion == HitRegion.Head) ? 1 : 0)) * (float)gunMultiplier, val, hitRegion, hitRegion == HitRegion.Leg && point.y - ((Component)enemy).transform.position.y < 0.2f * Plugin.Instance.ModelScale(((NetworkBehaviour)enemy).NetworkObjectId) * 1.84f, Kind(kind, num2 / Mathf.Max(0.01f, Plugin.Instance.ModelScale(((NetworkBehaviour)enemy).NetworkObjectId))), val3);
					return true;
				}
			}
			return false;
		}

		public static bool OriginalImpact(ulong client, EnemyAI native, object shot, Vector3 direction, Vector3 point, string kind)
		{
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: 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_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: 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_0329: Unknown result type (might be due to invalid IL or missing references)
			//IL_033b: Unknown result type (might be due to invalid IL or missing references)
			//IL_037c: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.Instance.IsHost)
			{
				GanadoEnemy enemy = native as GanadoEnemy;
				if (enemy != null && Plugin.IsGanado(enemy) && !(shotWeapon == null))
				{
					int weapon = (int)shotWeapon.GetValue(shot);
					int num = (int)shotLevel.GetValue(shot);
					if (!OriginalWeaponDamage.ValidWeapon(weapon))
					{
						return false;
					}
					long shot2 = (long)shotId.GetValue(shot);
					if (!originalHits.Claim(shot2, ((NetworkBehaviour)enemy).NetworkObjectId))
					{
						return true;
					}
					Vector3 source = (Vector3)((kind == "blast") ? shotImpact : shotOrigin).GetValue(shot);
					RaycastHit val = ((IEnumerable<RaycastHit>)(from h in Physics.RaycastAll(point - ((Vector3)(ref direction)).normalized * 0.08f, direction, 0.16f, -1, (QueryTriggerInteraction)2)
						orderby ((RaycastHit)(ref h)).distance
						select h)).FirstOrDefault((Func<RaycastHit, bool>)((RaycastHit h) => (Object)(object)((Component)((RaycastHit)(ref h)).collider).GetComponentInParent<EnemyAI>() == (Object)(object)enemy));
					Collider collider = ((RaycastHit)(ref val)).collider;
					if ((Object)(object)((collider != null) ? ((Component)collider).GetComponent<GanadoWeaponHit>() : null) != (Object)null && Plugin.Instance.ShootWeapon(enemy))
					{
						return true;
					}
					Collider collider2 = ((RaycastHit)(ref val)).collider;
					HitRegion hitRegion = ((collider2 == null) ? ((HitRegion?)null) : ((Component)collider2).GetComponent<GanadoHurtRegion>()?.Region) ?? Plugin.Instance.Region(enemy, point);
					if (kind == "blast")
					{
						GanadoHurtRegion ganadoHurtRegion = ((Component)enemy).GetComponentsInChildren<GanadoHurtRegion>().OrderBy(delegate(GanadoHurtRegion z)
						{
							//IL_0018: Unknown result type (might be due to invalid IL or missing references)
							//IL_001d: Unknown result type (might be due to invalid IL or missing references)
							//IL_0010: Unknown result type (might be due to invalid IL or missing references)
							//IL_0023: Unknown result type (might be due to invalid IL or missing references)
							//IL_0028: Unknown result type (might be due to invalid IL or missing references)
							//IL_002d: Unknown result type (might be due to invalid IL or missing references)
							Collider component = ((Component)z).GetComponent<Collider>();
							Vector3 val2 = ((component != null) ? component.ClosestPoint(source) : ((Component)z).transform.position) - source;
							return ((Vector3)(ref val2)).sqrMagnitude;
						}).FirstOrDefault();
						hitRegion = (((Object)(object)ganadoHurtRegion != (Object)null) ? ganadoHurtRegion.Region : HitRegion.Body);
					}
					bool flag = ((hitRegion == HitRegion.Head || hitRegion == HitRegion.Parasite) ? true : false);
					bool flag2 = flag;
					bool flag3 = Plugin.Instance.IsCrawler(enemy);
					float num2 = Vector3.Distance(source, point) / Mathf.Max(0.01f, Plugin.Instance.ModelScale(((NetworkBehaviour)enemy).NetworkObjectId));
					int num3 = OriginalWeaponDamage.Damage(weapon, num, flag2 && !flag3, num2, (byte)(flag2 ? ((byte)Random.Range(0, 256)) : 0), (byte)((flag2 && OriginalWeaponDamage.Shotgun(weapon) && num2 < 6f) ? ((byte)Random.Range(0, 256)) : 0), (byte)((flag2 && OriginalWeaponDamage.NativeWeapon(weapon) == 2 && num >= 6) ? ((byte)Random.Range(0, 256)) : 0), !flag3 && Plugin.Instance.IsExposed(enemy));
					if (flag3)
					{
						num3 = PlagaRules.CrawlerDamage(num3, flash: false);
					}
					PlayerControllerB? obj = ((IEnumerable<PlayerControllerB>)StartOfRound.Instance.allPlayerScripts).FirstOrDefault((Func<PlayerControllerB, bool>)((PlayerControllerB p) => (Object)(object)p != (Object)null && p.isPlayerControlled && p.actualClientId == client));
					Plugin instance = Plugin.Instance;
					GanadoEnemy enemy2 = enemy;
					float force = OriginalWeaponDamage.ToHealth(num3, HealthMultiplier);
					PlayerControllerB player = obj;
					HitRegion region = hitRegion;
					flag = hitRegion == HitRegion.Leg && point.y - ((Component)enemy).transform.position.y < 0.2f * Plugin.Instance.ModelScale(((NetworkBehaviour)enemy).NetworkObjectId) * 1.84f;
					ImpactKind kind2 = Kind(kind, num2);
					Vector3? source2 = source;
					int num4 = OriginalWeaponDamage.NativeWeapon(weapon);
					bool suppressPlaga = ((num4 == 46 || num4 == 48) ? true : false);
					instance.PrecisionHit(enemy2, force, player, region, flag, kind2, source2, suppressPlaga);
					return true;
				}
			}
			return false;
		}

		public static bool LootInventory(PlayerControllerB player, out LootInventory inventory)
		{
			inventory = new LootInventory();
			if ((object)lootInventory == null)
			{
				Type type = AccessTools.TypeByName("RE4Company.EnemySupport");
				lootInventory = (((object)type != null) ? AccessTools.Method(type, "Inventory", (Type[])null, (Type[])null) : null);
			}
			if (!(lootInventory?.Invoke(null, new object[1] { player.actualClientId }) is int[] array) || array.Length != 512)
			{
				return false;
			}
			Array.Copy(array, 0, inventory.Counts, 0, 256);
			Array.Copy(array, 256, inventory.Ammo, 0, 256);
			inventory.Life = Math.Max(0, player.health) * 12;
			return true;
		}

		public static bool Consumable(ulong client, EnemyAI enemy, int id, Vector3 point)
		{
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.Instance.IsHost || !(enemy is GanadoEnemy ganadoEnemy) || !Plugin.IsGanado(ganadoEnemy))
			{
				return false;
			}
			PlayerControllerB val = ((IEnumerable<PlayerControllerB>)StartOfRound.Instance.allPlayerScripts).FirstOrDefault((Func<PlayerControllerB, bool>)((PlayerControllerB p) => (Object)(object)p != (Object)null && p.isPlayerControlled && p.actualClientId == client));
			int num;
			switch (id)
			{
			case 14:
				if (!Plugin.Instance.Flash(ganadoEnemy, val))
				{
					((EnemyAI)ganadoEnemy).SetEnemyStunned(true, 5f, val);
				}
				return true;
			default:
				num = 10;
				break;
			case 1:
				num = 2500;
				break;
			}
			int originalDamage = num;
			Plugin.Instance.PrecisionHit(ganadoEnemy, OriginalWeaponDamage.ToHealth(originalDamage, HealthMultiplier), val, HitRegion.Body, ankle: false, (id == 1) ? ImpactKind.Blast : ImpactKind.Bullet, point);
			return true;
		}

		public static bool DropLoot(string kind, int count, Vector3 position)
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			object obj = directorInstance?.GetValue(null);
			if (obj == null || addLoot == null)
			{
				return false;
			}
			if (!(lootField?.GetValue(worldField?.GetValue(obj)) is ICollection { Count: var count2 } collection))
			{
				return false;
			}
			try
			{
				addLoot.Invoke(obj, new object[3] { kind, count, position });
				return collection.Count > count2;
			}
			catch (TargetInvocationException ex)
			{
				Plugin.Error(ex.InnerException ?? ex);
				return false;
			}
		}

		public static IEnumerable<CodeInstruction> AimTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			MethodInfo ray = AccessTools.Method(typeof(Physics), "Raycast", new Type[6]
			{
				typeof(Vector3),
				typeof(Vector3),
				typeof(RaycastHit).MakeByRefType(),
				typeof(float),
				typeof(int),
				typeof(QueryTriggerInteraction)
			}, (Type[])null);
			MethodInfo replacement = AccessTools.Method(typeof(GameplayBridge), "AimRaycast", (Type[])null, (Type[])null);
			bool replaced = false;
			foreach (CodeInstruction instruction in instructions)
			{
				if (CodeInstructionExtensions.Calls(instruction, ray))
				{
					instruction.opcode = OpCodes.Call;
					instruction.operand = replacement;
					replaced = true;
				}
				yield return instruction;
			}
			if (!replaced)
			{
				throw new InvalidOperationException("RE4 Gameplay camera target ray was not found");
			}
		}

		public static bool AimRaycast(Vector3 origin, Vector3 direction, out RaycastHit hit, float range, int mask, QueryTriggerInteraction query)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: 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_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: 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_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: 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)
			Physics.SyncTransforms();
			bool flag = Physics.Raycast(origin, direction, ref hit, range, mask, query);
			float num = (flag ? ((RaycastHit)(ref hit)).distance : range);
			RaycastHit val = (from h in Physics.RaycastAll(origin, direction, num, -1, (QueryTriggerInteraction)2).Where(delegate(RaycastHit h)
				{
					GanadoEnemy ganadoEnemy = ((Component)((RaycastHit)(ref h)).collider).GetComponentInParent<GanadoEnemy>() ?? ((Component)((RaycastHit)(ref h)).collider).GetComponent<GanadoWeaponHit>()?.Enemy;
					return ganadoEnemy != null && Plugin.IsGanado(ganadoEnemy) && (!((EnemyAI)ganadoEnemy).isEnemyDead || (Object)(object)((Component)((RaycastHit)(ref h)).collider).GetComponent<GanadoWeaponHit>() != (Object)null);
				})
				orderby ((RaycastHit)(ref h)).distance
				select h).FirstOrDefault();
			if ((Object)(object)((RaycastHit)(ref val)).collider != (Object)null)
			{
				hit = val;
				((RaycastHit)(ref hit)).point = ((RaycastHit)(ref val)).point + direction * 0.04f;
				return true;
			}
			return flag;
		}

		private static Vector3 Origin(PlayerControllerB p)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			return (Vector3)origin.Invoke(null, new object[1] { p });
		}

		public static bool Shoot(ulong __0, Vector3 __1, Vector3 __2, float __3, int __4, bool __5, ref bool __result)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: 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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: 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_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.Instance.IsHost)
			{
				return true;
			}
			Physics.SyncTransforms();
			float num = __3;
			RaycastHit val = default(RaycastHit);
			if (Physics.Raycast(__1, __2, ref val, __3, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1))
			{
				num = ((RaycastHit)(ref val)).distance + 0.05f;
			}
			RaycastHit val2 = ((IEnumerable<RaycastHit>)(from h in Physics.RaycastAll(__1, __2, num, -1, (QueryTriggerInteraction)2)
				orderby ((RaycastHit)(ref h)).distance
				select h)).FirstOrDefault((Func<RaycastHit, bool>)delegate(RaycastHit h)
			{
				EnemyAI val3 = (EnemyAI)(((object)((Component)((RaycastHit)(ref h)).collider).GetComponentInParent<EnemyAI>()) ?? ((object)((Component)((RaycastHit)(ref h)).collider).GetComponent<GanadoWeaponHit>()?.Enemy));
				return val3 != null && (!val3.isEnemyDead || (Object)(object)((Component)((RaycastHit)(ref h)).collider).GetComponent<GanadoWeaponHit>() != (Object)null);
			});
			if (!((Object)(object)((RaycastHit)(ref val2)).collider == (Object)null))
			{
				GanadoEnemy ganadoEnemy = ((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent<GanadoEnemy>() ?? ((Component)((RaycastHit)(ref val2)).collider).GetComponent<GanadoWeaponHit>()?.Enemy;
				if (ganadoEnemy != null && Plugin.IsGanado(ganadoEnemy))
				{
					if ((Object)(object)((Component)((RaycastHit)(ref val2)).collider).GetComponent<GanadoWeaponHit>() != (Object)null && Plugin.Instance.ShootWeapon(ganadoEnemy))
					{
						__result = true;
						return false;
					}
					if (!__5)
					{
						object obj = currentShot?.GetValue(null);
						if (obj != null && OriginalImpact(__0, (EnemyAI)(object)ganadoEnemy, obj, __2, ((RaycastHit)(ref val2)).point, ((string)impactKind?.Invoke(null, new object[1] { __0 })) ?? "bullet"))
						{
							__result = true;
							return false;
						}
					}
					HitRegion hitRegion = ((!__5) ? (((Component)((RaycastHit)(ref val2)).collider).GetComponent<GanadoHurtRegion>()?.Region ?? Plugin.Instance.Region(ganadoEnemy, ((RaycastHit)(ref val2)).point)) : HitRegion.Body);
					PlayerControllerB player = ((IEnumerable<PlayerControllerB>)StartOfRound.Instance.allPlayerScripts).FirstOrDefault((Func<PlayerControllerB, bool>)((PlayerControllerB p) => (Object)(object)p != (Object)null && p.isPlayerControlled && p.actualClientId == __0));
					ImpactKind kind = ((!__5) ? Kind(((string)impactKind?.Invoke(null, new object[1] { __0 })) ?? "bullet", ((RaycastHit)(ref val2)).distance / Mathf.Max(0.01f, Plugin.Instance.ModelScale(((NetworkBehaviour)ganadoEnemy).NetworkObjectId))) : ImpactKind.Bullet);
					Plugin.Instance.PrecisionHit(ganadoEnemy, ScaleDamage((EnemyAI)(object)ganadoEnemy, Mathf.Max(1, Mathf.RoundToInt((float)__4 / 28f)) + ((hitRegion == HitRegion.Head) ? 1 : 0)) * (float)(__5 ? 1 : gunMultiplier), player, hitRegion, hitRegion == HitRegion.Leg && ((RaycastHit)(ref val2)).point.y - ((Component)ganadoEnemy).transform.position.y < 0.2f * Plugin.Instance.ModelScale(((NetworkBehaviour)ganadoEnemy).NetworkObjectId) * 1.84f, kind, __1);
					__result = true;
					return false;
				}
			}
			return true;
		}

		public static bool Melee(ulong __0, PlayerControllerB __1, Vector3 __2, bool __3, ref bool __result)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: 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)
			if (!Plugin.Instance.IsHost)
			{
				return true;
			}
			if (RoundManager.Instance.SpawnedEnemies.Any(delegate(EnemyAI e)
			{
				if ((Object)(object)e != (Object)null && !e.isEnemyDead)
				{
					CentipedeAI val2 = (CentipedeAI)(object)((e is CentipedeAI) ? e : null);
					if (val2 == null || !((Object)(object)val2.clingingToPlayer == (Object)(object)__1))
					{
						FlowerSnakeEnemy val3 = (FlowerSnakeEnemy)(object)((e is FlowerSnakeEnemy) ? e : null);
						if (val3 != null)
						{
							return (Object)(object)val3.clingingToPlayer == (Object)(object)__1;
						}
						return false;
					}
					return true;
				}
				return false;
			}))
			{
				return true;
			}
			Vector3 from = Origin(__1);
			if (__3 && Plugin.Instance.Kick(__1, from, __2))
			{
				__result = true;
				return false;
			}
			RaycastHit val = ((IEnumerable<RaycastHit>)(from h in Physics.SphereCastAll(@from, 0.8f, __2, 2.2f, -1, (QueryTriggerInteraction)2)
				orderby ((RaycastHit)(ref h)).distance
				select h)).FirstOrDefault((Func<RaycastHit, bool>)delegate(RaycastHit h)
			{
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				EnemyAI componentInParent2 = ((Component)((RaycastHit)(ref h)).collider).GetComponentInParent<EnemyAI>();
				return componentInParent2 != null && !componentInParent2.isEnemyDead && !Physics.Linecast(from, ((RaycastHit)(ref h)).collider.ClosestPoint(from), StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1);
			});
			if (!((Object)(object)((RaycastHit)(ref val)).collider == (Object)null))
			{
				GanadoEnemy componentInParent = ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<GanadoEnemy>();
				if (componentInParent != null && Plugin.IsGanado(componentInParent))
				{
					__result = !__3;
					if (!__3)
					{
						Plugin.Instance.PrecisionHit(componentInParent, 1f, __1, HitRegion.Body);
					}
					return false;
				}
			}
			return true;
		}

		public static void ConsumeWindow(EnemyAI enemy)
		{
			object obj = directorInstance?.GetValue(null);
			if (obj != null && nativeWindows?.GetValue(obj) is Dictionary<EnemyAI, float> dictionary)
			{
				dictionary.Remove(enemy);
			}
		}

		public static void CanKick(object __instance, PlayerControllerB __0, ref bool __result)
		{
			Dictionary<EnemyAI, float> dictionary = nativeWindows?.GetValue(__instance) as Dictionary<EnemyAI, float>;
			if ((dictionary != null) & __result)
			{
				bool flag = RoundManager.Instance.SpawnedEnemies.Any(delegate(EnemyAI e)
				{
					if ((Object)(object)e != (Object)null && !e.isEnemyDead)
					{
						CentipedeAI val = (CentipedeAI)(object)((e is CentipedeAI) ? e : null);
						if (val == null || !((Object)(object)val.clingingToPlayer == (Object)(object)__0))
						{
							FlowerSnakeEnemy val2 = (FlowerSnakeEnemy)(object)((e is FlowerSnakeEnemy) ? e : null);
							if (val2 != null)
							{
								return (Object)(object)val2.clingingToPlayer == (Object)(object)__0;
							}
							return false;
						}
						return true;
					}
					return false;
				});
				bool flag2 = dictionary.Any((KeyValuePair<EnemyAI, float> w) => (Object)(object)w.Key != (Object)null && !w.Key.isEnemyDead && w.Value > Time.time && Vector3.Distance(((Component)w.Key).transform.position, ((Component)__0).transform.position) < 2.5f && (!(w.Key is GanadoEnemy enemy) || !Plugin.IsGanado(enemy)));
				__result = flag || flag2;
			}
			if (Plugin.Instance.CanKick(__0))
			{
				__result = true;
			}
		}
	}
	public sealed class GanadoWeapon
	{
		public readonly GameObject Root;

		private readonly Transform hand;

		private readonly Vector3 heldPosition;

		private readonly Vector3 heldScale;

		private readonly Quaternion heldRotation;

		private readonly Vector3 flightCenter;

		private readonly Vector3[] visiblePoints;

		private readonly VillageWeapon kind;

		private readonly GameObject? flame;

		private readonly BoxCollider? bombHitbox;

		public Vector3 ReleasePoint => Root.transform.TransformPoint(flightCenter);

		public GanadoWeapon(Re4Rig rig, VillageWeapon kind = VillageWeapon.Hatchet)
		{
			//IL_0042: 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_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: 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_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			this.kind = kind;
			Root = Assets.Weapon(rig, kind);
			hand = Root.transform.parent;
			heldPosition = Root.transform.localPosition;
			heldRotation = Root.transform.localRotation;
			heldScale = Root.transform.localScale;
			Mesh sharedMesh = Root.GetComponent<SkinnedMeshRenderer>().sharedMesh;
			Vector3[] points = sharedMesh.vertices;
			visiblePoints = (from i in sharedMesh.triangles.Distinct()
				select points[i]).ToArray();
			Bounds val = default(Bounds);
			((Bounds)(ref val))..ctor(visiblePoints[0], Vector3.zero);
			Vector3[] array = visiblePoints;
			foreach (Vector3 val2 in array)
			{
				((Bounds)(ref val)).Encapsulate(val2);
			}
			flightCenter = ((Bounds)(ref val)).center;
			if (kind == VillageWeapon.Dynamite)
			{
				bombHitbox = Root.AddComponent<BoxCollider>();
				((Collider)bombHitbox).isTrigger = true;
				bombHitbox.center = ((Bounds)(ref val)).center;
				bombHitbox.size = ((Bounds)(ref val)).size + Vector3.one * 0.03f;
				Root.AddComponent<GanadoWeaponHit>().Enemy = ((Component)rig).GetComponentInParent<GanadoEnemy>();
				((Collider)bombHitbox).enabled = false;
			}
			if ((kind == VillageWeapon.Torch || kind == VillageWeapon.Dynamite) ? true : false)
			{
				flame = VillageFlame.Create(Root.transform, kind == VillageWeapon.Torch);
			}
		}

		public void Present(bool armed, Vector3 drop, bool flying, Vector3 velocity, double launched, bool lost, float yaw, float extrapolate, float weaponScale, bool lit = false)
		{
			//IL_00a4: 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_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: 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_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: 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_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)bombHitbox != (Object)null)
			{
				((Collider)bombHitbox).enabled = lit && !lost;
			}
			if ((Object)(object)flame != (Object)null)
			{
				flame.SetActive(!lost && (kind == VillageWeapon.Torch || lit));
			}
			Root.SetActive(!lost);
			if (armed)
			{
				if ((Object)(object)Root.transform.parent != (Object)(object)hand)
				{
					Root.transform.SetParent(hand, false);
					Root.transform.localPosition = heldPosition;
					Root.transform.localRotation = heldRotation;
					Root.transform.localScale = heldScale;
				}
				return;
			}
			if ((Object)(object)Root.transform.parent != (Object)null)
			{
				Root.transform.SetParent((Transform)null, true);
			}
			if (flying)
			{
				Quaternion quaternion = OriginalAxe.Rotation(new Vector3(velocity.x, velocity.y, velocity.z), Plugin.Now - launched);
				Root.transform.rotation = new Quaternion(quaternion.X, quaternion.Y, quaternion.Z, quaternion.W);
				Vector3 vector = OriginalAxe.Predict(new Vector3(drop.x, drop.y, drop.z), new Vector3(velocity.x, velocity.y, velocity.z), weaponScale, extrapolate);
				Vector3 val = default(Vector3);
				((Vector3)(ref val))..ctor(vector.X, vector.Y, vector.Z);
				Root.transform.position = val - Root.transform.TransformVector(flightCenter);
			}
			else
			{
				Root.transform.rotation = Quaternion.Euler(0f, yaw, 0f);
				float num = visiblePoints.Min((Vector3 p) => Root.transform.TransformVector(p - flightCenter).y);
				Root.transform.position = drop + Vector3.up * (0.005f - num) - Root.transform.TransformVector(flightCenter);
			}
		}

		public bool Contact(PlayerControllerB target)
		{
			//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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: 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_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			float[] obj = ((kind != VillageWeapon.Hoe) ? new float[2] { 0.2f, -0.05f } : new float[6] { 1f, 0.7f, 0.4f, 0.1f, -0.3f, -0.6f });
			Vector3 val = Root.transform.TransformPoint(new Vector3(0f, 0f, (float)((kind != VillageWeapon.Hoe) ? 1 : 2)));
			float num = 0.25f * Root.transform.lossyScale.y;
			float[] array = obj;
			foreach (float num2 in array)
			{
				Vector3 val2 = Root.transform.TransformPoint(new Vector3(0f, 0f, num2));
				if (Physics.OverlapCapsule(val, val2, num, -1, (QueryTriggerInteraction)2).Any((Collider c) => (Object)(object)((Component)c).GetComponentInParent<PlayerControllerB>() == (Object)(object)target))
				{
					return true;
				}
			}
			return false;
		}
	}
	public static class GanadoBalance
	{
		public static float HealthMultiplier(bool gameplay, float firearmMultiplier, float conversion = 0.25f)
		{
			if (!gameplay)
			{
				return 1f;
			}
			return ((float.IsFinite(conversion) && conversion > 0f) ? conversion : 0.25f) * ((float.IsFinite(firearmMultiplier) && firearmMultiplier > 0f) ? firearmMultiplier : 1f);
		}
	}
	public sealed class GanadoBrain
	{
		public readonly GanadoEnemy Enemy;

		private HealthPool hitPoints;

		public GanadoState State;

		public double Started;

		public double NextAttack;

		public int Variant;

		public PlayerControllerB? Target;

		public bool Armed;

		public readonly VillageWeapon Weapon;

		public bool WeaponLit;

		public double FuseAt;

		public uint ExplosionSerial;

		public Vector3 ExplosionPosition;

		private bool spareBomb = true;

		private double fuseFlightAt;

		public Vector3 DropPosition;

		public Vector3 WeaponVelocity;

		public bool InFlight;

		public bool WeaponLost;

		public double Launched;

		public float WeaponYaw;

		private double throwAt;

		private double retrieveAt;

		private double flightAt;

		public float WeaponScale = 1f;

		public Vector3 LastSeen;

		public PlayerControllerB? LootOwner;

		private double seenAt = -100.0;

		private double thinkAt;

		private double routeAt;

		private double damageAt;

		private double previousAge = -0.001;

		private double runAgain;

		private double waitUntil;

		private bool contact;

		private int escapePresses;

		private double lastEscape = -100.0;

		private double reactionGuard;

		private double investigateUntil;

		private Vector3 investigation;

		private bool pointNotified;

		private double idleUntil;

		private Quaternion idleHeading;

		private readonly NavMeshPath path = new NavMeshPath();

		private bool ready;

		private double dashCatchAt;

		private int runSteps;

		private float runDistance;

		private static readonly Dictionary<InteractTrigger, GanadoBrain> ladderOwners = new Dictionary<InteractTrigger, GanadoBrain>();

		private InteractTrigger? ladder;

		private Vector3 ladderBottom;

		private Vector3 ladderTop;

		private Vector3 climbStart;

		private Vector3 rungAxis;

		private float ladderRemaining;

		private float climbHeight;

		private float mountRise;

		private float topRise;

		public float PoseFrame = -1f;

		public float PoseRate;

		private double ladderScanAt;

		private double fallAt;

		private bool falling;

		private double fallAge;

		private double dodgeAimAt = -1.0;

		private double dodgeReady;

		private double hideUntil;

		private double headLockAt = -1.0;

		private double guardWalkUntil;

		private double headAimSince = -1.0;

		private double walkInstance = -1.0;

		private bool headGuardEnabled;

		private double corePrevious = -0.001;

		private bool coreContact;

		private bool biteSelected;

		public bool PoisonActive;

		public Vector3 PoisonPosition;

		public Vector3 PoisonVelocity;

		public double PoisonAt;

		private double poisonReady;

		private double poisonTick;

		private double born;

		private double spiderWait;

		private int spiderLoops;

		private bool parasiteHit;

		private bool bladeRaised;

		private byte previousBlade;

		public readonly PlagaDamageAccumulator PlayerDamage = new PlagaDamageAccumulator();

		public float HitPoints => hitPoints.Remaining;

		public double WeaponAt => flightAt;

		public bool Kickable => MotionBank.Kickable(State, Plugin.Now - Started, Variant);

		public bool CanInvestigate
		{
			get
			{
				if ((Object)(object)Enemy != (Object)null && (Object)(object)Target == (Object)null && !((EnemyAI)Enemy).isEnemyDead && !OnLadder && !GanadoRules.Attacking(State))
				{
					return !DamageReactionRules.IsReaction(State);
				}
				return false;
			}
		}

		public bool OnLadder
		{
			get
			{
				GanadoState state = State;
				if (state - 54 <= GanadoState.Walk)
				{
					return true;
				}
				return false;
			}
		}

		public Vector3 LadderExit => ladderTop;

		public PlagaForm Plaga { get; private set; }

		public double PlagaAt { get; private set; }

		public double CoreAttackAt { get; private set; } = -1.0;

		public void ReleaseLocks(double now)
		{
			NextAttack = (throwAt = now);
		}

		public void Escape(ulong client, double now)
		{
			GanadoState state = State;
			bool flag = ((state == GanadoState.Hold || state - 46 <= GanadoState.Alert || state == GanadoState.SpiderHold) ? true : false);
			if (flag && (Object)(object)Target != (Object)null && Target.actualClientId == client && GrabRules.AcceptPress(now, lastEscape))
			{
				lastEscape = now;
				escapePresses++;
			}
		}

		public GanadoBrain(GanadoEnemy enemy)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			Enemy = enemy;
			hitPoints = new HealthPool(Plugin.Instance.StartingHealth);
			((EnemyAI)Enemy).enemyHP = Mathf.CeilToInt(hitPoints.Remaining);
			Weapon = enemy.Loadout;
			Armed = Weapon != VillageWeapon.None;
			LastSeen = ((Component)enemy).transform.position;
			Started = Plugin.Now;
			Variant = (int)(((NetworkBehaviour)enemy).NetworkObjectId % 19);
			idleUntil = Plugin.Now + 4.0 + (double)(((NetworkBehaviour)enemy).NetworkObjectId % 5);
			throwAt = Plugin.Now;
			dashCatchAt = Plugin.Now + (double)Random.Range(0, 150) / 30.0;
			runAgain = Plugin.Now + (double)Random.Range(0, 150) / 90.0;
			if (SpawnRules.Crawler(enemy.Pool))
			{
				InitializeCrawler(Plugin.Now);
				Target = enemy.ParasiteVictim;
				LootOwner = enemy.ParasiteOwner;
				if ((Object)(object)Target != (Object)null)
				{
					LastSeen = ((Component)Target).transform.position;
					seenAt = Plugin.Now;