Decompiled source of ConfigurableScorpions v1.0.0

plugins/com.github.GABRlEL.ConfigurableScorpions.dll

Decompiled a day ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Peak.Afflictions;
using Photon.Pun;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("com.github.GABRlEL.ConfigurableScorpions")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("com.github.GABRlEL.ConfigurableScorpions")]
[assembly: AssemblyTitle("ConfigurableScorpions")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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 BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace ConfigurableScorpions
{
	[BepInPlugin("com.github.GABRlEL.ConfigurableScorpions", "ConfigurableScorpions", "0.1.0")]
	public class Plugin : BaseUnityPlugin
	{
		internal enum DamageTypeOverride
		{
			Vanilla = -1,
			Injury,
			Hunger,
			Cold,
			Poison,
			Crab,
			Curse,
			Drowsy,
			Weight,
			Hot,
			Thorns,
			Spores,
			Web
		}

		private Harmony? _harmony;

		public const string Id = "com.github.GABRlEL.ConfigurableScorpions";

		internal static ManualLogSource Log { get; private set; }

		internal static ConfigEntry<bool> CfgEnablePlayerTargeting { get; private set; }

		internal static ConfigEntry<bool> CfgOnlyAggressiveWhenHeld { get; private set; }

		internal static ConfigEntry<float> CfgAggroDistanceMultiplier { get; private set; }

		internal static ConfigEntry<bool> CfgRequireLineOfSight { get; private set; }

		internal static ConfigEntry<bool> CfgTargetPoisonedPlayers { get; private set; }

		internal static ConfigEntry<float> CfgMovementSpeedMultiplier { get; private set; }

		internal static ConfigEntry<float> CfgTurnRateMultiplier { get; private set; }

		internal static ConfigEntry<float> CfgSleepDistanceMultiplier { get; private set; }

		internal static ConfigEntry<float> CfgWakeRadiusMultiplier { get; private set; }

		internal static ConfigEntry<float> CfgAttackStartDistance { get; private set; }

		internal static ConfigEntry<float> CfgAttackDistance { get; private set; }

		internal static ConfigEntry<float> CfgAttackAngle { get; private set; }

		internal static ConfigEntry<float> CfgAttackCooldownSeconds { get; private set; }

		internal static ConfigEntry<float> CfgStingDelaySeconds { get; private set; }

		internal static ConfigEntry<float> CfgHeldStingTimeMultiplier { get; private set; }

		internal static ConfigEntry<float> CfgDamageMultiplier { get; private set; }

		internal static ConfigEntry<bool> CfgEnableInitialDamageTick { get; private set; }

		internal static ConfigEntry<bool> CfgEnableOvertimeDamageTick { get; private set; }

		internal static ConfigEntry<float> CfgInitialDamageMultiplier { get; private set; }

		internal static ConfigEntry<float> CfgOvertimeDamageMultiplier { get; private set; }

		internal static ConfigEntry<DamageTypeOverride> CfgDamageType { get; private set; }

		public static string Name => "ConfigurableScorpions";

		public static string Version => "0.1.0";

		private void Awake()
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Expected O, but got Unknown
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Expected O, but got Unknown
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Expected O, but got Unknown
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Expected O, but got Unknown
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Expected O, but got Unknown
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Expected O, but got Unknown
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Expected O, but got Unknown
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Expected O, but got Unknown
			//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cf: Expected O, but got Unknown
			//IL_0302: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Expected O, but got Unknown
			//IL_033f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0349: Expected O, but got Unknown
			//IL_03bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c6: Expected O, but got Unknown
			//IL_03f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0403: Expected O, but got Unknown
			//IL_0439: Unknown result type (might be due to invalid IL or missing references)
			//IL_0443: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			CfgEnablePlayerTargeting = ((BaseUnityPlugin)this).Config.Bind<bool>("Targeting", "EnablePathfindingToPlayer", true, "Enable/disable player target acquisition for scorpions while they're on the ground. If disabled, scorpions will only patrol (and won't chase players) unless they're being held.");
			CfgOnlyAggressiveWhenHeld = ((BaseUnityPlugin)this).Config.Bind<bool>("Targeting", "OnlyAggressiveWhenHeld", false, "If enabled, scorpions will only target/attack while held as an item. On the ground they will only patrol.");
			CfgAggroDistanceMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Targeting", "AggroDistanceMultiplier", 1f, new ConfigDescription("Multiplier applied to the scorpion's aggro radius (Mob.aggroDistance). 1 = vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), Array.Empty<object>()));
			CfgRequireLineOfSight = ((BaseUnityPlugin)this).Config.Bind<bool>("Targeting", "RequireLineOfSight", true, "If true (vanilla), scorpions only target players they have line-of-sight to (terrain blocks). If false, they can target through terrain.");
			CfgTargetPoisonedPlayers = ((BaseUnityPlugin)this).Config.Bind<bool>("Targeting", "TargetPoisonedPlayers", false, "If true, scorpions will target players even if they already have PoisonOverTime. false = vanilla.");
			CfgMovementSpeedMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "MovementSpeedMultiplier", 1f, new ConfigDescription("Multiplier applied to the scorpion's movement speed (Mob.movementSpeed). 1 = vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), Array.Empty<object>()));
			CfgTurnRateMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "TurnRateMultiplier", 1f, new ConfigDescription("Multiplier applied to the scorpion's turn rate (Mob.turnRate). 1 = vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), Array.Empty<object>()));
			CfgSleepDistanceMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "SleepDistanceMultiplier", 1f, new ConfigDescription("Multiplier for the distance used when deciding a scorpion can go to sleep (vanilla uses Mob.sleepDistance for both sleep and wake). 1 = vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), Array.Empty<object>()));
			CfgWakeRadiusMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "WakeRadiusMultiplier", 1f, new ConfigDescription("Multiplier for the distance used when deciding a sleeping scorpion should wake up (vanilla uses Mob.sleepDistance for both sleep and wake). 1 = vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), Array.Empty<object>()));
			CfgStingDelaySeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Attack", "StingDelaySeconds", -1f, "Override for the delay (in seconds) between starting the attack and the sting happening. Set to -1 to keep the game's value.");
			CfgHeldStingTimeMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Attack", "HeldStingTimeMultiplier", 1f, new ConfigDescription("Multiplier applied to scorpion sting delay while the scorpion is held as an item. 1 = vanilla. This multiplies the effective Mob.attackTime only while held (after any StingDelaySeconds override).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), Array.Empty<object>()));
			CfgAttackStartDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Attack", "AttackStartDistance", -1f, new ConfigDescription("Override for the distance at which scorpions begin an attack (Mob.attackStartDistance). Set to -1 to keep vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1f, 50f), Array.Empty<object>()));
			CfgAttackDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Attack", "AttackDistance", -1f, new ConfigDescription("Override for the distance at which scorpions can hit their attack (Mob.attackDistance). Set to -1 to keep vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1f, 50f), Array.Empty<object>()));
			CfgAttackAngle = ((BaseUnityPlugin)this).Config.Bind<float>("Attack", "AttackAngle", -1f, new ConfigDescription("Override for the attack cone angle in degrees (Mob.attackAngle). Set to -1 to keep vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1f, 360f), Array.Empty<object>()));
			CfgAttackCooldownSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Attack", "AttackCooldownSeconds", -1f, new ConfigDescription("Override for the base attack cooldown in seconds (Mob private field attackCooldown). Set to -1 to keep vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1f, 60f), Array.Empty<object>()));
			CfgDamageMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Attack", "DamageMultiplier", 1f, new ConfigDescription("Global multiplier for scorpion status damage (applies to BOTH the initial sting tick and the overtime tick). 1 = vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
			CfgEnableInitialDamageTick = ((BaseUnityPlugin)this).Config.Bind<bool>("Attack", "EnableInitialDamageTick", true, "Enable/disable the single (instant) status tick applied when the sting connects. true = vanilla.");
			CfgEnableOvertimeDamageTick = ((BaseUnityPlugin)this).Config.Bind<bool>("Attack", "EnableOvertimeDamageTick", true, "Enable/disable the over-time status application after the sting. true = vanilla.");
			CfgInitialDamageMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Attack", "InitialDamageMultiplier", 1f, new ConfigDescription("Multiplier for ONLY the initial (instant) sting status tick. 1 = vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
			CfgOvertimeDamageMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Attack", "OvertimeDamageMultiplier", 1f, new ConfigDescription("Multiplier for ONLY the over-time status tick rate (per second). 1 = vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
			CfgDamageType = ((BaseUnityPlugin)this).Config.Bind<DamageTypeOverride>("Attack", "DamageType", DamageTypeOverride.Vanilla, "Controls the status/damage type a scorpion sting applies. Vanilla keeps the game's original setting (Poison).\nCold = freeze, Hot = burn, Spores = shroom.\nNote: Non-Poison over-time is applied locally (not via the game's built-in PoisonOverTime affliction).");
			try
			{
				_harmony = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
				_harmony.PatchAll();
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Failed to apply Harmony patches: {arg}");
			}
			Log.LogInfo((object)("Plugin " + Name + " is loaded!"));
		}
	}
	[HarmonyPatch]
	internal static class ScorpionPatches
	{
		private sealed class AttackAnimSyncState
		{
			public bool Initialized;

			public float PrefabAttackTime;

			public float BaseAnimSpeed = 1f;

			public bool TriggeredThisAttack;
		}

		private static readonly MethodInfo? SetTargetChar = AccessTools.PropertySetter(typeof(Mob), "targetChar");

		private static readonly FieldRef<Mob, bool> AttackingRef = AccessTools.FieldRefAccess<Mob, bool>("attacking");

		private static readonly FieldRef<Mob, float> TimeLastCheckedForTargetRef = AccessTools.FieldRefAccess<Mob, float>("_timeLastCheckedForTarget");

		private static readonly FieldRef<Mob, float> TimeLastSwitchedTargetRef = AccessTools.FieldRefAccess<Mob, float>("_timeLastSwitchedTarget");

		private static readonly FieldRef<Mob, float> TargetSwitchCooldownRef = AccessTools.FieldRefAccess<Mob, float>("targetSwitchCooldown");

		private static readonly FieldRef<Mob, float> TargetCheckCooldownRef = AccessTools.FieldRefAccess<Mob, float>("targetCheckCooldown");

		private static readonly FieldRef<Mob, Character> TargetCharRef = AccessTools.FieldRefAccess<Mob, Character>("_targetChar");

		private static readonly FieldRef<Mob, Vector3> NormalRef = AccessTools.FieldRefAccess<Mob, Vector3>("normal");

		private static readonly FieldRef<Mob, float> AttackCooldownRef = AccessTools.FieldRefAccess<Mob, float>("attackCooldown");

		private static readonly FieldRef<Mob, float> InRangeForAttackTimeRef = AccessTools.FieldRefAccess<Mob, float>("inRangeForAttackTime");

		private static readonly FieldRef<Mob, float> TimeLastAttackedRef = AccessTools.FieldRefAccess<Mob, float>("_timeLastAttacked");

		private static readonly FieldRef<Mob, float> PostAttackRestRef = AccessTools.FieldRefAccess<Mob, float>("postAttackRest");

		private static readonly FieldRef<Mob, float> WhiffRefundRef = AccessTools.FieldRefAccess<Mob, float>("whiffRefund");

		private static readonly MethodInfo? MobInflictAttackMI = AccessTools.Method(typeof(Mob), "InflictAttack", (Type[])null, (Type[])null);

		private static readonly ConditionalWeakTable<Mob, AttackAnimSyncState> AttackAnimStates = new ConditionalWeakTable<Mob, AttackAnimSyncState>();

		private static readonly FieldRef<Mob, MobItem> MobItemRef = AccessTools.FieldRefAccess<Mob, MobItem>("_mobItem");

		private static readonly FieldRef<Mob, Rigidbody> RigRef = AccessTools.FieldRefAccess<Mob, Rigidbody>("rig");

		private static readonly FieldInfo? MobStateField = AccessTools.Field(typeof(Mob), "_mobState");

		private static readonly MethodInfo? MobStateGetter = AccessTools.PropertyGetter(typeof(Mob), "mobState");

		private static AttackAnimSyncState GetAttackAnimState(Mob mob)
		{
			return AttackAnimStates.GetValue(mob, (Mob _) => new AttackAnimSyncState());
		}

		private static bool IsInAttackCooldown(Mob mob)
		{
			return Time.time < TimeLastAttackedRef.Invoke(mob) + AttackCooldownRef.Invoke(mob);
		}

		private static bool TryGetMobStateWalking(Mob mob, out bool isWalking)
		{
			isWalking = false;
			try
			{
				object obj = null;
				if (MobStateField != null)
				{
					obj = MobStateField.GetValue(mob);
				}
				else if (MobStateGetter != null)
				{
					obj = MobStateGetter.Invoke(mob, null);
				}
				if (obj == null)
				{
					return false;
				}
				isWalking = string.Equals(obj.ToString(), "Walking", StringComparison.Ordinal);
				return true;
			}
			catch
			{
				return false;
			}
		}

		private static bool InTargetingCooldown(Mob mob)
		{
			float time = Time.time;
			return time < Mathf.Max(TimeLastCheckedForTargetRef.Invoke(mob) + TargetCheckCooldownRef.Invoke(mob), TimeLastSwitchedTargetRef.Invoke(mob) + TargetSwitchCooldownRef.Invoke(mob));
		}

		private static Vector3 Center(Mob mob)
		{
			//IL_0006: 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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			return ((Component)mob).transform.position + NormalRef.Invoke(mob) * 0.2f;
		}

		private static bool IsNearCharacterWithinRadius(Mob mob, float radius)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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)
			Vector3 val = Center(mob);
			foreach (Character allCharacter in Character.AllCharacters)
			{
				if ((Object)(object)allCharacter != (Object)null && Vector3.Distance(val, allCharacter.Center) < radius)
				{
					return true;
				}
			}
			return false;
		}

		private static bool IsHeldAsItem(Mob mob)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Invalid comparison between Unknown and I4
			Item component = ((Component)mob).GetComponent<Item>();
			if ((Object)(object)component != (Object)null)
			{
				return (int)component.itemState == 1;
			}
			return false;
		}

		private static void ClearTarget(Mob mob)
		{
			try
			{
				SetTargetChar?.Invoke(mob, new object[1]);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogDebug((object)("Failed to clear scorpion target (safe to ignore): " + ex.Message));
			}
		}

		[HarmonyPatch(typeof(Mob), "Start")]
		[HarmonyPostfix]
		private static void MobStart_Postfix(Mob __instance)
		{
			if (__instance is Scorpion)
			{
				float value = Plugin.CfgStingDelaySeconds.Value;
				if (value >= 0f)
				{
					__instance.attackTime = value;
				}
				float num = Mathf.Max(0f, Plugin.CfgMovementSpeedMultiplier.Value);
				if (!Mathf.Approximately(num, 1f))
				{
					__instance.movementSpeed *= num;
				}
				float num2 = Mathf.Max(0f, Plugin.CfgTurnRateMultiplier.Value);
				if (!Mathf.Approximately(num2, 1f))
				{
					__instance.turnRate *= num2;
				}
				float value2 = Plugin.CfgAttackStartDistance.Value;
				if (value2 >= 0f)
				{
					__instance.attackStartDistance = value2;
				}
				float value3 = Plugin.CfgAttackDistance.Value;
				if (value3 >= 0f)
				{
					__instance.attackDistance = value3;
				}
				float value4 = Plugin.CfgAttackAngle.Value;
				if (value4 >= 0f)
				{
					__instance.attackAngle = value4;
				}
				float value5 = Plugin.CfgAttackCooldownSeconds.Value;
				if (value5 >= 0f)
				{
					AttackCooldownRef.Invoke(__instance) = value5;
				}
			}
		}

		[HarmonyPatch(typeof(Mob), "Attacking")]
		[HarmonyPrefix]
		private static bool MobAttacking_Prefix(Mob __instance)
		{
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: 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_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			if (!(__instance is Scorpion))
			{
				return true;
			}
			float value = Plugin.CfgHeldStingTimeMultiplier.Value;
			if (!IsHeldAsItem(__instance) || Mathf.Approximately(value, 1f))
			{
				AttackAnimSyncState attackAnimState = GetAttackAnimState(__instance);
				if (attackAnimState.Initialized && (Object)(object)__instance.anim != (Object)null)
				{
					__instance.anim.speed = attackAnimState.BaseAnimSpeed;
				}
				attackAnimState.TriggeredThisAttack = false;
				return true;
			}
			AttackAnimSyncState attackAnimState2 = GetAttackAnimState(__instance);
			if (!attackAnimState2.Initialized)
			{
				attackAnimState2.PrefabAttackTime = Mathf.Max(0.01f, __instance.attackTime);
				attackAnimState2.BaseAnimSpeed = (((Object)(object)__instance.anim != (Object)null) ? __instance.anim.speed : 1f);
				attackAnimState2.Initialized = true;
			}
			Character val = TargetCharRef.Invoke(__instance);
			if ((Object)(object)val != (Object)null)
			{
				if (!AttackingRef.Invoke(__instance))
				{
					if (__instance.distanceToTarget < __instance.attackStartDistance && !IsInAttackCooldown(__instance) && ((MonoBehaviourPun)__instance).photonView.IsMine)
					{
						((MonoBehaviourPun)__instance).photonView.RPC("RPC_StartAttack", (RpcTarget)0, Array.Empty<object>());
					}
					InRangeForAttackTimeRef.Invoke(__instance) = 0f;
					attackAnimState2.TriggeredThisAttack = false;
					if (!AttackingRef.Invoke(__instance))
					{
						return false;
					}
				}
				float num = InRangeForAttackTimeRef.Invoke(__instance);
				float num2 = Mathf.Max(0f, __instance.attackTime * value);
				float num3 = Mathf.Max(0.01f, attackAnimState2.PrefabAttackTime);
				float num4 = Mathf.Max(0f, num2 - num3);
				float deltaTime = Time.deltaTime;
				float num5 = num + deltaTime;
				if (!attackAnimState2.TriggeredThisAttack && num5 >= num4)
				{
					if ((Object)(object)__instance.anim != (Object)null)
					{
						float speed = attackAnimState2.BaseAnimSpeed;
						if (num2 > 0.01f && num2 < num3)
						{
							speed = attackAnimState2.BaseAnimSpeed * (num3 / num2);
						}
						__instance.anim.speed = speed;
						__instance.anim.SetTrigger("Attack");
					}
					attackAnimState2.TriggeredThisAttack = true;
				}
				else if ((Object)(object)__instance.anim != (Object)null)
				{
					__instance.anim.speed = attackAnimState2.BaseAnimSpeed;
				}
				InRangeForAttackTimeRef.Invoke(__instance) = num5;
				if (num5 > num2)
				{
					if (__instance.distanceToTarget < __instance.attackDistance)
					{
						Vector3 val2 = ((Component)__instance).transform.forward + Vector3.up;
						Vector3 normalized = ((Vector3)(ref val2)).normalized;
						val2 = val.Center - ((Component)__instance).transform.position;
						if (Vector3.Angle(normalized, ((Vector3)(ref val2)).normalized) < __instance.attackAngle)
						{
							MobInflictAttackMI?.Invoke(__instance, new object[1] { val });
							TimeLastAttackedRef.Invoke(__instance) = Time.time;
							goto IL_0305;
						}
					}
					float num6 = Mathf.Clamp01(WhiffRefundRef.Invoke(__instance));
					float num7 = AttackCooldownRef.Invoke(__instance);
					float num8 = PostAttackRestRef.Invoke(__instance);
					TimeLastAttackedRef.Invoke(__instance) = Time.time - num6 * Mathf.Max(num7, num8);
					goto IL_0305;
				}
			}
			else
			{
				InRangeForAttackTimeRef.Invoke(__instance) = 0f;
				attackAnimState2.TriggeredThisAttack = false;
				if ((Object)(object)__instance.anim != (Object)null)
				{
					__instance.anim.speed = attackAnimState2.BaseAnimSpeed;
				}
			}
			goto IL_0371;
			IL_0305:
			AttackingRef.Invoke(__instance) = false;
			attackAnimState2.TriggeredThisAttack = false;
			if ((Object)(object)__instance.anim != (Object)null)
			{
				__instance.anim.speed = attackAnimState2.BaseAnimSpeed;
			}
			goto IL_0371;
			IL_0371:
			return false;
		}

		[HarmonyPatch(typeof(Mob), "TestSleepMode")]
		[HarmonyPrefix]
		private static bool MobTestSleepMode_Prefix(Mob __instance)
		{
			//IL_00bc: 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_00d4: Unknown result type (might be due to invalid IL or missing references)
			if (!(__instance is Scorpion))
			{
				return true;
			}
			float num = Mathf.Max(0f, Plugin.CfgSleepDistanceMultiplier.Value);
			float num2 = Mathf.Max(0f, Plugin.CfgWakeRadiusMultiplier.Value);
			if (Mathf.Approximately(num, 1f) && Mathf.Approximately(num2, 1f))
			{
				return true;
			}
			float sleepDistance = __instance.sleepDistance;
			float radius = sleepDistance * num;
			float radius2 = sleepDistance * num2;
			if (__instance.sleeping)
			{
				if (IsNearCharacterWithinRadius(__instance, radius2))
				{
					__instance.sleeping = false;
					__instance.UpdateSleeping();
				}
			}
			else
			{
				MobItem val = MobItemRef.Invoke(__instance);
				Rigidbody val2 = RigRef.Invoke(__instance);
				if (!TryGetMobStateWalking(__instance, out var isWalking))
				{
					return true;
				}
				if (isWalking && ((Object)(object)val == (Object)null || (int)((Item)val).itemState == 0) && (Object)(object)val2 != (Object)null)
				{
					Vector3 linearVelocity = val2.linearVelocity;
					if (((Vector3)(ref linearVelocity)).magnitude < 1f && !IsNearCharacterWithinRadius(__instance, radius))
					{
						__instance.sleeping = true;
						__instance.UpdateSleeping();
					}
				}
			}
			return false;
		}

		[HarmonyPatch(typeof(Mob), "Targeting")]
		[HarmonyPrefix]
		private static bool MobTargeting_Prefix(Mob __instance, ref float __state)
		{
			//IL_0111: 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_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			__state = float.NaN;
			if (!(__instance is Scorpion))
			{
				return true;
			}
			bool flag = IsHeldAsItem(__instance);
			if (Plugin.CfgOnlyAggressiveWhenHeld.Value && !flag)
			{
				ClearTarget(__instance);
				return false;
			}
			if (!Plugin.CfgEnablePlayerTargeting.Value && !flag)
			{
				ClearTarget(__instance);
				return false;
			}
			float num = Mathf.Max(0f, Plugin.CfgAggroDistanceMultiplier.Value);
			bool flag2 = !Mathf.Approximately(num, 1f);
			bool flag3 = !Plugin.CfgRequireLineOfSight.Value;
			bool value = Plugin.CfgTargetPoisonedPlayers.Value;
			if (!flag2 && !flag3 && !value)
			{
				return true;
			}
			if (flag2 && !flag3 && !value)
			{
				__state = __instance.aggroDistance;
				__instance.aggroDistance = __state * num;
				return true;
			}
			if (InTargetingCooldown(__instance) || (AttackingRef.Invoke(__instance) && (Object)(object)TargetCharRef.Invoke(__instance) != (Object)null))
			{
				return false;
			}
			TimeLastCheckedForTargetRef.Invoke(__instance) = Time.time;
			Character val = null;
			float num2 = __instance.aggroDistance * num;
			bool value2 = Plugin.CfgRequireLineOfSight.Value;
			bool value3 = Plugin.CfgTargetPoisonedPlayers.Value;
			Vector3 val2 = Center(__instance);
			Character forcedCharacterTarget = __instance.forcedCharacterTarget;
			Affliction val3 = default(Affliction);
			foreach (Character allCharacter in Character.AllCharacters)
			{
				if (!allCharacter.data.fullyConscious || ((Object)(object)forcedCharacterTarget != (Object)null && (Object)(object)allCharacter != (Object)(object)forcedCharacterTarget))
				{
					continue;
				}
				float num3 = Vector3.Distance(((Component)__instance).transform.position, allCharacter.Center);
				if (num3 >= num2 || (!value3 && allCharacter.refs.afflictions.HasAfflictionType((AfflictionType)0, ref val3)))
				{
					continue;
				}
				if (value2)
				{
					RaycastHit val4 = HelperFunctions.LineCheck(val2, allCharacter.Center, (LayerType)1, 0f, (QueryTriggerInteraction)1);
					if (Object.op_Implicit((Object)(object)((RaycastHit)(ref val4)).transform))
					{
						continue;
					}
				}
				num2 = num3;
				val = allCharacter;
			}
			try
			{
				SetTargetChar?.Invoke(__instance, new object[1] { val });
			}
			catch (Exception ex)
			{
				Plugin.Log.LogDebug((object)("Failed to set scorpion target (safe to ignore): " + ex.Message));
			}
			return false;
		}

		[HarmonyPatch(typeof(Mob), "Targeting")]
		[HarmonyPostfix]
		private static void MobTargeting_Postfix(Mob __instance, float __state)
		{
			if (__instance is Scorpion && !float.IsNaN(__state))
			{
				__instance.aggroDistance = __state;
			}
		}

		[HarmonyPatch(typeof(Scorpion), "InflictAttack")]
		[HarmonyPrefix]
		private static bool ScorpionInflictAttack_Prefix(Scorpion __instance, Character character)
		{
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Invalid comparison between Unknown and I4
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Expected O, but got Unknown
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			bool flag = Plugin.CfgDamageType.Value == Plugin.DamageTypeOverride.Vanilla || Plugin.CfgDamageType.Value == Plugin.DamageTypeOverride.Poison;
			bool flag2 = Mathf.Approximately(Plugin.CfgDamageMultiplier.Value, 1f);
			bool value = Plugin.CfgEnableInitialDamageTick.Value;
			bool value2 = Plugin.CfgEnableOvertimeDamageTick.Value;
			bool flag3 = Mathf.Approximately(Plugin.CfgInitialDamageMultiplier.Value, 1f);
			bool flag4 = Mathf.Approximately(Plugin.CfgOvertimeDamageMultiplier.Value, 1f);
			if (flag && flag2 && value && value2 && flag3 && flag4)
			{
				return true;
			}
			if (!character.IsLocal)
			{
				return false;
			}
			float num = Mathf.Max(0f, Plugin.CfgDamageMultiplier.Value);
			float num2 = Mathf.Max(0f, Plugin.CfgInitialDamageMultiplier.Value);
			float num3 = Mathf.Max(0f, Plugin.CfgOvertimeDamageMultiplier.Value);
			bool value3 = Plugin.CfgEnableInitialDamageTick.Value;
			bool value4 = Plugin.CfgEnableOvertimeDamageTick.Value;
			float num4 = num * num2;
			float num5 = num * num3;
			STATUSTYPE val = (STATUSTYPE)((Plugin.CfgDamageType.Value == Plugin.DamageTypeOverride.Vanilla) ? Plugin.DamageTypeOverride.Poison : Plugin.CfgDamageType.Value);
			float num6 = 1f - character.refs.afflictions.statusSum;
			float num7 = Mathf.Max(0.5f, num6 + 0.05f);
			float totalPoisonTime = __instance.totalPoisonTime;
			float num8 = (value3 ? (0.025f * num4) : 0f);
			float num9 = (value4 ? (num7 / Mathf.Max(0.01f, totalPoisonTime) * num5) : 0f);
			if (num8 > 0f)
			{
				character.refs.afflictions.AddStatus(val, num8, false, true);
			}
			if (totalPoisonTime > 0f && num9 > 0f)
			{
				if ((int)val == 3)
				{
					character.refs.afflictions.AddAffliction((Affliction)new Affliction_PoisonOverTime(totalPoisonTime, 0f, num9), false);
				}
				else
				{
					ScorpionCustomDotRunner scorpionCustomDotRunner = ((Component)character).gameObject.GetComponent<ScorpionCustomDotRunner>();
					if ((Object)(object)scorpionCustomDotRunner == (Object)null)
					{
						scorpionCustomDotRunner = ((Component)character).gameObject.AddComponent<ScorpionCustomDotRunner>();
					}
					scorpionCustomDotRunner.Stack(val, num9, totalPoisonTime);
				}
			}
			character.AddForceAtPosition(500f * ((Mob)__instance).mesh.forward, ((Component)__instance).transform.position, 2f);
			return false;
		}
	}
	internal sealed class ScorpionCustomDotRunner : MonoBehaviour
	{
		private Character? _character;

		private STATUSTYPE _statusType;

		private float _statusPerSecond;

		private float _timeRemaining;

		private void Awake()
		{
			_character = ((Component)this).GetComponent<Character>();
			((Behaviour)this).enabled = false;
		}

		public void Stack(STATUSTYPE statusType, float statusPerSecond, float duration)
		{
			//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)
			_statusType = statusType;
			_statusPerSecond = Mathf.Max(_statusPerSecond, statusPerSecond);
			_timeRemaining += duration;
			((Behaviour)this).enabled = true;
		}

		private void Update()
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_character == (Object)null || !_character.IsLocal)
			{
				((Behaviour)this).enabled = false;
				return;
			}
			if (_timeRemaining <= 0f || _statusPerSecond <= 0f)
			{
				Object.Destroy((Object)(object)this);
				return;
			}
			float deltaTime = Time.deltaTime;
			_timeRemaining -= deltaTime;
			_character.refs.afflictions.AddStatus(_statusType, _statusPerSecond * deltaTime, false, true);
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}