Decompiled source of UKEnemyIdentifier v1.1.0

plugins/UKEnemyIdentifier/UKEnemyIdentifier.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UKEnemyIdentifier.Components;
using UKEnemyIdentifier.Utils;
using UKEnemyIdentifier.Utils.Il;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("UKEnemyIdentifier")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("UKEnemyIdentifier")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("23B65D15-307A-40B5-B785-189FDD449F1A")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyVersion("1.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace UKEnemyIdentifier
{
	[BepInProcess("ULTRAKILL.exe")]
	[BepInPlugin("dev.flazhik.ukenemyidentifier", "UKEnemyIdentifier", "1.1.0")]
	public class Plugin : BaseUnityPlugin
	{
		private Harmony _harmony;

		private void Awake()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			_harmony = new Harmony("dev.flazhik.ukenemyidentifier");
			_harmony.PatchAll();
		}
	}
	internal static class PluginInfo
	{
		public const string Guid = "dev.flazhik.ukenemyidentifier";

		public const string Name = "UKEnemyIdentifier";

		public const string Version = "1.1.0";
	}
}
namespace UKEnemyIdentifier.Utils
{
	public static class ObjectExtensions
	{
		public static bool IsOneOf(this object v, params object[] options)
		{
			return options.Any((object o) => o.Equals(v));
		}
	}
	public static class ReflectionUtils
	{
		private const BindingFlags BindingFlagsFields = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

		public static T GetPrivate<T>(object instance, string field)
		{
			return (T)instance.GetType().GetField(field, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).GetValue(instance);
		}

		public static CodeInstruction IL(OpCode opCode)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			return new CodeInstruction(opCode, (object)null);
		}

		public static CodeInstruction IL(OpCode opCode, object inst)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			return new CodeInstruction(opCode, inst);
		}

		public static IEnumerable<CodeInstruction> IL(params (OpCode opCode, object inst)[] instructions)
		{
			return ((IEnumerable<(OpCode, object)>)instructions).Select((Func<(OpCode, object), CodeInstruction>)(((OpCode opCode, object inst) i) => new CodeInstruction(i.opCode, i.inst))).ToList();
		}

		public static bool IsLdloc(CodeInstruction instruction)
		{
			return instruction.opcode.IsOneOf(OpCodes.Ldloc_0, OpCodes.Ldloc_1, OpCodes.Ldloc_2, OpCodes.Ldloc_3, OpCodes.Ldloc_S, OpCodes.Ldloc);
		}

		public static bool IsStloc(CodeInstruction instruction)
		{
			return instruction.opcode.IsOneOf(OpCodes.Stloc_0, OpCodes.Stloc_1, OpCodes.Stloc_2, OpCodes.Stloc_3, OpCodes.Stloc_S, OpCodes.Stloc);
		}

		public static int GetLocalIndex(CodeInstruction instruction)
		{
			if (instruction.opcode.IsOneOf(OpCodes.Ldloc_0, OpCodes.Stloc_0))
			{
				return 0;
			}
			if (instruction.opcode.IsOneOf(OpCodes.Ldloc_1, OpCodes.Stloc_1))
			{
				return 1;
			}
			if (instruction.opcode.IsOneOf(OpCodes.Ldloc_2, OpCodes.Stloc_2))
			{
				return 2;
			}
			if (instruction.opcode.IsOneOf(OpCodes.Ldloc_3, OpCodes.Stloc_3))
			{
				return 3;
			}
			if (!(instruction.operand is LocalBuilder localBuilder))
			{
				return -1;
			}
			return localBuilder.LocalIndex;
		}

		public static CodeInstruction MirrorLdloc(CodeInstruction instruction)
		{
			return (CodeInstruction)(GetLocalIndex(instruction) switch
			{
				0 => IL(OpCodes.Ldloc_0), 
				1 => IL(OpCodes.Ldloc_1), 
				2 => IL(OpCodes.Ldloc_2), 
				3 => IL(OpCodes.Ldloc_3), 
				-1 => null, 
				_ => (instruction.operand is LocalBuilder inst) ? IL(OpCodes.Ldloc, inst) : null, 
			});
		}

		public static Type LocalType(MethodBase method, int index)
		{
			MethodBody methodBody = method?.GetMethodBody();
			if (methodBody == null || index < 0 || index >= methodBody.LocalVariables.Count)
			{
				return null;
			}
			return methodBody.LocalVariables[index].LocalType;
		}

		public static CodeInstruction FindObjectLocal(IReadOnlyList<CodeInstruction> instructions, int index, MethodBase method, Type type, int depth = 6)
		{
			int num = index - 1;
			while (num >= 0 && num >= index - depth)
			{
				if (IsLdloc(instructions[num]))
				{
					Type type2 = LocalType(method, GetLocalIndex(instructions[num]));
					if (type2 != null && type.IsAssignableFrom(type2))
					{
						return instructions[num];
					}
				}
				num--;
			}
			return null;
		}

		public static IEnumerable<CodeInstruction> ToGameObject(CodeInstruction localLoad, Type localType)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			if (typeof(GameObject).IsAssignableFrom(localType))
			{
				return new List<CodeInstruction> { localLoad };
			}
			return new List<CodeInstruction>
			{
				localLoad,
				new CodeInstruction(OpCodes.Callvirt, (object)AccessTools.Method(typeof(Component), "get_gameObject", (Type[])null, (Type[])null))
			};
		}
	}
}
namespace UKEnemyIdentifier.Utils.Il
{
	public static class EnemyIdentifierEmitters
	{
		private static readonly MethodInfo ManagerInstance = AccessTools.Method(typeof(EnemyIdentifierManager), "get_Instance", (Type[])null, (Type[])null);

		private static readonly MethodInfo GetGameObject = AccessTools.Method(typeof(Component), "get_gameObject", (Type[])null, (Type[])null);

		private static readonly FieldInfo LastHurtingFactorField = AccessTools.Field(typeof(EnemyIdentifierManager), "LastHurtingFactor");

		private static readonly MethodInfo RegisterFactorMethod = AccessTools.Method(typeof(EnemyIdentifierManager), "RegisterFactor", new Type[2]
		{
			typeof(GameObject),
			typeof(EnemyIdentifier)
		}, (Type[])null);

		private static readonly MethodInfo RegisterExplosionMethod = AccessTools.Method(typeof(EnemyIdentifierManager), "RegisterExplosion", new Type[2]
		{
			typeof(Component),
			typeof(Explosion)
		}, (Type[])null);

		public static IEnumerable<CodeInstruction> RegisterExplosion(CodeInstruction explosionLoad)
		{
			return ReflectionUtils.IL((OpCodes.Call, ManagerInstance), (OpCodes.Ldarg_0, null)).Concat(new List<CodeInstruction> { explosionLoad }).Concat(ReflectionUtils.IL((OpCodes.Callvirt, RegisterExplosionMethod)));
		}

		public static List<CodeInstruction> LastHurtingFactor()
		{
			return ReflectionUtils.IL((OpCodes.Call, ManagerInstance), (OpCodes.Ldarg_0, null), (OpCodes.Call, GetGameObject), (OpCodes.Stfld, LastHurtingFactorField)).ToList();
		}

		public static IEnumerable<CodeInstruction> RegisterHurtingFactor<TOwner>(CodeInstruction valueLoad, Type valueType)
		{
			return ReflectionUtils.IL((OpCodes.Call, ManagerInstance)).Concat(ReflectionUtils.ToGameObject(valueLoad, valueType)).Concat(ReflectionUtils.IL((OpCodes.Ldarg_0, null), (OpCodes.Ldfld, AccessTools.Field(typeof(TOwner), "eid")), (OpCodes.Callvirt, RegisterFactorMethod)));
		}

		public static IEnumerable<CodeInstruction> RegisterHurtingFactor<TOwner>(LocalBuilder local, Type valueType)
		{
			return RegisterHurtingFactor<TOwner>(ReflectionUtils.IL(OpCodes.Ldloc, local), valueType);
		}
	}
	public enum AnchorMatchMode
	{
		Single,
		All,
		First,
		Optional
	}
	public sealed class TranspilerBuilder
	{
		private readonly MethodBase _original;

		private readonly ILGenerator _generator;

		private readonly string _method;

		private List<CodeInstruction> Instructions { get; }

		private TranspilerBuilder(IEnumerable<CodeInstruction> instructions, MethodBase original, ILGenerator generator)
		{
			Instructions = instructions.ToList();
			_original = original;
			_generator = generator;
			_method = ((original == null) ? "?" : (original.DeclaringType?.Name + "." + original.Name));
		}

		public static TranspilerBuilder ForInstructions(IEnumerable<CodeInstruction> instructions, MethodBase original, ILGenerator generator = null)
		{
			return new TranspilerBuilder(instructions, original, generator);
		}

		public TranspilerBuilder Before(Anchor anchor, Func<List<CodeInstruction>> emit, AnchorMatchMode mode = AnchorMatchMode.Single)
		{
			return Apply(anchor, emit, mode, after: false);
		}

		public TranspilerBuilder After(Anchor anchor, Func<List<CodeInstruction>> emit, AnchorMatchMode mode = AnchorMatchMode.Single)
		{
			return Apply(anchor, emit, mode, after: true);
		}

