Decompiled source of UltraMisery v0.1.0

BepInEx/plugins/UltraMisery/UltraMisery.dll

Decompiled 20 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using ULTRAKILL.Cheats;
using ULTRAKILL.Enemy;
using ULTRAKILL.Portal;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.AddressableAssets;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[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("UltraMisery")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("UltraMisery")]
[assembly: AssemblyTitle("UltraMisery")]
[assembly: AssemblyVersion("1.0.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 UltraMisery
{
	internal static class AiAttackCorrections
	{
		private sealed class Burst
		{
			internal bool Active;
		}

		private static readonly ConditionalWeakTable<Turret, Burst> Bursts = new ConditionalWeakTable<Turret, Burst>();

		internal static void SetBurst(Turret sentry, bool active)
		{
			Bursts.GetOrCreateValue(sentry).Active = active;
		}

		internal static bool InBurst(Turret sentry)
		{
			if (UltraMiseryState.IsActive && Bursts.TryGetValue(sentry, out var value))
			{
				return value.Active;
			}
			return false;
		}

		internal static EnemyIdentifier Target(Component shooter)
		{
			if (!LifestealRules.AiCombatAllowed || !Object.op_Implicit((Object)(object)shooter))
			{
				return null;
			}
			EnemyIdentifier component = shooter.GetComponent<EnemyIdentifier>();
			EnemyTarget val = ((Object.op_Implicit((Object)(object)component) && !component.dead) ? component.target : null);
			if (val == null || !val.isValid || !val.isEnemy)
			{
				return null;
			}
			return val.enemyIdentifier;
		}

		internal static Vector3 Aim(EnemyIdentifier target, Component shooter)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			Enemy component = ((Component)target).GetComponent<Enemy>();
			return LargeBossTargetRules.Aim((Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.chest)) ? component.chest.transform.position : (Object.op_Implicit((Object)(object)target.overrideCenter) ? target.overrideCenter.position : ((Component)target).transform.position), shooter);
		}
	}
	[HarmonyPatch(typeof(Streetcleaner), "Update")]
	internal static class StreetcleanerResumeNavigationPatch
	{
		private static void Prefix(EnemyIdentifier ___eid, NavMeshAgent ___nma, bool ___dead, bool ___dodging)
		{
			if (!(!UltraMiseryState.IsActive || ___dead || ___dodging) && Object.op_Implicit((Object)(object)___eid) && ___eid.target != null && ___eid.target.isValid && Object.op_Implicit((Object)(object)___nma) && ((Behaviour)___nma).enabled && ___nma.isOnNavMesh && !___nma.isOnOffMeshLink)
			{
				___nma.isStopped = false;
			}
		}
	}
	[HarmonyPatch(typeof(Guttertank), "UpdateLineOfSightTimer")]
	internal static class GuttertankDirectTargetRecoveryPatch
	{
		private static void Prefix(TargetHandle ___targetHandle, ref Vector3 ___lastDimensionalTarget)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (UltraMiseryState.IsActive && ___targetHandle != (TargetHandle)null && ((PortalHandleSequence)(ref ___targetHandle.portals)).Count == 0 && DroneTargetRules.IsLive(___targetHandle.target))
			{
				___lastDimensionalTarget = Vector3.zero;
			}
		}
	}
	[HarmonyPatch(typeof(Streetcleaner), "UpdateVision")]
	internal static class StreetcleanerDirectTargetRecoveryPatch
	{
		private static void Postfix(TargetHandle ___targetHandle, ref Vector3 ___lastDimensionalTarget)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (UltraMiseryState.IsActive && ___targetHandle != (TargetHandle)null && ((PortalHandleSequence)(ref ___targetHandle.portals)).Count == 0 && DroneTargetRules.IsLive(___targetHandle.target))
			{
				___lastDimensionalTarget = Vector3.zero;
			}
		}
	}
	[HarmonyPatch(/*Could not decode attribute arguments.*/)]
	internal static class StreetcleanerVisionSafetyPatch
	{
		private static bool Prefix(Streetcleaner __instance, Enemy ___mach, ref Vector3 __result)
		{
			//IL_0025: 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_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			if (!UltraMiseryState.IsActive || (Object.op_Implicit((Object)(object)___mach) && Object.op_Implicit((Object)(object)___mach.chest)))
			{
				return true;
			}
			__result = ((Component)__instance).transform.position + Vector3.up;
			return false;
		}
	}
	[HarmonyPatch(typeof(Turret), "AimAt")]
	internal static class SentryBodyAimPatch
	{
		private static void Prefix(Turret __instance, ref Vector3 position, ref Vector3 direction, ref float distance, PortalTraversalV2[] traversals)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: 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)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			EnemyIdentifier val = AiAttackCorrections.Target((Component)(object)__instance);
			if (Object.op_Implicit((Object)(object)val) && (traversals == null || traversals.Length == 0))
			{
				position = AiAttackCorrections.Aim(val, (Component)(object)__instance);
				Vector3 val2 = position - ((EnemyScript)__instance).VisionSourcePosition;
				direction = ((Vector3)(ref val2)).normalized;
				distance = ((Vector3)(ref val2)).magnitude;
			}
		}
	}
	[HarmonyPatch(typeof(Turret), "Shoot")]
	internal static class SentryShotAimPatch
	{
		private static void Prefix(Turret __instance, bool ___isBarrelPortalCrossed, Transform ___barrelTip, ref Quaternion ___shootRotation)
		{
			//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_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			EnemyIdentifier val = AiAttackCorrections.Target((Component)(object)__instance);
			if (!(!Object.op_Implicit((Object)(object)val) || ___isBarrelPortalCrossed) && Object.op_Implicit((Object)(object)___barrelTip))
			{
				Vector3 position = ((Component)__instance).transform.position;
				position.y = ___barrelTip.position.y;
				Vector3 val2 = AiAttackCorrections.Aim(val, (Component)(object)__instance) - position;
				if (((Vector3)(ref val2)).sqrMagnitude > 0.001f)
				{
					___shootRotation = Quaternion.LookRotation(val2);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Turret), "StopAction")]
	internal static class SentryKeepFiringStancePatch
	{
		private static bool Prefix(Turret __instance)
		{
			if (AiAttackCorrections.InBurst(__instance))
			{
				return !SentryEndlessBurstPatch.HasLivingTarget(__instance);
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Turret), "Update")]
	internal static class SentryContinueAcrossTargetsPatch
	{
		private static void Postfix(Turret __instance, bool ___aiming, Animator ___anim, ref bool ___inAction)
		{
			if (!AiAttackCorrections.InBurst(__instance))
			{
				return;
			}
			if (!SentryEndlessBurstPatch.HasLivingTarget(__instance))
			{
				AiAttackCorrections.SetBurst(__instance, active: false);
				__instance.CancelAim(false);
				___inAction = false;
				return;
			}
			___inAction = true;
			if (Object.op_Implicit((Object)(object)___anim))
			{
				___anim.SetBool("Aiming", true);
			}
			if (!___aiming && !((MonoBehaviour)__instance).IsInvoking("PreReAim") && !((MonoBehaviour)__instance).IsInvoking("ReAim"))
			{
				((MonoBehaviour)__instance).Invoke("PreReAim", 0.25f);
			}
		}
	}
	[HarmonyPatch(typeof(Turret), "OnDisable")]
	internal static class SentryResetBurstPatch
	{
		private static void Postfix(Turret __instance)
		{
			AiAttackCorrections.SetBurst(__instance, active: false);
		}
	}
	[HarmonyPatch(typeof(Minotaur), "RamStart")]
	internal static class MinotaurRamEnemyHitboxesPatch
	{
		private static void Postfix(Minotaur __instance, EnemyIdentifier ___eid, GameObject ___ramStuff)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			if (LifestealRules.AiCombatAllowed && Object.op_Implicit((Object)(object)___ramStuff) && Object.op_Implicit((Object)(object)___eid))
			{
				(((Component)__instance).GetComponent<UltraMiseryRamSweep>() ?? ((Component)__instance).gameObject.AddComponent<UltraMiseryRamSweep>()).Begin(__instance, ___eid, ___ramStuff);
				SwingCheck2[] componentsInChildren = ___ramStuff.GetComponentsInChildren<SwingCheck2>(true);
				foreach (SwingCheck2 obj in componentsInChildren)
				{
					obj.eid = ___eid;
					obj.type = ___eid.enemyType;
					obj.startActive = true;
					obj.DamageStart();
				}
			}
		}
	}
	internal sealed class UltraMiseryRamSweep : MonoBehaviour
	{
		private static readonly MethodInfo HitEnemy = AccessTools.Method(typeof(SwingCheck2), "CheckEidCollision", (Type[])null, (Type[])null);

		private readonly Collider[] overlaps = (Collider[])(object)new Collider[64];

		private Minotaur minotaur;

		private EnemyIdentifier owner;

		private SwingCheck2[] checks;

		private Collider[] boxes;

		private Vector3 previous;

		internal void Begin(Minotaur source, EnemyIdentifier eid, GameObject ram)
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			minotaur = source;
			owner = eid;
			if (checks == null)
			{
				checks = ram.GetComponentsInChildren<SwingCheck2>(true);
				boxes = (Collider[])(object)new Collider[checks.Length];
				for (int i = 0; i < checks.Length; i++)
				{
					boxes[i] = ((Component)checks[i]).GetComponent<Collider>();
				}
				if (checks.Length == 0)
				{
					Plugin.Log.LogWarning((object)"Minotaur ram has no native SwingCheck2 hitbox; inspect this prefab.");
				}
			}
			previous = ((Component)this).transform.position;
		}

		private void FixedUpdate()
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: 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_0068: 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_0075: 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_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_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: 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_0179: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)minotaur) || !Object.op_Implicit((Object)(object)owner) || owner.dead || !LifestealRules.AiCombatAllowed || minotaur.ramTimer <= 0f)
			{
				previous = ((Component)this).transform.position;
				return;
			}
			Vector3 val = ((Component)this).transform.position - previous;
			previous = ((Component)this).transform.position;
			for (int i = 0; i < checks.Length; i++)
			{
				if (!(minotaur.ramTimer > 0f))
				{
					break;
				}
				SwingCheck2 val2 = checks[i];
				Collider val3 = boxes[i];
				if (!Object.op_Implicit((Object)(object)val2) || !Object.op_Implicit((Object)(object)val3) || !val3.enabled || !((Component)val3).gameObject.activeInHierarchy)
				{
					continue;
				}
				Bounds bounds = val3.bounds;
				((Bounds)(ref bounds)).Encapsulate(new Bounds(((Bounds)(ref bounds)).center - val, ((Bounds)(ref bounds)).size));
				int num = Physics.OverlapBoxNonAlloc(((Bounds)(ref bounds)).center, ((Bounds)(ref bounds)).extents, overlaps, Quaternion.identity, 5120, (QueryTriggerInteraction)2);
				for (int j = 0; j < num; j++)
				{
					if (!(minotaur.ramTimer > 0f))
					{
						break;
					}
					Collider val4 = overlaps[j];
					overlaps[j] = null;
					EnemyIdentifier enemy = FriendlyFireRules.GetEnemy(val4);
					if (Object.op_Implicit((Object)(object)enemy) && !((Object)(object)enemy == (Object)(object)owner) && !enemy.dead)
					{
						Bounds bounds2 = val3.bounds;
						Vector3 center = ((Bounds)(ref bounds2)).center;
						bounds2 = val4.bounds;
						if (!Physics.Linecast(center, ((Bounds)(ref bounds2)).center, LayerMask.op_Implicit(LayerMaskDefaults.Get((LMD)1)), (QueryTriggerInteraction)1))
						{
							HitEnemy.Invoke(val2, new object[2] { enemy, val4 });
						}
					}
				}
			}
		}
	}
	internal static class AiCombatRules
	{
		internal static bool AllowsAiCombat(bool active, bool cheatsEnabled, bool enemiesAttackEachOther)
		{
			return active && cheatsEnabled && enemiesAttackEachOther;
		}

		internal static EnemyType CollisionExclusionType(EnemyType original)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			if (!LifestealRules.AiCombatAllowed)
			{
				return original;
			}
			return (EnemyType)(-1);
		}

		internal static bool SupportRole(EnemyIdentifier eid)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between Unknown and I4
			if (!SupportEnemyCombatRules.IsSupport(eid))
			{
				return (int)eid.enemyType == 12;
			}
			return true;
		}
	}
	[HarmonyPatch(/*Could not decode attribute arguments.*/)]
	internal static class StrictAiCombatTargetGatePatch
	{
		[HarmonyPriority(0)]
		private static void Postfix(EnemyIdentifier __instance, ref bool __result)
		{
			if (UltraMiseryState.IsActive && !AiCombatRules.SupportRole(__instance))
			{
				__result = LifestealRules.AiCombatAllowed && !BlindEnemies.Blind;
			}
		}
	}
	[HarmonyPatch(typeof(EnemyIdentifier), "Update")]
	internal static class RefreshAiCombatGatePatch
	{
		private static void Prefix(EnemyIdentifier __instance)
		{
			if (UltraMiseryState.IsActive && !__instance.dead)
			{
				bool aiCombatAllowed = LifestealRules.AiCombatAllowed;
				__instance.immuneToFriendlyFire = !aiCombatAllowed;
				if (!AiCombatRules.SupportRole(__instance) && __instance.target != null && ((aiCombatAllowed && __instance.target.isPlayer) || (!aiCombatAllowed && __instance.target.isEnemy)))
				{
					__instance.target = null;
					__instance.UpdateTarget();
				}
			}
		}
	}
	[HarmonyPatch(/*Could not decode attribute arguments.*/)]
	internal static class AiCombatIgnorePlayerPatch
	{
		[HarmonyPriority(0)]
		private static void Postfix(ref bool __result)
		{
			if (LifestealRules.AiCombatAllowed)
			{
				__result = true;
			}
		}
	}
	[HarmonyPatch(typeof(EnemyIdentifier), "IsTypeFriendly")]
	internal static class AiSameSpeciesTargetPatch
	{
		private static void Postfix(EnemyIdentifier __instance, EnemyIdentifier owner, ref bool __result)
		{
			if (LifestealRules.AiCombatAllowed)
			{
				__result = (Object)(object)__instance == (Object)(object)owner;
			}
		}
	}
	[HarmonyPatch]
	internal static class AiHurtExceptionsPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			return from m in typeof(EnemyIdentifier).GetMethods(BindingFlags.Static | BindingFlags.Public)
				where m.Name == "CheckHurtException"
				select m;
		}

		private static void Postfix(ref bool __result)
		{
			if (LifestealRules.AiCombatAllowed)
			{
				__result = false;
			}
		}
	}
	[HarmonyPatch]
	internal static class AiSameSpeciesCollisionPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(Projectile), "Collided", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(SwingCheck2), "CheckEidCollision", (Type[])null, (Type[])null);
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			bool projectile = __originalMethod.DeclaringType == typeof(Projectile);
			FieldInfo field = AccessTools.Field(__originalMethod.DeclaringType, projectile ? "safeEnemyType" : "type");
			int index = 0;
			int replaced = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				yield return instruction;
				if (instruction.opcode == OpCodes.Ldfld && object.Equals(instruction.operand, field) && index++ == (projectile ? 1 : 0))
				{
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(AiCombatRules), "CollisionExclusionType", (Type[])null, (Type[])null));
					replaced++;
				}
			}
			if (replaced != 1)
			{
				throw new InvalidOperationException("AI species collision hook changed: " + __originalMethod);
			}
		}
	}
	[HarmonyPatch(typeof(Projectile), "Collided")]
	internal static class AiProjectileNoSelfHitPatch
	{
		private static bool Prefix(Projectile __instance, Collider other)
		{
			if (!LifestealRules.AiCombatAllowed)
			{
				return true;
			}
			EnemyIdentifier enemy = FriendlyFireRules.GetEnemy(other);
			if (__instance.parried || __instance.playerBullet)
			{
				return true;
			}
			UltraMiseryAttackOwner componentInParent = ((Component)__instance).GetComponentInParent<UltraMiseryAttackOwner>();
			EnemyIdentifier val = ((Object.op_Implicit((Object)(object)componentInParent) && Object.op_Implicit((Object)(object)componentInParent.Owner)) ? componentInParent.Owner : LifestealRules.Resolve((Component)(object)__instance));
			if (Object.op_Implicit((Object)(object)enemy))
			{
				return (Object)(object)enemy != (Object)(object)val;
			}
			return true;
		}
	}
	[HarmonyPatch]
	internal static class AiSameSpeciesBeamPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			return from m in typeof(RevolverBeam).GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
				where m.Name == "PiercingShotCheck" || m.Name == "ExecuteHits"
				select m;
		}

		private static void Prefix(RevolverBeam __instance)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Invalid comparison between Unknown and I4
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Invalid comparison between Unknown and I4
			if (LifestealRules.AiCombatAllowed && !__instance.deflected && ((int)__instance.beamType == 3 || (int)__instance.beamType == 2))
			{
				EnemyIdentifier val = LifestealRules.Resolve((Component)(object)__instance);
				if (Object.op_Implicit((Object)(object)val) && !__instance.hitEids.Contains(val))
				{
					__instance.hitEids.Add(val);
				}
			}
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			FieldInfo field = AccessTools.Field(typeof(RevolverBeam), "ignoreEnemyType");
			int replaced = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				yield return instruction;
				if (instruction.opcode == OpCodes.Ldfld && object.Equals(instruction.operand, field))
				{
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(AiCombatRules), "CollisionExclusionType", (Type[])null, (Type[])null));
					replaced++;
				}
			}
			if (replaced != 2)
			{
				throw new InvalidOperationException("Enemy hitscan species gate changed: " + replaced);
			}
		}
	}
	[HarmonyPatch(typeof(EnemyIdentifier), "DeliverDamage")]
	internal static class AiAttributedSelfDamageGuardPatch
	{
		private static bool Prefix(EnemyIdentifier __instance)
		{
			if (LifestealRules.AiCombatAllowed && Object.op_Implicit((Object)(object)LifestealRules.Attacker))
			{
				return (Object)(object)LifestealRules.Attacker != (Object)(object)__instance;
			}
			return true;
		}
	}
	[HarmonyPatch]
	internal static class AiSameSpeciesOtherRangedPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(ContinuousBeam), "FixedUpdate", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(Nail), "HitEnemy", (Type[])null, (Type[])null);
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			FieldInfo field = AccessTools.Field(__originalMethod.DeclaringType, "safeEnemyType");
			int count = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				yield return instruction;
				if (instruction.opcode == OpCodes.Ldfld && object.Equals(instruction.operand, field))
				{
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(AiCombatRules), "CollisionExclusionType", (Type[])null, (Type[])null));
					count++;
				}
			}
			if (count != ((__originalMethod.DeclaringType == typeof(Nail)) ? 1 : 2))
			{
				throw new InvalidOperationException("Ranged species gate changed: " + __originalMethod);
			}
		}
	}
	[HarmonyPatch(typeof(SwingCheck2), "CheckEidCollision")]
	internal static class AiMeleeNoSelfHitPatch
	{
		private static bool Prefix(SwingCheck2 __instance, EnemyIdentifier enid)
		{
			if (!LifestealRules.AiCombatAllowed)
			{
				return true;
			}
			if ((Object)(object)__instance.eid == (Object)(object)enid)
			{
				return false;
			}
			if (Object.op_Implicit((Object)(object)__instance.eid))
			{
				__instance.eid.immuneToFriendlyFire = false;
			}
			return true;
		}
	}
	internal sealed class UltraMiseryDuelWatch : MonoBehaviour
	{
		internal AiStalemateRules.Duel Duel;

		private void LateUpdate()
		{
			if (Duel != null)
			{
				if (!Duel.Valid)
				{
					Duel = null;
				}
				else
				{
					Duel.Sample();
				}
			}
		}
	}
	internal static class AiStalemateRules
	{
		internal sealed class Duel
		{
			internal EnemyIdentifier A;

			internal EnemyIdentifier B;

			internal Enemy BodyA;

			internal Enemy BodyB;

			internal float Since;

			internal float LowWater;

			internal float Threshold;

			internal float NextSample;

			internal bool Damping;

			internal bool Valid
			{
				get
				{
					if (LifestealRules.AiCombatAllowed && Object.op_Implicit((Object)(object)A) && Object.op_Implicit((Object)(object)B) && Object.op_Implicit((Object)(object)BodyA) && Object.op_Implicit((Object)(object)BodyB) && !A.dead && !B.dead && A.target != null && B.target != null && (Object)(object)A.target.enemyIdentifier == (Object)(object)B)
					{
						return (Object)(object)B.target.enemyIdentifier == (Object)(object)A;
					}
					return false;
				}
			}

			internal void Sample()
			{
				//IL_009e: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
				if (!(Time.time < NextSample))
				{
					NextSample = Time.time + 0.25f;
					float num = BodyA.health + BodyB.health;
					if (!Damping && num <= LowWater - Threshold)
					{
						Since = Time.time;
						LowWater = num;
					}
					if (!Damping && Time.time - Since >= 15f)
					{
						Damping = true;
						Plugin.Log.LogInfo((object)$"AI stalemate: reducing lifesteal/parry healing equally for {A.enemyType} #{((Object)A).GetInstanceID()} and {B.enemyType} #{((Object)B).GetInstanceID()} over 30 seconds.");
					}
				}
			}
		}

		internal static bool AllowsHitLifesteal(EnemyType attacker, EnemyType victim)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return attacker != victim;
		}

		internal static float HealingScale(float elapsed)
		{
			return Math.Max(0f, Math.Min(1f, 1f - Math.Max(0f, elapsed - 15f) / 30f));
		}

		internal static float Scale(EnemyIdentifier enemy)
		{
			if (!LifestealRules.AiCombatAllowed || !Object.op_Implicit((Object)(object)enemy) || enemy.target == null || !enemy.target.isEnemy)
			{
				return 1f;
			}
			EnemyIdentifier enemyIdentifier = enemy.target.enemyIdentifier;
			if (!Object.op_Implicit((Object)(object)enemyIdentifier) || (Object)(object)enemyIdentifier == (Object)(object)enemy || enemyIdentifier.dead || enemyIdentifier.target == null || (Object)(object)enemyIdentifier.target.enemyIdentifier != (Object)(object)enemy)
			{
				return 1f;
			}
			UltraMiseryDuelWatch ultraMiseryDuelWatch = ((Component)enemy).GetComponent<UltraMiseryDuelWatch>() ?? ((Component)enemy).gameObject.AddComponent<UltraMiseryDuelWatch>();
			if (ultraMiseryDuelWatch.Duel != null && ultraMiseryDuelWatch.Duel.Valid)
			{
				if (!ultraMiseryDuelWatch.Duel.Damping)
				{
					return 1f;
				}
				return HealingScale(Time.time - ultraMiseryDuelWatch.Duel.Since);
			}
			UltraMiseryDuelWatch ultraMiseryDuelWatch2 = ((Component)enemyIdentifier).GetComponent<UltraMiseryDuelWatch>() ?? ((Component)enemyIdentifier).gameObject.AddComponent<UltraMiseryDuelWatch>();
			Enemy component = ((Component)enemy).GetComponent<Enemy>();
			Enemy component2 = ((Component)enemyIdentifier).GetComponent<Enemy>();
			if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component2))
			{
				return 1f;
			}
			Duel duel = new Duel
			{
				A = enemy,
				B = enemyIdentifier,
				BodyA = component,
				BodyB = component2,
				Since = Time.time,
				LowWater = component.health + component2.health,
				Threshold = Mathf.Max(0.01f, (LifestealRules.State(enemy).MaximumHealth + LifestealRules.State(enemyIdentifier).MaximumHealth) * 0.01f)
			};
			ultraMiseryDuelWatch.Duel = (ultraMiseryDuelWatch2.Duel = duel);
			return 1f;
		}
	}
	internal static class AiTargetRecoveryRules
	{
		private sealed class Watch
		{
			internal EnemyIdentifier Target;

			internal EnemyIdentifier Replacement;

			internal float LastDamage;

			internal float FailedSince = -1f;

			internal float NextCheck;

			internal float HoldUntil;

			internal readonly Dictionary<EnemyIdentifier, float> Avoid = new Dictionary<EnemyIdentifier, float>();
		}

		private static readonly ConditionalWeakTable<EnemyIdentifier, Watch> Watches = new ConditionalWeakTable<EnemyIdentifier, Watch>();

		internal static bool TimedOut(float now, float lastDamage, float failedSince)
		{
			if (!(now - lastDamage >= 12f))
			{
				if (failedSince >= 0f && now - failedSince >= 6f)
				{
					return now - lastDamage >= 6f;
				}
				return false;
			}
			return true;
		}

		private static bool Alive(EnemyIdentifier e)
		{
			if (Object.op_Implicit((Object)(object)e) && !e.dead)
			{
				return ((Component)e).gameObject.activeInHierarchy;
			}
			return false;
		}

		internal static bool Avoided(EnemyIdentifier owner, EnemyIdentifier candidate)
		{
			if (Watches.TryGetValue(owner, out var value) && Object.op_Implicit((Object)(object)candidate) && value.Avoid.TryGetValue(candidate, out var value2))
			{
				return Time.time < value2;
			}
			return false;
		}

		internal static void Damage(EnemyIdentifier owner, EnemyIdentifier victim, float amount)
		{
			if (amount > 0f && Object.op_Implicit((Object)(object)owner) && Object.op_Implicit((Object)(object)victim) && Watches.TryGetValue(owner, out var value) && (Object)(object)value.Target == (Object)(object)victim)
			{
				value.LastDamage = Time.time;
				value.FailedSince = -1f;
			}
		}

		internal static void Apply(EnemyIdentifier owner)
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Expected O, but got Unknown
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Invalid comparison between Unknown and I4
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0333: Unknown result type (might be due to invalid IL or missing references)
			//IL_033d: Expected O, but got Unknown
			if (!LifestealRules.AiCombatAllowed || BlindEnemies.Blind || owner.dead || AiCombatRules.SupportRole(owner))
			{
				Watches.Remove(owner);
				return;
			}
			Watch orCreateValue = Watches.GetOrCreateValue(owner);
			float time = Time.time;
			if (Alive(orCreateValue.Replacement) && time < orCreateValue.HoldUntil && Avoided(owner, owner.target?.enemyIdentifier))
			{
				owner.target = new EnemyTarget(((Component)orCreateValue.Replacement).transform);
			}
			EnemyIdentifier val = owner.target?.enemyIdentifier;
			if (!Alive(val))
			{
				orCreateValue.Target = null;
				return;
			}
			if ((Object)(object)orCreateValue.Target != (Object)(object)val)
			{
				orCreateValue.Target = val;
				orCreateValue.LastDamage = time;
				orCreateValue.FailedSince = -1f;
			}
			if (time < orCreateValue.NextCheck)
			{
				return;
			}
			orCreateValue.NextCheck = time + 0.5f;
			NavMeshAgent component = ((Component)owner).GetComponent<NavMeshAgent>();
			if (owner.stationary || !Object.op_Implicit((Object)(object)component) || !((Behaviour)component).enabled || !component.isOnNavMesh || component.isOnOffMeshLink || component.isStopped || component.pathPending || (int)component.pathStatus <= 0)
			{
				orCreateValue.FailedSince = -1f;
			}
			else if (orCreateValue.FailedSince < 0f)
			{
				orCreateValue.FailedSince = time;
			}
			if (!TimedOut(time, orCreateValue.LastDamage, orCreateValue.FailedSince))
			{
				return;
			}
			EnemyTracker instance = MonoSingleton<EnemyTracker>.Instance;
			if (!Object.op_Implicit((Object)(object)instance))
			{
				return;
			}
			EnemyIdentifier val2 = null;
			float num = float.PositiveInfinity;
			foreach (EnemyIdentifier currentEnemy in instance.GetCurrentEnemies())
			{
				if (Alive(currentEnemy) && !((Object)(object)currentEnemy == (Object)(object)owner) && !((Object)(object)currentEnemy == (Object)(object)val) && !currentEnemy.ignoredByEnemies && !Avoided(owner, currentEnemy))
				{
					Vector3 val3 = ((Component)currentEnemy).transform.position - ((Component)owner).transform.position;
					float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude;
					if (!(sqrMagnitude >= num) && new EnemyTarget(((Component)currentEnemy).transform).isValid)
					{
						val2 = currentEnemy;
						num = sqrMagnitude;
					}
				}
			}
			if (!Object.op_Implicit((Object)(object)val2))
			{
				orCreateValue.NextCheck = time + 2f;
				return;
			}
			List<EnemyIdentifier> list = new List<EnemyIdentifier>();
			foreach (KeyValuePair<EnemyIdentifier, float> item in orCreateValue.Avoid)
			{
				if (!Alive(item.Key) || item.Value <= time)
				{
					list.Add(item.Key);
				}
			}
			foreach (EnemyIdentifier item2 in list)
			{
				orCreateValue.Avoid.Remove(item2);
			}
			orCreateValue.Avoid[val] = time + 20f;
			orCreateValue.Replacement = val2;
			orCreateValue.HoldUntil = time + 20f;
			orCreateValue.Target = val2;
			orCreateValue.LastDamage = time;
			orCreateValue.FailedSince = -1f;
			SupportEnemyCombatRules.EnsureVisionTarget(val2);
			owner.target = new EnemyTarget(((Component)val2).transform);
		}
	}
	[HarmonyPatch(typeof(EnemyIdentifier), "Update")]
	internal static class AiTargetRecoveryUpdatePatch
	{
		private static void Postfix(EnemyIdentifier __instance)
		{
			AiTargetRecoveryRules.Apply(__instance);
		}
	}
	internal static class AllEnemiesEnrageBridge
	{
		private const string PluginTypeName = "AllEnemiesEnragable.AllEnemiesEnragablePlugin";

		private static bool resolved;

		private static FieldInfo forceEnrageField;

		private static MethodInfo enrageEnemyMethod;

		internal static bool TryGetForceEnrage(out bool value)
		{
			Resolve();
			if (forceEnrageField == null)
			{
				value = false;
				return false;
			}
			value = (bool)forceEnrageField.GetValue(null);
			return true;
		}

		internal static bool TrySetForceEnrage(bool value)
		{
			Resolve();
			if (forceEnrageField == null)
			{
				return false;
			}
			forceEnrageField.SetValue(null, value);
			return true;
		}

		internal static bool TryEnrageEnemy(EnemyIdentifier enemy)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			Resolve();
			if (enrageEnemyMethod == null || !Object.op_Implicit((Object)(object)enemy) || enemy.dead)
			{
				return false;
			}
			try
			{
				enrageEnemyMethod.Invoke(null, new object[1] { enemy });
				return true;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)$"All-enemy enrage failed for {enemy.enemyType}: {ex.GetBaseException().Message}");
				return false;
			}
		}

		private static void Resolve()
		{
			if (resolved)
			{
				return;
			}
			resolved = true;
			Type type = AccessTools.TypeByName("AllEnemiesEnragable.AllEnemiesEnragablePlugin");
			if (type == null)
			{
				Plugin.Log.LogWarning((object)"AllEnemiesEnragable was not found; only enemies with native enrage support can be enraged.");
				return;
			}
			forceEnrageField = AccessTools.Field(type, "ForceEnrage");
			enrageEnemyMethod = AccessTools.Method(type, "EnrageEnemy", new Type[1] { typeof(EnemyIdentifier) }, (Type[])null);
			if (forceEnrageField == null || enrageEnemyMethod == null)
			{
				Plugin.Log.LogWarning((object)"AllEnemiesEnragable was found, but its force-enrage API was not compatible.");
			}
			else
			{
				Plugin.Log.LogInfo((object)"Connected to AllEnemiesEnragable force-enrage API.");
			}
		}
	}
	internal static class AngryCompatibility
	{
		private const string Name = "ULTRAMISERY";

		private static Type manager;

		private static Type difficulty;

		private static Type config;

		private static object entry;

		private static FieldInfo ukmdIndex;

		private static readonly BindingFlags All = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		internal static void Install(Harmony harmony)
		{
			if (!Chainloader.PluginInfos.TryGetValue("com.eternalUnion.angryLevelLoader", out var value))
			{
				return;
			}
			try
			{
				Assembly assembly = ((object)value.Instance).GetType().Assembly;
				manager = assembly.GetType("AngryLevelLoader.Managers.AngryDifficultyManager", throwOnError: true);
				difficulty = assembly.GetType("AngryLevelLoader.Managers.AngryDifficulty", throwOnError: true);
				config = assembly.GetType("AngryLevelLoader.Managers.ConfigManager", throwOnError: true);
				harmony.Patch((MethodBase)manager.GetMethod("Init", All), (HarmonyMethod)null, Hook("Register"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				harmony.Patch((MethodBase)difficulty.GetMethod("SetDifficulty", All), (HarmonyMethod)null, Hook("Apply"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				harmony.Patch((MethodBase)difficulty.GetMethod("UnsetDifficulty", All), (HarmonyMethod)null, Hook("Unset"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				harmony.Patch((MethodBase)manager.GetMethod("SetDifficultyFromPrefs", All), Hook("FromPrefs"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				GuardUkmdRegistration(harmony);
				if ((bool)manager.GetField("_inited", All).GetValue(null))
				{
					Register();
				}
				((MonoBehaviour)Plugin.Instance).StartCoroutine(RefreshField());
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Angry integration failed: " + ex));
			}
		}

		private static HarmonyMethod Hook(string method)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			return new HarmonyMethod(typeof(AngryCompatibility).GetMethod(method, All));
		}

		private static void GuardUkmdRegistration(Harmony harmony)
		{
			if (Chainloader.PluginInfos.TryGetValue("com.whyis2plus2.UKMDUnlocker", out var value))
			{
				Type? type = ((object)value.Instance).GetType().Assembly.GetType("UKMDUnlocker.Compat.AngryFix");
				MethodInfo methodInfo = type?.GetNestedType("Patches", BindingFlags.NonPublic)?.GetMethod("AddUKMDToDifficultyList", All);
				ukmdIndex = type?.GetField("ukmdIdx", All);
				if (methodInfo == null || ukmdIndex == null)
				{
					Plugin.Log.LogWarning((object)"UKMD Unlocker registration guard unavailable for this version.");
				}
				else
				{
					harmony.Patch((MethodBase)methodInfo, Hook("KeepSingleUkmd"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		internal static int FindNamedEntry(IList list, FieldInfo nameField, string name)
		{
			for (int i = 0; i < list.Count; i++)
			{
				if ((string)nameField.GetValue(list[i]) == name)
				{
					return i;
				}
			}
			return -1;
		}

		private static bool KeepSingleUkmd()
		{
			int num = FindNamedEntry((IList)manager.GetField("difficulties", All).GetValue(null), difficulty.GetField("name", All), "UKMD");
			if (num < 0)
			{
				return true;
			}
			ukmdIndex.SetValue(null, num);
			return false;
		}

		private static void Register()
		{
			IList list = (IList)manager.GetField("difficulties", All).GetValue(null);
			int num = FindNamedEntry(list, difficulty.GetField("name", All), "ULTRAMISERY");
			if (num >= 0)
			{
				entry = list[num];
				return;
			}
			entry = Activator.CreateInstance(difficulty, "ULTRAMISERY", 5);
			list.Add(entry);
			Plugin.Log.LogInfo((object)"Registered ULTRAMISERY in Angry Level Loader difficulty list (UKMD base).");
		}

		private static IEnumerator RefreshField()
		{
			yield return null;
			object value = config.GetField("difficultyField", All).GetValue(null);
			if (value == null)
			{
				yield break;
			}
			object value2 = value.GetType().GetField("internalDifficultyField", All).GetValue(value);
			if (!((IList)value2.GetType().GetField("values", All).GetValue(value2)).Contains("ULTRAMISERY"))
			{
				value2.GetType().GetMethod("AddValue", All).Invoke(value2, new object[1] { "ULTRAMISERY" });
			}
			object value3 = value.GetType().GetField("currentUi", All).GetValue(value);
			Object val = (Object)((value3 is Object) ? value3 : null);
			if (val != null && Object.op_Implicit(val))
			{
				object? value4 = value3.GetType().GetField("difficultyList", All).GetValue(value3);
				Dropdown val2 = (Dropdown)((value4 is Dropdown) ? value4 : null);
				if (Object.op_Implicit((Object)(object)val2) && !val2.options.Exists((OptionData o) => o.text == "ULTRAMISERY"))
				{
					val2.AddOptions(new List<string> { "ULTRAMISERY" });
				}
			}
		}

		private static void Apply(object __instance)
		{
			UltraMiseryState.SetSelected(__instance == entry);
		}

		private static void Unset(object __instance)
		{
			if (__instance == entry)
			{
				UltraMiseryState.SetSelected(selected: false);
			}
		}

		private static bool FromPrefs()
		{
			if (!UltraMiseryState.IsActive || entry == null)
			{
				return true;
			}
			manager.GetMethod("ForceSetDifficulty", All).Invoke(null, new object[1] { entry });
			return false;
		}
	}
	internal static class AttackRecoveryRules
	{
		internal sealed class Timer
		{
			internal float Age;
		}

		private static readonly ConditionalWeakTable<Component, Timer> Timers = new ConditionalWeakTable<Component, Timer>();

		internal static void Reset(Component component)
		{
			Timers.Remove(component);
		}

		internal static bool Expired(Component component, bool busy, Animator animator)
		{
			if (!UltraMiseryState.IsActive || !busy || !Object.op_Implicit((Object)(object)component) || !component.gameObject.activeInHierarchy)
			{
				Reset(component);
				return false;
			}
			Timer orCreateValue = Timers.GetOrCreateValue(component);
			if (Object.op_Implicit((Object)(object)animator) && ((Behaviour)animator).enabled && animator.speed > 0f)
			{
				orCreateValue.Age += Time.deltaTime * animator.speed;
			}
			if (orCreateValue.Age < 8f)
			{
				return false;
			}
			Reset(component);
			return true;
		}

		internal static void StopAudioIfPresent(AudioSource source)
		{
			if (Object.op_Implicit((Object)(object)source) || !UltraMiseryState.IsActive)
			{
				source.Stop();
			}
		}
	}
	[HarmonyPatch]
	internal static class FreshAirborneAttackAnimationPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(ZombieProjectiles), "Swing", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(ZombieMelee), "Swing", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(Turret), "StartWindup", (Type[])null, (Type[])null);
		}

		private static void Prefix(EnemyScript __instance, Animator ___anim)
		{
			if (EnemyAwarenessRules.CanAttack((Component)(object)__instance))
			{
				AttackRecoveryRules.Reset((Component)(object)__instance);
				Enemy component = ((Component)__instance).GetComponent<Enemy>();
				if (Object.op_Implicit((Object)(object)component) && !component.grounded && Object.op_Implicit((Object)(object)___anim))
				{
					___anim.ResetTrigger("StartFalling");
					___anim.SetBool("Falling", false);
				}
			}
		}
	}
	[HarmonyPatch(typeof(ZombieProjectiles), "Update")]
	internal static class ProjectileHuskAttackRecoveryPatch
	{
		private static void Postfix(ZombieProjectiles __instance, EnemyIdentifier ___eid, Animator ___anim)
		{
			if (!Object.op_Implicit((Object)(object)___eid) || ___eid.dead)
			{
				AttackRecoveryRules.Reset((Component)(object)__instance);
			}
			else if (AttackRecoveryRules.Expired((Component)(object)__instance, __instance.swinging, ___anim))
			{
				__instance.DamageEnd();
				__instance.CancelAttack();
				__instance.SwingEnd();
			}
		}
	}
	[HarmonyPatch(typeof(ZombieMelee), "Update")]
	internal static class MeleeHuskAttackRecoveryPatch
	{
		private static void Postfix(ZombieMelee __instance, EnemyIdentifier ___eid, Animator ___anim, bool ___inAction)
		{
			if (!Object.op_Implicit((Object)(object)___eid) || ___eid.dead)
			{
				AttackRecoveryRules.Reset((Component)(object)__instance);
			}
			else if (AttackRecoveryRules.Expired((Component)(object)__instance, ___inAction || __instance.damaging, ___anim))
			{
				__instance.DamageEnd();
				__instance.CancelAttack();
				__instance.SwingEnd();
			}
		}
	}
	[HarmonyPatch(typeof(MaliciousFace), "Update")]
	internal static class MaliciousFaceMissingChargeAudioPatch
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			MethodInfo stop = AccessTools.Method(typeof(AudioSource), "Stop", Type.EmptyTypes, (Type[])null);
			int count = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if (CodeInstructionExtensions.Calls(instruction, stop))
				{
					instruction.opcode = OpCodes.Call;
					instruction.operand = AccessTools.Method(typeof(AttackRecoveryRules), "StopAudioIfPresent", (Type[])null, (Type[])null);
					count++;
				}
				yield return instruction;
			}
			if (count != 1)
			{
				throw new InvalidOperationException("Malicious Face charge-audio hook changed: " + count);
			}
		}
	}
	[HarmonyPatch(typeof(SwordsMachine), "HeatSwordThrow")]
	internal static class SwordsmachineLostThrowTargetPatch
	{
		private static bool Prefix(SwordsMachine __instance, EnemyIdentifier ___eid, Animator ___anim)
		{
			if (!UltraMiseryState.IsActive || !Object.op_Implicit((Object)(object)___eid) || ___eid.dead)
			{
				return true;
			}
			if (___eid.target != null && ___eid.target.isValid)
			{
				return true;
			}
			___eid.UpdateTarget();
			if (___eid.target != null && ___eid.target.isValid)
			{
				return true;
			}
			__instance.DamageStop();
			__instance.CoolSword();
			__instance.StopAction();
			if (Object.op_Implicit((Object)(object)___anim))
			{
				___anim.SetTrigger("AnimationCancel");
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(EnemyIdentifier), "PuppetSpawn")]
	internal static class BloodTreePuppetSpawnPatch
	{
		private static void Prefix(EnemyIdentifier __instance)
		{
			if (UltraMiseryState.IsActive && Object.op_Implicit((Object)(object)__instance) && __instance.sandified)
			{
				__instance.Desandify(false);
			}
		}
	}
	[HarmonyPatch(typeof(EnemyIdentifier), "Sandify")]
	internal static class BloodTreePuppetSandifyPatch
	{
		private static bool Prefix(EnemyIdentifier __instance)
		{
			if (!UltraMiseryState.IsActive || !Object.op_Implicit((Object)(object)__instance) || !__instance.puppet)
			{
				return true;
			}
			if (__instance.sandified)
			{
				__instance.Desandify(false);
			}
			return false;
		}
	}
	internal sealed class UltraMiseryMassCannon : MonoBehaviour
	{
	}
	internal static class BossAiAreaDamageRules
	{
		private sealed class Contacts
		{
			internal readonly HashSet<int> Victims = new HashSet<int>();
		}

		private static readonly ConditionalWeakTable<PhysicalShockwave, Contacts> Hits = new ConditionalWeakTable<PhysicalShockwave, Contacts>();

		internal static bool SlamAllowed(bool aiCombat, EnemyType source)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Invalid comparison between Unknown and I4
			if (aiCombat)
			{
				return (int)source == 0;
			}
			return false;
		}

		internal static void DamageSlam(PhysicalShockwave wave, Collider col, EnemyIdentifier victim)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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_009f: Unknown result type (might be due to invalid IL or missing references)
			if (!SlamAllowed(LifestealRules.AiCombatAllowed, wave.enemyType) || !wave.enemy || !Object.op_Implicit((Object)(object)victim) || victim.dead)
			{
				return;
			}
			EnemyIdentifier val = LifestealRules.Resolve((Component)(object)wave);
			if (!Object.op_Implicit((Object)(object)val) || (Object)(object)val == (Object)(object)victim || (int)val.enemyType != 0 || wave.damage <= 0 || !Hits.GetOrCreateValue(wave).Victims.Add(((Object)victim).GetInstanceID()))
			{
				return;
			}
			EnemyIdentifier attacker = LifestealRules.Attacker;
			try
			{
				LifestealRules.Attacker = val;
				victim.hitter = "enemy";
				GameObject gameObject = ((Component)col).gameObject;
				Vector3 zero = Vector3.zero;
				Bounds bounds = col.bounds;
				victim.DeliverDamage(gameObject, zero, ((Bounds)(ref bounds)).center, (float)wave.damage / 10f, false, 0f, (GameObject)null, false, false);
			}
			finally
			{
				LifestealRules.Attacker = attacker;
			}
		}
	}
	[HarmonyPatch(typeof(Explosion), "Collide")]
	internal static class MassCannonAiExplosionPatch
	{
		internal struct State
		{
			internal bool Changed;

			internal bool Enemy;

			internal bool FriendlyFire;

			internal AffectedSubjects CanHit;

			internal List<EnemyType> Ignore;
		}

		private static bool Prefix(Explosion __instance, Collider other, out State __state)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: 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)
			__state = default(State);
			if (!LifestealRules.AiCombatAllowed || !Object.op_Implicit((Object)(object)((Component)__instance).GetComponentInParent<UltraMiseryMassCannon>()))
			{
				return true;
			}
			EnemyIdentifier enemy = FriendlyFireRules.GetEnemy(other);
			if (!Object.op_Implicit((Object)(object)enemy))
			{
				return true;
			}
			EnemyIdentifier val = LifestealRules.Resolve((Component)(object)__instance);
			if (Object.op_Implicit((Object)(object)val) && (Object)(object)enemy == (Object)(object)val)
			{
				return false;
			}
			__state = new State
			{
				Changed = true,
				Enemy = __instance.enemy,
				FriendlyFire = __instance.friendlyFire,
				CanHit = __instance.canHit,
				Ignore = __instance.toIgnore
			};
			__instance.enemy = false;
			__instance.friendlyFire = true;
			__instance.canHit = (AffectedSubjects)0;
			__instance.toIgnore = ((__instance.toIgnore == null) ? new List<EnemyType>() : new List<EnemyType>(__instance.toIgnore));
			__instance.toIgnore.RemoveAll((EnemyType type) => (int)type == 2);
			return true;
		}

		private static void Finalizer(Explosion __instance, State __state)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (__state.Changed && Object.op_Implicit((Object)(object)__instance))
			{
				__instance.enemy = __state.Enemy;
				__instance.friendlyFire = __state.FriendlyFire;
				__instance.canHit = __state.CanHit;
				__instance.toIgnore = __state.Ignore;
			}
		}
	}
	internal static class BoundaryRules
	{
		[HarmonyPatch(typeof(OutOfBounds), "OnTriggerEnter")]
		private static class AuthoredBoundaryPatch
		{
			private static void Prefix(OutOfBounds __instance, Collider other)
			{
				//IL_0064: Unknown result type (might be due to invalid IL or missing references)
				//IL_006a: Invalid comparison between Unknown and I4
				//IL_007c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0081: Unknown result type (might be due to invalid IL or missing references)
				NewMovement instance = MonoSingleton<NewMovement>.Instance;
				CheatsController instance2 = MonoSingleton<CheatsController>.Instance;
				if (Object.op_Implicit((Object)(object)other) && ((Component)other).CompareTag("Player") && ShouldRecord(UltraMiseryState.IsActive, SceneHelper.IsPlayingCustom, Object.op_Implicit((Object)(object)MonoSingleton<SandboxNavmesh>.Instance), Object.op_Implicit((Object)(object)instance2) && instance2.cheatsEnabled, Object.op_Implicit((Object)(object)instance) && instance.hp > 0 && !instance.levelOver, (int)__instance.targets != 2))
				{
					int sceneHandle = BoundaryRules.sceneHandle;
					Scene activeScene = SceneManager.GetActiveScene();
					if (sceneHandle != ((Scene)(ref activeScene)).handle)
					{
						Reset();
					}
					if (!crossed)
					{
						crossed = true;
						Plugin.Log.LogWarning((object)("UltraMisery: player entered authored OutOfBounds volume without cheats; this run cannot receive P rank. Volume: " + ((Object)__instance).name));
					}
				}
			}
		}

		private static int sceneHandle = -1;

		private static bool crossed;

		internal static bool InvalidRun
		{
			get
			{
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				int num = sceneHandle;
				Scene activeScene = SceneManager.GetActiveScene();
				if (num == ((Scene)(ref activeScene)).handle)
				{
					return crossed;
				}
				return false;
			}
		}

		internal static void Reset()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			Scene activeScene = SceneManager.GetActiveScene();
			sceneHandle = ((Scene)(ref activeScene)).handle;
			crossed = false;
		}

		internal static bool ShouldRecord(bool active, bool custom, bool sandbox, bool cheats, bool alive, bool playerVolume)
		{
			return active && !custom && !sandbox && !cheats && alive && playerVolume;
		}
	}
	internal static class ChandelierRules
	{
		internal static bool IsChandelierLabel(string value)
		{
			if (!string.IsNullOrEmpty(value))
			{
				return value.IndexOf("chandelier", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return false;
		}

		internal static bool Matches(Component hazard)
		{
			if (!UltraMiseryState.IsActive || !Object.op_Implicit((Object)(object)hazard))
			{
				return false;
			}
			DeathZone val = (DeathZone)(object)((hazard is DeathZone) ? hazard : null);
			if (val != null && IsChandelierLabel(val.deathType))
			{
				return true;
			}
			Transform val2 = hazard.transform;
			int num = 0;
			while (Object.op_Implicit((Object)(object)val2) && num < 4)
			{
				if (IsChandelierLabel(((Object)val2).name))
				{
					return true;
				}
				num++;
				val2 = val2.parent;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(DeathZone), "GotHit")]
	internal static class ChandelierEnemyDeathImmunityPatch
	{
		private static bool Prefix(DeathZone __instance, Collider other)
		{
			if (Object.op_Implicit((Object)(object)FriendlyFireRules.GetEnemy(other)))
			{
				return !ChandelierRules.Matches((Component)(object)__instance);
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(HurtZone), "DamageEnemy")]
	internal static class ChandelierEnemyDamageImmunityPatch
	{
		private static bool Prefix(HurtZone __instance, ref bool __result)
		{
			if (!ChandelierRules.Matches((Component)(object)__instance))
			{
				return true;
			}
			__result = true;
			return false;
		}
	}
	[HarmonyPatch(typeof(Explosion), "Collide")]
	internal static class ChandelierEnemyExplosionImmunityPatch
	{
		private static bool Prefix(Explosion __instance, Collider other)
		{
			if (Object.op_Implicit((Object)(object)FriendlyFireRules.GetEnemy(other)))
			{
				return !ChandelierRules.Matches((Component)(object)__instance);
			}
			return true;
		}
	}
	internal static class CutsceneAttackLockRules
	{
		private static readonly HashSet<CutsceneSkip> Active = new HashSet<CutsceneSkip>();

		private static readonly HashSet<V2> V2Intros = new HashSet<V2>();

		internal static bool Locked
		{
			get
			{
				//IL_003d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0042: Unknown result type (might be due to invalid IL or missing references)
				if (!UltraMiseryState.IsActive || SceneHelper.IsPlayingCustom || Object.op_Implicit((Object)(object)MonoSingleton<SandboxNavmesh>.Instance))
				{
					return false;
				}
				if (!Object.op_Implicit((Object)(object)MonoSingleton<NewMovement>.Instance) || MonoSingleton<NewMovement>.Instance.dead)
				{
					return false;
				}
				Scene activeScene = SceneManager.GetActiveScene();
				int scene = ((Scene)(ref activeScene)).handle;
				Active.RemoveWhere(delegate(CutsceneSkip item)
				{
					//IL_0016: Unknown result type (might be due to invalid IL or missing references)
					//IL_001b: Unknown result type (might be due to invalid IL or missing references)
					if (Object.op_Implicit((Object)(object)item) && ((Behaviour)item).isActiveAndEnabled)
					{
						Scene scene2 = ((Component)item).gameObject.scene;
						return ((Scene)(ref scene2)).handle != scene;
					}
					return true;
				});
				V2Intros.RemoveWhere(delegate(V2 item)
				{
					//IL_001e: 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)
					if (Object.op_Implicit((Object)(object)item) && ((Behaviour)item).isActiveAndEnabled && item.inIntro)
					{
						Scene scene2 = ((Component)item).gameObject.scene;
						return ((Scene)(ref scene2)).handle != scene;
					}
					return true;
				});
				if (Active.Count == 0)
				{
					return V2Intros.Count != 0;
				}
				return true;
			}
		}

		internal static void Track(V2 boss)
		{
			if (Object.op_Implicit((Object)(object)boss) && boss.inIntro)
			{
				V2Intros.Add(boss);
			}
		}

		internal static void Begin(CutsceneSkip cutscene)
		{
			Active.Add(cutscene);
		}

		internal static void End(CutsceneSkip cutscene)
		{
			Active.Remove(cutscene);
		}

		internal static bool IsAttack(string name)
		{
			switch (name)
			{
			default:
				return name == "Hook";
			case "PrimaryFire":
			case "SecondaryFire":
			case "Punch":
				return true;
			}
		}
	}
	[HarmonyPatch(typeof(V2), "Start")]
	internal static class V2IntroAttackLockPatch
	{
		private static void Postfix(V2 __instance)
		{
			CutsceneAttackLockRules.Track(__instance);
		}
	}
	[HarmonyPatch(typeof(CutsceneSkip), "OnEnable")]
	internal static class CutsceneAttackLockBeginPatch
	{
		private static void Prefix(CutsceneSkip __instance)
		{
			CutsceneAttackLockRules.Begin(__instance);
		}
	}
	[HarmonyPatch(typeof(CutsceneSkip), "OnDisable")]
	internal static class CutsceneAttackLockEndPatch
	{
		private static void Prefix(CutsceneSkip __instance)
		{
			CutsceneAttackLockRules.End(__instance);
		}
	}
	[HarmonyPatch(typeof(CutsceneSkip), "LateUpdate")]
	internal static class CutsceneAttackLockSkipPatch
	{
		private static void Prefix(bool ___waitingForInput, out bool __state)
		{
			__state = ___waitingForInput;
		}

		private static void Postfix(CutsceneSkip __instance, bool ___waitingForInput, bool __state)
		{
			if (__state && !___waitingForInput)
			{
				CutsceneAttackLockRules.End(__instance);
			}
		}
	}
	[HarmonyPatch]
	internal static class CutsceneAttackInputPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			string[] array = new string[3] { "IsPressed", "WasPerformedThisFrame", "WasCanceledThisFrame" };
			foreach (string text in array)
			{
				yield return AccessTools.PropertyGetter(typeof(InputActionState), text);
			}
		}

		private static void Postfix(InputActionState __instance, ref bool __result)
		{
			if (__result && CutsceneAttackLockRules.IsAttack(__instance.Action.name) && CutsceneAttackLockRules.Locked)
			{
				__result = false;
			}
		}
	}
	[HarmonyPatch]
	internal static class CutsceneWeaponEmissionPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			(Type, string[])[] array = new(Type, string[])[7]
			{
				(typeof(Revolver), new string[3] { "Shoot", "ThrowCoin", "Punch" }),
				(typeof(Shotgun), new string[3] { "Shoot", "ShootSinks", "ShootSaw" }),
				(typeof(ShotgunHammer), new string[3] { "Impact", "ThrowNade", "ShootSaw" }),
				(typeof(Nailgun), new string[3] { "Shoot", "ShootMagnet", "ShootZapper" }),
				(typeof(Railcannon), new string[1] { "Shoot" }),
				(typeof(RocketLauncher), new string[3] { "Shoot", "ShootCannonball", "ShootNapalm" }),
				(typeof(Punch), new string[1] { "PunchStart" })
			};
			for (int i = 0; i < array.Length; i++)
			{
				(Type, string[]) entry = array[i];
				MethodInfo[] methods = entry.Item1.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo in methods)
				{
					if (Array.IndexOf(entry.Item2, methodInfo.Name) >= 0)
					{
						yield return methodInfo;
					}
				}
			}
		}

		private static bool Prefix()
		{
			return !CutsceneAttackLockRules.Locked;
		}
	}
	internal static class DamageBonusRules
	{
		internal static readonly MethodInfo FactorMethod = typeof(DamageBonusRules).GetMethod("Factor", BindingFlags.Static | BindingFlags.NonPublic);

		internal static float InvertBonus(float factor)
		{
			if (!(factor > 1f))
			{
				return factor;
			}
			return 1f / factor;
		}

		internal static float InvertCritical(float critical, float limb)
		{
			if (critical <= 0f || limb <= 0f)
			{
				return critical;
			}
			return (1f / (1f + limb * critical) - 1f) / limb;
		}

		internal static float Factor(float value)
		{
			if (!UltraMiseryState.IsActive)
			{
				return value;
			}
			return InvertBonus(value);
		}
	}
	[HarmonyPatch]
	internal static class InvertedEnemyLocationalBonusPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			Type[] array = new Type[4]
			{
				typeof(Enemy),
				typeof(Zombie),
				typeof(Machine),
				typeof(Statue)
			};
			foreach (Type type in array)
			{
				yield return AccessTools.DeclaredMethod(type, "GetHurt", (Type[])null, (Type[])null);
			}
		}

		private static void Prefix(GameObject target, ref float critMultiplier)
		{
			if (UltraMiseryState.IsActive && Object.op_Implicit((Object)(object)target))
			{
				float limb = (target.CompareTag("Head") ? 1f : ((target.CompareTag("Limb") || target.CompareTag("EndLimb")) ? 0.5f : 0f));
				critMultiplier = DamageBonusRules.InvertCritical(critMultiplier, limb);
			}
		}
	}
	[HarmonyPatch(typeof(Nail), "GetFodderDamageMultiplier")]
	internal static class InvertedNailSpeciesBonusPatch
	{
		private static void Postfix(ref float __result)
		{
			__result = DamageBonusRules.Factor(__result);
		}
	}
	[HarmonyPatch(typeof(EnemyIdentifier), "DeliverDamage")]
	internal static class InvertedEnemyWeaknessBonusPatch
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			bool weaknessElement = false;
			int count = 0;
			List<CodeInstruction> code = new List<CodeInstruction>(instructions);
			for (int i = 0; i < code.Count; i++)
			{
				CodeInstruction instruction = code[i];
				yield return instruction;
				if (instruction.opcode == OpCodes.Ldfld && instruction.operand is FieldInfo { Name: "weaknessMultipliers" })
				{
					weaknessElement = true;
				}
				bool num = weaknessElement && instruction.opcode == OpCodes.Ldelem_R4;
				if (num)
				{
					weaknessElement = false;
				}
				if (num | (instruction.opcode == OpCodes.Ldfld && instruction.operand is FieldInfo fieldInfo2 && fieldInfo2.Name == "totalDamageTakenMultiplier") | (instruction.opcode == OpCodes.Ldc_R4 && object.Equals(instruction.operand, 1.5f) && i + 1 < code.Count && code[i + 1].opcode == OpCodes.Mul))
				{
					yield return new CodeInstruction(OpCodes.Call, (object)DamageBonusRules.FactorMethod);
					count++;
				}
			}
			if (count != 3)
			{
				throw new InvalidOperationException("Enemy damage modifier IL changed: " + count);
			}
		}
	}
	[HarmonyPatch]
	internal static class InvertedEnemyWeakSpotBonusPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(Enemy), "CalculateDamage", (Type[])null, (Type[])null);
			yield return AccessTools.DeclaredMethod(typeof(Statue), "GetHurt", (Type[])null, (Type[])null);
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			List<CodeInstruction> code = new List<CodeInstruction>(instructions);
			int count = 0;
			for (int i = 0; i < code.Count; i++)
			{
				yield return code[i];
				if (code[i].opcode == OpCodes.Ldfld && code[i].operand is FieldInfo { Name: "extraDamageMultiplier" } && i + 1 < code.Count && code[i + 1].opcode == OpCodes.Mul)
				{
					yield return new CodeInstruction(OpCodes.Call, (object)DamageBonusRules.FactorMethod);
					count++;
				}
			}
			if (count != ((!(__originalMethod.DeclaringType == typeof(Statue))) ? 1 : 3))
			{
				throw new InvalidOperationException("Weak-spot modifier IL changed: " + __originalMethod?.ToString() + " " + count);
			}
		}
	}
	[HarmonyPatch]
	internal static class InvertedAttackSpecificBonusPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(Enemy), "HandleParrying", (Type[])null, (Type[])null);
			yield return AccessTools.DeclaredMethod(typeof(Zombie), "GetHurt", (Type[])null, (Type[])null);
			yield return AccessTools.DeclaredMethod(typeof(Machine), "GetHurt", (Type[])null, (Type[])null);
			yield return AccessTools.DeclaredMethod(typeof(Statue), "GetHurt", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(Explosion), "Collide", (Type[])null, (Type[])null);
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			List<CodeInstruction> code = new List<CodeInstruction>(instructions);
			Type owner = __originalMethod.DeclaringType;
			bool explosion = owner == typeof(Explosion);
			int count = 0;
			for (int i = 0; i < code.Count; i++)
			{
				CodeInstruction instruction = code[i];
				yield return instruction;
				if (i + 1 < code.Count && !(code[i + 1].opcode != OpCodes.Mul) && ((instruction.opcode == OpCodes.Ldc_R4 && (object.Equals(instruction.operand, 2f) || (owner != typeof(Zombie) && object.Equals(instruction.operand, 1.5f)))) | (explosion && instruction.opcode == OpCodes.Ldfld && instruction.operand is FieldInfo fieldInfo && fieldInfo.Name == "enemyDamageMultiplier")))
				{
					yield return new CodeInstruction(OpCodes.Call, (object)DamageBonusRules.FactorMethod);
					count++;
				}
			}
			int num = (explosion ? 4 : ((!(owner == typeof(Enemy))) ? 1 : 2));
			if (count != num)
			{
				throw new InvalidOperationException("Attack bonus IL changed: " + __originalMethod?.ToString() + " " + count);
			}
		}
	}
	[HarmonyPatch]
	internal static class InvertedAirborneHuskBonusPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.DeclaredMethod(typeof(Enemy), "GetHurt", (Type[])null, (Type[])null);
			yield return AccessTools.DeclaredMethod(typeof(Zombie), "GetHurt", (Type[])null, (Type[])null);
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			bool found = false;
			foreach (CodeInstruction instruction in instructions)
			{
				yield return instruction;
				if (!found && instruction.opcode == OpCodes.Ldc_R4 && object.Equals(instruction.operand, 1.5f))
				{
					yield return new CodeInstruction(OpCodes.Call, (object)DamageBonusRules.FactorMethod);
					found = true;
				}
			}
			if (!found)
			{
				throw new InvalidOperationException("Airborne husk modifier IL changed");
			}
		}
	}
	[HarmonyPatch(typeof(EnemyIdentifier), "ProcessDeath")]
	internal static class RemoveGuttermanCorpsePatch
	{
		private static void Postfix(EnemyIdentifier __instance)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Invalid comparison between Unknown and I4
			if (UltraMiseryState.IsActive && __instance.dead && (int)__instance.enemyType == 33)
			{
				Collider[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<Collider>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					componentsInChildren[i].enabled = false;
				}
				Renderer[] componentsInChildren2 = ((Component)__instance).GetComponentsInChildren<Renderer>(true);
				for (int i = 0; i < componentsInChildren2.Length; i++)
				{
					componentsInChildren2[i].enabled = false;
				}
				Object.Destroy((Object)(object)((Component)__instance).gameObject);
			}
		}
	}
	[HarmonyPatch(typeof(Gutterman), "Start")]
	internal static class RemovePreDeadGuttermanPatch
	{
		private static void Postfix(Gutterman __instance)
		{
			if (UltraMiseryState.IsActive && __instance.dead)
			{
				Object.Destroy((Object)(object)((Component)__instance).gameObject);
			}
		}
	}
	internal sealed class UltraMiseryHiddenGuttermanCorpse : MonoBehaviour
	{
		private Renderer[] renderers;

		private Collider[] colliders;

		private bool[] rendererStates;

		private bool[] colliderStates;

		private EnemyIdentifier enemy;

		private void Awake()
		{
			enemy = ((Component)this).GetComponent<EnemyIdentifier>();
			renderers = ((Component)this).GetComponentsInChildren<Renderer>(true);
			colliders = ((Component)this).GetComponentsInChildren<Collider>(true);
			rendererStates = Array.ConvertAll(renderers, (Renderer item) => item.enabled);
			colliderStates = Array.ConvertAll(colliders, (Collider item) => item.enabled);
		}

		private void LateUpdate()
		{
			if (Object.op_Implicit((Object)(object)enemy) && !enemy.dead)
			{
				for (int i = 0; i < renderers.Length; i++)
				{
					if (Object.op_Implicit((Object)(object)renderers[i]))
					{
						renderers[i].enabled = rendererStates[i];
					}
				}
				for (int j = 0; j < colliders.Length; j++)
				{
					if (Object.op_Implicit((Object)(object)colliders[j]))
					{
						colliders[j].enabled = colliderStates[j];
					}
				}
				Object.Destroy((Object)(object)this);
				return;
			}
			Renderer[] array = renderers;
			foreach (Renderer val in array)
			{
				if (Object.op_Implicit((Object)(object)val))
				{
					val.enabled = false;
				}
			}
			Collider[] array2 = colliders;
			foreach (Collider val2 in array2)
			{
				if (Object.op_Implicit((Object)(object)val2))
				{
					val2.enabled = false;
				}
			}
		}

		internal void HideNow()
		{
			Renderer[] array = renderers;
			foreach (Renderer val in array)
			{
				if (Object.op_Implicit((Object)(object)val))
				{
					val.enabled = false;
				}
			}
			Collider[] array2 = colliders;
			foreach (Collider val2 in array2)
			{
				if (Object.op_Implicit((Object)(object)val2))
				{
					val2.enabled = false;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Gutterman), "Death")]
	internal static class HideGuttermanCorpsePatch
	{
		private static void Prefix(Gutterman __instance)
		{
			if (UltraMiseryState.IsActive && !Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<UltraMiseryHiddenGuttermanCorpse>()))
			{
				((Component)__instance).gameObject.AddComponent<UltraMiseryHiddenGuttermanCorpse>();
			}
		}

		private static void Postfix(Gutterman __instance)
		{
			if (UltraMiseryState.IsActive)
			{
				(((Component)__instance).GetComponent<UltraMiseryHiddenGuttermanCorpse>() ?? ((Component)__instance).gameObject.AddComponent<UltraMiseryHiddenGuttermanCorpse>()).HideNow();
			}
		}
	}
	[HarmonyPatch]
	internal static class GroundWaveMissingTargetPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			string[] array = new string[3] { "Update", "FixedUpdate", "TrackTick" };
			foreach (string text in array)
			{
				yield return AccessTools.Method(typeof(GroundWave), text, (Type[])null, (Type[])null);
			}
		}

		private static bool Prefix(GroundWave __instance)
		{
			if (!UltraMiseryState.IsActive || (__instance.target != null && Object.op_Implicit((Object)(object)__instance.target.trackedTransform)))
			{
				return true;
			}
			((MonoBehaviour)__instance).CancelInvoke();
			((Component)__instance).gameObject.SetActive(false);
			Object.Destroy((Object)(object)((Component)__instance).gameObject);
			return false;
		}
	}
	[HarmonyPatch(typeof(Deathcatcher), "Start")]
	internal static class DeathcatcherNoIdolRevivalSetupPatch
	{
		private static void Postfix(Deathcatcher __instance)
		{
			if (UltraMiseryState.IsActive)
			{
				__instance.canRespawnIdols = false;
			}
		}
	}
	[HarmonyPatch(typeof(Deathcatcher), "EnemyDeath")]
	internal static class DeathcatcherNoIdolRevivalPatch
	{
		private static bool Prefix(EnemyIdentifier eid)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Invalid comparison between Unknown and I4
			if (UltraMiseryState.IsActive && Object.op_Implicit((Object)(object)eid))
			{
				return (int)eid.enemyType != 21;
			}
			return true;
		}
	}
	internal sealed class UltraMiseryDifficultyMarker : MonoBehaviour
	{
	}
	internal static class DifficultySelectionUi
	{
		private const float VisibleHierarchySettleSeconds = 0.75f;

		private static int candidateParentId;

		private static float candidateFirstSeenAt;

		internal static void ResetReconciliation()
		{
			candidateParentId = 0;
			candidateFirstSeenAt = 0f;
		}

		internal static void ReconcileVisibleButton()
		{
			UltraMiseryDifficultyMarker ultraMiseryDifficultyMarker = FindVisibleButton();
			if (Object.op_Implicit((Object)(object)ultraMiseryDifficultyMarker))
			{
				DifficultyWheelInput.Ensure(((Component)ultraMiseryDifficultyMarker).transform);
				ResetReconciliation();
				return;
			}
			DifficultySelectButton val = FindVisibleSourceButton();
			if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)((Component)val).transform.parent))
			{
				ResetReconciliation();
				return;
			}
			int instanceID = ((Object)((Component)val).transform.parent).GetInstanceID();
			if (candidateParentId != instanceID)
			{
				candidateParentId = instanceID;
				candidateFirstSeenAt = Time.unscaledTime;
			}
			else if (!(Time.unscaledTime - candidateFirstSeenAt < 0.75f))
			{
				RemoveObsoleteHiddenButtons(((Component)val).transform.parent);
				GameObject val2 = CreateButton(val);
				if (Object.op_Implicit((Object)(object)val2))
				{
					Transform transform = val2.transform;
					RebuildContainingLayouts((RectTransform)(object)((transform is RectTransform) ? transform : null));
					Plugin.Log.LogInfo((object)("Reconciled visible ULTRAMISERY difficulty button beside " + GetHierarchyPath(((Component)val).transform) + "."));
					ResetReconciliation();
				}
			}
		}

		private static GameObject CreateButton(DifficultySelectButton source)
		{
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: 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)
			GameObject val = Object.Instantiate<GameObject>(((Component)source).gameObject, ((Component)source).transform.parent);
			val.SetActive(false);
			((Object)val).name = "UltraMisery";
			DifficultySelectButton component = val.GetComponent<DifficultySelectButton>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				Object.Destroy((Object)(object)val);
				return null;
			}
			component.difficulty = 5;
			val.AddComponent<UltraMiseryDifficultyMarker>();
			TMP_Text[] componentsInChildren = val.GetComponentsInChildren<TMP_Text>(true);
			TMP_Text val2 = null;
			TMP_Text[] array = componentsInChildren;
			foreach (TMP_Text val3 in array)
			{
				if (((Object)val3.transform).name == "Name")
				{
					val2 = val3;
					break;
				}
			}
			if (!Object.op_Implicit((Object)(object)val2) && componentsInChildren.Length != 0)
			{
				val2 = componentsInChildren[0];
			}
			if (Object.op_Implicit((Object)(object)val2))
			{
				val2.text = "ULTRAMISERY";
			}
			val.transform.SetSiblingIndex(((Component)source).transform.GetSiblingIndex() + 1);
			Transform transform = ((Component)source).transform;
			RectTransform val4 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			Transform transform2 = val.transform;
			RectTransform val5 = (RectTransform)(object)((transform2 is RectTransform) ? transform2 : null);
			if (Object.op_Implicit((Object)(object)val4) && Object.op_Implicit((Object)(object)val5) && !Object.op_Implicit((Object)(object)((Component)val.transform.parent).GetComponent<LayoutGroup>()))
			{
				Rect rect = val4.rect;
				float num = Mathf.Max(60f, ((Rect)(ref rect)).height + 8f);
				val5.anchoredPosition = val4.anchoredPosition + Vector2.down * num;
			}
			val.SetActive(true);
			DifficultyWheelInput.Ensure(val.transform);
			RebuildContainingLayouts(val5);
			return val;
		}

		private static UltraMiseryDifficultyMarker FindVisibleButton()
		{
			UltraMiseryDifficultyMarker[] array = Object.FindObjectsOfType<UltraMiseryDifficultyMarker>();
			foreach (UltraMiseryDifficultyMarker ultraMiseryDifficultyMarker in array)
			{
				if (Object.op_Implicit((Object)(object)ultraMiseryDifficultyMarker) && ((Component)ultraMiseryDifficultyMarker).gameObject.activeInHierarchy)
				{
					return ultraMiseryDifficultyMarker;
				}
			}
			return null;
		}

		private static void RemoveObsoleteHiddenButtons(Transform visibleParent)
		{
			UltraMiseryDifficultyMarker[] array = Resources.FindObjectsOfTypeAll<UltraMiseryDifficultyMarker>();
			foreach (UltraMiseryDifficultyMarker ultraMiseryDifficultyMarker in array)
			{
				if (Object.op_Implicit((Object)(object)ultraMiseryDifficultyMarker) && !((Component)ultraMiseryDifficultyMarker).gameObject.activeInHierarchy && (Object)(object)((Component)ultraMiseryDifficultyMarker).transform.parent != (Object)(object)visibleParent)
				{
					Object.Destroy((Object)(object)((Component)ultraMiseryDifficultyMarker).gameObject);
				}
			}
		}

		private static DifficultySelectButton FindVisibleSourceButton()
		{
			DifficultySelectButton result = null;
			DifficultySelectButton[] array = Object.FindObjectsOfType<DifficultySelectButton>();
			foreach (DifficultySelectButton val in array)
			{
				if (Object.op_Implicit((Object)(object)val) && ((Component)val).gameObject.activeInHierarchy && !Object.op_Implicit((Object)(object)((Component)val).GetComponent<UltraMiseryDifficultyMarker>()))
				{
					if (val.difficulty == 5)
					{
						return val;
					}
					if (val.difficulty == 4)
					{
						result = val;
					}
				}
			}
			return result;
		}

		private static void RebuildContainingLayouts(RectTransform rect)
		{
			Canvas.ForceUpdateCanvases();
			Transform val = (Transform)(object)rect;
			int num = 0;
			while (Object.op_Implicit((Object)(object)val) && num < 8)
			{
				RectTransform val2 = (RectTransform)(object)((val is RectTransform) ? val : null);
				if (Object.op_Implicit((Object)(object)val2))
				{
					LayoutRebuilder.ForceRebuildLayoutImmediate(val2);
				}
				num++;
				val = val.parent;
			}
			Canvas.ForceUpdateCanvases();
		}

		private static string GetHierarchyPath(Transform transform)
		{
			string text = (Object.op_Implicit((Object)(object)transform) ? ((Object)transform).name : "<missing>");
			Transform val = (Object.op_Implicit((Object)(object)transform) ? transform.parent : null);
			while (Object.op_Implicit((Object)(object)val))
			{
				text = ((Object)val).name + "/" + text;
				val = val.parent;
			}
			return text;
		}
	}
	[HarmonyPatch(typeof(DifficultySelectButton), "SetDifficulty")]
	internal static class UltraMiseryDifficultySelectionPatch
	{
		private static void Postfix(DifficultySelectButton __instance)
		{
			UltraMiseryState.SetSelected(Object.op_Implicit((Object)(object)__instance) && Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<UltraMiseryDifficultyMarker>()));
		}
	}
	[HarmonyPatch(typeof(DifficultyTitle), "Check")]
	internal static class UltraMiseryDifficultyTitlePatch
	{
		private static void Postfix(DifficultyTitle __instance)
		{
			if (UltraMiseryState.IsActive && Object.op_Implicit((Object)(object)__instance))
			{
				TMP_Text component = ((Component)__instance).GetComponent<TMP_Text>();
				if (Object.op_Implicit((Object)(object)component))
				{
					component.text = (__instance.lines ? "-- ULTRAMISERY --" : "ULTRAMISERY");
				}
			}
		}
	}
	internal sealed class DifficultyWheelInput : MonoBehaviour
	{
		private ScrollRect scroll;

		private Canvas canvas;

		private readonly List<RaycastResult> hits = new List<RaycastResult>();

		internal int LastScrollFrame = -1;

		internal static void Ensure(Transform button)
		{
			ScrollRect componentInParent = ((Component)button).GetComponentInParent<ScrollRect>();
			if (Object.op_Implicit((Object)(object)componentInParent) && !Object.op_Implicit((Object)(object)((Component)componentInParent).GetComponent<DifficultyWheelInput>()))
			{
				DifficultyWheelInput difficultyWheelInput = ((Component)componentInParent).gameObject.AddComponent<DifficultyWheelInput>();
				difficultyWheelInput.scroll = componentInParent;
				difficultyWheelInput.canvas = ((Component)componentInParent).GetComponentInParent<Canvas>();
			}
		}

		private void LateUpdate()
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: 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_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: 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)
			//IL_00cd: 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_00d3: 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_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Expected O, but got Unknown
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)scroll) || !((UIBehaviour)scroll).IsActive() || !Object.op_Implicit((Object)(object)scroll.viewport) || LastScrollFrame == Time.frameCount || Mouse.current == null || !Object.op_Implicit((Object)(object)EventSystem.current))
			{
				return;
			}
			Vector2 val = ((InputControl<Vector2>)(object)Mouse.current.scroll).ReadValue() / 120f;
			if (Mathf.Approximately(val.y, 0f))
			{
				return;
			}
			Vector2 val2 = ((InputControl<Vector2>)(object)((Pointer)Mouse.current).position).ReadValue();
			Camera val3 = ((Object.op_Implicit((Object)(object)canvas) && (int)canvas.renderMode != 0) ? canvas.worldCamera : null);
			if (!RectTransformUtility.RectangleContainsScreenPoint(scroll.viewport, val2, val3))
			{
				return;
			}
			PointerEventData val4 = new PointerEventData(EventSystem.current)
			{
				position = val2,
				scrollDelta = val
			};
			hits.Clear();
			EventSystem.current.RaycastAll(val4, hits);
			if (hits.Count > 0)
			{
				RaycastResult val5 = hits[0];
				if (!((RaycastResult)(ref val5)).gameObject.transform.IsChildOf(((Component)scroll).transform))
				{
					return;
				}
			}
			scroll.OnScroll(val4);
		}
	}
	[HarmonyPatch(typeof(ScrollRect), "OnScroll")]
	internal static class DifficultyWheelDeliveredPatch
	{
		private static void Postfix(ScrollRect __instance)
		{
			DifficultyWheelInput component = ((Component)__instance).GetComponent<DifficultyWheelInput>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.LastScrollFrame = Time.frameCount;
			}
		}
	}
	[HarmonyPatch]
	internal static class DroneHalfMovementSpeedPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(Drone), "FixedUpdate", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(Drone), "Dodge", new Type[1] { typeof(Vector3) }, (Type[])null);
		}

		private static void Prefix(EnemyIdentifier ___eid, out float? __state)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Invalid comparison between Unknown and I4
			__state = null;
			if (UltraMiseryState.IsActive && Object.op_Implicit((Object)(object)___eid) && (int)___eid.enemyType == 1)
			{
				__state = ___eid.totalSpeedModifier;
				___eid.totalSpeedModifier *= 0.5f;
			}
		}

		private static void Finalizer(EnemyIdentifier ___eid, float? __state)
		{
			if (Object.op_Implicit((Object)(object)___eid) && __state.HasValue)
			{
				___eid.totalSpeedModifier = __state.Value;
			}
		}
	}
	internal static class DroneTargetRules
	{
		internal static bool IsLive(ITarget target)
		{
			if (target != null)
			{
				Object val = (Object)(object)((target is Object) ? target : null);
				if (val == null || Object.op_Implicit(val))
				{
					GameObject gameObject = target.GameObject;
					if (!Object.op_Implicit((Object)(object)gameObject) || !gameObject.activeInHierarchy)
					{
						return false;
					}
					if (target is UltraMiserySupportTarget && !LifestealRules.AiCombatAllowed)
					{
						return false;
					}
					if (target.isEnemy)
					{
						if (Object.op_Implicit((Object)(object)target.EID))
						{
							return !target.EID.dead;
						}
						return false;
					}
					return true;
				}
			}
			return false;
		}
	}
	[HarmonyPatch]
	internal static class DroneStaleTargetPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			string[] array = new string[4] { "Update", "FixedUpdate", "SightCheck", "Shoot" };
			foreach (string text in array)
			{
				yield return AccessTools.Method(typeof(Drone), text, (Type[])null, (Type[])null);
			}
		}

		private static void Prefix(EnemyIdentifier ___eid, ref TargetHandle ___droneTargetHandle, ref TargetData ___droneTargetData, ref Vector3 ___lastDimensionalTarget)
		{
			//IL_006c: 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_0078: Unknown result type (might be due to invalid IL or missing references)
			if (UltraMiseryState.IsActive && !(___droneTargetHandle == (TargetHandle)null) && ((Object.op_Implicit((Object)(object)___eid) && ___eid.target != null && ___eid.target.isEnemy && ___droneTargetHandle.target != null && (Object)(object)___droneTargetHandle.target.EID != (Object)(object)___eid.target.enemyIdentifier) || !DroneTargetRules.IsLive(___droneTargetHandle.target)))
			{
				___droneTargetHandle = null;
				___droneTargetData = default(TargetData);
				___lastDimensionalTarget = Vector3.zero;
			}
		}
	}
	[HarmonyPatch(typeof(Drone), "ObstructionCheck", new Type[] { typeof(TargetData) })]
	internal static class OmniscientDroneFiringPatch
	{
		private static bool Prefix(Drone __instance, EnemyIdentifier ___eid, TargetData data, ref bool __result)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Invalid comparison between Unknown and I4
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (!EnemyAwarenessRules.CanAttack((Component)(object)__instance) || (int)___eid.enemyType != 1)
			{
				return true;
			}
			if (ObstructedAttackRules.Approaching(___eid))
			{
				return true;
			}
			__result = data.handle != (TargetHandle)null && DroneTargetRules.IsLive(data.handle.target);
			return false;
		}
	}
	internal sealed class UltraMiseryMortarClearance : MonoBehaviour
	{
		private Projectile shot;

		private Collider[] shells;

		private readonly List<(Collider Shot, Collider Unit)> changedPairs = new List<(Collider, Collider)>();

		internal void Bind(EnemyIdentifier owner)
		{
			shot = ((Component)this).GetComponent<Projectile>();
			shells = ((Component)this).GetComponentsInChildren<Collider>(true);
			Restore();
			Collider[] componentsInChildren = ((Component)owner).GetComponentsInChildren<Collider>(true);
			Collider[] array = shells;
			foreach (Collider val in array)
			{
				Collider[] array2 = componentsInChildren;
				foreach (Collider val2 in array2)
				{
					if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val2) && (Object)(object)val != (Object)(object)val2 && EarthmoverDefenceRules.HitsOwner(owner, val2) && !Physics.GetIgnoreCollision(val, val2))
					{
						Physics.IgnoreCollision(val, val2, true);
						changedPairs.Add((val, val2));
					}
				}
			}
		}

		private void Restore()
		{
			foreach (var changedPair in changedPairs)
			{
				if (Object.op_Implicit((Object)(object)changedPair.Shot) && Object.op_Implicit((Object)(object)changedPair.Unit))
				{
					Physics.IgnoreCollision(changedPair.Shot, changedPair.Unit, false);
				}
			}
			changedPairs.Clear();
		}

		private void Update()
		{
			UltraMiseryAttackOwner component = ((Component)this).GetComponent<UltraMiseryAttackOwner>();
			if (!UltraMiseryState.IsActive || !Object.op_Implicit((Object)(object)shot) || shot.parried || shot.friendly || shot.playerBullet || (Object.op_Implicit((Object)(object)component) && component.ReflectedByEnemy))
			{
				Restore();
				Object.Destroy((Object)(object)this);
			}
		}

		private void OnDestroy()
		{
			Restore();
		}
	}
	internal static class EarthmoverDefenceRules
	{
		internal static bool IsDefence(EnemyIdentifier enemy)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Invalid comparison between Unknown and I4
			if (!Object.op_Implicit((Object)(object)enemy))
			{
				return false;
			}
			if ((int)enemy.enemyType == 35 || Object.op_Implicit((Object)(object)((Component)enemy).GetComponentInChildren<MortarLauncher>(true)))
			{
				return true;
			}
			Transform val = ((Component)enemy).transform;
			while (Object.op_Implicit((Object)(object)val))
			{
				if (((Object)val).name.StartsWith("Centaur", StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
				val = val.parent;
			}
			return false;
		}

		internal static bool HitsOwner(EnemyIdentifier owner, Collider other)
		{
			if (Object.op_Implicit((Object)(object)owner) && Object.op_Implicit((Object)(object)other))
			{
				return (Object)(object)FriendlyFireRules.GetEnemy(other) == (Object)(object)owner;
			}
			return false;
		}
	}
	internal sealed class UltraMiseryDefenceRageSize : MonoBehaviour
	{
		private Transform anchor;

		internal void Bind(Transform target)
		{
			//IL_001a: 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)
			anchor = target;
			((Component)this).transform.SetParent((Transform)null, true);
			((Component)this).transform.localScale = Vector3.one * 0.5f;
			LateUpdate();
		}

		private void LateUpdate()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: 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)
			if (!Object.op_Implicit((Object)(object)anchor))
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
				return;
			}
			((Component)this).transform.position = anchor.position;
			((Component)this).transform.localScale = Vector3.one * 0.5f;
		}
	}
	[HarmonyPatch(typeof(Projectile), "Collided")]
	internal static class MortarOwnerCollisionPatch
	{
		private static bool Prefix(Projectile __instance, Collider other)
		{
			if (!UltraMiseryState.IsActive || __instance.parried || __instance.friendly || __instance.playerBullet)
			{
				return true;
			}
			UltraMiseryAttackOwner componentInParent = ((Component)__instance).GetComponentInParent<UltraMiseryAttackOwner>();
			if (Object.op_Implicit((Object)(object)componentInParent) && componentInParent.ReflectedByEnemy)
			{
				return true;
			}
			EnemyIdentifier val = LifestealRules.Resolve((Component)(object)__instance);
			if (!EarthmoverDefenceRules.HitsOwner(val, other))
			{
				return true;
			}
			return !Object.op_Implicit((Object)(object)((Component)val).GetComponentInChildren<MortarLauncher>(true));
		}
	}
	[HarmonyPatch(typeof(Explosion), "Collide")]
	internal static class MortarOwnerExplosionPatch
	{
		private static bool Prefix(Explosion __instance, Collider other)
		{
			if (!UltraMiseryState.IsActive)
			{
				return true;
			}
			UltraMiseryAttackOwner componentInParent = ((Component)__instance).GetComponentInParent<UltraMiseryAttackOwner>();
			if (Object.op_Implicit((Object)(object)componentInParent) && componentInParent.ReflectedByEnemy)
			{
				return true;
			}
			EnemyIdentifier val = LifestealRules.Resolve((Component)(object)__instance);
			if (!EarthmoverDefenceRules.HitsOwner(val, other))
			{
				return true;
			}
			return !Object.op_Implicit((Object)(object)((Component)val).GetComponentInChildren<MortarLauncher>(true));
		}
	}
	[HarmonyPatch(typeof(Arena), "Awake")]
	internal static class ArenaSupportEnemyPatch
	{
		private static void Prefix(Arena __instance)
		{
			if (!UltraMiseryState.IsActive || SceneHelper.IsPlayingCustom || Object.op_Implicit((Object)(object)MonoSingleton<SandboxNavmesh>.Instance))
			{
				return;
			}
			try
			{
				ActivateNextWave[] waves = __instance.GetWaves();
				if (waves == null || waves.Length == 0)
				{
					return;
				}
				ActivateNextWave[] array = waves;
				foreach (ActivateNextWave val in array)
				{
					if (Object.op_Implicit((Object)(object)val) && ((Component)val).transform.childCount != 0 && !IsInfinitePuppetSpawnerWave(((Component)val).transform))
					{
						Transform transform = ((Component)val).transform;
						List<Vector3> reserved = new List<Vector3>();
						EnsureEnemyType(transform, (EnemyType)21, reserved);
						EnsureEnemyType(transform, (EnemyType)39, reserved);
						EnsureEnemyType(transform, (EnemyType)12, reserved);
						UltraMiseryEnrageAudioGate.Bind(transform, ((Object)__instance).GetInstanceID());
					}
				}
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Arena support-enemy injection failed: {arg}");
			}
		}

		internal static GameObject EnsureEnemyType(Transform wave, EnemyType type, List<Vector3> reserved)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: 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_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: 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_00f4: 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)
			EnemyIdentifier[] componentsInChildren = ((Component)wave).GetComponentsInChildren<EnemyIdentifier>(true);
			foreach (EnemyIdentifier val in componentsInChildren)
			{
				if (IsSupportEnemy(val.enemyType))
				{
					Reserve(((Component)val).transform.position, reserved);
				}
				if (val.enemyType == type)
				{
					return ((Component)val).gameObject;
				}
			}
			GameObject enemyPrefab = MonoSingleton<DefaultReferenceManager>.Instance.GetEnemyPrefab(type);
			if (!Object.op_Implicit((Object)(object)enemyPrefab))
			{
				Plugin.Log.LogWarning((object)$"Could not find the {type} prefab for arena injection.");
				return null;
			}
			if (!TryFindPlacement(wave, reserved, out var position, out var rotation))
			{
				Plugin.Log.LogWarning((object)$"No safe reachable placement was found for {type} in arena wave {((Object)wave).name}; skipped injection.");
				return null;
			}
			GameObject obj = Object.Instantiate<GameObject>(enemyPrefab, position, rotation, wave);
			((Object)obj).name = $"UltraMisery Injected {type}";
			obj.SetActive(false);
			Reserve(position, reserved);
			Plugin.Log.LogDebug((object)$"Injected {type} into arena wave {((Object)wave).name} at {position}.");
			return obj;
		}

		private static bool IsSupportEnemy(EnemyType type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Invalid comparison between Unknown and I4
			if ((int)type != 21 && (int)type != 39)
			{
				return (int)type == 12;
			}
			return true;
		}

		internal static bool IsInfinitePuppetSpawnerWave(Transform wave)
		{
			if (!Object.op_Implicit((Object)(object)wave))
			{
				return false;
			}
			if (!Object.op_Implicit((Object)(object)((Component)wave).GetComponentInChildren<EnemySpawnRadius>(true)) && !Object.op_Implicit((Object)(object)((Component)wave).GetComponentInParent<EnemySpawnRadius>(true)))
			{
				return ((Object)wave).name.IndexOf("SuicideTree", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return true;
		}

		internal static bool IsBossEncounter(Transform wave)
		{
			//IL_001f: 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_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Invalid comparison between Unknown and I4
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected I4, but got Unknown
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Invalid comparison between Unknown and I4
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Invalid comparison between Unknown and I4
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Invalid comparison between Unknown and I4
			if (Object.op_Implicit((Object)(object)((Component)wave).GetComponentInChildren<BossHealthBar>(true)))
			{
				return true;
			}
			EnemyIdentifier[] componentsInChildren = ((Component)wave).GetComponentsInChildren<EnemyIdentifier>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				EnemyType enemyType = componentsInChildren[i].enemyType;
				if ((int)enemyType <= 11)
				{
					if ((int)enemyType != 8 && (int)enemyType != 11)
					{
						continue;
					}
				}
				else
				{
					switch (enemyType - 16)
					{
					default:
						if ((int)enemyType != 42)
						{
							continue;
						}
						break;
					case 0:
					case 1:
					case 2:
					case 6:
					case 11:
					case 12:
					case 13:
					case 14:
						break;
					case 3:
					case 4:
					case 5:
					case 7:
					case 8:
					case 9:
					case 10:
						continue;
					}
				}
				return true;
			}
			return false;
		}

		private static bool TryFindPlacement(Transform wave, List<Vector3> reserved, out Vector3 position, out Quaternion rotation)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing r