Decompiled source of RepoMutantEnemies v1.3.4

Matsu.MergedEnemyMod.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using REPOLib.Modules;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("Matsu.MergedEnemyMod")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.3.4.0")]
[assembly: AssemblyInformationalVersion("1.3.4")]
[assembly: AssemblyProduct("Matsu.MergedEnemyMod")]
[assembly: AssemblyTitle("Matsu.MergedEnemyMod")]
[assembly: AssemblyVersion("1.3.4.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Matsu.MergedEnemyMod
{
	internal static class AttackGeometry
	{
		public static float ClosestFraction(float px, float py, float pz, float ax, float ay, float az, float bx, float by, float bz)
		{
			float num = bx - ax;
			float num2 = by - ay;
			float num3 = bz - az;
			float num4 = num * num + num2 * num2 + num3 * num3;
			if (num4 <= 1E-06f)
			{
				return 0f;
			}
			return Math.Max(0f, Math.Min(1f, ((px - ax) * num + (py - ay) * num2 + (pz - az) * num3) / num4));
		}

		public static bool SweptSegment(float previous, float current, int segment, out float start, out float end)
		{
			start = Math.Max(0f, previous - (float)segment);
			end = Math.Min(1f, current - (float)segment);
			if (current >= previous && start <= end && start <= 1f)
			{
				return end >= 0f;
			}
			return false;
		}

		public static bool ExpandingRingCrossed(float distance, float height, float previousRadius, float currentRadius, float halfWidth, float minimumHeight, float maximumHeight)
		{
			if (currentRadius < previousRadius || height < minimumHeight || height > maximumHeight)
			{
				return false;
			}
			halfWidth = Math.Max(0f, halfWidth);
			if (distance >= Math.Max(0f, previousRadius - halfWidth))
			{
				return distance <= currentRadius + halfWidth;
			}
			return false;
		}

		public static float NormalizeRadians(float angle)
		{
			float num = (float)Math.PI * 2f;
			angle %= num;
			if (!(angle < 0f))
			{
				return angle;
			}
			return angle + num;
		}

		public static bool AngleInPositiveSweep(float angle, float start, float end, float tolerance)
		{
			if (end < start)
			{
				return false;
			}
			float num = (float)Math.PI * 2f;
			float num2 = end - start;
			tolerance = Math.Max(0f, tolerance);
			if (num2 + tolerance * 2f >= num)
			{
				return true;
			}
			float num3 = NormalizeRadians(angle - start);
			if (!(num3 <= num2 + tolerance))
			{
				return num3 >= num - tolerance;
			}
			return true;
		}

		public static float SafeOrbitRadius(float participantDistance, float challengeRadius, float pocketRadius)
		{
			participantDistance = Math.Max(0f, participantDistance);
			challengeRadius = Math.Max(0.5f, challengeRadius);
			pocketRadius = Math.Max(0.1f, pocketRadius);
			float val = Math.Max(0.5f, pocketRadius * 0.5f);
			float val2 = Math.Max(val, challengeRadius - pocketRadius * 0.5f);
			return Math.Max(val, Math.Min(val2, participantDistance));
		}
	}
	public sealed class BelladonnaFloorWave : MonoBehaviour
	{
		private Enemy? _source;

		private Transform _owner;

		private LineRenderer _ring;

		private Material? _material;

		private float _age;

		private float _radius;

		private float _previousRadius;

		private float _delay;

		private int _damage;

		private bool _hit;

		private bool _echo;

		private const float Warning = 0.9f;

		private const float Speed = 7f;

		private const float HalfWidth = 0.35f;

		public void Initialize(Vector3 origin, Enemy? source, Transform owner, float radius, int damage, float delay = 0f, bool echo = false)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Expected O, but got Unknown
			((Component)this).transform.position = origin;
			_source = source;
			_owner = owner;
			_radius = radius;
			_damage = damage;
			_delay = Mathf.Max(0f, delay);
			_echo = echo;
			_ring = ((Component)this).gameObject.AddComponent<LineRenderer>();
			_ring.useWorldSpace = false;
			_ring.loop = true;
			_ring.positionCount = 64;
			_ring.widthMultiplier = 0.7f;
			((Renderer)_ring).shadowCastingMode = (ShadowCastingMode)0;
			Shader val = Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Color");
			if ((Object)(object)val != (Object)null)
			{
				_material = new Material(val);
				((Renderer)_ring).material = _material;
			}
		}

		private void Update()
		{
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_owner == (Object)null || !((Component)_owner).gameObject.activeInHierarchy)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
				return;
			}
			_age += Time.deltaTime;
			float num = _age - _delay;
			float num2 = Mathf.Min(_radius, Mathf.Max(0f, num - 0.9f) * 7f);
			float num3 = ((num < 0.9f) ? Mathf.Lerp(0.18f, _echo ? 0.8f : 0.55f, Mathf.Clamp01((num + _delay) / Mathf.Max(0.1f, _delay + 0.9f))) : num2);
			for (int i = 0; i < 64; i++)
			{
				float num4 = (float)i * (float)Math.PI * 2f / 64f;
				_ring.SetPosition(i, new Vector3(Mathf.Cos(num4) * num3, 0.2f, Mathf.Sin(num4) * num3));
			}
			Color val = (Color)(_echo ? new Color(0.35f, 0.9f, 1f) : Color.yellow);
			LineRenderer ring = _ring;
			Color startColor = (_ring.endColor = (Color)((num < 0.9f) ? val : new Color(1f, 0.35f, 0.8f)));
			ring.startColor = startColor;
			if (!_hit && num >= 0.9f)
			{
				foreach (PlayerAvatar item in FusionShared.AllPlayers())
				{
					if (!((Object)(object)item == (Object)null) && FusionShared.IsLocalPlayer(item) && !FusionShared.IsPlayerDisabled(item))
					{
						Vector3 val3 = ((Component)item).transform.position - ((Component)this).transform.position;
						Vector2 val4 = new Vector2(val3.x, val3.z);
						if (AttackGeometry.ExpandingRingCrossed(((Vector2)(ref val4)).magnitude, val3.y, _previousRadius, num2, 0.35f, -0.6f, 0.65f) && !Physics.Linecast(((Component)this).transform.position + Vector3.up * 0.3f, ((Component)item).transform.position + Vector3.up * 0.3f, LayerMask.GetMask(new string[1] { "Default" }), (QueryTriggerInteraction)1))
						{
							_hit = true;
							FusionShared.HurtOwnedPlayer(item, _damage, ((Component)this).transform.position, _source);
							break;
						}
					}
				}
			}
			_previousRadius = num2;
			if (num >= 0.9f && num2 >= _radius)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)_material != (Object)null)
			{
				Object.Destroy((Object)(object)_material);
			}
		}
	}
	public sealed class BloodDebt : MonoBehaviour
	{
		private Enemy? _source;

		private EnemyHealth? _health;

		private LineRenderer? _line;

		private Material? _material;

		private float _remaining;

		private float _duration;

		private int _damage;

		private bool _finished;

		public PlayerAvatar? Target { get; private set; }

		public void Initialize(PlayerAvatar target, Enemy? source, EnemyHealth? health, float seconds, int damage)
		{
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Expected O, but got Unknown
			Target = target;
			_source = source;
			_health = health;
			_remaining = (_duration = seconds);
			_damage = damage;
			_line = ((Component)this).gameObject.AddComponent<LineRenderer>();
			_line.useWorldSpace = true;
			_line.positionCount = 2;
			_line.widthMultiplier = 0.09f;
			((Renderer)_line).shadowCastingMode = (ShadowCastingMode)0;
			Shader val = Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Color");
			if ((Object)(object)val != (Object)null)
			{
				_material = new Material(val);
				((Renderer)_line).material = _material;
			}
		}

		private void Update()
		{
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			if (_finished)
			{
				return;
			}
			if ((Object)(object)Target == (Object)null || FusionShared.IsPlayerDisabled(Target) || (Object)(object)_source == (Object)null || !((Component)_source).gameObject.activeInHierarchy || _source.IsStunned() || ((Object)(object)_health != (Object)null && FusionShared.GetHealthCurrent(_health) <= 0))
			{
				Finish();
				return;
			}
			_remaining -= Time.deltaTime;
			Vector3 val = ((Component)_source).transform.position + Vector3.up * 0.8f;
			if ((Object)(object)_line != (Object)null)
			{
				_line.SetPosition(0, val);
				_line.SetPosition(1, ((Component)Target).transform.position + Vector3.up * 0.8f);
				float num = 1f - Mathf.Clamp01(_remaining / _duration);
				Color val2 = Color.Lerp(Color.white, Color.red, num);
				LineRenderer? line = _line;
				Color startColor = (_line.endColor = val2);
				line.startColor = startColor;
				_line.widthMultiplier = 0.09f + num * 0.06f + (Mathf.Sin(Time.time * (6f + num * 8f)) + 1f) * 0.0125f;
			}
			if (!(_remaining > 0f))
			{
				_finished = true;
				FusionShared.HurtOwnedPlayer(Target, _damage, val, _source);
				Finish();
			}
		}

		private void Finish()
		{
			_finished = true;
			((Component)this).gameObject.SetActive(false);
			Object.Destroy((Object)(object)((Component)this).gameObject);
		}

		private void OnDestroy()
		{
			if ((Object)(object)_material != (Object)null)
			{
				Object.Destroy((Object)(object)_material);
			}
		}
	}
	public sealed class ContagionSporeCloud : MonoBehaviour
	{
		private const float WarningSeconds = 1f;

		private readonly RaycastHit[] _hits = (RaycastHit[])(object)new RaycastHit[24];

		private static readonly int CoverMask = LayerMask.GetMask(new string[1] { "Default" });

		private Enemy? _source;

		private Transform? _sourceRoot;

		private PlayerAvatar? _victim;

		private LineRenderer? _boundary;

		private Material? _material;

		private Light? _light;

		private float _radius;

		private float _lifetime;

		private float _threshold;

		private float _age;

		private float _exposure;

		private int _damage;

		private bool _victimExposed;

		public void Initialize(Vector3 center, Enemy? source, float radius, float lifetime, float exposureSeconds, int damage)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Expected O, but got Unknown
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Expected O, but got Unknown
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			((Component)this).transform.position = center;
			_source = source;
			object sourceRoot;
			if (!((Object)(object)source != (Object)null))
			{
				sourceRoot = null;
			}
			else
			{
				EnemyParent componentInParent = ((Component)source).GetComponentInParent<EnemyParent>();
				sourceRoot = ((componentInParent != null) ? ((Component)componentInParent).transform : null);
			}
			_sourceRoot = (Transform?)sourceRoot;
			_radius = radius;
			_lifetime = lifetime;
			_threshold = exposureSeconds;
			_damage = damage;
			_boundary = ((Component)this).gameObject.AddComponent<LineRenderer>();
			_boundary.useWorldSpace = false;
			_boundary.loop = true;
			_boundary.positionCount = 48;
			_boundary.widthMultiplier = 0.1f;
			((Renderer)_boundary).shadowCastingMode = (ShadowCastingMode)0;
			Shader val = Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Color");
			if ((Object)(object)val != (Object)null)
			{
				_material = new Material(val);
				((Renderer)_boundary).material = _material;
			}
			for (int i = 0; i < 48; i++)
			{
				float num = (float)i * (float)Math.PI * 2f / 48f;
				_boundary.SetPosition(i, new Vector3(Mathf.Cos(num) * radius, 0.12f, Mathf.Sin(num) * radius));
			}
			GameObject val2 = new GameObject("SporeGlow");
			val2.transform.SetParent(((Component)this).transform, false);
			val2.transform.localPosition = Vector3.up;
			_light = val2.AddComponent<Light>();
			_light.type = (LightType)2;
			_light.color = ContagionFusion.AuraColor;
			_light.range = radius * 2f;
			_light.shadows = (LightShadows)0;
		}

		private void Update()
		{
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			float age = _age;
			_age += Time.deltaTime;
			if (_age >= 1f + _lifetime)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
				return;
			}
			if ((Object)(object)_victim == (Object)null)
			{
				foreach (PlayerAvatar item in FusionShared.AllPlayers())
				{
					if ((Object)(object)item != (Object)null && FusionShared.IsLocalPlayer(item))
					{
						_victim = item;
						break;
					}
				}
			}
			bool flag = _age >= 1f;
			bool flag2 = (Object)(object)_victim != (Object)null && !FusionShared.IsPlayerDisabled(_victim);
			_victimExposed = flag2 && IsExposed(_victim);
			if (flag2 && flag)
			{
				float elapsed = HazardTiming.ActiveDelta(age, _age, 1f, _lifetime);
				if (HazardTiming.Exposure(ref _exposure, elapsed, _threshold, _victimExposed))
				{
					FusionShared.HurtOwnedPlayer(_victim, _damage, ((Component)this).transform.position, _source);
				}
			}
			else
			{
				_exposure = 0f;
			}
			float num = Mathf.Clamp01(_exposure / _threshold);
			Color val = (flag ? Color.Lerp(ContagionFusion.AuraColor, Color.red, num) : Color.yellow);
			val.a = Mathf.Clamp01((1f + _lifetime - _age) / 0.6f);
			if ((Object)(object)_boundary != (Object)null)
			{
				LineRenderer? boundary = _boundary;
				Color startColor = (_boundary.endColor = val);
				boundary.startColor = startColor;
				_boundary.widthMultiplier = 0.1f + num * 0.2f;
			}
			if ((Object)(object)_light != (Object)null)
			{
				_light.intensity = (flag ? (3f + num * 5f) : 1f);
			}
		}

		private bool IsExposed(PlayerAvatar player)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//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)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ((Component)player).transform.position - ((Component)this).transform.position;
			if (Mathf.Abs(val.y) > 2.5f || val.x * val.x + val.z * val.z > _radius * _radius)
			{
				return false;
			}
			Vector3 val2 = ((Component)this).transform.position + Vector3.up;
			Vector3 val3 = ((Component)player).transform.position + Vector3.up * 0.8f - val2;
			float magnitude = ((Vector3)(ref val3)).magnitude;
			if (magnitude < 0.01f)
			{
				return true;
			}
			int num = Physics.RaycastNonAlloc(val2, val3 / magnitude, _hits, magnitude, CoverMask, (QueryTriggerInteraction)1);
			if (num == _hits.Length)
			{
				return false;
			}
			for (int i = 0; i < num; i++)
			{
				Transform transform = ((RaycastHit)(ref _hits[i])).transform;
				if (!((Object)(object)transform == (Object)null) && !transform.IsChildOf(((Component)player).transform) && (!((Object)(object)_sourceRoot != (Object)null) || !transform.IsChildOf(_sourceRoot)))
				{
					return false;
				}
			}
			return true;
		}

		private void OnDestroy()
		{
			if ((Object)(object)_material != (Object)null)
			{
				Object.Destroy((Object)(object)_material);
			}
		}
	}
	public sealed class EffigyAnimationGuard : MonoBehaviour
	{
		private readonly Dictionary<Animator, RuntimeAnimatorController> _originals = new Dictionary<Animator, RuntimeAnimatorController>();

		private readonly Dictionary<Animator, AnimatorOverrideController> _overrides = new Dictionary<Animator, AnimatorOverrideController>();

		private readonly List<AnimationClip> _copies = new List<AnimationClip>();

		internal int RemovedEvents { get; private set; }

		internal void Initialize()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			if (_overrides.Count > 0)
			{
				return;
			}
			Dictionary<AnimationClip, AnimationClip> dictionary = new Dictionary<AnimationClip, AnimationClip>();
			Animator[] componentsInChildren = ((Component)this).GetComponentsInChildren<Animator>(true);
			foreach (Animator val in componentsInChildren)
			{
				RuntimeAnimatorController runtimeAnimatorController = val.runtimeAnimatorController;
				if ((Object)(object)runtimeAnimatorController == (Object)null)
				{
					continue;
				}
				AnimatorOverrideController val2 = new AnimatorOverrideController(runtimeAnimatorController);
				List<KeyValuePair<AnimationClip, AnimationClip>> list = new List<KeyValuePair<AnimationClip, AnimationClip>>();
				val2.GetOverrides(list);
				bool flag = false;
				for (int j = 0; j < list.Count; j++)
				{
					AnimationClip val3 = (((Object)(object)list[j].Value != (Object)null) ? list[j].Value : list[j].Key);
					AnimationEvent[] events = val3.events;
					AnimationEvent[] array = events.Where((AnimationEvent e) => e.functionName != "EliminateTarget").ToArray();
					if (events.Length != array.Length)
					{
						if (!dictionary.TryGetValue(val3, out var value))
						{
							value = Object.Instantiate<AnimationClip>(val3);
							((Object)value).name = ((Object)val3).name + " (Effigy safe copy)";
							value.events = array;
							dictionary[val3] = value;
							_copies.Add(value);
							RemovedEvents += events.Length - array.Length;
						}
						list[j] = new KeyValuePair<AnimationClip, AnimationClip>(list[j].Key, value);
						flag = true;
					}
				}
				if (!flag)
				{
					Object.Destroy((Object)(object)val2);
					continue;
				}
				val2.ApplyOverrides((IList<KeyValuePair<AnimationClip, AnimationClip>>)list);
				_originals[val] = runtimeAnimatorController;
				_overrides[val] = val2;
				val.runtimeAnimatorController = (RuntimeAnimatorController)(object)val2;
			}
		}

		private void OnDestroy()
		{
			foreach (KeyValuePair<Animator, AnimatorOverrideController> @override in _overrides)
			{
				if ((Object)(object)@override.Key != (Object)null && (Object)(object)@override.Key.runtimeAnimatorController == (Object)(object)@override.Value)
				{
					@override.Key.runtimeAnimatorController = _originals[@override.Key];
				}
				if ((Object)(object)@override.Value != (Object)null)
				{
					Object.Destroy((Object)(object)@override.Value);
				}
			}
			foreach (AnimationClip copy in _copies)
			{
				if ((Object)(object)copy != (Object)null)
				{
					Object.Destroy((Object)(object)copy);
				}
			}
			_originals.Clear();
			_overrides.Clear();
			_copies.Clear();
		}
	}
	internal readonly struct GluttonMealGrowth
	{
		internal readonly int Points;

		internal readonly int Damage;

		internal readonly int Hp;

		internal readonly float Mass;

		internal GluttonMealGrowth(int points, int damage, float mass, int hp)
		{
			Points = points;
			Damage = damage;
			Mass = mass;
			Hp = hp;
		}
	}
	internal sealed class GluttonReturnedValuable : MonoBehaviour
	{
		internal double EatAllowedAt;

		private AnimalFusion? _swallowedBy;

		private PhysGrabObject? _item;

		internal static bool IsProtected(PhysGrabObject item)
		{
			GluttonReturnedValuable component = ((Component)item).GetComponent<GluttonReturnedValuable>();
			if (component != null)
			{
				if (!((Object)(object)component._swallowedBy != (Object)null))
				{
					return ReworkAccess.Now < component.EatAllowedAt;
				}
				return true;
			}
			return false;
		}

		internal static void Hold(PhysGrabObject item, AnimalFusion owner)
		{
			GluttonReturnedValuable gluttonReturnedValuable = Get(item);
			gluttonReturnedValuable._item = item;
			gluttonReturnedValuable._swallowedBy = owner;
			item.OverrideDeactivate(0.5f);
		}

		internal static void Release(PhysGrabObject item, AnimalFusion owner)
		{
			GluttonReturnedValuable component = ((Component)item).GetComponent<GluttonReturnedValuable>();
			if ((Object)(object)component != (Object)null && (Object)(object)component._swallowedBy == (Object)(object)owner)
			{
				component._swallowedBy = null;
			}
		}

		private static GluttonReturnedValuable Get(PhysGrabObject item)
		{
			return ((Component)item).GetComponent<GluttonReturnedValuable>() ?? ((Component)item).gameObject.AddComponent<GluttonReturnedValuable>();
		}

		private void Update()
		{
			if ((Object)(object)_swallowedBy != (Object)null && (Object)(object)_item != (Object)null)
			{
				_item.OverrideDeactivate(0.5f);
			}
		}

		internal static void Protect(PhysGrabObject item, double until)
		{
			GluttonReturnedValuable gluttonReturnedValuable = Get(item);
			gluttonReturnedValuable.EatAllowedAt = Math.Max(gluttonReturnedValuable.EatAllowedAt, until);
		}
	}
	public class AnimalFusion : MonoBehaviour
	{
		private readonly Dictionary<PhysGrabObject, GluttonMealGrowth> _mealGrowth = new Dictionary<PhysGrabObject, GluttonMealGrowth>();

		private double _eatBlockedUntil;

		internal static readonly Color AuraColor = new Color(1f, 0.8f, 0.15f);

		private EnemyHealth? _health;

		private PhotonView? _pv;

		private bool _hpDone;

		private bool _killed;

		private bool _deathHooked;

		private float _glowTimer;

		private float _eatTimer;

		private int _totalPoints;

		private int _totalDamageAdded;

		private float _totalMassAdded;

		private int _totalHpAdded;

		private readonly List<PhysGrabObject> _belly = new List<PhysGrabObject>();

		internal void PrepareHealthForDamage()
		{
			EnsureHpDoubled();
			HookDeath();
		}

		internal void Damaged()
		{
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			if (!SemiFunc.IsMasterClientOrSingleplayer() || !((Behaviour)this).isActiveAndEnabled || (Object)(object)_health == (Object)null || FusionShared.GetHealthCurrent(_health) <= 0 || ReworkAccess.Read(_health, "dead", fallback: false) || ReworkAccess.Read(_health, "deadImpulse", fallback: false))
			{
				return;
			}
			double val = ReworkAccess.Now + (double)Plugin.GluttonHurtEatCooldownSeconds.Value;
			_eatBlockedUntil = Math.Max(_eatBlockedUntil, val);
			GluttonMealGrowth value = default(GluttonMealGrowth);
			int num = 0;
			bool flag = false;
			for (int i = 0; i < _belly.Count; i++)
			{
				PhysGrabObject val2 = _belly[i];
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				try
				{
					GluttonReturnedValuable.Protect(val2, _eatBlockedUntil);
					FusionShared.ProtectValuable(val2, Plugin.GluttonDropInvincibleSeconds.Value);
					GluttonReturnedValuable.Release(val2, this);
					val2.OverrideDeactivateReset();
					Vector2 val3 = Random.insideUnitCircle * 1.2f;
					val2.Teleport(((Component)this).transform.position + new Vector3(val3.x, 0.7f, val3.y), Quaternion.identity);
					_mealGrowth.TryGetValue(val2, out value);
					_mealGrowth.Remove(val2);
					_belly.RemoveAt(i);
					PhotonView component = ((Component)val2).GetComponent<PhotonView>();
					num = (((Object)(object)component != (Object)null) ? component.ViewID : 0);
					flag = true;
				}
				catch (Exception arg)
				{
					try
					{
						GluttonReturnedValuable.Hold(val2, this);
					}
					catch
					{
					}
					Plugin.Log.LogError((object)$"[Glutton] Could not return a valuable after damage: {arg}");
				}
				break;
			}
			if (SemiFunc.IsMultiplayer() && (Object)(object)_pv != (Object)null)
			{
				_pv.RPC("GluttonHurtRPC", (RpcTarget)0, new object[7]
				{
					value.Points,
					value.Damage,
					value.Mass,
					value.Hp,
					_eatBlockedUntil,
					num,
					Plugin.GluttonDropInvincibleSeconds.Value
				});
			}
			else
			{
				GluttonHurtRPC(value.Points, value.Damage, value.Mass, value.Hp, _eatBlockedUntil, num, Plugin.GluttonDropInvincibleSeconds.Value);
			}
			if (flag)
			{
				Plugin.Log.LogInfo((object)$"[Glutton] Returned one swallowed valuable after damage; {_belly.Count} remain. Eating paused for {Plugin.GluttonHurtEatCooldownSeconds.Value:0.##}s.");
			}
		}

		[PunRPC]
		private void GluttonHurtRPC(int points, int damage, float mass, int hp, double blockedUntil, int valuableViewId, float protectionSeconds, PhotonMessageInfo _info = default(PhotonMessageInfo))
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.IsMultiplayer() && !SemiFunc.MasterOnlyRPC(_info))
			{
				return;
			}
			_eatBlockedUntil = Math.Max(_eatBlockedUntil, blockedUntil);
			PhotonView val = ((valuableViewId != 0) ? PhotonView.Find(valuableViewId) : null);
			PhysGrabObject val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<PhysGrabObject>() : null);
			if ((Object)(object)val2 != (Object)null)
			{
				GluttonReturnedValuable.Protect(val2, _eatBlockedUntil);
				val2.OverrideDeactivateReset();
				FusionShared.ProtectValuable(val2, protectionSeconds);
			}
			int num = Mathf.Min(Mathf.Max(0, damage), _totalDamageAdded);
			float num2 = Mathf.Min(Mathf.Max(0f, mass), _totalMassAdded);
			int num3 = Mathf.Min(Mathf.Max(0, hp), _totalHpAdded);
			EnemyParent componentInParent = ((Component)this).GetComponentInParent<EnemyParent>();
			if (num != 0 && (Object)(object)componentInParent != (Object)null)
			{
				HurtCollider[] componentsInChildren = ((Component)componentInParent).GetComponentsInChildren<HurtCollider>(true);
				foreach (HurtCollider obj in componentsInChildren)
				{
					obj.playerDamage -= num;
				}
			}
			ApplyMassGrowth(0f - num2);
			if (num3 != 0 && SemiFunc.IsMasterClientOrSingleplayer() && (Object)(object)_health != (Object)null)
			{
				_health.health = Mathf.Max(1, _health.health - num3);
				int healthCurrent = FusionShared.GetHealthCurrent(_health);
				if (healthCurrent > 0)
				{
					FusionShared.SetHealthCurrent(_health, Mathf.Max(1, healthCurrent - num3));
				}
			}
			_totalPoints = Mathf.Max(0, _totalPoints - points);
			_totalDamageAdded -= num;
			_totalMassAdded = Mathf.Max(0f, _totalMassAdded - num2);
			_totalHpAdded -= num3;
		}

		private void ApplyMassGrowth(float delta)
		{
			if (delta == 0f)
			{
				return;
			}
			PhysGrabObject val = ReworkAccess.Find<PhysGrabObject>((Component)(object)this);
			if ((Object)(object)val != (Object)null && (Object)(object)val.rb != (Object)null)
			{
				val.massOriginal = Mathf.Max(0.1f, val.massOriginal + delta);
				if (ReworkAccess.Read(val, "timerAlterMass", 0f) <= 0f)
				{
					val.rb.mass = Mathf.Max(0.1f, val.rb.mass + delta);
				}
				return;
			}
			EnemyParent componentInParent = ((Component)this).GetComponentInParent<EnemyParent>();
			Rigidbody val2 = (((Object)(object)componentInParent != (Object)null) ? ((Component)componentInParent).GetComponentInChildren<Rigidbody>() : ((Component)this).GetComponentInParent<Rigidbody>());
			if ((Object)(object)val2 != (Object)null)
			{
				val2.mass = Mathf.Max(0.1f, val2.mass + delta);
			}
		}

		private void Awake()
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			_health = ((Component)this).GetComponentInParent<EnemyHealth>() ?? ((Component)this).GetComponentInChildren<EnemyHealth>();
			_pv = ((Component)this).GetComponent<PhotonView>();
			if ((Object)(object)_pv != (Object)null)
			{
				_pv.RefreshRpcMonoBehaviourCache();
			}
			if (SemiFunc.IsMasterClientOrSingleplayer() && (Object)(object)_health != (Object)null)
			{
				_health.health = Mathf.Max(1, Mathf.RoundToInt((float)_health.health * Plugin.CurrentHealthMultiplier()));
			}
			FusionShared.ApplyMutationGlow(((Component)this).transform, AuraColor);
		}

		private void HookDeath()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			if (_deathHooked || (Object)(object)_health == (Object)null)
			{
				return;
			}
			_deathHooked = true;
			try
			{
				_health.onDeathStart.AddListener((UnityAction)delegate
				{
					_killed = true;
				});
			}
			catch
			{
			}
		}

		private void Update()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			_glowTimer -= Time.deltaTime;
			if (_glowTimer <= 0f)
			{
				_glowTimer = 2f;
				FusionShared.ApplyMutationGlow(((Component)this).transform, AuraColor);
			}
			HookDeath();
			EnsureHpDoubled();
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				return;
			}
			for (int num = _belly.Count - 1; num >= 0; num--)
			{
				if ((Object)(object)_belly[num] == (Object)null)
				{
					_belly.RemoveAt(num);
				}
			}
			_eatTimer -= Time.deltaTime;
			if (!(_eatTimer > 0f))
			{
				_eatTimer = 0.6f;
				TryEat();
			}
		}

		private void TryEat()
		{
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			if (!SemiFunc.IsMasterClientOrSingleplayer() || !((Behaviour)this).isActiveAndEnabled || ReworkAccess.Now < _eatBlockedUntil || _killed || ((Object)(object)_health != (Object)null && (FusionShared.GetHealthCurrent(_health) <= 0 || ReworkAccess.Read(_health, "dead", fallback: false) || ReworkAccess.Read(_health, "deadImpulse", fallback: false))) || _belly.Count >= Plugin.GluttonMaxSwallowed.Value)
			{
				return;
			}
			try
			{
				Collider[] array = Physics.OverlapSphere(((Component)this).transform.position, Plugin.GluttonEatRadius.Value);
				for (int i = 0; i < array.Length; i++)
				{
					ValuableObject componentInParent = ((Component)array[i]).GetComponentInParent<ValuableObject>();
					if ((Object)(object)componentInParent == (Object)null)
					{
						continue;
					}
					PhysGrabObject component = ((Component)componentInParent).GetComponent<PhysGrabObject>();
					if (!((Object)(object)component == (Object)null) && !_belly.Contains(component) && !GluttonReturnedValuable.IsProtected(component) && !component.grabbed && !((Object)(object)((Component)componentInParent).GetComponentInParent<EnemyParent>() != (Object)null))
					{
						_belly.Add(component);
						GluttonReturnedValuable.Hold(component, this);
						int num = SizePoints(componentInParent);
						GluttonMealGrowth value = new GluttonMealGrowth(num, Mathf.Max(0, Plugin.GluttonDamagePerPoint.Value) * num, Mathf.Max(0f, Plugin.GluttonMassPerPoint.Value) * (float)num, Mathf.Max(0, Plugin.GluttonHpPerPoint.Value) * num);
						_mealGrowth[component] = value;
						if (SemiFunc.IsMultiplayer() && (Object)(object)_pv != (Object)null)
						{
							_pv.RPC("GluttonBuffRPC", (RpcTarget)0, new object[4] { num, value.Damage, value.Mass, value.Hp });
						}
						else
						{
							GluttonBuffRPC(num, value.Damage, value.Mass, value.Hp);
						}
						Plugin.Log.LogInfo((object)$"[Glutton] Swallowed '{((Object)componentInParent).name}' (+{num}pt, {_belly.Count} in the belly).");
						if (_belly.Count >= Plugin.GluttonMaxSwallowed.Value)
						{
							break;
						}
					}
				}
			}
			catch
			{
			}
		}

		private static int SizePoints(ValuableObject val)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Collider[] componentsInChildren = ((Component)val).GetComponentsInChildren<Collider>();
				if (componentsInChildren.Length == 0)
				{
					return 1;
				}
				Bounds bounds = componentsInChildren[0].bounds;
				Collider[] array = componentsInChildren;
				foreach (Collider val2 in array)
				{
					((Bounds)(ref bounds)).Encapsulate(val2.bounds);
				}
				float num = Mathf.Max(new float[3]
				{
					((Bounds)(ref bounds)).size.x,
					((Bounds)(ref bounds)).size.y,
					((Bounds)(ref bounds)).size.z
				});
				if (num < 0.4f)
				{
					return 1;
				}
				if (num < 0.9f)
				{
					return 2;
				}
				if (num < 1.6f)
				{
					return 3;
				}
				return 4;
			}
			catch
			{
				return 1;
			}
		}

		[PunRPC]
		private void GluttonBuffRPC(int points, int dmgAdd, float massAdd, int hpAdd, PhotonMessageInfo _info = default(PhotonMessageInfo))
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.IsMultiplayer() && !SemiFunc.MasterOnlyRPC(_info))
			{
				return;
			}
			try
			{
				_totalPoints += points;
				EnemyParent componentInParent = ((Component)this).GetComponentInParent<EnemyParent>();
				if ((Object)(object)componentInParent != (Object)null)
				{
					HurtCollider[] componentsInChildren = ((Component)componentInParent).GetComponentsInChildren<HurtCollider>(true);
					foreach (HurtCollider obj in componentsInChildren)
					{
						obj.playerDamage += dmgAdd;
					}
				}
				_totalDamageAdded += dmgAdd;
				ApplyMassGrowth(massAdd);
				_totalMassAdded += massAdd;
				if (SemiFunc.IsMasterClientOrSingleplayer() && (Object)(object)_health != (Object)null)
				{
					EnemyHealth? health = _health;
					health.health += hpAdd;
					int healthCurrent = FusionShared.GetHealthCurrent(_health);
					if (healthCurrent > 0)
					{
						FusionShared.SetHealthCurrent(_health, healthCurrent + hpAdd);
					}
				}
				_totalHpAdded += hpAdd;
				Plugin.Log.LogInfo((object)$"[Glutton#{((Object)this).GetInstanceID()}] Grew stronger (+{points}pt, total {_totalPoints}) — this individual only.");
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"[Glutton] buff error: {arg}");
			}
		}

		private void OnDisable()
		{
			if (_killed)
			{
				Regurgitate(withInvincibility: true);
				ResetGrowth();
				_killed = false;
			}
		}

		private void OnDestroy()
		{
			Regurgitate(withInvincibility: false);
		}

		private void ResetGrowth()
		{
			if (_totalPoints == 0)
			{
				return;
			}
			try
			{
				EnemyParent componentInParent = ((Component)this).GetComponentInParent<EnemyParent>();
				if (_totalDamageAdded != 0 && (Object)(object)componentInParent != (Object)null)
				{
					HurtCollider[] componentsInChildren = ((Component)componentInParent).GetComponentsInChildren<HurtCollider>(true);
					foreach (HurtCollider obj in componentsInChildren)
					{
						obj.playerDamage -= _totalDamageAdded;
					}
				}
				if (_totalMassAdded != 0f)
				{
					ApplyMassGrowth(0f - _totalMassAdded);
				}
				if (_totalHpAdded != 0 && SemiFunc.IsMasterClientOrSingleplayer() && (Object)(object)_health != (Object)null)
				{
					_health.health = Mathf.Max(1, _health.health - _totalHpAdded);
				}
				Plugin.Log.LogInfo((object)$"[Glutton#{((Object)this).GetInstanceID()}] Killed — growth reset (-{_totalPoints}pt undone).");
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"[Glutton] growth reset error: {arg}");
			}
			finally
			{
				_totalPoints = 0;
				_totalDamageAdded = 0;
				_totalMassAdded = 0f;
				_totalHpAdded = 0;
			}
		}

		private void OnEnable()
		{
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				return;
			}
			foreach (PhysGrabObject item in _belly)
			{
				if (!((Object)(object)item == (Object)null))
				{
					try
					{
						GluttonReturnedValuable.Hold(item, this);
					}
					catch
					{
					}
				}
			}
		}

		private void Regurgitate(bool withInvincibility)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: 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)
			if (!SemiFunc.IsMasterClientOrSingleplayer() || _belly.Count == 0)
			{
				return;
			}
			Vector3 val = ((Component)this).transform.position + Vector3.up * 0.5f;
			int num = 0;
			foreach (PhysGrabObject item in _belly)
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				try
				{
					GluttonReturnedValuable.Release(item, this);
					item.OverrideDeactivateReset();
					Vector2 val2 = Random.insideUnitCircle * 1.2f;
					item.Teleport(val + new Vector3(val2.x, 0.2f, val2.y), Quaternion.identity);
					if (withInvincibility)
					{
						FusionShared.ProtectValuable(item, Plugin.GluttonDropInvincibleSeconds.Value);
						GluttonReturnedValuable.Protect(item, ReworkAccess.Now + (double)Plugin.GluttonHurtEatCooldownSeconds.Value);
					}
					num++;
				}
				catch
				{
				}
			}
			_belly.Clear();
			_mealGrowth.Clear();
			if (num > 0)
			{
				Plugin.Log.LogInfo((object)$"[Glutton] Coughed up {num} valuables (killed={_killed}).");
			}
		}

		private void EnsureHpDoubled()
		{
			if (!_hpDone && !((Object)(object)_health == (Object)null))
			{
				_hpDone = true;
				if (SemiFunc.IsMasterClientOrSingleplayer())
				{
					FusionShared.SetHealthCurrent(_health, _health.health);
				}
			}
		}
	}
	[HarmonyPatch(typeof(EnemyHealth), "Hurt")]
	internal static class GluttonDamagePatch
	{
		private readonly struct HitState
		{
			internal readonly AnimalFusion? Glutton;

			internal readonly int Health;

			internal HitState(AnimalFusion glutton, int health)
			{
				Glutton = glutton;
				Health = health;
			}
		}

		private static void Prefix(EnemyHealth __instance, out HitState __state)
		{
			__state = default(HitState);
			if (SemiFunc.IsMasterClientOrSingleplayer() && !ReworkAccess.Read(__instance, "dead", fallback: false) && !ReworkAccess.Read(__instance, "deadImpulse", fallback: false))
			{
				AnimalFusion animalFusion = ReworkAccess.Find<AnimalFusion>((Component)(object)__instance);
				if (!((Object)(object)animalFusion == (Object)null) && ((Behaviour)animalFusion).isActiveAndEnabled)
				{
					animalFusion.PrepareHealthForDamage();
					__state = new HitState(animalFusion, FusionShared.GetHealthCurrent(__instance));
				}
			}
		}

		private static void Postfix(EnemyHealth __instance, HitState __state)
		{
			if (!((Object)(object)__state.Glutton == (Object)null))
			{
				int healthCurrent = FusionShared.GetHealthCurrent(__instance);
				if (healthCurrent > 0 && healthCurrent < __state.Health)
				{
					__state.Glutton.Damaged();
				}
			}
		}
	}
	internal static class GroundHazard
	{
		internal static bool TryProject(Vector3 position, Vector3 reference, Transform? ignore, out Vector3 floor)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			floor = position;
			if (!Finite(position) || !Finite(reference))
			{
				return false;
			}
			RaycastHit[] array = Physics.RaycastAll(new Vector3(position.x, reference.y + 0.35f, position.z), Vector3.down, 5f, LayerMask.GetMask(new string[1] { "Default" }), (QueryTriggerInteraction)1);
			float num = float.PositiveInfinity;
			RaycastHit[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				RaycastHit val = array2[i];
				if (!((Object)(object)((RaycastHit)(ref val)).collider == (Object)null) && (!((Object)(object)ignore != (Object)null) || !((Component)((RaycastHit)(ref val)).collider).transform.IsChildOf(ignore)) && GroundHazardRules.ValidFloor(((RaycastHit)(ref val)).point.y, reference.y, ((RaycastHit)(ref val)).normal.y) && !(((RaycastHit)(ref val)).distance >= num))
				{
					num = ((RaycastHit)(ref val)).distance;
					floor = ((RaycastHit)(ref val)).point + Vector3.up * 0.08f;
				}
			}
			return !float.IsPositiveInfinity(num);
		}

		private static bool Finite(Vector3 p)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: 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)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			if (!float.IsNaN(p.x) && !float.IsNaN(p.y) && !float.IsNaN(p.z) && !float.IsInfinity(p.x) && !float.IsInfinity(p.y))
			{
				return !float.IsInfinity(p.z);
			}
			return false;
		}
	}
	internal static class HazardTiming
	{
		public static float ActiveDelta(float previous, float current, float warning, float lifetime)
		{
			return Math.Max(0f, Math.Min(current, warning + lifetime) - Math.Max(previous, warning));
		}

		public static bool Exposure(ref float exposure, float elapsed, float threshold, bool exposed)
		{
			exposure = Math.Max(0f, exposure + Math.Max(0f, elapsed) * (exposed ? 1f : (-2f)));
			if (exposure < threshold)
			{
				return false;
			}
			exposure = 0f;
			return true;
		}

		public static int NextCut(ref float age, ref int next, float warning, float interval)
		{
			if (next >= 2 || age < warning + (float)next * interval)
			{
				return -1;
			}
			int result = next++;
			if (next == 1)
			{
				age = warning;
			}
			return result;
		}
	}
	public sealed class ChatterjawFusion : ReworkedMutation
	{
		internal static readonly Color AuraColor = new Color(1f, 0.36f, 0.45f);

		private EnemyHeadController _head;

		private double _nextCast;

		private ChatterjawSweep? _trap;

		private void Awake()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			_head = ((Component)this).GetComponent<EnemyHeadController>();
			Setup(AuraColor);
			_nextCast = ReworkAccess.Now + 2.0;
		}

		protected override void Update()
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Invalid comparison between Unknown and I4
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Invalid comparison between Unknown and I4
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: 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_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			base.Update();
			if (!base.Living || base.Stunned)
			{
				ClearEffects();
				_trap = null;
			}
			else
			{
				if (!base.Host || (Object)(object)_trap != (Object)null || (Object)(object)Enemy == (Object)null || ReworkAccess.Now < _nextCast || ((int)Enemy.CurrentState != 4 && (int)Enemy.CurrentState != 5))
				{
					return;
				}
				Vector3 val = (((Object)(object)Body?.rb != (Object)null) ? Body.rb.position : ((Component)this).transform.position);
				PlayerAvatar val2 = FusionShared.NearestPlayer(val, 12f);
				if (!((Object)(object)val2 == (Object)null) && ReworkAccess.Clear(val, ReworkAccess.Chest(val2), Root) && GroundHazard.TryProject(((Component)val2).transform.position, ((Component)val2).transform.position, Root, out var floor))
				{
					Vector3 val3 = ((Component)val2).transform.position - val;
					val3.y = 0f;
					if (((Vector3)(ref val3)).sqrMagnitude < 0.01f)
					{
						val3 = Vector3.forward;
					}
					Send(1, (Vector3[]?)(object)new Vector3[2]
					{
						floor,
						floor + ((Vector3)(ref val3)).normalized
					});
					_nextCast = ReworkAccess.Now + 8.0;
				}
			}
		}

		internal void Bite()
		{
			if (base.Host && base.Living && !base.Stunned && (Object)(object)_trap != (Object)null)
			{
				Send(2);
			}
		}

		internal void BreakTrap()
		{
			if (base.Host && (Object)(object)_trap != (Object)null)
			{
				Send(3);
			}
		}

		protected override void Receive(int kind, Vector3[] points, int[] ids, double time, float value)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: 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_009b: Unknown result type (might be due to invalid IL or missing references)
			if (kind == 1 && points.Length == 2 && base.Living && !base.Stunned)
			{
				ClearEffects();
				_trap = Effect<ChatterjawSweep>("Chatterjaw open floor jaw");
				_trap.Initialize(this, points[0], points[1] - points[0], time);
				_nextCast = time + 8.0;
				EnemyHeadController head = _head;
				if (head != null)
				{
					EnemyHeadAnimationSystem animationSystem = head.AnimationSystem;
					if (animationSystem != null)
					{
						Sound teethChatter = animationSystem.TeethChatter;
						if (teethChatter != null)
						{
							teethChatter.Play(points[0], 1f, 1f, 1f, 1f);
						}
					}
				}
			}
			if (kind == 2)
			{
				_trap?.BeginSnap(time);
			}
			if (kind == 3)
			{
				ClearEffects();
				_trap = null;
			}
		}
	}
	public sealed class ChatterjawSweep : MonoBehaviour
	{
		private ChatterjawFusion _source;

		private Vector3 _origin;

		private double _time;

		private double _snapTime;

		private bool _biting;

		private bool _resolved;

		private readonly Transform[] _upper = (Transform[])(object)new Transform[10];

		private readonly Transform[] _lower = (Transform[])(object)new Transform[10];

		private readonly Vector3[] _positions = (Vector3[])(object)new Vector3[10];

		private LineRenderer _rim;

		internal void Initialize(ChatterjawFusion source, Vector3 origin, Vector3 forward, double time)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: 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_004f: 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)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Expected O, but got Unknown
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			_source = source;
			_origin = origin;
			_time = time;
			Vector3[] array = (Vector3[])(object)new Vector3[33];
			for (int i = 0; i < array.Length; i++)
			{
				float num = (float)i * (float)Math.PI * 2f / (float)(array.Length - 1);
				array[i] = origin + new Vector3(Mathf.Cos(num), 0f, Mathf.Sin(num)) * 2f;
			}
			_rim = ReworkVisual.Line(((Component)this).transform, ChatterjawFusion.AuraColor, 0.16f, array);
			for (int j = 0; j < _positions.Length; j++)
			{
				float num2 = (float)j * (float)Math.PI * 2f / (float)_positions.Length;
				_positions[j] = origin + new Vector3(Mathf.Cos(num2), 0f, Mathf.Sin(num2)) * 1.8f;
				_upper[j] = ReworkVisual.Shape(((Component)this).transform, (PrimitiveType)3, _positions[j] + Vector3.up * 1.3f, new Vector3(0.35f, 0.5f, 0.35f), Color.white).transform;
				_lower[j] = ReworkVisual.Shape(((Component)this).transform, (PrimitiveType)3, _positions[j] + Vector3.up * 0.2f, new Vector3(0.35f, 0.4f, 0.35f), Color.white).transform;
			}
			GameObject val = new GameObject("Breakable jaw molar");
			val.transform.SetParent(((Component)this).transform, false);
			val.transform.position = origin + Vector3.up * 0.45f;
			val.layer = LayerMask.NameToLayer("PhysGrabObject");
			ReworkTarget reworkTarget = val.AddComponent<ReworkTarget>();
			reworkTarget.HitPoints = 20;
			reworkTarget.Radius = 0.45f;
			SphereCollider val2 = val.AddComponent<SphereCollider>();
			val2.radius = 0.45f;
			reworkTarget.Hitbox = (Collider?)(object)val2;
			reworkTarget.Broken = source.BreakTrap;
			Rigidbody obj = val.AddComponent<Rigidbody>();
			obj.isKinematic = true;
			obj.useGravity = false;
			ReworkVisual.Shape(val.transform, (PrimitiveType)3, val.transform.position, new Vector3(0.6f, 0.65f, 0.6f), ChatterjawFusion.AuraColor);
		}

		internal void BeginSnap(double time)
		{
			if (!_biting)
			{
				_biting = true;
				_snapTime = time;
			}
		}

		private bool Contact(PlayerAvatar player)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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_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)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ((Component)player).transform.position - _origin;
			Vector2 val2 = new Vector2(val.x, val.z);
			if (JawTrapRules.Contact(((Vector2)(ref val2)).magnitude, val.y))
			{
				return ReworkAccess.Clear(_origin + Vector3.up * 0.4f, ReworkAccess.Chest(player), _source.Root);
			}
			return false;
		}

		private void Update()
		{
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Unknown result type (might be due to invalid IL or missing references)
			if (!((Behaviour)this).isActiveAndEnabled || (Object)(object)_source == (Object)null || !_source.Living || _source.Stunned)
			{
				((Component)this).gameObject.SetActive(false);
				Object.Destroy((Object)(object)((Component)this).gameObject);
				return;
			}
			double num = ReworkAccess.Now - _time;
			if (!_biting && _source.Host && num >= 1.5 && num < 8.0)
			{
				foreach (PlayerAvatar item in FusionShared.AllPlayers())
				{
					if (ReworkAccess.Alive(item) && Contact(item))
					{
						_source.Bite();
						break;
					}
				}
			}
			float num2 = (_biting ? Mathf.Clamp01((float)((ReworkAccess.Now - _snapTime) / 0.6499999761581421)) : 0f);
			LineRenderer rim = _rim;
			Color startColor = (_rim.endColor = (_biting ? Color.red : ChatterjawFusion.AuraColor));
			rim.startColor = startColor;
			for (int i = 0; i < _positions.Length; i++)
			{
				_upper[i].position = _positions[i] + Vector3.up * Mathf.Lerp(1.3f, 0.45f, num2);
				_lower[i].position = _positions[i] + Vector3.up * Mathf.Lerp(0.2f, 0.45f, num2);
			}
			if (_biting && !_resolved && ReworkAccess.Now - _snapTime >= 0.6499999761581421)
			{
				_resolved = true;
				EnemyHeadController component = ((Component)_source).GetComponent<EnemyHeadController>();
				if (component != null)
				{
					EnemyHeadAnimationSystem animationSystem = component.AnimationSystem;
					if (animationSystem != null)
					{
						Sound teethChatter = animationSystem.TeethChatter;
						if (teethChatter != null)
						{
							teethChatter.Play(_origin, 1f, 1f, 1f, 1f);
						}
					}
				}
				ReworkVisual.Burst(_origin, ChatterjawFusion.AuraColor, 2f);
				foreach (PlayerAvatar item2 in FusionShared.AllPlayers())
				{
					if (ReworkAccess.Alive(item2) && FusionShared.IsLocalPlayer(item2) && Contact(item2))
					{
						FusionShared.HurtOwnedPlayer(item2, 75, _origin, _source.Enemy);
					}
				}
			}
			if (num >= 8.649999618530273 || (_resolved && ReworkAccess.Now - _snapTime > 1.049999976158142))
			{
				((Component)this).gameObject.SetActive(false);
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}
	}
	public sealed class KaleidoscopePrismSweep : MonoBehaviour
	{
		private static readonly Color[] BladeColors = (Color[])(object)new Color[3]
		{
			new Color(0.05f, 1f, 1f),
			new Color(1f, 0.12f, 0.8f),
			new Color(1f, 0.85f, 0.08f)
		};

		private readonly LineRenderer[] _blades = (LineRenderer[])(object)new LineRenderer[3];

		private readonly Material?[] _materials = (Material?[])(object)new Material[3];

		private readonly HashSet<int> _hitPlayers = new HashSet<int>();

		private Vector3 _center;

		private float _baseAngle;

		private float _warning;

		private float _sweepSeconds;

		private float _radius;

		private float _halfWidth;

		private int _damage;

		private Enemy? _source;

		private Transform? _sourceRoot;

		private float _age;

		public void Initialize(Vector3 center, Vector3 forward, float warning, float sweepSeconds, float radius, float halfWidth, int damage, Enemy? source)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Expected O, but got Unknown
			_center = center;
			forward.y = 0f;
			if (((Vector3)(ref forward)).sqrMagnitude < 0.01f)
			{
				forward = Vector3.forward;
			}
			((Vector3)(ref forward)).Normalize();
			_baseAngle = Mathf.Atan2(forward.z, forward.x);
			_warning = warning;
			_sweepSeconds = sweepSeconds;
			_radius = radius;
			_halfWidth = halfWidth;
			_damage = damage;
			_source = source;
			object sourceRoot;
			if (source == null)
			{
				sourceRoot = null;
			}
			else
			{
				EnemyParent componentInParent = ((Component)source).GetComponentInParent<EnemyParent>();
				sourceRoot = ((componentInParent != null) ? ((Component)componentInParent).transform : null);
			}
			_sourceRoot = (Transform?)sourceRoot;
			Shader val = Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Color");
			for (int i = 0; i < _blades.Length; i++)
			{
				GameObject val2 = new GameObject($"PrismBlade{i + 1}");
				val2.transform.SetParent(((Component)this).transform, false);
				LineRenderer val3 = val2.AddComponent<LineRenderer>();
				_blades[i] = val3;
				val3.useWorldSpace = true;
				val3.positionCount = 2;
				val3.widthMultiplier = _halfWidth * 2f;
				((Renderer)val3).shadowCastingMode = (ShadowCastingMode)0;
				((Renderer)val3).receiveShadows = false;
				if ((Object)(object)val != (Object)null)
				{
					_materials[i] = new Material(val);
					((Renderer)val3).material = _materials[i];
				}
			}
			FusionShared.SpawnWarningRing(_center, KaleidoscopeFusion.AuraColor, 0.2f, _radius, Mathf.Min(0.8f, _warning));
			UpdateBlades(_baseAngle, active: false);
		}

		private void Update()
		{
			float age = _age;
			_age += Time.deltaTime;
			float num = Mathf.Clamp01((age - _warning) / _sweepSeconds);
			float num2 = Mathf.Clamp01((_age - _warning) / _sweepSeconds);
			float num3 = (float)Math.PI * 2f / 3f;
			float previousAngle = _baseAngle + num * num3;
			float num4 = _baseAngle + num2 * num3;
			bool flag = num2 > 0f;
			UpdateBlades(num4, flag);
			if (flag)
			{
				TestSweptBlades(previousAngle, num4);
			}
			if (_age >= _warning + _sweepSeconds)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}

		private void UpdateBlades(float angle, bool active)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: 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)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			Vector3 direction = default(Vector3);
			for (int i = 0; i < _blades.Length; i++)
			{
				float num = angle + (float)i / 3f * (float)Math.PI * 2f;
				((Vector3)(ref direction))..ctor(Mathf.Cos(num), 0f, Mathf.Sin(num));
				Vector3 val = _center + Vector3.up * 0.5f;
				Vector3 val2 = Clip(val, direction, _radius);
				LineRenderer val3 = _blades[i];
				if (!((Object)(object)val3 == (Object)null))
				{
					val3.SetPosition(0, val);
					val3.SetPosition(1, val2);
					Color val4 = BladeColors[i];
					val4.a = (active ? 0.9f : (0.28f + Mathf.Abs(Mathf.Sin(_age * 9f)) * 0.35f));
					Color startColor = (val3.endColor = val4);
					val3.startColor = startColor;
				}
			}
		}

		private Vector3 Clip(Vector3 start, Vector3 direction, float distance)
		{
			//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)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			return FusionShared.ClipToDefaultCover(start, direction, distance, _sourceRoot);
		}

		private void TestSweptBlades(float previousAngle, float currentAngle)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: 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_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			foreach (PlayerAvatar item in FusionShared.AllPlayers())
			{
				if ((Object)(object)item == (Object)null || !FusionShared.IsLocalPlayer(item) || FusionShared.IsPlayerDisabled(item))
				{
					continue;
				}
				int instanceID = ((Object)item).GetInstanceID();
				if (_hitPlayers.Contains(instanceID))
				{
					continue;
				}
				Vector3 val = ((Component)item).transform.position + Vector3.up * 0.5f;
				Vector3 val2 = val - (_center + Vector3.up * 0.5f);
				float num = Mathf.Abs(val2.y);
				val2.y = 0f;
				float magnitude = ((Vector3)(ref val2)).magnitude;
				if (num > 2.3f || magnitude > _radius + _halfWidth || FusionShared.HasDefaultCover(_center + Vector3.up * 0.5f, val, _sourceRoot))
				{
					continue;
				}
				float angle = Mathf.Atan2(val2.z, val2.x);
				float tolerance = ((magnitude <= _halfWidth) ? ((float)Math.PI) : Mathf.Asin(Mathf.Clamp(_halfWidth / magnitude, 0f, 1f)));
				bool flag = false;
				for (int i = 0; i < 3; i++)
				{
					float num2 = (float)i / 3f * (float)Math.PI * 2f;
					if (AttackGeometry.AngleInPositiveSweep(angle, previousAngle + num2, currentAngle + num2, tolerance))
					{
						flag = true;
						break;
					}
				}
				if (flag)
				{
					_hitPlayers.Add(instanceID);
					FusionShared.HurtOwnedPlayer(item, _damage, _center, _source);
					FusionShared.SpawnWarningRing(GroundHazard.TryProject(((Component)item).transform.position, ((Component)item).transform.position, _sourceRoot, out var floor) ? floor : ((Component)item).transform.position, Color.white, 1.25f, 0.1f, 0.28f);
				}
			}
		}

		private void OnDestroy()
		{
			Material[] materials = _materials;
			foreach (Material val in materials)
			{
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)val);
				}
			}
		}
	}
	internal sealed class MutationGenerationSettings
	{
		internal const int WireVersion = 1;

		internal readonly int HostActor;

		internal readonly float ChancePerLevel;

		internal readonly float MaxChance;

		internal readonly int MaxMutantsPerLevel;

		internal readonly int SurgeInterval;

		internal readonly string DisabledMutants;

		internal MutationGenerationSettings(int hostActor, float chancePerLevel, float maxChance, int maxMutantsPerLevel, int surgeInterval, string disabledMutants)
		{
			HostActor = hostActor;
			ChancePerLevel = chancePerLevel;
			MaxChance = maxChance;
			MaxMutantsPerLevel = maxMutantsPerLevel;
			SurgeInterval = surgeInterval;
			DisabledMutants = disabledMutants ?? "";
		}

		internal object[] ToWire()
		{
			return new object[7] { 1, HostActor, ChancePerLevel, MaxChance, MaxMutantsPerLevel, SurgeInterval, DisabledMutants };
		}

		internal static bool TryFromWire(object raw, int expectedHostActor, out MutationGenerationSettings settings)
		{
			settings = null;
			if (!(raw is object[] array) || array.Length != 7 || !(array[0] is int num) || num != 1 || !(array[1] is int num2) || num2 <= 0 || num2 != expectedHostActor || !(array[2] is float num3) || float.IsNaN(num3) || float.IsInfinity(num3) || !(array[3] is float num4) || float.IsNaN(num4) || float.IsInfinity(num4) || !(array[4] is int num5) || num5 < 0 || !(array[5] is int num6) || num6 < 0 || !(array[6] is string disabledMutants))
			{
				return false;
			}
			settings = new MutationGenerationSettings(num2, num3, num4, num5, num6, disabledMutants);
			return true;
		}

		internal bool SameRulesAs(MutationGenerationSettings other)
		{
			if (other != null && ChancePerLevel == other.ChancePerLevel && MaxChance == other.MaxChance && MaxMutantsPerLevel == other.MaxMutantsPerLevel && SurgeInterval == other.SurgeInterval)
			{
				return string.Equals(DisabledMutants, other.DisabledMutants, StringComparison.Ordinal);
			}
			return false;
		}
	}
	internal static class MutationHostSync
	{
		internal const string RoomPropertyKey = "com.matsu.repomutations.generation.v1";

		private static Room? _room;

		private static int _hostActor;

		private static MutationGenerationSettings? _hostFrozen;

		private static MutationGenerationSettings? _effective;

		private static float _nextPublishAttempt;

		private static bool _loggedHostRules;

		private static bool _loggedGuestRules;

		private static bool _loggedLocalDifference;

		private static MutationHostSyncDriver? _driver;

		internal static MutationGenerationSettings Current => _effective ?? Local(0);

		internal static void Install()
		{
			SceneManager.sceneLoaded -= OnSceneLoaded;
			SceneManager.sceneLoaded += OnSceneLoaded;
			EnsureDriver();
		}

		private static void OnSceneLoaded(Scene _, LoadSceneMode __)
		{
			EnsureDriver();
		}

		private static void EnsureDriver()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			if (!((Object)(object)_driver != (Object)null))
			{
				GameObject val = new GameObject("REPO Mutant Enemies host settings");
				Object.DontDestroyOnLoad((Object)val);
				_driver = val.AddComponent<MutationHostSyncDriver>();
				Plugin.Log.LogInfo((object)"[Mutation Sync] Persistent room-settings driver ready.");
			}
		}

		internal static bool TryGet(out MutationGenerationSettings settings)
		{
			if (!PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null)
			{
				ResetRoom();
				settings = Local(0);
				_effective = settings;
				return true;
			}
			Room currentRoom = PhotonNetwork.CurrentRoom;
			int num = ((PhotonNetwork.MasterClient != null) ? PhotonNetwork.MasterClient.ActorNumber : 0);
			if (_room != currentRoom || _hostActor != num)
			{
				_room = currentRoom;
				_hostActor = num;
				_hostFrozen = null;
				_effective = null;
				_nextPublishAttempt = 0f;
				_loggedHostRules = false;
				_loggedGuestRules = false;
				_loggedLocalDifference = false;
			}
			if (num <= 0)
			{
				settings = null;
				return false;
			}
			if (PhotonNetwork.IsMasterClient)
			{
				if (_hostFrozen == null)
				{
					_hostFrozen = Local(num);
				}
				settings = _hostFrozen;
				_effective = settings;
				Publish(currentRoom, settings);
				return true;
			}
			if (((Dictionary<object, object>)(object)((RoomInfo)currentRoom).CustomProperties).TryGetValue((object)"com.matsu.repomutations.generation.v1", out object value) && MutationGenerationSettings.TryFromWire(value, num, out settings))
			{
				_effective = settings;
				if (!_loggedGuestRules)
				{
					_loggedGuestRules = true;
					Plugin.Log.LogInfo((object)($"[Mutation Sync] Using host {num}'s level cap {settings.MaxMutantsPerLevel}, " + $"surge interval {settings.SurgeInterval}, chance {settings.ChancePerLevel}, " + $"max chance {settings.MaxChance} and disabled-mutant list."));
				}
				if (!_loggedLocalDifference && !settings.SameRulesAs(Local(num)))
				{
					_loggedLocalDifference = true;
					Plugin.Log.LogInfo((object)"[Mutation Sync] Local mutation-generation settings differ; the host's settings take precedence for this room.");
				}
				return true;
			}
			_effective = null;
			settings = null;
			return false;
		}

		private static MutationGenerationSettings Local(int actor)
		{
			return new MutationGenerationSettings(actor, Plugin.MutationChancePerLevel.Value, Plugin.MutationMaxChance.Value, Mathf.Max(0, Plugin.MutationMaxMutantsPerLevel.Value), Mathf.Max(0, Plugin.MutationSurgeInterval.Value), Plugin.MutationDisabledMutants.Value ?? "");
		}

		private static void Publish(Room room, MutationGenerationSettings settings)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			//IL_0069: Expected O, but got Unknown
			if ((!((Dictionary<object, object>)(object)((RoomInfo)room).CustomProperties).TryGetValue((object)"com.matsu.repomutations.generation.v1", out object value) || !MutationGenerationSettings.TryFromWire(value, settings.HostActor, out MutationGenerationSettings settings2) || !settings2.SameRulesAs(settings)) && !(Time.realtimeSinceStartup < _nextPublishAttempt))
			{
				_nextPublishAttempt = Time.realtimeSinceStartup + 2f;
				Hashtable val = new Hashtable();
				((Dictionary<object, object>)val).Add((object)"com.matsu.repomutations.generation.v1", (object)settings.ToWire());
				if (room.SetCustomProperties(val, (Hashtable)null, (WebFlags)null) && !_loggedHostRules)
				{
					_loggedHostRules = true;
					Plugin.Log.LogInfo((object)($"[Mutation Sync] Host published level cap {settings.MaxMutantsPerLevel}, " + $"surge interval {settings.SurgeInterval} and mutation-selection settings for this room."));
				}
			}
		}

		private static void ResetRoom()
		{
			if (_room != null)
			{
				_room = null;
				_hostActor = 0;
				_hostFrozen = null;
				_effective = null;
				_loggedHostRules = false;
				_loggedGuestRules = false;
				_loggedLocalDifference = false;
				MutationAttach.ClearPending();
			}
		}

		internal static void Tick()
		{
			if (TryGet(out MutationGenerationSettings _))
			{
				MutationAttach.FlushPending();
			}
		}
	}
	internal sealed class MutationHostSyncDriver : MonoBehaviour
	{
		private void Update()
		{
			MutationHostSync.Tick();
		}
	}
	internal static class MutationRules
	{
		public static bool IsSurge(int displayedLevel, int interval)
		{
			if (displayedLevel > 0 && interval > 0)
			{
				return displayedLevel % interval == 0;
			}
			return false;
		}

		public static float Chance(int displayedLevel, int interval, float perLevel, float cap)
		{
			if (IsSurge(displayedLevel, interval))
			{
				return 1f;
			}
			return Math.Min((float)displayedLevel * perLevel, cap);
		}

		public static float Roll(int id, uint salt)
		{
			int num = (int)((uint)id ^ salt) * -1640531535;
			int num2 = (num ^ (num >>> 13)) * -1640531535;
			return (float)(uint)((num2 ^ (num2 >>> 16)) & 0xFFFFFF) / 16777216f;
		}

		public static int HunterVariant(int id, bool deadeyeEnabled, bool ricochetEnabled)
		{
			if (!deadeyeEnabled)
			{
				if (!ricochetEnabled)
				{
					return 0;
				}
				return 2;
			}
			if (!ricochetEnabled)
			{
				return 1;
			}
			if (!(Roll(id, 2713765095u) < 0.5f))
			{
				return 1;
			}
			return 2;
		}

		public static int TickVariant(int id, bool bloodBankEnabled, bool powerLeechEnabled)
		{
			if (!bloodBankEnabled)
			{
				if (!powerLeechEnabled)
				{
					return 0;
				}
				return 2;
			}
			if (!powerLeechEnabled)
			{
				return 1;
			}
			if (!(Roll(id, 1909172081u) < 0.5f))
			{
				return 1;
			}
			return 2;
		}

		public static bool ShouldExplodeBalloonRemoval(bool manualRemove, bool isAuthority)
		{
			if (isAuthority)
			{
				return !manualRemove;
			}
			return false;
		}
	}
	internal sealed class MutationBudget
	{
		private readonly Dictionary<int, int> reservations = new Dictionary<int, int>();

		private int level = -1;

		private int sceneHandle = int.MinValue;

		internal int Used { get; private set; }

		internal void BeginLevel(int displayedLevel, int currentSceneHandle)
		{
			if (level != displayedLevel || sceneHandle != currentSceneHandle)
			{
				level = displayedLevel;
				sceneHandle = currentSceneHandle;
				reservations.Clear();
				Used = 0;
			}
		}

		internal bool TryReserve(int id, int bodies, int maximum)
		{
			if (reservations.ContainsKey(id))
			{
				return true;
			}
			bodies = Math.Max(1, bodies);
			maximum = Math.Max(0, maximum);
			if (maximum != 0 && (bodies > maximum || Used > maximum - bodies))
			{
				return false;
			}
			reservations.Add(id, bodies);
			Used = ((Used > int.MaxValue - bodies) ? int.MaxValue : (Used + bodies));
			return true;
		}

		internal int Remaining(int maximum)
		{
			if (maximum > 0)
			{
				return Math.Max(0, maximum - Used);
			}
			return int.MaxValue;
		}
	}
	internal static class FusionShared
	{
		private static ParticleScriptExplosion? _sharedExplosion;

		private static GameObject? _explosionPrefab;

		private static readonly List<PlayerAvatar> _noPlayers = new List<PlayerAvatar>();

		private static FieldInfo? _healthCurrentField;

		private static FieldInfo? _impactDetectorField;

		private static MethodInfo? _hurtMultiplierMethod;

		private static FieldInfo? _explSizeField;

		private static FieldInfo? _explDmgField;

		private static FieldInfo? _explDmgEnemyField;

		private const string AuraLightName = "MatsuMutationAura";

		private static readonly List<Renderer> AuraRenderers = new List<Renderer>(64);

		private static readonly List<Material> AuraMaterials = new List<Material>(8);

		private static PropertyInfo? _navAgentProp;

		private static FieldInfo? _navAgentField;

		private static MethodInfo? _navDisableMethod;

		private static FieldInfo? _wrapAgentField;

		private static FieldInfo? _damageResistanceField;

		private static FieldInfo? _damageResistanceTimerField;

		private static FieldInfo? _tumbleField;

		private static FieldInfo? _tumblePhysGrabObjectField;

		private static FieldInfo? _clientPositionField;

		private static FieldInfo? _clientPositionCurrentField;

		private static FieldInfo? _visualPositionField;

		private static FieldInfo? _isDisabledField;

		private static readonly RaycastHit[] CoverHits = (RaycastHit[])(object)new RaycastHit[32];

		public static List<PlayerAvatar> AllPlayers()
		{
			GameDirector instance = GameDirector.instance;
			if (!((Object)(object)instance != (Object)null) || instance.PlayerList == null)
			{
				return _noPlayers;
			}
			return instance.PlayerList;
		}

		public static bool NearestPlayerWithin(Vector3 from, float range)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Max(0f, range) * Mathf.Max(0f, range);
			foreach (PlayerAvatar item in AllPlayers())
			{
				if (!((Object)(object)item == (Object)null) && !IsPlayerDisabled(item))
				{
					Vector3 val = from - ((Component)item).transform.position;
					if (((Vector3)(ref val)).sqrMagnitude <= num)
					{
						return true;
					}
				}
			}
			return false;
		}

		public static List<PlayerAvatar> PlayersInRadius(Vector3 center, float radius)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			List<PlayerAvatar> list = new List<PlayerAvatar>();
			float num = Mathf.Max(0f, radius) * Mathf.Max(0f, radius);
			foreach (PlayerAvatar item in AllPlayers())
			{
				if (!((Object)(object)item == (Object)null) && !IsPlayerDisabled(item))
				{
					Vector3 val = center - ((Component)item).transform.position;
					if (((Vector3)(ref val)).sqrMagnitude <= num)
					{
						list.Add(item);
					}
				}
			}
			return list;
		}

		public static PlayerAvatar? NearestPlayer(Vector3 from, float maxDistance)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			PlayerAvatar result = null;
			float num = Mathf.Max(0f, maxDistance) * Mathf.Max(0f, maxDistance);
			foreach (PlayerAvatar item in AllPlayers())
			{
				if (!((Object)(object)item == (Object)null) && !IsPlayerDisabled(item))
				{
					Vector3 val = from - ((Component)item).transform.position;
					float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
					if (sqrMagnitude <= num)
					{
						num = sqrMagnitude;
						result = item;
					}
				}
			}
			return result;
		}

		public static List<PhysGrabObject> PhysObjectsInRadius(Vector3 center, float radius)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			HashSet<PhysGrabObject> hashSet = new HashSet<PhysGrabObject>();
			Collider[] array = Physics.OverlapSphere(center, radius);
			foreach (Collider val in array)
			{
				if (!((Object)(object)val == (Object)null))
				{
					PhysGrabObject componentInParent = ((Component)val).GetComponentInParent<PhysGrabObject>();
					if ((Object)(object)componentInParent != (Object)null && (Object)(object)componentInParent.rb != (Object)null && !componentInParent.grabbed && (Object)(object)((Component)componentInParent).GetComponentInParent<EnemyParent>() == (Object)null)
					{
						hashSet.Add(componentInParent);
					}
				}
			}
			return new List<PhysGrabObject>(hashSet);
		}

		private static void SetExplField(ParticlePrefabExplosion pe, ref FieldInfo? cache, string name, object val)
		{
			try
			{
				if ((object)cache == null)
				{
					cache = typeof(ParticlePrefabExplosion).GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
				cache?.SetValue(pe, val);
			}
			catch
			{
			}
		}

		public static ParticlePrefabExplosion? ExplodeAuthoritative(Vector3 pos, float size, int playerDmg, int enemyDmg, PhysGrabObject? ignoreSelf = null, Enemy? enemyHost = null, float force = 1f)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			ParticlePrefabExplosion val = null;
			if ((Object)(object)_sharedExplosion == (Object)null)
			{
				_sharedExplosion = Object.FindObjectOfType<ParticleScriptExplosion>(true);
			}
			if ((Object)(object)_sharedExplosion != (Object)null)
			{
				try
				{
					val = _sharedExplosion.Spawn(pos, size, playerDmg, enemyDmg, force, false, false, 1f);
				}
				catch
				{
					val = null;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				if ((Object)(object)_explosionPrefab == (Object)null)
				{
					_explosionPrefab = Resources.Load<GameObject>("Effects/Part Prefab Explosion");
				}
				if ((Object)(object)_explosionPrefab != (Object)null)
				{
					val = Object.Instantiate<GameObject>(_explosionPrefab, pos, Quaternion.identity).GetComponent<ParticlePrefabExplosion>();
					if ((Object)(object)val != (Object)null)
					{
						SetExplField(val, ref _explSizeField, "explosionSize", size);
						SetExplField(val, ref _explDmgField, "explosionDamage", playerDmg);
						SetExplField(val, ref _explDmgEnemyField, "explosionDamageEnemy", enemyDmg);
						try
						{
							ParticleSystem particleFire = val.particleFire;
							if (particleFire != null)
							{
								particleFire.Play();
							}
							ParticleSystem particleSmoke = val.particleSmoke;
							if (particleSmoke != null)
							{
								particleSmoke.Play();
							}
							if ((Object)(object)val.light != (Object)null)
							{
								((Behaviour)val.light).enabled = true;
							}
						}
						catch
						{
						}
					}
				}
			}
			if ((Object)(object)val != (Object)null && (Object)(object)val.HurtCollider != (Object)null)
			{
				try
				{
					if ((Object)(object)ignoreSelf != (Object)null && val.HurtCollider.ignoreObjects != null)
					{
						val.HurtCollider.ignoreObjects.Add(ignoreSelf);
					}
					if ((Object)(object)enemyHost != (Object)null)
					{
						val.HurtCollider.enemyHost = enemyHost;
					}
				}
				catch
				{
				}
			}
			return val;
		}

		public static void ApplyMutationGlow(Transform root, Color color)
		{
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)root == (Object)null)
			{
				return;
			}
			try
			{
				Transform val = root.Find("MatsuMutationAura");
				Light val2;
				if ((Object)(object)val != (Object)null)
				{
					val2 = ((Component)val).GetComponent<Light>();
				}
				else
				{
					GameObject val3 = new GameObject("MatsuMutationAura");
					val3.transform.SetParent(root, false);
					val3.transform.localPosition = Vector3.zero;
					val2 = val3.AddComponent<Light>();
					val2.type = (LightType)2;
					val2.shadows = (LightShadows)0;
				}
				if ((Object)(object)val2 != (Object)null)
				{
					val2.color = color;
					val2.range = Plugin.MutationAuraRange.Value;
					val2.intensity = Plugin.MutationAuraIntensity.Value;
					val2.renderMode = (LightRenderMode)1;
				}
			}
			catch
			{
			}
			float num = Mathf.Max(1f, Plugin.MutationAuraIntensity.Value * 0.6f);
			Color val4 = color * num;
			EnemyParent componentInParent = ((Component)root).GetComponentInParent<EnemyParent>();
			((Component)(((componentInParent != null) ? ((Component)componentInParent).transform : null) ?? root)).GetComponentsInChildren<Renderer>(true, AuraRenderers);
			foreach (Renderer auraRenderer in AuraRenderers)
			{
				if ((Object)(object)auraRenderer == (Object)null || ((Object)((Component)auraRenderer).gameObject).name == "MatsuMutationAura")
				{
					continue;
				}
				auraRenderer.GetMaterials(AuraMaterials);
				foreach (Material auraMaterial in AuraMaterials)
				{
					if ((Object)(object)auraMaterial == (Object)null)
					{
						continue;
					}
					try
					{
						if (auraMaterial.HasProperty("_EmissionColor"))
						{
							auraMaterial.EnableKeyword("_EMISSION");
							auraMaterial.globalIlluminationFlags = (MaterialGlobalIlluminationFlags)1;
							auraMaterial.SetColor("_EmissionColor", val4);
						}
						auraMaterial.SetFloat("_FresnelAmount", 1f);
						auraMaterial.SetFloat("_FresnelScale", 1f);
						auraMaterial.SetFloat("_FresnelPower", 5f);
						auraMaterial.SetFloat("_FresnelBias", 0f);
						auraMaterial.SetColor("_FresnelColor", color);
						auraMaterial.SetFloat("_FresnelEmission", 1f);
					}
					catch
					{
					}
				}
			}
			AuraMaterials.Clear();
			AuraRenderers.Clear();
		}

		public static void SetHealthCurrent(EnemyHealth health, int value)
		{
			try
			{
				if (_healthCurrentField == null)
				{
					_healthCurrentField = typeof(EnemyHealth).GetField("healthCurrent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
				_healthCurrentField?.SetValue(health, value);
			}
			catch
			{
			}
		}

		public static void ProtectValuable(PhysGrabObject pgo, float seconds)
		{
			try
			{
				if (pgo != null)
				{
					pgo.OverrideIndestructible(Mathf.Max(0.1f, seconds));
				}
			}
			catch
			{
			}
		}

		public static void ExplodePlayerOnly(Vector3 pos, float size, int playerDamage, float force, Enemy? source = null)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			ParticlePrefabExplosion val = ExplodeAuthoritative(pos, size, playerDamage, 0, null, source, force);
			try
			{
				if ((Object)(object)val == (Object)null || (Object)(object)val.HurtCollider == (Object)null || val.HurtCollider.ignoreObjects == null)
				{
					return;
				}
				EnemyDirector instance = EnemyDirector.instance;
				if ((Object)(object)instance == (Object)null || instance.enemiesSpawned == null)
				{
					return;
				}
				foreach (EnemyParent item2 in instance.enemiesSpawned)
				{
					if (!((Object)(object)item2 == (Object)null))
					{
						PhysGrabObject[] componentsInChildren = ((Component)item2).GetComponentsInChildren<PhysGrabObject>(true);
						foreach (PhysGrabObject item in componentsInChildren)
						{
							val.HurtCollider.ignoreObjects.Add(item);
						}
					}
				}
			}
			catch
			{
			}
		}

		public static void ExplodeGrenadePlayerOnly(Vector3 pos)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			ExplodePlayerOnly(pos, 0.8f, 50, 2f);
		}

		public static void FreezeAgent(Enemy enemy)
		{
			try
			{
				if ((Object)(object)enemy == (Object)null)
				{
					return;
				}
				object obj = null;
				if ((object)_navAgentProp == null)
				{
					_navAgentProp = typeof(Enemy).GetProperty("NavMeshAgent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
				if (_navAgentProp != null)
				{
					obj = _navAgentProp.GetValue(enemy);