		public TranspilerBuilder AfterStore(Anchor anchor, Type valueType, Func<CodeInstruction, Type, IEnumerable<CodeInstruction>> emit, AnchorMatchMode mode = AnchorMatchMode.Single, int depth = 6)
		{
			List<int> list = Select(Positions(anchor), mode);
			if (list == null)
			{
				ReportAnchorError(anchor.Name, Positions(anchor).Count, mode);
				return this;
			}
			for (int num = list.Count - 1; num >= 0; num--)
			{
				CodeInstruction val = ReflectionUtils.FindObjectLocal(Instructions, list[num], _original, valueType, depth);
				CodeInstruction val2 = ((val == null) ? null : ReflectionUtils.MirrorLdloc(val));
				if (val2 == null)
				{
					ReportAnchorError(anchor.Name, 0, mode);
				}
				else
				{
					Type arg = ReflectionUtils.LocalType(_original, ReflectionUtils.GetLocalIndex(val)) ?? valueType;
					Instructions.InsertRange(list[num] + 1, emit(val2, arg));
				}
			}
			return this;
		}

		public TranspilerBuilder AfterLocalStore(Type valueType, Func<CodeInstruction, Type, IEnumerable<CodeInstruction>> emit, AnchorMatchMode mode = AnchorMatchMode.Single)
		{
			List<int> list = new List<int>();
			for (int i = 0; i < Instructions.Count; i++)
			{
				if (ReflectionUtils.IsStloc(Instructions[i]) && ReflectionUtils.LocalType(_original, ReflectionUtils.GetLocalIndex(Instructions[i])) == valueType)
				{
					list.Add(i);
				}
			}
			string anchor = "store(" + valueType.Name + ")";
			List<int> list2 = Select(list, mode);
			if (list2 == null)
			{
				ReportAnchorError(anchor, list.Count, mode);
				return this;
			}
			for (int num = list2.Count - 1; num >= 0; num--)
			{
				CodeInstruction val = ReflectionUtils.MirrorLdloc(Instructions[list2[num]]);
				if (val == null)
				{
					ReportAnchorError(anchor, 0, mode);
				}
				else
				{
					Instructions.InsertRange(list2[num] + 1, emit(val, valueType));
				}
			}
			return this;
		}

		public TranspilerBuilder AfterStack(Anchor anchor, Type valueType, Func<LocalBuilder, Type, IEnumerable<CodeInstruction>> emit, AnchorMatchMode mode = AnchorMatchMode.Single)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			List<int> list = Positions(anchor);
			List<int> list2 = Select(list, mode);
			if (list2 == null || _generator == null)
			{
				ReportAnchorError(anchor.Name, list.Count, mode);
				return this;
			}
			for (int num = list2.Count - 1; num >= 0; num--)
			{
				LocalBuilder localBuilder = _generator.DeclareLocal(valueType);
				List<CodeInstruction> list3 = new List<CodeInstruction>
				{
					new CodeInstruction(OpCodes.Stloc, (object)localBuilder)
				};
				list3.AddRange(emit(localBuilder, valueType));
				list3.Add(ReflectionUtils.IL(OpCodes.Ldloc, localBuilder));
				Instructions.InsertRange(list2[num] + 1, list3);
			}
			return this;
		}

		public IEnumerable<CodeInstruction> Build()
		{
			return Instructions;
		}

		private TranspilerBuilder Apply(Anchor anchor, Func<List<CodeInstruction>> emit, AnchorMatchMode mode, bool after)
		{
			List<int> list = Positions(anchor);
			List<int> list2 = Select(list, mode);
			if (list2 == null)
			{
				ReportAnchorError(anchor.Name, list.Count, mode);
				return this;
			}
			for (int num = list2.Count - 1; num >= 0; num--)
			{
				Instructions.InsertRange(list2[num] + (after ? 1 : 0), emit());
			}
			return this;
		}

		private List<int> Positions(Anchor anchor)
		{
			List<int> list = new List<int>();
			for (int i = 0; i < Instructions.Count; i++)
			{
				if (anchor.Matches(Instructions[i]))
				{
					list.Add(i);
				}
			}
			return list;
		}

		private static List<int> Select(List<int> positions, AnchorMatchMode mode)
		{
			if (!IsAcceptable(positions.Count, mode))
			{
				return null;
			}
			if (mode != AnchorMatchMode.First)
			{
				return positions;
			}
			return positions.GetRange(0, 1);
		}

		private static bool IsAcceptable(int count, AnchorMatchMode mode)
		{
			return mode switch
			{
				AnchorMatchMode.Single => count == 1, 
				AnchorMatchMode.All => count > 0, 
				AnchorMatchMode.First => count > 0, 
				AnchorMatchMode.Optional => count <= 1, 
				_ => false, 
			};
		}

		private void ReportAnchorError(string anchor, int anchorsCount, AnchorMatchMode mode)
		{
			Debug.LogError(anchorsCount switch
			{
				0 => _method + ": anchor '" + anchor + "' not found, skipping injection", 
				1 => $"{_method}: anchor '{anchor}' cannot be used ({mode}), skipping injection", 
				_ => $"{_method}: anchor '{anchor}' matched {anchorsCount} times ({mode}), skipping injection", 
			});
		}
	}
	public sealed class Anchor(string name, Func<CodeInstruction, bool> matches)
	{
		public string Name { get; } = name;

		public Func<CodeInstruction, bool> Matches { get; } = matches;
	}
	public static class UltrakillInstructions
	{
		private static readonly MethodInfo NewMovementGetHurt = AccessTools.Method(typeof(NewMovement), "GetHurt", new Type[7]
		{
			typeof(int),
			typeof(bool),
			typeof(float),
			typeof(bool),
			typeof(bool),
			typeof(float),
			typeof(bool)
		}, (Type[])null);

		public static readonly Anchor GetHurt = new Anchor("NewMovement::GetHurt", (CodeInstruction i) => i.opcode == OpCodes.Callvirt && CodeInstructionExtensions.OperandIs(i, (MemberInfo)NewMovementGetHurt));

		public static readonly Anchor ProjectileTarget = StoreTo(typeof(Projectile), "target", "targetHandle");

		public static readonly Anchor Instantiate = new Anchor("Object::Instantiate", (CodeInstruction i) => i.opcode == OpCodes.Call && i.operand is MethodInfo { Name: "Instantiate" } methodInfo && methodInfo.DeclaringType == typeof(Object));

		public static Anchor GetComponent(Type componentType)
		{
			return new Anchor("GetComponent<" + componentType.Name + ">", (CodeInstruction instruction) => instruction.opcode == OpCodes.Callvirt && instruction.operand is MethodInfo { Name: "GetComponent", IsGenericMethod: not false } methodInfo && methodInfo.GetGenericArguments()[0] == componentType);
		}

		public static Anchor CallTo(Type declaringType, string methodName)
		{
			return new Anchor(declaringType.Name + "::" + methodName, (CodeInstruction instruction) => instruction.opcode.IsOneOf(OpCodes.Call, OpCodes.Callvirt) && instruction.operand is MethodInfo methodInfo && methodInfo.Name == methodName && methodInfo.DeclaringType == declaringType);
		}

		public static Anchor StoreTo(Type declaringType, params string[] fields)
		{
			return new Anchor(declaringType.Name + "::" + string.Join("/", fields), delegate(CodeInstruction instruction)
			{
				if (instruction.opcode == OpCodes.Stfld && instruction.operand is FieldInfo fieldInfo && fieldInfo.DeclaringType == declaringType)
				{
					string name = fieldInfo.Name;
					object[] options = fields;
					return name.IsOneOf(options);
				}
				return false;
			});
		}
	}
}
namespace UKEnemyIdentifier.Patches
{
	[HarmonyPatch(typeof(BlackHoleProjectile))]
	public class BlackHoleProjectilePatch
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(BlackHoleProjectile), "OnTriggerEnter")]
		public static bool BlackHoleProjectile_OnTriggerEnter_Prefix(BlackHoleProjectile __instance, Collider other)
		{
			if (__instance.enemy && __instance.target != null && __instance.target.IsTargetTransform(((Component)other).gameObject.transform))
			{
				MonoSingleton<EnemyIdentifierManager>.Instance.LastHurtingFactor = ((Component)__instance).gameObject;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(CancerousRodent))]
	public class CancerousRodentPatch
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(CancerousRodent), "FireBurst")]
		public static IEnumerable<CodeInstruction> CancerousRodent_FireBurst_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return TranspilerBuilder.ForInstructions(instructions, __originalMethod).AfterStore(UltrakillInstructions.StoreTo(typeof(Projectile), "damage"), typeof(Projectile), EnemyIdentifierEmitters.RegisterHurtingFactor<CancerousRodent>, AnchorMatchMode.Single, 10).Build();
		}
	}
	[HarmonyPatch(typeof(Coin))]
	public class CoinPatch
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(Coin), "ShootAtPlayer")]
		public static IEnumerable<CodeInstruction> Coin_ShootAtPlayer_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return TranspilerBuilder.ForInstructions(instructions, __originalMethod).Before(UltrakillInstructions.GetHurt, EnemyIdentifierEmitters.LastHurtingFactor).Build();
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Coin), "SpawnBeam")]
		public static void Coin_SpawnBeam_Postfix(GameObject __result, EnemyIdentifier ___eid)
		{
			if (!((Object)(object)__result == (Object)null) && !((Object)(object)___eid == (Object)null))
			{
				MonoSingleton<EnemyIdentifierManager>.Instance.RegisterFactor(__result, ___eid);
			}
		}
	}
	[HarmonyPatch(typeof(ContinuousBeam))]
	public class ContinuousBeamPatch
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(ContinuousBeam), "Update")]
		public static IEnumerable<CodeInstruction> ContinuousBeam_Update_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return TranspilerBuilder.ForInstructions(instructions, __originalMethod).Before(UltrakillInstructions.GetHurt, EnemyIdentifierEmitters.LastHurtingFactor, AnchorMatchMode.Optional).Build();
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(ContinuousBeam), "FixedUpdate")]
		public static IEnumerable<CodeInstruction> ContinuousBeam_FixedUpdate_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return TranspilerBuilder.ForInstructions(instructions, __originalMethod).Before(UltrakillInstructions.GetHurt, EnemyIdentifierEmitters.LastHurtingFactor).Build();
		}
	}
	[HarmonyPatch(typeof(DroneFlesh))]
	public class DroneFleshPatch
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(DroneFlesh), "ShootBeam")]
		public static IEnumerable<CodeInstruction> DroneFlesh_ShootBeam_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return TranspilerBuilder.ForInstructions(instructions, __originalMethod).AfterLocalStore(typeof(GameObject), EnemyIdentifierEmitters.RegisterHurtingFactor<DroneFlesh>, AnchorMatchMode.First).Build();
		}
	}
	[HarmonyPatch(typeof(Drone))]
	public class DronePatch
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(Drone), "SetProjectileSettings")]
		public static void Drone_SetProjectileSettings_Postfix(Projectile proj, EnemyIdentifier ___eid)
		{
			MonoSingleton<EnemyIdentifierManager>.Instance.RegisterFactor(((Component)proj).gameObject, ___eid);
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(Drone), "ShootSecondary")]
		public static IEnumerable<CodeInstruction> Drone_ShootSecondary_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return TranspilerBuilder.ForInstructions(instructions, __originalMethod).AfterStore(UltrakillInstructions.StoreTo(typeof(Pincer), "firedMessageReceiver"), typeof(Pincer), RegisterPincerBeams).Build();
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(Drone), "Explode")]
		public static IEnumerable<CodeInstruction> Drone_Explode_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return TranspilerBuilder.ForInstructions(instructions, __originalMethod).AfterLocalStore(typeof(Explosion), SetExplosionOrigin).Build();
		}

		private static IEnumerable<CodeInstruction> RegisterPincerBeams(CodeInstruction pincerLoad, Type pincerType)
		{
			return ReflectionUtils.ToGameObject(pincerLoad, pincerType).Concat(ReflectionUtils.IL((OpCodes.Ldarg_0, null), (OpCodes.Ldfld, AccessTools.Field(typeof(Drone), "eid")), (OpCodes.Call, AccessTools.Method(typeof(DronePatch), "RegisterBeamFactors", new Type[2]
			{
				typeof(GameObject),
				typeof(EnemyIdentifier)
			}, (Type[])null))));
		}

		private static IEnumerable<CodeInstruction> SetExplosionOrigin(CodeInstruction explosionLoad, Type _)
		{
			return new List<CodeInstruction> { explosionLoad }.Concat(ReflectionUtils.IL((OpCodes.Ldarg_0, null), (OpCodes.Ldfld, AccessTools.Field(typeof(Drone), "eid")), (OpCodes.Stfld, AccessTools.Field(typeof(Explosion), "originEnemy"))));
		}

		private static void RegisterBeamFactors(GameObject pincer, EnemyIdentifier eid)
		{
			if (!((Object)(object)pincer == (Object)null) && !((Object)(object)eid == (Object)null))
			{
				RevolverBeam[] componentsInChildren = pincer.GetComponentsInChildren<RevolverBeam>(true);
				foreach (RevolverBeam val in componentsInChildren)
				{
					MonoSingleton<EnemyIdentifierManager>.Instance.RegisterFactor(((Component)val).gameObject, eid);
				}
				ContinuousBeam[] componentsInChildren2 = pincer.GetComponentsInChildren<ContinuousBeam>(true);
				foreach (ContinuousBeam val2 in componentsInChildren2)
				{
					MonoSingleton<EnemyIdentifierManager>.Instance.RegisterFactor(((Component)val2).gameObject, eid);
				}
			}
		}
	}
	[HarmonyPatch(typeof(EnemyNailgun))]
	public class EnemyNailgunPatch
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(EnemyNailgun), "FixedUpdate")]
		public static IEnumerable<CodeInstruction> EnemyNailgun_FixedUpdate_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return TranspilerBuilder.ForInstructions(instructions, __originalMethod).AfterLocalStore(typeof(GameObject), EnemyIdentifierEmitters.RegisterHurtingFactor<EnemyNailgun>, AnchorMatchMode.First).Build();
		}
	}
	[HarmonyPatch(typeof(EnemyRevolver))]
	public class EnemyRevolverPatch
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(EnemyRevolver), "Fire")]
		public static IEnumerable<CodeInstruction> EnemyRevolver_Fire_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
		{
			List<CodeInstruction> list = instructions.ToList();
			RegisterBullet(list, generator, AccessTools.Field(typeof(EnemyRevolver), "bullet"));
			SetRevolverHurtingFactor(list);
			return list;
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(EnemyRevolver), "AltFire")]
		public static IEnumerable<CodeInstruction> EnemyRevolver_AltFire_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
		{
			List<CodeInstruction> list = instructions.ToList();
			RegisterBullet(list, generator, AccessTools.Field(typeof(EnemyRevolver), "altBullet"));
			SetRevolverHurtingFactor(list);
			return list;
		}

		private static void RegisterBullet(List<CodeInstruction> instructions, ILGenerator generator, FieldInfo bulletField)
		{
			if (bulletField == null)
			{
				return;
			}
			for (int i = 0; i < instructions.Count; i++)
			{
				if (instructions[i].opcode != OpCodes.Ldfld || !CodeInstructionExtensions.OperandIs(instructions[i], (MemberInfo)bulletField))
				{
					continue;
				}
				int num = -1;
				for (int j = i + 1; j < instructions.Count && j <= i + 8; j++)
				{
					if (!(instructions[j].opcode != OpCodes.Call) && instructions[j].operand is MethodInfo methodInfo && !(methodInfo.Name != "Instantiate"))
					{
						num = j;
						break;
					}
				}
				if (num >= 0)
				{
					LocalBuilder item = generator.DeclareLocal(typeof(GameObject));
					instructions.InsertRange(num + 1, ReflectionUtils.IL((OpCodes.Stloc, item), (OpCodes.Ldloc, item), (OpCodes.Call, AccessTools.Method(typeof(EnemyIdentifierManager), "get_Instance", (Type[])null, (Type[])null)), (OpCodes.Ldloc, item), (OpCodes.Ldarg_0, null), (OpCodes.Ldfld, AccessTools.Field(typeof(EnemyRevolver), "eid")), (OpCodes.Callvirt, AccessTools.Method(typeof(EnemyIdentifierManager), "RegisterFactor", new Type[2]
					{
						typeof(GameObject),
						typeof(EnemyIdentifier)
					}, (Type[])null))));
				}
				break;
			}
		}

		private static void SetRevolverHurtingFactor(List<CodeInstruction> instructions)
		{
			IEnumerable<CodeInstruction> collection = ReflectionUtils.IL((OpCodes.Call, AccessTools.Method(typeof(EnemyIdentifierManager), "get_Instance", (Type[])null, (Type[])null)), (OpCodes.Ldloc_1, null), (OpCodes.Callvirt, AccessTools.Method(typeof(Component), "get_gameObject", (Type[])null, (Type[])null)), (OpCodes.Ldarg_0, null), (OpCodes.Ldfld, AccessTools.Field(typeof(EnemyRevolver), "eid")), (OpCodes.Callvirt, AccessTools.Method(typeof(EnemyIdentifierManager), "RegisterFactor", new Type[2]
			{
				typeof(GameObject),
				typeof(EnemyIdentifier)
			}, (Type[])null)));
			instructions.InsertRange(instructions.Count - 1, collection);
		}
	}
	[HarmonyPatch(typeof(EnemyShotgun))]
	public class EnemyShotgunPatch
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(EnemyShotgun), "Fire")]
		public static IEnumerable<CodeInstruction> EnemyShotgun_Fire_Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			LocalBuilder localBuilder = null;
			List<CodeInstruction> list = instructions.ToList();
			for (int i = 0; i < list.Count; i++)
			{
				if (ProjectileOperand(list[i]))
				{
					localBuilder = (LocalBuilder)list[i].operand;
				}
				if (FireInjectionPoint(list[i]))
				{
					if (localBuilder != null)
					{
						SetShotgunHurtingFactor(list, localBuilder, i);
					}
					break;
				}
			}
			return list;
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(EnemyShotgun), "AltFire")]
		public static IEnumerable<CodeInstruction> EnemyShotgun_AltFire_Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = instructions.ToList();
			for (int i = 0; i < list.Count; i++)
			{
				if (AltFireInjectionPoint(list[i]))
				{
					SetGrenadeHurtingFactor(list, i);
					break;
				}
			}
			return list;
		}

		private static bool FireInjectionPoint(CodeInstruction instruction)
		{
			if (instruction.opcode == OpCodes.Stfld)
			{
				return CodeInstructionExtensions.OperandIs(instruction, (MemberInfo)AccessTools.Field(typeof(Projectile), "spreaded"));
			}
			return false;
		}

		private static bool AltFireInjectionPoint(CodeInstruction instruction)
		{
			if (instruction.opcode == OpCodes.Stfld)
			{
				return CodeInstructionExtensions.OperandIs(instruction, (MemberInfo)AccessTools.Field(typeof(Grenade), "enemy"));
			}
			return false;
		}

		private static bool ProjectileOperand(CodeInstruction instruction)
		{
			if (instruction.opcode == OpCodes.Ldloc_S && instruction.operand is LocalBuilder localBuilder)
			{
				return localBuilder.LocalType == typeof(Projectile);
			}
			return false;
		}

		private static void SetShotgunHurtingFactor(List<CodeInstruction> instructions, LocalBuilder projectile, int index)
		{
			instructions.InsertRange(index, ReflectionUtils.IL((OpCodes.Call, AccessTools.Method(typeof(EnemyIdentifierManager), "get_Instance", (Type[])null, (Type[])null)), (OpCodes.Ldloc_S, projectile), (OpCodes.Callvirt, AccessTools.Method(typeof(Component), "get_gameObject", (Type[])null, (Type[])null)), (OpCodes.Ldarg_0, null), (OpCodes.Ldfld, AccessTools.Field(typeof(EnemyShotgun), "eid")), (OpCodes.Callvirt, AccessTools.Method(typeof(EnemyIdentifierManager), "RegisterFactor", new Type[2]
			{
				typeof(GameObject),
				typeof(EnemyIdentifier)
			}, (Type[])null))));
		}

		private static void SetGrenadeHurtingFactor(List<CodeInstruction> instructions, int index)
		{
			instructions.InsertRange(index, ReflectionUtils.IL((OpCodes.Ldloc_2, null), (OpCodes.Ldarg_0, null), (OpCodes.Ldfld, AccessTools.Field(typeof(EnemyShotgun), "eid")), (OpCodes.Stfld, AccessTools.Field(typeof(Grenade), "originEnemy"))));
		}
	}
	[HarmonyPatch(typeof(Explosion))]
	public class ExplosionPatch
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(Explosion), "Collide")]
		public static IEnumerable<CodeInstruction> Explosion_Collide_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return TranspilerBuilder.ForInstructions(instructions, __originalMethod).Before(UltrakillInstructions.GetHurt, EnemyIdentifierEmitters.LastHurtingFactor).Build();
		}
	}
	[HarmonyPatch(typeof(Ferryman))]
	public class FerrymanPatch
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(Ferryman), "SpawnLightningBolt")]
		public static IEnumerable<CodeInstruction> Ferryman_SpawnLightningBolt_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return TranspilerBuilder.ForInstructions(instructions, __originalMethod).AfterLocalStore(typeof(LightningStrikeExplosive), EnemyIdentifierEmitters.RegisterHurtingFactor<Ferryman>).Build();
		}
	}
	[HarmonyPatch(typeof(FireZone))]
	public class FireZonePatch
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(FireZone), "OnTriggerStay")]
		public static IEnumerable<CodeInstruction> FireZone_OnTriggerStay_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return TranspilerBuilder.ForInstructions(instructions, __originalMethod).Before(UltrakillInstructions.GetHurt, EnemyIdentifierEmitters.LastHurtingFactor).Build();
		}
	}
	[HarmonyPatch(typeof(FleshPrison))]
	public class FleshPrisonPatch
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(FleshPrison), "Update")]
		public static IEnumerable<CodeInstruction> FleshPrison_Update_Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = instructions.ToList();
			for (int i = 0; i < list.Count; i++)
			{
				if (!(list[i].opcode != OpCodes.Stloc_S) && list[i].operand is LocalBuilder && ((LocalBuilder)list[i].operand).LocalIndex == 11)
				{
					LocalBuilder projectile = (LocalBuilder)list[i].operand;
					SetProjectileHurtingFactor(list, projectile, i + 1);
					break;
				}
			}
			return list;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(FleshPrison), "SpawnBlackHole")]
		public static void FleshPrison_SpawnBlackHole_Postfix(FleshPrison __instance, BlackHoleProjectile ___currentBlackHole, EnemyIdentifier ___eid)
		{
			MonoSingleton<EnemyIdentifierManager>.Instance.RegisterFactor(((Component)___currentBlackHole).gameObject, ___eid);
		}

		private static void SetProjectileHurtingFactor(List<CodeInstruction> instructions, LocalBuilder projectile, int index)
		{
			instructions.InsertRange(index, ReflectionUtils.IL((OpCodes.Call, AccessTools.Method(typeof(EnemyIdentifierManager), "get_Instance", (Type[])null, (Type[])null)), (OpCodes.Ldloc_S, projectile), (OpCodes.Ldarg_0, null), (OpCodes.Ldfld, AccessTools.Field(typeof(FleshPrison), "eid")), (OpCodes.Callvirt, AccessTools.Method(typeof(EnemyIdentifierManager), "RegisterFactor", new Type[2]
			{
				typeof(GameObject),
				typeof(EnemyIdentifier)
			}, (Type[])null))));
		}
	}
	[HarmonyPatch(typeof(GabrielBase))]
	public class GabrielBasePatch
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(GabrielSecond), "ThrowSwords")]
		public static void GabrielSecond_ThrowSwords_Postfix(GabrielSecond __instance)
		{
			GabrielBase gabe = __instance.gabe;
			if (!((Object)(object)gabe == (Object)null) && !((Object)(object)gabe.currentCombinedSwordsThrown == (Object)null) && !((Object)(object)gabe.eid == (Object)null))
			{
				MonoSingleton<EnemyIdentifierManager>.Instance.RegisterFactor(((Component)gabe.currentCombinedSwordsThrown).gameObject, gabe.eid);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(GabrielBase), "SpawnSummonedSwords")]
		public static void GabrielBase_SpawnSummonedSwords_Postfix(GabrielBase __instance, GameObject ___currentSwords)
		{
			if (!((Object)(object)___currentSwords == (Object)null) && !((Object)(object)__instance.eid == (Object)null))
			{
				Projectile[] componentsInChildren = ___currentSwords.GetComponentsInChildren<Projectile>();
				foreach (Projectile val in componentsInChildren)
				{
					MonoSingleton<EnemyIdentifierManager>.Instance.RegisterFactor(((Component)val).gameObject, __instance.eid);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Gabriel))]
	public class GabrielPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(Gabriel), "ThrowWeapon")]
		public static void Gabriel_ThrowWeapon_Postfix(Gabriel __instance, GameObject ___thrownObject)
		{
			GabrielBase component = ((Component)__instance).GetComponent<GabrielBase>();
			Projectile[] componentsInChildren = ___thrownObject.GetComponentsInChildren<Projectile>();
			foreach (Projectile val in componentsInChildren)
			{
				MonoSingleton<EnemyIdentifierManager>.Instance.RegisterFactor(((Component)val).gameObject, component.eid);
			}
		}
	}
	[HarmonyPatch(typeof(GroundWave))]
	public class GroundWavePatch
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(GroundWave), "Start")]
		public static void GroundWave_Start_Postfix(HurtZone ___hurtzone, EnemyIdentifier ___eid)
		{
			if (!((Object)(object)___hurtzone == (Object)null) && !((Object)(object)___eid == (Object)null))
			{
				MonoSingleton<EnemyIdentifierManager>.Instance.RegisterFactor(((Component)___hurtzone).gameObject, ___eid);
			}
		}
	}
	[HarmonyPatch(typeof(Gutterman))]
	public class GuttermanPatch
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(Gutterman), "FixedUpdate")]
		public static IEnumerable<CodeInstruction> Gutterman_FixedUpdate_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod, ILGenerator generator)
		{
			return TranspilerBuilder.ForInstructions(instructions, __originalMethod, generator).AfterStack(UltrakillInstructions.Instantiate, typeof(GameObject), EnemyIdentifierEmitters.RegisterHurtingFactor<Gutterman>).Build();
		}
	}
	[HarmonyPatch(typeof(HurtZone))]
	public class HurtZonePatch
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(HurtZone), "FixedUpdate")]
		public static IEnumerable<CodeInstruction> HurtZone_FixedUpdate_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return TranspilerBuilder.ForInstructions(instructions, __originalMethod).Before(UltrakillInstructions.GetHurt, EnemyIdentifierEmitters.LastHurtingFactor, AnchorMatchMode.All).Build();
		}
	}
	[HarmonyPatch(typeof(LightningStrikeExplosive))]
	public class LightningStrikeExplosivePatch
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(LightningStrikeExplosive), "Start")]
		public static IEnumerable<CodeInstruction> LightningStrikeExplosive_Start_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return TranspilerBuilder.ForInstructions(instructions, __originalMethod).AfterLocalStore(typeof(Explosion), (CodeInstruction explosionLoad, Type _) => EnemyIdentifierEmitters.RegisterExplosion(explosionLoad), AnchorMatchMode.First).Build();
		}
	}
	[HarmonyPatch(typeof(MaliciousFace))]
	public class MaliciousFacePatch
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(MaliciousFace), "ShootProj")]
		public static void MaliciousFace_ShootProj_Postfix(GameObject ___currentProj, EnemyIdentifier ___eid)
		{
			if (!((Object)(object)___currentProj == (Object)null) && !((Object)(object)___eid == (Object)null))
			{
				MonoSingleton<EnemyIdentifierManager>.Instance.RegisterFactor(___currentProj, ___eid);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(MaliciousFace), "BeamFire")]
		public static void MaliciousFace_BeamFire_Postfix(GameObject ___currentBeam, EnemyIdentifier ___eid)
		{
			RevolverBeam val = default(RevolverBeam);
			if (!((Object)(object)___currentBeam == (Object)null) && !((Object)(object)___eid == (Object)null) && ___currentBeam.TryGetComponent<RevolverBeam>(ref val))
			{
				MonoSingleton<EnemyIdentifierManager>.Instance.RegisterFactor(((Component)val).gameObject, ___eid);
			}
		}
	}
	[HarmonyPatch(typeof(Mandalore))]
	public class MandalorePatch
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(Mandalore), "FullBurst")]
		public static IEnumerable<CodeInstruction> Mandalore_FullBurst_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
		{
			List<CodeInstruction> list = instructions.ToList();
			for (int i = 0; i < list.Count; i++)
			{
				if (FullAutoInjectionPoint(list[i]))
				{
					SetFullAutoHurtingFactor(list, i + 2, generator);
					break;
				}
			}
			return list;
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(Mandalore), "FullerBurst")]
		public static IEnumerable<CodeInstruction> Mandalore_FullerBurst_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
		{
			List<CodeInstruction> list = instructions.ToList();
			for (int i = 0; i < list.Count; i++)
			{
				if (FullerAutoInjectionPoint(list[i]))
				{
					SetFullerAutoHurtingFactor(list, i + 2, generator);
					break;
				}
			}
			return list;
		}

		private static bool FullAutoInjectionPoint(CodeInstruction instruction)
		{
			if (instruction.opcode == OpCodes.Stfld)
			{
				return CodeInstructionExtensions.OperandIs(instruction, (MemberInfo)AccessTools.Field(typeof(Projectile), "precheckForCollisions"));
			}
			return false;
		}

		private static bool FullerAutoInjectionPoint(CodeInstruction instruction)
		{
			if (instruction.opcode == OpCodes.Stfld)
			{
				return CodeInstructionExtensions.OperandIs(instruction, (MemberInfo)AccessTools.Field(typeof(Projectile), "safeEnemyType"));
			}
			return false;
		}

		private static void SetFullAutoHurtingFactor(List<CodeInstruction> instructions, int index, ILGenerator generator)
		{
			LocalBuilder item = generator.DeclareLocal(typeof(Projectile));
			instructions.InsertRange(index, ReflectionUtils.IL((OpCodes.Stloc_S, item), (OpCodes.Call, AccessTools.Method(typeof(EnemyIdentifierManager), "get_Instance", (Type[])null, (Type[])null)), (OpCodes.Ldloc_S, item), (OpCodes.Callvirt, AccessTools.Method(typeof(Component), "get_gameObject", (Type[])null, (Type[])null)), (OpCodes.Ldarg_0, null), (OpCodes.Ldfld, AccessTools.Field(typeof(Mandalore), "eid")), (OpCodes.Callvirt, AccessTools.Method(typeof(EnemyIdentifierManager), "RegisterFactor", new Type[2]
			{
				typeof(GameObject),
				typeof(EnemyIdentifier)
			}, (Type[])null)), (OpCodes.Dup, null)));
		}

		private static void SetFullerAutoHurtingFactor(List<CodeInstruction> instructions, int index, ILGenerator generator)
		{
			LocalBuilder item = generator.DeclareLocal(typeof(Projectile));
			instructions.InsertRange(index, ReflectionUtils.IL((OpCodes.Stloc_S, item), (OpCodes.Call, AccessTools.Method(typeof(EnemyIdentifierManager), "get_Instance", (Type[])null, (Type[])null)), (OpCodes.Ldloc_S, item), (OpCodes.Callvirt, AccessTools.Method(typeof(Component), "get_gameObject", (Type[])null, (Type[])null)), (OpCodes.Ldarg_0, null), (OpCodes.Ldfld, AccessTools.Field(typeof(Mandalore), "eid")), (OpCodes.Callvirt, AccessTools.Method(typeof(EnemyIdentifierManager), "RegisterFactor", new Type[2]
			{
				typeof(GameObject),
				typeof(EnemyIdentifier)
			}, (Type[])null)), (OpCodes.Dup, null)));
		}
	}
	[HarmonyPatch(typeof(Mannequin))]
	public class MannequinPatch
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(Mannequin), "ShootProjectile")]
		public static IEnumerable<CodeInstruction> Mannequin_ShootProjectile_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return TranspilerBuilder.ForInstructions(instructions, __originalMethod).AfterStore(UltrakillInstructions.ProjectileTarget, typeof(Projectile), EnemyIdentifierEmitters.RegisterHurtingFactor<Mannequin>).Build();
		}
	}
	[HarmonyPatch(typeof(Mass))]
	public class MassPatch
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(Mass), "SlamImpact")]
		private static IEnumerable<CodeInstruction> Mass_SlamImpact_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return TranspilerBuilder.ForInstructions(instructions, __originalMethod).AfterLocalStore(typeof(PhysicalShockwave), EnemyIdentifierEmitters.RegisterHurtingFactor<Mass>, AnchorMatchMode.First).Build();
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(Mass), "SwingEnd")]
		private static IEnumerable<CodeInstruction> Mass_SwingEnd_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod, ILGenerator generator)
		{
			return TranspilerBuilder.ForInstructions(instructions, __originalMethod, generator).AfterStack(UltrakillInstructions.GetComponent(typeof(PhysicalShockwave)), typeof(PhysicalShockwave), EnemyIdentifierEmitters.RegisterHurtingFactor<Mass>, AnchorMatchMode.First).Build();
		}
	}
	[HarmonyPatch]
	internal static class MassShootProjectilePatch
	{
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(Mass), "ShootProjectile", (Type[])null, (Type[])null);
		}

		[HarmonyPrepare]
		public static bool Prepare()
		{
			return TargetMethod() != null;
		}

		[HarmonyTranspiler]
		public static IEnumerable<CodeInstruction> Mass_ShootProjectile_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return TranspilerBuilder.ForInstructions(instructions, __originalMethod).AfterStore(UltrakillInstructions.ProjectileTarget, typeof(Projectile), EnemyIdentifierEmitters.RegisterHurtingFactor<Mass>).Build();
		}
	}
	[HarmonyPatch(typeof(MassSpear))]
	public class MassSpearPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(MassSpear), "DelayedPlayerCheck")]
		private static bool Mass_ShootHoming_Prefix(bool ___deflected, MassSpear __instance)
		{
			if (___deflected)
			{
				return false;
			}
			MonoSingleton<EnemyIdentifierManager>.Instance.LastHurtingFactor = ((Component)__instance).gameObject;
			return true;
		}
	}
	[HarmonyPatch(typeof(Mindflayer))]
	public class MindflayerPatch
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(Mindflayer), "ShootProjectiles")]
		public static IEnumerable<CodeInstruction> Mindflayer_ShootProjectiles_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return TranspilerBuilder.ForInstructions(instructions, __originalMethod).AfterStore(UltrakillInstructions.ProjectileTarget, typeof(Projectile), EnemyIdentifierEmitters.RegisterHurtingFactor<Mindflayer>, AnchorMatchMode.All, 10).Build();
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Mindflayer), "StartBeam")]
		public static void Mindflayer_StartBeam_Postfix(EnemyIdentifier ___eid, Mindflayer __instance)
		{
			ContinuousBeam val = default(ContinuousBeam);
			if (((Component)__instance.tempBeam).TryGetComponent<ContinuousBeam>(ref val))
			{
				MonoSingleton<EnemyIdentifierManager>.Instance.RegisterFactor(((Component)val).gameObject, ___eid);
			}
		}
	}
	[HarmonyPatch(typeof(MinosPrime))]
	public class MinosPrimePatch
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(MinosPrime), "AirRaycastAttack")]
		public static IEnumerable<CodeInstruction> MinosPrime_AirRaycastAttack_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return TranspilerBuilder.ForInstructions(instructions, __originalMethod).Before(UltrakillInstructions.GetHurt, EnemyIdentifierEmitters.LastHurtingFactor).AfterStore(UltrakillInstructions.StoreTo(typeof(PhysicalShockwave), "damage"), typeof(PhysicalShockwave), EnemyIdentifierEmitters.RegisterHurtingFactor<MinosPrime>, AnchorMatchMode.Single, 10)
				.Build();
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(MinosPrime), "ProjectileShoot")]
		public static IEnumerable<CodeInstruction> MinosPrime_ProjectileShoot_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return TranspilerBuilder.ForInstructions(instructions, __originalMethod).AfterStore(UltrakillInstructions.ProjectileTarget, typeof(Projectile), EnemyIdentifierEmitters.RegisterHurtingFactor<MinosPrime>, AnchorMatchMode.Single, 12).Build();
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(MinosPrime), "Start")]
		public static void MinosPrime_Start_Postfix(MinosPrime __instance, EnemyIdentifier ___eid)
		{
			Explosion[] componentsInChildren = __instance.explosion.GetComponentsInChildren<Explosion>();
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].originEnemy = ___eid;
			}
		}
	}
	[HarmonyPatch(typeof(Minotaur))]
	public class MinotaurPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(Minotaur), "Start")]
		public static void Minotaur_Start_Postfix(GameObject ___hammerExplosion, GameObject ___hammerBigExplosion, EnemyIdentifier ___eid)
		{
			Explosion[] componentsInChildren = ___hammerExplosion.GetComponentsInChildren<Explosion>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].originEnemy = ___eid;
			}
			componentsInChildren = ___hammerBigExplosion.GetComponentsInChildren<Explosion>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].originEnemy = ___eid;
			}
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(Minotaur), "MeatSplash")]
		public static IEnumerable<CodeInstruction> Minotaur_MeatSplash_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return TranspilerBuilder.ForInstructions(instructions, __originalMethod).Before(UltrakillInstructions.CallTo(typeof(Transform), "SetParent"), EnemyIdentifierEmitters.LastHurtingFactor).Build();
		}
	}
	[HarmonyPatch(typeof(MirrorReaper))]
	public class MirrorReaperPatch
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(MirrorReaper), "SpawnProjectiles")]
		public static IEnumerable<CodeInstruction> MirrorReaper_SpawnProjectiles_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return TranspilerBuilder.ForInstructions(instructions, __originalMethod).AfterStore(UltrakillInstructions.ProjectileTarget, typeof(Projectile), EnemyIdentifierEmitters.RegisterHurtingFactor<MirrorReaper>).Build();
		}
	}
	[HarmonyPatch(typeof(MortarLauncher))]
	public class MortarLauncherPatch
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(MortarLauncher), "ShootHoming")]
		public static IEnumerable<CodeInstruction> MortarLauncher_ShootHoming_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
		{
			List<CodeInstruction> list = instructions.ToList();
			for (int i = 0; i < list.Count; i++)
			{
				if (InjectionPoint(list[i]))
				{
					SetProjectileHurtingFactor(list, i + 2, generator);
					break;
				}
			}
			return list;
		}

		private static bool InjectionPoint(CodeInstruction instruction)
		{
			if (instruction.opcode == OpCodes.Stfld)
			{
				return CodeInstructionExtensions.OperandIs(instruction, (MemberInfo)AccessTools.Field(typeof(Projectile), "damage"));
			}
			return false;
		}

		private static void SetProjectileHurtingFactor(List<CodeInstruction> instructions, int index, ILGenerator generator)
		{
			LocalBuilder item = generator.DeclareLocal(typeof(Projectile));
			instructions.InsertRange(index, ReflectionUtils.IL((OpCodes.Stloc_S, item), (OpCodes.Call, AccessTools.Method(typeof(EnemyIdentifierManager), "get_Instance", (Type[])null, (Type[])null)), (OpCodes.Ldloc_S, item), (OpCodes.Callvirt, AccessTools.Method(typeof(Component), "get_gameObject", (Type[])null, (Type[])null)), (OpCodes.Ldarg_0, null), (OpCodes.Ldfld, AccessTools.Field(typeof(MortarLauncher), "eid")), (OpCodes.Callvirt, AccessTools.Method(typeof(EnemyIdentifierManager), "RegisterFactor", new Type[2]
			{
				typeof(GameObject),
				typeof(EnemyIdentifier)
			}, (Type[])null)), (OpCodes.Dup, null)));
		}
	}
	[HarmonyPatch(typeof(Nail))]
	public class NailPatch
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(Nail), "OnCollisionEnter")]
		public static IEnumerable<CodeInstruction> Nail_OnCollisionEnter_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return TranspilerBuilder.ForInstructions(instructions, __originalMethod).Before(UltrakillInstructions.GetHurt, EnemyIdentifierEmitters.LastHurtingFactor).Build();
		}
	}
	[HarmonyPatch(typeof(NewMovement))]
	public class NewMovementPatch
	{
		public struct NewMovementPatchState
		{
			public bool Invincible;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(NewMovement), "GetHurt")]
		public static void NewMovement_GetHurt_Postfix(NewMovement __instance, NewMovementPatchState __state, int damage)
		{
			try
			{
				EnemyIdentifierManager instance = MonoSingleton<EnemyIdentifierManager>.Instance;
				if (!instance.DeadAlready && damage != 0 && !__state.Invincible)
				{
					EnemyIdentifier eid = instance.IdentifyEnemy();
					bool flag = __instance.hp == 0;
					if (flag)
					{
						instance.DeadAlready = true;
					}
					instance.PlayerHurt(eid, damage, flag);
				}
			}
			catch (Exception)
			{
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(NewMovement), "Respawn")]
		public static void NewMovement_Respawn_Prefix(NewMovement __instance)
		{
			EnemyIdentifierManager instance = MonoSingleton<EnemyIdentifierManager>.Instance;
			if (instance != null)
			{
				instance.DeadAlready = false;
			}
		}
	}
	[HarmonyPatch(typeof(Explosion))]
	public class PhysicalShockwavePatch
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(PhysicalShockwave), "CheckCollision")]
		public static bool PhysicalShockwave_CheckCollision_Prefix(Collider col, PhysicalShockwave __instance)
		{
			if (!__instance.hasHurtPlayer && ((Component)col).gameObject.layer != 15 && ((Component)col).gameObject.CompareTag("Player"))
			{
				MonoSingleton<EnemyIdentifierManager>.Instance.LastHurtingFactor = ((Component)__instance).gameObject;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Power))]
	public class PowerPatch
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(Power), "ThrowSpear")]
		public static IEnumerable<CodeInstruction> Power_ThrowSpear_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return TranspilerBuilder.ForInstructions(instructions, __originalMethod).AfterLocalStore(typeof(Projectile), EnemyIdentifierEmitters.RegisterHurtingFactor<Power>, AnchorMatchMode.First).Build();
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(Power), "ThrowSpinner")]
		public static IEnumerable<CodeInstruction> Power_ThrowSpinner_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return TranspilerBuilder.ForInstructions(instructions, __originalMethod).AfterLocalStore(typeof(Projectile), EnemyIdentifierEmitters.RegisterHurtingFactor<Power>, AnchorMatchMode.First).Build();
		}
	}
	[HarmonyPatch(typeof(Projectile))]
	public class ProjectilePatch
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(Projectile), "TimeToDie")]
		public static bool Projectile_TimeToDie_Prefix(Projectile __instance)
		{
			MonoSingleton<EnemyIdentifierManager>.Instance.LastHurtingFactor = ((Component)__instance).gameObject;
			return true;
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(Projectile), "Explode")]
		public static IEnumerable<CodeInstruction> Projectile_Explode_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod, ILGenerator generator)
		{
			return PatchExplosions(instructions, __originalMethod, generator);
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(Projectile), "CreateExplosionEffect")]
		public static IEnumerable<CodeInstruction> Projectile_CreateExplosionEffect_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod, ILGenerator generator)
		{
			return PatchExplosions(instructions, __originalMethod, generator);
		}

		private static IEnumerable<CodeInstruction> PatchExplosions(IEnumerable<CodeInstruction> instructions, MethodBase originalMethod, ILGenerator generator)
		{
			return TranspilerBuilder.ForInstructions(instructions, originalMethod, generator).AfterStack(UltrakillInstructions.Instantiate, typeof(GameObject), RegisterEffectZones).AfterLocalStore(typeof(Explosion), SetExplosionOrigin, AnchorMatchMode.Optional)
				.Build();
		}

		private static IEnumerable<CodeInstruction> RegisterEffectZones(LocalBuilder effect, Type _)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			return new List<CodeInstruction>
			{
				new CodeInstruction(OpCodes.Ldloc, (object)effect)
			}.Concat(ReflectionUtils.IL((OpCodes.Call, AccessTools.Method(typeof(EnemyIdentifierManager), "get_Instance", (Type[])null, (Type[])null)), (OpCodes.Ldarg_0, null), (OpCodes.Callvirt, AccessTools.Method(typeof(EnemyIdentifierManager), "GetIdentifierFor", new Type[1] { typeof(Component) }, (Type[])null)), (OpCodes.Call, AccessTools.Method(typeof(ProjectilePatch), "RegisterEffectZones", new Type[2]
			{
				typeof(GameObject),
				typeof(EnemyIdentifier)
			}, (Type[])null))));
		}

		private static IEnumerable<CodeInstruction> SetExplosionOrigin(CodeInstruction explosionLoad, Type _)
		{
			return new List<CodeInstruction> { explosionLoad }.Concat(ReflectionUtils.IL((OpCodes.Call, AccessTools.Method(typeof(EnemyIdentifierManager), "get_Instance", (Type[])null, (Type[])null)), (OpCodes.Ldarg_0, null), (OpCodes.Callvirt, AccessTools.Method(typeof(EnemyIdentifierManager), "GetIdentifierFor", new Type[1] { typeof(Component) }, (Type[])null)), (OpCodes.Stfld, AccessTools.Field(typeof(Explosion), "originEnemy"))));
		}

		private static void RegisterEffectZones(GameObject effect, EnemyIdentifier eid)
		{
			if (!((Object)(object)effect == (Object)null) && !((Object)(object)eid == (Object)null))
			{
				HurtZone[] componentsInChildren = effect.GetComponentsInChildren<HurtZone>(true);
				foreach (HurtZone val in componentsInChildren)
				{
					MonoSingleton<EnemyIdentifierManager>.Instance.RegisterFactor(((Component)val).gameObject, eid);
				}
			}
		}
	}
	[HarmonyPatch(typeof(ProjectileSpread))]
	public class ProjectileSpreadPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(ProjectileSpread), "Start")]
		private static bool ProjectileSpread_Start_Prefix(ProjectileSpread __instance, ref EnemyIdentifier __state)
		{
			EnemyIdentifier identifierFor = MonoSingleton<EnemyIdentifierManager>.Instance.GetIdentifierFor((Component)(object)((Component)__instance).GetComponentInChildren<Projectile>());
			if ((Object)(object)identifierFor != (Object)null)
			{
				__state = identifierFor;
			}
			return true;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ProjectileSpread), "Start")]
		private static void ProjectileSpread_Start_Postfix(ProjectileSpread __instance, EnemyIdentifier __state)
		{
			if (!((Object)(object)__state == (Object)null))
			{
				Projectile[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<Projectile>();
				foreach (Projectile val in componentsInChildren)
				{
					MonoSingleton<EnemyIdentifierManager>.Instance.RegisterFactor(((Component)val).gameObject, __state);
				}
			}
		}
	}
	[HarmonyPatch(typeof(RevolverBeam))]
	public class RevolverBeamPatch
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(RevolverBeam), "ExecuteHits")]
		public static IEnumerable<CodeInstruction> RevolverBeam_ExecuteHits_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return TranspilerBuilder.ForInstructions(instructions, __originalMethod).Before(UltrakillInstructions.GetHurt, EnemyIdentifierEmitters.LastHurtingFactor).Build();
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(RevolverBeam), "HitSomething")]
		public static IEnumerable<CodeInstruction> RevolverBeam_HitSomething_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return TranspilerBuilder.ForInstructions(instructions, __originalMethod).AfterLocalStore(typeof(Explosion), (CodeInstruction explosionLoad, Type _) => EnemyIdentifierEmitters.RegisterExplosion(explosionLoad), AnchorMatchMode.All).Build();
		}
	}
	[HarmonyPatch(typeof(Sisyphus))]
	public class SisyphusPatch
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(Sisyphus), "FixedUpdate")]
		public static IEnumerable<CodeInstruction> StatueBoss_FixedUpdate_Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = instructions.ToList();
			for (int i = 0; i < list.Count; i++)
			{
				if (LandingWaveInjectionPoint(list[i]))
				{
					SetWaveHurtingFactor(list, i + 1);
					break;
				}
			}
			return list;
		}

		private static bool LandingWaveInjectionPoint(CodeInstruction instruction)
		{
			if (instruction.opcode == OpCodes.Stfld)
			{
				return CodeInstructionExtensions.OperandIs(instruction, (MemberInfo)AccessTools.Field(typeof(PhysicalShockwave), "speed"));
			}
			return false;
		}

		private static void SetWaveHurtingFactor(List<CodeInstruction> instructions, int index)
		{
			instructions.InsertRange(index, ReflectionUtils.IL((OpCodes.Call, AccessTools.Method(typeof(EnemyIdentifierManager), "get_Instance", (Type[])null, (Type[])null)), (OpCodes.Ldloc_2, null), (OpCodes.Callvirt, AccessTools.Method(typeof(Component), "get_gameObject", (Type[])null, (Type[])null)), (OpCodes.Ldarg_0, null), (OpCodes.Ldfld, AccessTools.Field(typeof(Sisyphus), "eid")), (OpCodes.Callvirt, AccessTools.Method(typeof(EnemyIdentifierManager), "RegisterFactor", new Type[2]
			{
				typeof(GameObject),
				typeof(EnemyIdentifier)
			}, (Type[])null))));
		}
	}
	[HarmonyPatch(typeof(SisyphusPrime))]
	public class SisyphusPrimePatch
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(SisyphusPrime), "CreateShockwave")]
		public static void SisyphusPrime_CreateShockwave_Postfix(EnemyIdentifier ___eid, ref PhysicalShockwave __result)
		{
			MonoSingleton<EnemyIdentifierManager>.Instance.RegisterFactor(((Component)__result).gameObject, ___eid);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(SisyphusPrime), "Start")]
		public static void SisyphusPrime_Start_Postfix(SisyphusPrime __instance, EnemyIdentifier ___eid)
		{
			Explosion[] componentsInChildren = __instance.explosion.GetComponentsInChildren<Explosion>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].originEnemy = ___eid;
			}
			componentsInChildren = __instance.sparkleExplosion.GetComponentsInChildren<Explosion>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].originEnemy = ___eid;
			}
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(SisyphusPrime), "DropAttackActivate")]
		public static IEnumerable<CodeInstruction> SisyphusPrime_DropAttackActivate_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return TranspilerBuilder.ForInstructions(instructions, __originalMethod).Before(UltrakillInstructions.GetHurt, EnemyIdentifierEmitters.LastHurtingFactor).AfterStore(UltrakillInstructions.StoreTo(typeof(PhysicalShockwave), "damage"), typeof(PhysicalShockwave), EnemyIdentifierEmitters.RegisterHurtingFactor<SisyphusPrime>, AnchorMatchMode.Single, 10)
				.Build();
		}
	}
	[HarmonyPatch(typeof(StatueBoss))]
	public class StatueBossPatch
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(StatueBoss), "OrbSpawn")]
		public static IEnumerable<CodeInstruction> StatueBoss_OrbSpawn_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return RegisterAfter(instructions, __originalMethod, (CodeInstruction instruction) => instruction.opcode == OpCodes.Stfld && CodeInstructionExtensions.OperandIs(instruction, (MemberInfo)AccessTools.Field(typeof(Projectile), "target")), typeof(Projectile));
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(StatueBoss), "StompHit")]
		public static IEnumerable<CodeInstruction> StatueBoss_StompHit_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return RegisterAfter(instructions, __originalMethod, (CodeInstruction instruction) => instruction.opcode == OpCodes.Stfld && CodeInstructionExtensions.OperandIs(instruction, (MemberInfo)AccessTools.Field(typeof(PhysicalShockwave), "enemyType")), typeof(PhysicalShockwave));
		}

		private static IEnumerable<CodeInstruction> RegisterAfter(IEnumerable<CodeInstruction> instructions, MethodBase originalMethod, Func<CodeInstruction, bool> storePredicate, Type spawnedType)
		{
			List<CodeInstruction> list = instructions.ToList();
			CodeInstruction val = null;
			Type localType = null;
			for (int i = 0; i < list.Count; i++)
			{
				if (ReflectionUtils.IsLdloc(list[i]))
				{
					Type type = ReflectionUtils.LocalType(originalMethod, ReflectionUtils.GetLocalIndex(list[i]));
					if (type != null && spawnedType.IsAssignableFrom(type))
					{
						val = list[i];
						localType = type;
					}
				}
				if (storePredicate(list[i]) && val != null)
				{
					CodeInstruction val2 = ReflectionUtils.MirrorLdloc(val);
					if (val2 != null)
					{
						list.InsertRange(i + 1, ReflectionUtils.IL((OpCodes.Call, AccessTools.Method(typeof(EnemyIdentifierManager), "get_Instance", (Type[])null, (Type[])null))).Concat(ReflectionUtils.ToGameObject(val2, localType)).Concat(ReflectionUtils.IL((OpCodes.Ldarg_0, null), (OpCodes.Ldfld, AccessTools.Field(typeof(StatueBoss), "eid")), (OpCodes.Callvirt, AccessTools.Method(typeof(EnemyIdentifierManager), "RegisterFactor", new Type[2]
						{
							typeof(GameObject),
							typeof(EnemyIdentifier)
						}, (Type[])null)))));
					}
					break;
				}
			}
			return list;
		}
	}
	[HarmonyPatch(typeof(SwingCheck2))]
	public class SwingCheck2Patch
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(SwingCheck2), "CheckCollision")]
		public static IEnumerable<CodeInstruction> SwingCheck2_CheckCollision_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return TranspilerBuilder.ForInstructions(instructions, __originalMethod).Before(UltrakillInstructions.GetHurt, EnemyIdentifierEmitters.LastHurtingFactor).Build();
		}
	}
	[HarmonyPatch(typeof(Turret))]
	public class TurretPatch
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(Turret), "Shoot")]
		public static IEnumerable<CodeInstruction> Turret_Shoot_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return TranspilerBuilder.ForInstructions(instructions, __originalMethod).AfterStore(UltrakillInstructions.StoreTo(typeof(RevolverBeam), "target"), typeof(RevolverBeam), EnemyIdentifierEmitters.RegisterHurtingFactor<Turret>).Build();
		}
	}
	[HarmonyPatch(typeof(V2))]
	public class V2Patch
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(V2), "ThrowCoins")]
		public static IEnumerable<CodeInstruction> V2_ThrowCoins_Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = instructions.ToList();
			for (int i = 0; i < list.Count; i++)
			{
				if (InjectionPoint(list[i]))
				{
					SetCoinEnemyId(list, i + 9);
					break;
				}
			}
			return list;
		}

		private static bool InjectionPoint(CodeInstruction instruction)
		{
			if (instruction.opcode == OpCodes.Ldfld)
			{
				return CodeInstructionExtensions.OperandIs(instruction, (MemberInfo)AccessTools.Field(typeof(Coin), "flash"));
			}
			return false;
		}

		private static void SetCoinEnemyId(List<CodeInstruction> instructions, int index)
		{
			instructions.InsertRange(index, ReflectionUtils.IL((OpCodes.Ldloc_2, null), (OpCodes.Ldarg_0, null), (OpCodes.Ldfld, AccessTools.Field(typeof(V2), "eid")), (OpCodes.Stfld, AccessTools.Field(typeof(Coin), "eid"))));
		}
	}
	[HarmonyPatch(typeof(VirtueInsignia))]
	public class VirtueInsigniaPatch
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(VirtueInsignia), "OnTriggerEnter")]
		public static IEnumerable<CodeInstruction> VirtueInsignia_OnTriggerEnter_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return TranspilerBuilder.ForInstructions(instructions, __originalMethod).Before(UltrakillInstructions.GetHurt, EnemyIdentifierEmitters.LastHurtingFactor).Build();
		}
	}
	[HarmonyPatch(typeof(ZombieProjectiles))]
	public class ZombieProjectilesPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(ZombieProjectiles), "ThrowProjectile")]
		public static void ZombieProjectiles_ThrowProjectile_Postfix(GameObject ___currentProjectile, EnemyIdentifier ___eid, ZombieProjectiles __instance)
		{
			Projectile componentInChildren = ___currentProjectile.gameObject.GetComponentInChildren<Projectile>();
			if ((Object)(object)componentInChildren == (Object)null)
			{
				return;
			}
			MonoSingleton<EnemyIdentifierManager>.Instance.RegisterFactor(((Component)componentInChildren).gameObject, ___eid);
			ProjectileSpread val = default(ProjectileSpread);
			if (___currentProjectile.TryGetComponent<ProjectileSpread>(ref val))
			{
				Projectile[] componentsInChildren = ___currentProjectile.GetComponentsInChildren<Projectile>();
				foreach (Projectile val2 in componentsInChildren)
				{
					MonoSingleton<EnemyIdentifierManager>.Instance.RegisterFactor(((Component)val2).gameObject, ___eid);
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ZombieProjectiles), "ShootProjectile")]
		public static void ZombieProjectiles_ShootProjectile_Postfix(GameObject ___currentProjectile, EnemyIdentifier ___eid, ZombieProjectiles __instance)
		{
			if (!((Object)(object)___currentProjectile == (Object)null))
			{
				Projectile val = default(Projectile);
				if (___currentProjectile.TryGetComponent<Projectile>(ref val))
				{
					MonoSingleton<EnemyIdentifierManager>.Instance.RegisterFactor(((Component)val).gameObject, ___eid);
				}
				ProjectileSpread val2 = default(ProjectileSpread);
				if (___currentProjectile.TryGetComponent<ProjectileSpread>(ref val2))
				{
					ProjectileSpread componentInChildren = ((Component)val2).GetComponentInChildren<ProjectileSpread>();
					MonoSingleton<EnemyIdentifierManager>.Instance.RegisterFactor(((Component)componentInChildren).gameObject, ___eid);
				}
			}
		}
	}
}
namespace UKEnemyIdentifier.Components
{
	[ConfigureSingleton(/*Could not decode attribute arguments.*/)]
	public class EnemyIdentifierManager : MonoSingleton<EnemyIdentifierManager>
	{
		public class PlayerHurtEvent
		{
			public EnemyIdentifier EnemyId;

			public bool PlayerIsKilled;

			public int Damage;
		}

		public delegate void PlayerHurtEventDelegate(PlayerHurtEvent data);

		internal bool DeadAlready;

		internal GameObject LastHurtingFactor;

		private List<(GameObject go, EnemyIdentifier eid)> _killingFactorByOrigin = new List<(GameObject, EnemyIdentifier)>();

		public event PlayerHurtEventDelegate OnPlayerHurt;

		private void Start()
		{
			SceneManager.sceneLoaded += delegate
			{
				DeadAlready = false;
			};
			((MonoBehaviour)this).InvokeRepeating("ListCleanup", 1f, 1f);
		}

		private void ListCleanup()
		{
			_killingFactorByOrigin = _killingFactorByOrigin.Where(((GameObject go, EnemyIdentifier eid) e) => (Object)(object)e.go != (Object)null && (Object)(object)e.eid != (Object)null).ToList();
		}

		private void Update()
		{
			LastHurtingFactor = null;
		}

		internal void RegisterFactor(GameObject factor, EnemyIdentifier emitter)
		{
			_killingFactorByOrigin.Add((factor, emitter));
			if ((Object)(object)factor == (Object)null || (Object)(object)emitter == (Object)null)
			{
				return;
			}
			foreach (Explosion item in from explosion in factor.GetComponentsInChildren<Explosion>(true)
				where (Object)(object)explosion.originEnemy == (Object)null
				select explosion)
			{
				item.originEnemy = emitter;
			}
			HurtZone[] componentsInChildren = factor.GetComponentsInChildren<HurtZone>(true);
			foreach (HurtZone val in componentsInChildren)
			{
				_killingFactorByOrigin.Add((((Component)val).gameObject, emitter));
			}
			ContinuousBeam[] componentsInChildren2 = factor.GetComponentsInChildren<ContinuousBeam>(true);
			foreach (ContinuousBeam val2 in componentsInChildren2)
			{
				_killingFactorByOrigin.Add((((Component)val2).gameObject, emitter));
			}
			RevolverBeam[] componentsInChildren3 = factor.GetComponentsInChildren<RevolverBeam>(true);
			foreach (RevolverBeam val3 in componentsInChildren3)
			{
				_killingFactorByOrigin.Add((((Component)val3).gameObject, emitter));
			}
		}

		internal EnemyIdentifier GetIdentifierFor(Component component)
		{
			return (from pair in _killingFactorByOrigin
				where (Object)(object)pair.go == (Object)(object)component.gameObject
				select pair.eid).FirstOrDefault();
		}

		internal void RegisterExplosion(Component component, Explosion explosion)
		{
			EnemyIdentifier identifierFor = GetIdentifierFor(component);
			if (!((Object)(object)identifierFor == (Object)null))
			{
				explosion.originEnemy = identifierFor;
			}
		}

		internal EnemyIdentifier IdentifyEnemy()
		{
			if ((Object)(object)LastHurtingFactor == (Object)null)
			{
				return null;
			}
			if (!EnemyItselfIsDamagingFactor(out var identifier) && !EnemyIdStoredInDictionary(out identifier) && !LookForEnemyIdInDamagingFactor(out identifier))
			{
				return null;
			}
			return identifier;
		}

		private bool EnemyIdStoredInDictionary(out EnemyIdentifier identifier)
		{
			Projectile val = default(Projectile);
			PhysicalShockwave val2 = default(PhysicalShockwave);
			MassSpear val3 = default(MassSpear);
			RevolverBeam val4 = default(RevolverBeam);
			ContinuousBeam val5 = default(ContinuousBeam);
			Nail val6 = default(Nail);
			HurtZone val7 = default(HurtZone);
			BlackHoleProjectile val8 = default(BlackHoleProjectile);
			if (LastHurtingFactor.TryGetComponent<Projectile>(ref val) || LastHurtingFactor.TryGetComponent<PhysicalShockwave>(ref val2) || LastHurtingFactor.TryGetComponent<MassSpear>(ref val3) || LastHurtingFactor.TryGetComponent<RevolverBeam>(ref val4) || LastHurtingFactor.TryGetComponent<ContinuousBeam>(ref val5) || LastHurtingFactor.TryGetComponent<Nail>(ref val6) || LastHurtingFactor.TryGetComponent<HurtZone>(ref val7) || LastHurtingFactor.TryGetComponent<BlackHoleProjectile>(ref val8))
			{
				identifier = FindByHurtingFactor((Object)(object)LastHurtingFactor);
				return true;
			}
			identifier = null;
			return false;
			EnemyIdentifier FindByHurtingFactor(Object go)
			{
				return (from pair in _killingFactorByOrigin
					where (Object)(object)pair.go == go
					select pair.eid).FirstOrDefault();
			}
		}

		private bool EnemyItselfIsDamagingFactor(out EnemyIdentifier identifier)
		{
			MinosPrime minos = default(MinosPrime);
			if (LastHurtingFactor.TryGetComponent<MinosPrime>(ref minos))
			{
				return Found(() => ReflectionUtils.GetPrivate<EnemyIdentifier>(minos, "eid"), out identifier);
			}
			SisyphusPrime sissy = default(SisyphusPrime);
			if (LastHurtingFactor.TryGetComponent<SisyphusPrime>(ref sissy))
			{
				return Found(() => ReflectionUtils.GetPrivate<EnemyIdentifier>(sissy, "eid"), out identifier);
			}
			GabrielSecond gabrielSecond = default(GabrielSecond);
			if (LastHurtingFactor.TryGetComponent<GabrielSecond>(ref gabrielSecond))
			{
				return Found(() => ReflectionUtils.GetPrivate<EnemyIdentifier>(gabrielSecond, "eid"), out identifier);
			}
			identifier = null;
			return false;
			static bool Found(Func<EnemyIdentifier> callback, out EnemyIdentifier i)
			{
				i = callback();
				return true;
			}
		}

		private bool LookForEnemyIdInDamagingFactor(out EnemyIdentifier identifier)
		{
			SwingCheck2 swingCheck = default(SwingCheck2);
			if (LastHurtingFactor.TryGetComponent<SwingCheck2>(ref swingCheck))
			{
				return Found(() => swingCheck.eid, out identifier);
			}
			Explosion explosion = default(Explosion);
			if (LastHurtingFactor.TryGetComponent<Explosion>(ref explosion))
			{
				return Found(() => explosion.originEnemy, out identifier);
			}
			FireZone thisFffire = default(FireZone);
			if (LastHurtingFactor.TryGetComponent<FireZone>(ref thisFffire))
			{
				return Found(() => ((int)thisFffire.source != 1) ? null : ReflectionUtils.GetPrivate<Streetcleaner>(thisFffire, "sc").eid, out identifier);
			}
			VirtueInsignia virtueBeam = default(VirtueInsignia);
			if (LastHurtingFactor.TryGetComponent<VirtueInsignia>(ref virtueBeam))
			{
				return Found(() => ((Component)virtueBeam.parentEnemy).gameObject.GetComponent<EnemyIdentifier>(), out identifier);
			}
			Coin coin = default(Coin);
			if (LastHurtingFactor.TryGetComponent<Coin>(ref coin))
			{
				return Found(() => ReflectionUtils.GetPrivate<EnemyIdentifier>(coin, "eid"), out identifier);
			}
			identifier = null;
			return false;
			static bool Found(Func<EnemyIdentifier> callback, out EnemyIdentifier i)
			{
				i = callback();
				return true;
			}
		}

		internal void PlayerHurt(EnemyIdentifier eid, int damage, bool playerKilled = false)
		{
			PlayerHurtEventDelegate playerHurtEventDelegate = this.OnPlayerHurt;
			if (playerHurtEventDelegate == null)
			{
				return;
			}
			PlayerHurtEvent data = new PlayerHurtEvent
			{
				EnemyId = eid,
				PlayerIsKilled = playerKilled,
				Damage = damage
			};
			Delegate[] invocationList = playerHurtEventDelegate.GetInvocationList();
			foreach (Delegate obj in invocationList)
			{
				try
				{
					((PlayerHurtEventDelegate)obj)(data);
				}
				catch (Exception)
				{
				}
			}
		}
	}
}