Rats/Snowlance.Rats.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
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 Dissonance;
using GameNetcodeStuff;
using HarmonyLib;
using LethalLib.Extras;
using LethalLib.Modules;
using Microsoft.CodeAnalysis;
using Rats;
using Snowlance.Rats.NetcodePatcher;
using Unity.Netcode;
using Unity.Netcode.Components;
using UnityEngine;
using UnityEngine.AI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("ClientNetworkTransform")]
[assembly: IgnoresAccessChecksTo("DissonanceVoip")]
[assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")]
[assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")]
[assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")]
[assembly: IgnoresAccessChecksTo("Unity.Burst")]
[assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")]
[assembly: IgnoresAccessChecksTo("Unity.Collections")]
[assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")]
[assembly: IgnoresAccessChecksTo("Unity.Jobs")]
[assembly: IgnoresAccessChecksTo("Unity.Mathematics")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")]
[assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")]
[assembly: IgnoresAccessChecksTo("Unity.Services.QoS")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Relay")]
[assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")]
[assembly: IgnoresAccessChecksTo("Unity.Timeline")]
[assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UI")]
[assembly: AssemblyCompany("Snowlance.Rats")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.2.1.0")]
[assembly: AssemblyInformationalVersion("1.2.1+266a7100629447b860770f0a99ed14544fe1c2d6")]
[assembly: AssemblyProduct("Rats")]
[assembly: AssemblyTitle("Snowlance.Rats")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[module: NetcodePatchedAssembly]
internal class <Module>
{
	static <Module>()
	{
	}
}
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;
		}
	}
}
public class RatAICollisionDetect : MonoBehaviour, IHittable
{
	public RatAI mainScript;

	public bool canCollideWithEnemies;

	public bool onlyCollideWhenGrounded;

	private void OnTriggerStay(Collider other)
	{
		if (((Component)other).CompareTag("Player"))
		{
			if (onlyCollideWhenGrounded)
			{
				CharacterController component = ((Component)other).gameObject.GetComponent<CharacterController>();
				if (!((Object)(object)component != (Object)null) || !component.isGrounded)
				{
					return;
				}
				mainScript.OnCollideWithPlayer(other);
			}
			mainScript.OnCollideWithPlayer(other);
		}
		else if (!onlyCollideWhenGrounded && canCollideWithEnemies && ((Component)other).CompareTag("Enemy"))
		{
			EnemyAICollisionDetect component2 = ((Component)other).gameObject.GetComponent<EnemyAICollisionDetect>();
			if ((Object)(object)component2 != (Object)null)
			{
				mainScript.OnCollideWithEnemy(other, component2.mainScript);
			}
		}
	}

	bool IHittable.Hit(int force, Vector3 hitDirection, PlayerControllerB playerWhoHit, bool playHitSFX, int hitID)
	{
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		if (onlyCollideWhenGrounded)
		{
			Debug.Log((object)"Enemy collision detect returned false");
			return false;
		}
		mainScript.HitEnemyOnLocalClient(force, hitDirection, playerWhoHit, playHitSFX, hitID);
		return true;
	}
}
namespace Rats
{
	[HarmonyPatch(typeof(Landmine))]
	internal class LandminePatch
	{
		private static ManualLogSource logger = Plugin.LoggerInstance;

		[HarmonyPostfix]
		[HarmonyPatch("SpawnExplosion")]
		public static void SpawnExplosionPostfix(Vector3 explosionPosition, bool spawnExplosionEffect = false, float killRange = 1f, float damageRange = 1f, int nonLethalDamage = 50, float physicsForce = 0f, GameObject overridePrefab = null, bool goThroughCar = false)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			foreach (RatAI spawnedRat in RatManager.SpawnedRats)
			{
				float num = Vector3.Distance(((Component)spawnedRat).transform.position, explosionPosition);
				if (num < damageRange)
				{
					spawnedRat.HitFromExplosion(num);
				}
			}
		}
	}
	[HarmonyPatch(typeof(RoundManager))]
	internal class RoundManagerPatch
	{
		private static ManualLogSource logger = Plugin.LoggerInstance;

		[HarmonyPostfix]
		[HarmonyPatch("DespawnPropsAtEndOfRound")]
		public static void DespawnPropsAtEndOfRoundPostfix()
		{
		}
	}
	internal class TESTING : MonoBehaviour
	{
		private static ManualLogSource logger = Plugin.LoggerInstance;

		public static bool testing = false;

		public static bool noSpawning = false;

		[HarmonyPostfix]
		[HarmonyPatch(typeof(HUDManager), "PingScan_performed")]
		public static void PingScan_performedPostFix()
		{
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(HUDManager), "SubmitChat_performed")]
		public static void SubmitChat_performedPrefix(HUDManager __instance)
		{
			//IL_01d7: 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_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: 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_0195: Unknown result type (might be due to invalid IL or missing references)
			string text = __instance.chatTextField.text;
			string[] array = text.Split(" ");
			switch (array[0])
			{
			case "/spawnRat":
			{
				RatNest closestNest = RatManager.GetClosestNest(((Component)Plugin.localPlayer).transform.position);
				closestNest.SpawnRats(int.Parse(array[1]));
				Plugin.log("Spawning " + array[1] + " rats");
				break;
			}
			case "/spawnNest":
			{
				Vector3 position = ((Component)Plugin.localPlayer).transform.position + ((Component)Plugin.localPlayer).transform.forward * 1f;
				RatManager.SpawnNest(position);
				break;
			}
			case "/testing":
				testing = !testing;
				HUDManager.Instance.DisplayTip("Testing", testing.ToString(), false, false, "LC_Tip1");
				break;
			case "/spawning":
				noSpawning = !noSpawning;
				HUDManager.Instance.DisplayTip("NoSpawning", noSpawning.ToString(), false, false, "LC_Tip1");
				break;
			case "/enemies":
			{
				foreach (SpawnableEnemyWithRarity enemy in GetEnemies())
				{
					Plugin.log(((Object)enemy.enemyType).name);
				}
				break;
			}
			case "/refresh":
				RoundManager.Instance.RefreshEnemiesList();
				HoarderBugAI.RefreshGrabbableObjectsInMapList();
				break;
			case "/levels":
			{
				SelectableLevel[] levels = StartOfRound.Instance.levels;
				foreach (SelectableLevel val2 in levels)
				{
					Plugin.log(((Object)val2).name);
				}
				break;
			}
			case "/dungeon":
				Plugin.log(((Object)RoundManager.Instance.dungeonGenerator.Generator.DungeonFlow).name);
				break;
			case "/dungeons":
			{
				IndoorMapType[] dungeonFlowTypes = RoundManager.Instance.dungeonFlowTypes;
				foreach (IndoorMapType val in dungeonFlowTypes)
				{
					Plugin.log(((Object)val.dungeonFlow).name);
				}
				break;
			}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(RoundManager), "SpawnEnemyFromVent")]
		public static bool SpawnEnemyFromVentPreFix()
		{
			if (noSpawning)
			{
				return false;
			}
			return true;
		}

		public static List<SpawnableEnemyWithRarity> GetEnemies()
		{
			Plugin.log("Getting enemies");
			List<SpawnableEnemyWithRarity> list = new List<SpawnableEnemyWithRarity>();
			list = (from x in GameObject.Find("Terminal").GetComponentInChildren<Terminal>().moonsCatalogueList.SelectMany((SelectableLevel x) => x.Enemies.Concat(x.DaytimeEnemies).Concat(x.OutsideEnemies))
				where x != null && (Object)(object)x.enemyType != (Object)null && ((Object)x.enemyType).name != null
				select x).GroupBy((SpawnableEnemyWithRarity x) => ((Object)x.enemyType).name, (string k, IEnumerable<SpawnableEnemyWithRarity> v) => v.First()).ToList();
			Plugin.log($"Enemy types: {list.Count}");
			return list;
		}

		public static void LogChat(string msg)
		{
			HUDManager.Instance.AddChatMessage(msg, "Server");
		}

		public static Vector3 GetSpeed()
		{
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: 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)
			//IL_027c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_03de: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_040c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0411: Unknown result type (might be due to invalid IL or missing references)
			//IL_0416: Unknown result type (might be due to invalid IL or missing references)
			//IL_0417: Unknown result type (might be due to invalid IL or missing references)
			//IL_041c: Unknown result type (might be due to invalid IL or missing references)
			//IL_041e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0425: Unknown result type (might be due to invalid IL or missing references)
			//IL_042a: Unknown result type (might be due to invalid IL or missing references)
			//IL_042f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0431: Unknown result type (might be due to invalid IL or missing references)
			//IL_0433: Unknown result type (might be due to invalid IL or missing references)
			//IL_0437: Unknown result type (might be due to invalid IL or missing references)
			//IL_036c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0377: Unknown result type (might be due to invalid IL or missing references)
			//IL_038e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0393: Unknown result type (might be due to invalid IL or missing references)
			//IL_039d: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_032e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0345: 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_0162: Unknown result type (might be due to invalid IL or missing references)
			float num = Plugin.localPlayer.movementSpeed / Plugin.localPlayer.carryWeight;
			if (Plugin.localPlayer.sinkingValue > 0.73f)
			{
				num = 0f;
			}
			else
			{
				if (Plugin.localPlayer.isCrouching)
				{
					num /= 1.5f;
				}
				else if (Plugin.localPlayer.criticallyInjured && !Plugin.localPlayer.isCrouching)
				{
					num *= Plugin.localPlayer.limpMultiplier;
				}
				if (Plugin.localPlayer.isSpeedCheating)
				{
					num *= 15f;
				}
				if (Plugin.localPlayer.movementHinderedPrev > 0)
				{
					num /= 2f * Plugin.localPlayer.hinderedMultiplier;
				}
				if (Plugin.localPlayer.drunkness > 0f)
				{
					num *= StartOfRound.Instance.drunknessSpeedEffect.Evaluate(Plugin.localPlayer.drunkness) / 5f + 1f;
				}
				if (!Plugin.localPlayer.isCrouching && Plugin.localPlayer.crouchMeter > 1.2f)
				{
					num *= 0.5f;
				}
				if (!Plugin.localPlayer.isCrouching)
				{
					float num2 = Vector3.Dot(Plugin.localPlayer.playerGroundNormal, Plugin.localPlayer.walkForce);
					if (num2 > 0.05f)
					{
						Plugin.localPlayer.slopeModifier = Mathf.MoveTowards(Plugin.localPlayer.slopeModifier, num2, (Plugin.localPlayer.slopeModifierSpeed + 0.45f) * Time.deltaTime);
					}
					else
					{
						Plugin.localPlayer.slopeModifier = Mathf.MoveTowards(Plugin.localPlayer.slopeModifier, num2, Plugin.localPlayer.slopeModifierSpeed / 2f * Time.deltaTime);
					}
					num = Mathf.Max(num * 0.8f, num + Plugin.localPlayer.slopeIntensity * Plugin.localPlayer.slopeModifier);
				}
			}
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(0f, 0f, 0f);
			int num3 = Physics.OverlapSphereNonAlloc(((Component)Plugin.localPlayer).transform.position, 0.65f, Plugin.localPlayer.nearByPlayers, StartOfRound.Instance.playersMask);
			for (int i = 0; i < num3; i++)
			{
				val += Vector3.Normalize((((Component)Plugin.localPlayer).transform.position - ((Component)Plugin.localPlayer.nearByPlayers[i]).transform.position) * 100f) * 1.2f;
			}
			int num4 = Physics.OverlapSphereNonAlloc(((Component)Plugin.localPlayer).transform.position, 1.25f, Plugin.localPlayer.nearByPlayers, 524288);
			for (int j = 0; j < num4; j++)
			{
				EnemyAICollisionDetect component = ((Component)Plugin.localPlayer.nearByPlayers[j]).gameObject.GetComponent<EnemyAICollisionDetect>();
				if ((Object)(object)component != (Object)null && (Object)(object)component.mainScript != (Object)null && !component.mainScript.isEnemyDead && Vector3.Distance(((Component)Plugin.localPlayer).transform.position, ((Component)Plugin.localPlayer.nearByPlayers[j]).transform.position) < component.mainScript.enemyType.pushPlayerDistance)
				{
					val += Vector3.Normalize((((Component)Plugin.localPlayer).transform.position - ((Component)Plugin.localPlayer.nearByPlayers[j]).transform.position) * 100f) * component.mainScript.enemyType.pushPlayerForce;
				}
			}
			Vector3 val2 = Plugin.localPlayer.walkForce * num * Plugin.localPlayer.sprintMultiplier + new Vector3(0f, Plugin.localPlayer.fallValue, 0f) + val;
			return val2 + Plugin.localPlayer.externalForces;
		}
	}
	[BepInPlugin("Snowlance.Rats", "Rats", "1.2.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public static Plugin PluginInstance;

		public static ManualLogSource LoggerInstance;

		private readonly Harmony harmony = new Harmony("Snowlance.Rats");

		public static AssetBundle ModAssets;

		public static bool IsLoggingEnabled;

		public static ConfigEntry<bool> configHolidayRats;

		public static ConfigEntry<bool> configEnableDebugging;

		public static ConfigEntry<int> configMaxRats;

		public static ConfigEntry<float> configAIIntervalTime;

		public static ConfigEntry<int> configBatchGroupCount;

		public static ConfigEntry<float> configBatchUpdateInterval;

		public static ConfigEntry<bool> configEnableRatKing;

		public static ConfigEntry<string> configRatKingLevelRarities;

		public static ConfigEntry<string> configRatKingCustomLevelRarities;

		public static ConfigEntry<float> configRatKingSummonChanceRatDeath;

		public static ConfigEntry<float> configRatKingSummonChancePoison;

		public static ConfigEntry<float> configRatKingSummonChanceApparatus;

		public static ConfigEntry<float> configRatKingSummonChanceNests;

		public static ConfigEntry<int> configRatKingDamage;

		public static ConfigEntry<float> configRatKingRallyCooldown;

		public static ConfigEntry<float> configRatKingLoseDistance;

		public static ConfigEntry<float> configRatKingIdleTime;

		public static ConfigEntry<string> configSewerGrateSpawnWeightCurve;

		public static ConfigEntry<int> configMinRatSpawnTime;

		public static ConfigEntry<int> configMaxRatSpawnTime;

		public static ConfigEntry<int> configFoodToSpawnRat;

		public static ConfigEntry<int> configEnemyFoodPerHPPoint;

		public static ConfigEntry<bool> configUseJermaRats;

		public static ConfigEntry<float> configDefenseRadius;

		public static ConfigEntry<float> configTimeToIncreaseThreat;

		public static ConfigEntry<int> configThreatToAttackPlayer;

		public static ConfigEntry<int> configHighPlayerThreat;

		public static ConfigEntry<int> configThreatToAttackEnemy;

		public static ConfigEntry<float> configSwarmRadius;

		public static ConfigEntry<int> configMaxDefenseRats;

		public static ConfigEntry<float> configDistanceNeededToLoseRats;

		public static ConfigEntry<int> configEnemyHitsToDoDamage;

		public static ConfigEntry<int> configPlayerFoodAmount;

		public static ConfigEntry<int> configRatDamage;

		public static ConfigEntry<float> configSqueakChance;

		public static ConfigEntry<int> configRatPoisonPrice;

		public static ConfigEntry<float> configRatPoisonMaxFluid;

		public static ConfigEntry<float> configRatPoisonPourRate;

		public static ConfigEntry<float> configPoisonToCloseNest;

		public static ConfigEntry<int> configGlueTrapPrice;

		public static ConfigEntry<int> configGlueBoardAmount;

		public static ConfigEntry<int> configScrapValuePerRat;

		public static ConfigEntry<int> configMaxRatsOnGlueTrap;

		public static ConfigEntry<int> configSnapTrapsPrice;

		public static ConfigEntry<int> configSnapTrapAmount;

		public static ConfigEntry<float> configSnapTrapsDespawnTime;

		public static ConfigEntry<int> configRatCrownMinValue;

		public static ConfigEntry<int> configRatCrownMaxValue;

		public static PlayerControllerB localPlayer => GameNetworkManager.Instance.localPlayerController;

		public static bool IsServerOrHost => NetworkManager.Singleton.IsServer || NetworkManager.Singleton.IsHost;

		public static PlayerControllerB PlayerFromId(ulong id)
		{
			return StartOfRound.Instance.allPlayerScripts[StartOfRound.Instance.ClientPlayerList[id]];
		}

		private void Awake()
		{
			if ((Object)(object)PluginInstance == (Object)null)
			{
				PluginInstance = this;
			}
			LoggerInstance = ((BaseUnityPlugin)PluginInstance).Logger;
			harmony.PatchAll();
			InitializeNetworkBehaviours();
			configHolidayRats = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Holiday Rats", false, "Rats spawn with a santa hat");
			configEnableDebugging = ((BaseUnityPlugin)this).Config.Bind<bool>("Debugging", "Enable Debugging", false, "Allows debug logs to show in the logs");
			configMaxRats = ((BaseUnityPlugin)this).Config.Bind<int>("Performance", "Maximum Rats", 50, "The maximum number of rats that can be on the map. Lowering this can improve performance.");
			configAIIntervalTime = ((BaseUnityPlugin)this).Config.Bind<float>("Performance", "AI Interval Time", 0.3f, "The interval in which rats will update their AI (Changing position, doing complex calculations, etc). Setting this higher can improve performance but can also make the rats freeze in place more often while lower values makes them constantly moving but can decrease performance. Funnily enough the rats move more rat like when this is set higher.");
			configBatchGroupCount = ((BaseUnityPlugin)this).Config.Bind<int>("Performance", "Batch Group Count", 5, "The amount of groups the rats will be split into to update. (if you dont know what this means, just leave this config alone)");
			configBatchUpdateInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Performance", "Batch Update Interval", 0.2f, "The amount of time between each group update. (if you dont know what this means, just leave this config alone)");
			configEnableRatKing = ((BaseUnityPlugin)this).Config.Bind<bool>("Rat King", "Enable Rat King", true, "Set to false to disable spawning the rat king.");
			configRatKingLevelRarities = ((BaseUnityPlugin)this).Config.Bind<string>("Rat King Rarities", "Level Rarities", "All: 20", "Rarities for each level. Example formatting: ExperimentationLevel:5, AssuranceLevel:6, VowLevel:9, OffenseLevel:10, AdamanceLevel:10, MarchLevel:10, RendLevel:75, DineLevel:75, TitanLevel:75, ArtificeLevel:20, EmbrionLevel:25, Modded:15");
			configRatKingCustomLevelRarities = ((BaseUnityPlugin)this).Config.Bind<string>("Rat King Rarities", "Custom Level Rarities", "", "Rarities for modded levels. Same formatting as level rarities.");
			configRatKingSummonChanceRatDeath = ((BaseUnityPlugin)this).Config.Bind<float>("Rat King", "Rat Death Summon Chance", 0.01f, "The chance the rat king will spawn when killing a rat at high threat.");
			configRatKingSummonChancePoison = ((BaseUnityPlugin)this).Config.Bind<float>("Rat King", "Poison Summon Chance", 0.5f, "The chance the rat king will spawn when disabling a nest with rat poison.");
			configRatKingSummonChanceApparatus = ((BaseUnityPlugin)this).Config.Bind<float>("Rat King", "Apparatus Summon Chance", 0.05f, "The chance the rat king will spawn when pulling the apparatus.");
			configRatKingSummonChanceNests = ((BaseUnityPlugin)this).Config.Bind<float>("Rat King", "All Nests Disabled Summon Chance", 0.85f, "The chance the rat king will spawn when all the nests are disabled.");
			configRatKingDamage = ((BaseUnityPlugin)this).Config.Bind<int>("Rat King", "Damage", 25, "The amount of damage the rat king does.");
			configRatKingRallyCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Rat King", "Rally Cooldown", 30f, "The cooldown for the rat kings rally ability.");
			configRatKingLoseDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Rat King", "Distance to Lose Rat King", 20f, "The distance from the rat king you need to be to lose him. Does not apply when rampaged or hunting.");
			configRatKingIdleTime = ((BaseUnityPlugin)this).Config.Bind<float>("Rat King", "Idle Time", 5f, "The amount of time the rat king will spend idling when reaching a destination during his roam routine.");
			configSewerGrateSpawnWeightCurve = ((BaseUnityPlugin)this).Config.Bind<string>("Nest", "Spawn Weight Curve", "Vanilla - 0,0 ; 1,2 | Custom - 0,0 ; 1,2", "The MoonName - CurveSpawnWeight for the SewerGrate(Rat nest).");
			configMinRatSpawnTime = ((BaseUnityPlugin)this).Config.Bind<int>("Nest", "Minimum Rat Spawn Time", 5, "The minimum time in seconds before a rat can spawn from the nest.");
			configMaxRatSpawnTime = ((BaseUnityPlugin)this).Config.Bind<int>("Nest", "Maximum Rat Spawn Time", 20, "The maximum time in seconds before a rat can spawn from the nest.");
			configFoodToSpawnRat = ((BaseUnityPlugin)this).Config.Bind<int>("Nest", "Food Required to Spawn Rat", 5, "The amount of food needed in the nest to spawn a new rat.");
			configEnemyFoodPerHPPoint = ((BaseUnityPlugin)this).Config.Bind<int>("Nest", "Food Per HP Point", 10, "How much food points one HP will equal for enemies. ex: if 10 thumper will give 40 food points.");
			configUseJermaRats = ((BaseUnityPlugin)this).Config.Bind<bool>("Rats", "Use Jerma Rats", false, "Uses a lower quality model for the rats with no animations. Can help with performance if enabled.");
			configDefenseRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Rats", "Defense Radius", 5f, "The radius in which defense rats protect the nest.");
			configTimeToIncreaseThreat = ((BaseUnityPlugin)this).Config.Bind<float>("Rats", "Time to Increase Threat", 2.5f, "The time needed to add a threat point for a player when they are in line of sight of the rat.");
			configThreatToAttackPlayer = ((BaseUnityPlugin)this).Config.Bind<int>("Rats", "Threat to Attack Player", 100, "The threat level at which rats begin attacking the player.");
			configHighPlayerThreat = ((BaseUnityPlugin)this).Config.Bind<int>("Rats", "High Player Threat", 250, "The threat level at which rats will call for the rat king and the rat king will attack players.");
			configThreatToAttackEnemy = ((BaseUnityPlugin)this).Config.Bind<int>("Rats", "Threat to Attack Enemy", 50, "The threat level at which rats begin attacking enemy entities.");
			configSwarmRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Rats", "Swarm Radius", 3f, "The radius in which rats swarm around their target.");
			configMaxDefenseRats = ((BaseUnityPlugin)this).Config.Bind<int>("Rats", "Maximum Defense Rats", 10, "The maximum number of defense rats assigned to protect the nest.");
			configDistanceNeededToLoseRats = ((BaseUnityPlugin)this).Config.Bind<float>("Rats", "Distance Needed to Lose Rats", 25f, "The distance the player must be from rats to lose them.");
			configEnemyHitsToDoDamage = ((BaseUnityPlugin)this).Config.Bind<int>("Rats", "Enemy Hits to Do Damage", 10, "The amount of attacks needed to do 1 shovel hit of damage to an enemy. If 10, thumper will need to be attacked 40 times by a rat.");
			configPlayerFoodAmount = ((BaseUnityPlugin)this).Config.Bind<int>("Rats", "Player Food Amount", 30, "How much food points a player corpse gives when brought to the nest.");
			configRatDamage = ((BaseUnityPlugin)this).Config.Bind<int>("Rats", "Rat Damage", 2, "The damage dealt by a rat when attacking.");
			configSqueakChance = ((BaseUnityPlugin)this).Config.Bind<float>("Rats", "Squeak Chance", 0.01f, "The chance a rat will squeak when completing a run cycle (every second)");
			configRatPoisonPrice = ((BaseUnityPlugin)this).Config.Bind<int>("Rat Poison", "Store Price", 40, "The cost of rat poison in the store.");
			configRatPoisonMaxFluid = ((BaseUnityPlugin)this).Config.Bind<float>("Rat Poison", "Max Fluid", 5f, "The amount of rat poison in a container of rat poison.");
			configRatPoisonPourRate = ((BaseUnityPlugin)this).Config.Bind<float>("Rat Poison", "Pour Rate", 0.1f, "How fast the rat poison pours out of the container.");
			configPoisonToCloseNest = ((BaseUnityPlugin)this).Config.Bind<float>("Rat Poison", "Poison To Close Nest", 1f, "The amount of poison you need to pour in a rat nest to disable it. Disabling a nest prevents rats from spawning and has a chance to spawn the rat king.");
			configGlueTrapPrice = ((BaseUnityPlugin)this).Config.Bind<int>("Glue Trap", "Store Price", 20, "The cost of the glue trap in the store.");
			configGlueBoardAmount = ((BaseUnityPlugin)this).Config.Bind<int>("Glue Trap", "Glue Board Amount", 4, "The amount of glue boards you get in the glue trap item.");
			configScrapValuePerRat = ((BaseUnityPlugin)this).Config.Bind<int>("Glue Trap", "Scrap Value Per Rat", 2, "The scrap value added to the glue board per rat stuck.");
			configMaxRatsOnGlueTrap = ((BaseUnityPlugin)this).Config.Bind<int>("Glue Trap", "Maximum Rats on Glue Trap", 5, "The maximum number of rats that can be caught on a single glue trap before it becomes full.");
			configSnapTrapsPrice = ((BaseUnityPlugin)this).Config.Bind<int>("Snap Traps", "Store Price", 50, "The cost of the box of snap traps in the store.");
			configSnapTrapAmount = ((BaseUnityPlugin)this).Config.Bind<int>("Snap Traps", "Snap Trap Amount", 100, "The amount of snap traps that come with a Box Of Snap Traps.");
			configSnapTrapsDespawnTime = ((BaseUnityPlugin)this).Config.Bind<float>("Snap Traps", "Despawn Time", 10f, "The time for snap traps to despawn after being triggered.");
			configRatCrownMinValue = ((BaseUnityPlugin)this).Config.Bind<int>("Rat Crown", "Minimum Scrap Value", 300, "The minimum scrap value of the crown.");
			configRatCrownMaxValue = ((BaseUnityPlugin)this).Config.Bind<int>("Rat Crown", "Maximum Scrap Value", 500, "The maximum scrap value of the crown.");
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			ModAssets = AssetBundle.LoadFromFile(Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "rats_assets"));
			if ((Object)(object)ModAssets == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"Failed to load custom assets.");
				return;
			}
			LoggerInstance.LogDebug((object)("Got AssetBundle at: " + Path.Combine(directoryName, "rats_assets")));
			EnemyType val = ModAssets.LoadAsset<EnemyType>("Assets/ModAssets/RatKingEnemy.asset");
			if ((Object)(object)val == (Object)null)
			{
				LoggerInstance.LogError((object)"Error: Couldnt get Rat from assets");
				return;
			}
			LoggerInstance.LogDebug((object)"Got Rat prefab");
			TerminalNode val2 = ModAssets.LoadAsset<TerminalNode>("Assets/ModAssets/Bestiary/RatKingTN.asset");
			TerminalKeyword val3 = ModAssets.LoadAsset<TerminalKeyword>("Assets/ModAssets/Bestiary/RatKingTK.asset");
			LoggerInstance.LogDebug((object)"Registering enemy network prefab...");
			NetworkPrefabs.RegisterNetworkPrefab(val.enemyPrefab);
			LoggerInstance.LogDebug((object)"Registering enemy...");
			Enemies.RegisterEnemy(val, GetLevelRarities(configRatKingLevelRarities.Value), GetCustomLevelRarities(configRatKingCustomLevelRarities.Value), val2, val3);
			SpawnableMapObjectDef val4 = ModAssets.LoadAsset<SpawnableMapObjectDef>("Assets/ModAssets/RatSpawn.asset");
			if ((Object)(object)val4 == (Object)null)
			{
				LoggerInstance.LogError((object)"Error: Couldnt get RatSpawnPrefab from assets");
				return;
			}
			LoggerInstance.LogDebug((object)"Registering rat spawn network prefab...");
			NetworkPrefabs.RegisterNetworkPrefab(val4.spawnableMapObject.prefabToSpawn);
			RatManager.RatNestPrefab = val4.spawnableMapObject.prefabToSpawn;
			LoggerInstance.LogDebug((object)"Registering RatSpawn");
			RegisterInsideMapObjectWithConfig(val4, configSewerGrateSpawnWeightCurve.Value);
			GameObject val5 = ModAssets.LoadAsset<GameObject>("Assets/ModAssets/Rat.prefab");
			NetworkPrefabs.RegisterNetworkPrefab(val5);
			GameObject val6 = ModAssets.LoadAsset<GameObject>("Assets/ModAssets/JermaRat.prefab");
			NetworkPrefabs.RegisterNetworkPrefab(val6);
			Item val7 = ModAssets.LoadAsset<Item>("Assets/ModAssets/RatPoisonItem.asset");
			NetworkPrefabs.RegisterNetworkPrefab(val7.spawnPrefab);
			Utilities.FixMixerGroups(val7.spawnPrefab);
			Items.RegisterShopItem(val7, configRatPoisonPrice.Value);
			Item val8 = ModAssets.LoadAsset<Item>("Assets/ModAssets/GlueTrapItem.asset");
			NetworkPrefabs.RegisterNetworkPrefab(val8.spawnPrefab);
			Utilities.FixMixerGroups(val8.spawnPrefab);
			Items.RegisterShopItem(val8, configGlueTrapPrice.Value);
			Item val9 = ModAssets.LoadAsset<Item>("Assets/ModAssets/GlueBoardItem.asset");
			NetworkPrefabs.RegisterNetworkPrefab(val9.spawnPrefab);
			Utilities.FixMixerGroups(val9.spawnPrefab);
			Items.RegisterItem(val9);
			Item val10 = ModAssets.LoadAsset<Item>("Assets/ModAssets/BoxOfSnapTrapsItem.asset");
			NetworkPrefabs.RegisterNetworkPrefab(val10.spawnPrefab);
			Utilities.FixMixerGroups(val10.spawnPrefab);
			Items.RegisterShopItem(val10, configSnapTrapsPrice.Value);
			Item val11 = ModAssets.LoadAsset<Item>("Assets/ModAssets/RatCrownItem.asset");
			val11.minValue = configRatCrownMinValue.Value;
			val11.maxValue = configRatCrownMaxValue.Value;
			NetworkPrefabs.RegisterNetworkPrefab(val11.spawnPrefab);
			Utilities.FixMixerGroups(val11.spawnPrefab);
			Items.RegisterScrap(val11, 0, (LevelTypes)1, (string[])null);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Snowlance.Rats v1.2.1 has loaded!");
		}

		public static void log(object message)
		{
			if (IsLoggingEnabled || TESTING.testing)
			{
				LoggerInstance.LogDebug(message);
			}
		}

		protected void RegisterInsideMapObjectWithConfig(SpawnableMapObjectDef mapObjDef, string configString)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			var (dictionary, dictionary2) = ConfigParsingWithCurve(configString);
			foreach (KeyValuePair<LevelTypes, string> item in dictionary)
			{
				AnimationCurve animationCurve2 = CreateCurveFromString(item.Value, ((Object)mapObjDef.spawnableMapObject.prefabToSpawn).name);
				MapObjects.RegisterMapObject(mapObjDef, item.Key, (Func<SelectableLevel, AnimationCurve>)((SelectableLevel level) => animationCurve2));
			}
			foreach (KeyValuePair<string, string> item2 in dictionary2)
			{
				AnimationCurve animationCurve = CreateCurveFromString(item2.Value, ((Object)mapObjDef.spawnableMapObject.prefabToSpawn).name);
				MapObjects.RegisterMapObject(mapObjDef, (LevelTypes)1, new string[1] { item2.Key }, (Func<SelectableLevel, AnimationCurve>)((SelectableLevel level) => animationCurve));
			}
		}

		protected (Dictionary<LevelTypes, string> spawnRateByLevelType, Dictionary<string, string> spawnRateByCustomLevelType) ConfigParsingWithCurve(string configMoonRarity)
		{
			//IL_00cf: 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)
			Dictionary<LevelTypes, string> dictionary = new Dictionary<LevelTypes, string>();
			Dictionary<string, string> dictionary2 = new Dictionary<string, string>();
			foreach (string item in from s in configMoonRarity.Split('|')
				select s.Trim())
			{
				string[] array = (from s in item.Split('-')
					select s.Trim()).ToArray();
				if (array.Length != 2)
				{
					continue;
				}
				string text = array[0].ToLowerInvariant();
				if (text == "custom")
				{
					text = "modded";
				}
				if (Enum.TryParse<LevelTypes>(text, ignoreCase: true, out LevelTypes result))
				{
					dictionary[result] = array[1];
					continue;
				}
				string value = text + "level";
				if (Enum.TryParse<LevelTypes>(value, ignoreCase: true, out result))
				{
					dictionary[result] = array[1];
				}
				else
				{
					dictionary2[text] = array[1];
				}
			}
			return (dictionary, dictionary2);
		}

		public AnimationCurve CreateCurveFromString(string keyValuePairs, string nameOfThing)
		{
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Expected O, but got Unknown
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Expected O, but got Unknown
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			string[] array = (from s in keyValuePairs.Split(';')
				select s.Trim()).ToArray();
			if (array.Length == 0)
			{
				if (int.TryParse(keyValuePairs, out var result))
				{
					return new AnimationCurve((Keyframe[])(object)new Keyframe[2]
					{
						new Keyframe(0f, 0f),
						new Keyframe(1f, (float)result)
					});
				}
				LoggerInstance.LogError((object)("Invalid key-value pairs format: " + keyValuePairs));
				return new AnimationCurve((Keyframe[])(object)new Keyframe[2]
				{
					new Keyframe(0f, 0f),
					new Keyframe(1f, 0f)
				});
			}
			List<Keyframe> list = new List<Keyframe>();
			string[] array2 = array;
			foreach (string text in array2)
			{
				string[] array3 = (from s in text.Split(',')
					select s.Trim()).ToArray();
				if (array3.Length == 2 && float.TryParse(array3[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2) && float.TryParse(array3[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result3))
				{
					list.Add(new Keyframe(result2, result3));
					continue;
				}
				LoggerInstance.LogError((object)("Failed config for hazard: " + nameOfThing));
				LoggerInstance.LogError((object)$"Split pair length: {array3.Length}");
				LoggerInstance.LogError((object)$"Could parse first value: {float.TryParse(array3[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var result4)}, instead got: {result4}, with splitPair0 being: {array3[0]}");
				LoggerInstance.LogError((object)$"Could parse second value: {float.TryParse(array3[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result5)}, instead got: {result5}, with splitPair1 being: {array3[1]}");
				LoggerInstance.LogError((object)("Invalid key,value pair format: " + text));
			}
			AnimationCurve val = new AnimationCurve(list.ToArray());
			for (int j = 0; j < list.Count; j++)
			{
				val.SmoothTangents(j, 0.5f);
			}
			return val;
		}

		public Dictionary<LevelTypes, int> GetLevelRarities(string levelsString)
		{
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Dictionary<LevelTypes, int> dictionary = new Dictionary<LevelTypes, int>();
				if (levelsString != null && levelsString != "")
				{
					string[] array = levelsString.Split(',');
					string[] array2 = array;
					foreach (string text in array2)
					{
						string[] array3 = text.Split(':');
						if (array3.Length == 2)
						{
							string text2 = array3[0].Trim();
							string text3 = array3[1].Trim();
							if (Enum.TryParse<LevelTypes>(text2, out LevelTypes result) && int.TryParse(text3, out var result2))
							{
								dictionary.Add(result, result2);
							}
							else
							{
								LoggerInstance.LogError((object)("Error: Invalid level rarity: " + text2 + ":" + text3));
							}
						}
					}
				}
				return dictionary;
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Error: {arg}");
				return null;
			}
		}

		public Dictionary<string, int> GetCustomLevelRarities(string levelsString)
		{
			try
			{
				Dictionary<string, int> dictionary = new Dictionary<string, int>();
				if (levelsString != null)
				{
					string[] array = levelsString.Split(',');
					string[] array2 = array;
					foreach (string text in array2)
					{
						string[] array3 = text.Split(':');
						if (array3.Length == 2)
						{
							string text2 = array3[0].Trim();
							string text3 = array3[1].Trim();
							if (int.TryParse(text3, out var result))
							{
								dictionary.Add(text2, result);
							}
							else
							{
								LoggerInstance.LogError((object)("Error: Invalid level rarity: " + text2 + ":" + text3));
							}
						}
					}
				}
				return dictionary;
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Error: {arg}");
				return null;
			}
		}

		private static void InitializeNetworkBehaviours()
		{
			Type[] types = Assembly.GetExecutingAssembly().GetTypes();
			Type[] array = types;
			foreach (Type type in array)
			{
				MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic);
				MethodInfo[] array2 = methods;
				foreach (MethodInfo methodInfo in array2)
				{
					object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false);
					if (customAttributes.Length != 0)
					{
						methodInfo.Invoke(null, null);
					}
				}
			}
			LoggerInstance.LogDebug((object)"Finished initializing network behaviours");
		}
	}
	public class RatAI : NetworkBehaviour
	{
		public enum State
		{
			ReturnToNest,
			Routine,
			Swarming
		}

		private static ManualLogSource logger = Plugin.LoggerInstance;

		public AudioClip[] SqueakSFX;

		public AudioClip[] AttackSFX;

		public AudioClip[] HitSFX;

		public AudioClip[] NibbleSFX;

		public AudioClip ScreamSFX;

		public AudioClip[] HappyBirthdayRatSFX;

		public Transform RatMouth;

		public GameObject ChristmasHat;

		public NavMeshAgent agent;

		public Animator creatureAnimator;

		public Transform eye;

		public int enemyHP;

		public AudioSource creatureSFX;

		public AudioSource creatureVoice;

		public bool IsJermaRat;

		private float updateDestinationInterval;

		public bool isEnemyDead;

		private bool moveTowardsDestination;

		private Vector3 destination;

		private bool isOutside;

		private Transform? targetNode;

		private bool inSpecialAnimation;

		private State currentBehaviorState = State.Routine;

		public PlayerControllerB? targetPlayer;

		public EnemyAI? targetEnemy;

		private DeadBodyInfo? heldBody;

		private bool holdingFood;

		private int hashDie;

		private bool grabbingBody;

		private bool returningBodyToNest;

		public RatNest? Nest;

		private float timeSinceCollision;

		private float timeSinceAddThreat;

		private float spinTimer;

		private NavMeshPath path1;

		private Coroutine? ratCoroutine;

		public bool rallyRat;

		public bool defenseRat;

		private bool pathingToNest;

		private const float idleTime = 1f;

		private float swarmRadius;

		private int maxDefenseRats;

		private float distanceToLoseRats;

		private int ratDamage;

		private float AIIntervalTime;

		public void StopTaskRoutine()
		{
			((MonoBehaviour)this).StopAllCoroutines();
			ratCoroutine = null;
		}

		public void Start()
		{
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Expected O, but got Unknown
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			hashDie = Animator.StringToHash("die");
			AIIntervalTime = Plugin.configAIIntervalTime.Value;
			swarmRadius = Plugin.configSwarmRadius.Value;
			maxDefenseRats = Plugin.configMaxDefenseRats.Value;
			distanceToLoseRats = Plugin.configDistanceNeededToLoseRats.Value;
			ratDamage = Plugin.configRatDamage.Value;
			ChristmasHat.SetActive(Plugin.configHolidayRats.Value);
			updateDestinationInterval = AIIntervalTime;
			path1 = new NavMeshPath();
			currentBehaviorState = State.ReturnToNest;
			Nest = RatManager.GetClosestNest(((Component)this).transform.position);
			if (Plugin.IsServerOrHost)
			{
				SwitchToBehaviorState(State.Routine);
			}
			Plugin.log("Rat spawned");
		}

		public override void OnNetworkDespawn()
		{
			((NetworkBehaviour)this).OnNetworkDespawn();
			if ((Object)(object)RatManager.Instance != (Object)null)
			{
				RatManager.Instance.RemoveRat(this);
			}
		}

		public void Update()
		{
			if (!isEnemyDead && !StartOfRound.Instance.allPlayersDead)
			{
				timeSinceCollision += Time.deltaTime;
				timeSinceAddThreat += Time.deltaTime;
			}
		}

		public void SwitchToBehaviorState(State state)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			if (currentBehaviorState == state)
			{
				return;
			}
			StopTaskRoutine();
			switch (state)
			{
			case State.ReturnToNest:
				ResetRat();
				Nest = RatManager.GetClosestNest(((Component)this).transform.position, checkForPath: true);
				break;
			case State.Routine:
				if (Nest.DefenseRats.Count < maxDefenseRats)
				{
					Nest.DefenseRats.Add(this);
					defenseRat = true;
					ratCoroutine = ((MonoBehaviour)this).StartCoroutine(SwarmCoroutine(Nest, RatManager.defenseRadius));
				}
				else
				{
					ratCoroutine = ((MonoBehaviour)this).StartCoroutine(ScoutCoroutine());
				}
				break;
			case State.Swarming:
				if ((Object)(object)targetPlayer != (Object)null)
				{
					ratCoroutine = ((MonoBehaviour)this).StartCoroutine(SwarmCoroutine(targetPlayer, swarmRadius));
				}
				else if ((Object)(object)targetEnemy != (Object)null)
				{
					ratCoroutine = ((MonoBehaviour)this).StartCoroutine(SwarmCoroutine(targetEnemy, swarmRadius));
				}
				else
				{
					Plugin.LoggerInstance.LogError((object)"No target to attack");
				}
				break;
			}
			SwitchToBehaviorClientRpc(state);
		}

		public void ResetRat()
		{
			foreach (RatNest nest in RatNest.Nests)
			{
				if ((Object)(object)nest == (Object)null)
				{
					logger.LogError((object)"nest is null in ResetRat()");
				}
				else
				{
					nest.DefenseRats.Remove(this);
				}
			}
			rallyRat = false;
			defenseRat = false;
		}

		public void DoAIInterval()
		{
			//IL_003b: 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_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0310: Unknown result type (might be due to invalid IL or missing references)
			//IL_031b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			if (isEnemyDead || StartOfRound.Instance.allPlayersDead || inSpecialAnimation)
			{
				return;
			}
			if (moveTowardsDestination)
			{
				agent.SetDestination(destination);
			}
			switch (currentBehaviorState)
			{
			case State.ReturnToNest:
				agent.speed = 5f;
				if (pathingToNest && ReachedDestination())
				{
					if (holdingFood)
					{
						Nest.AddFood();
					}
					holdingFood = false;
					if (returningBodyToNest)
					{
						DropBody(deactivate: true);
						Nest.AddFood(RatManager.playerFoodAmount);
					}
					pathingToNest = false;
					SwitchToBehaviorState(State.Routine);
					break;
				}
				if ((Object)(object)Nest == (Object)null || !Nest.IsOpen || !SetDestinationToPosition(((Component)Nest).transform.position, checkForPath: true))
				{
					Nest = RatManager.GetClosestNest(((Component)this).transform.position, checkForPath: true);
					if ((Object)(object)Nest == (Object)null)
					{
						pathingToNest = false;
						Roam();
						break;
					}
				}
				pathingToNest = true;
				RoamStop();
				break;
			case State.Routine:
				agent.speed = 5f;
				if (grabbingBody)
				{
					GrabbableObject grabBodyObject = targetPlayer.deadBody.grabBodyObject;
					if (SetDestinationToPosition(((Component)grabBodyObject).transform.position, checkForPath: true))
					{
						if (ReachedDestination())
						{
							GrabBody();
							returningBodyToNest = true;
							SwitchToBehaviorState(State.ReturnToNest);
						}
						break;
					}
				}
				CheckForThreatsInLOS();
				break;
			case State.Swarming:
				agent.speed = 10f;
				if ((Object)(object)targetPlayer != (Object)null)
				{
					if (rallyRat)
					{
						if (!SetDestinationToPosition(((Component)targetPlayer).transform.position, checkForPath: true))
						{
							rallyRat = false;
							SwitchToBehaviorState(State.ReturnToNest);
						}
					}
					else if (Vector3.Distance(((Component)targetPlayer).transform.position, ((Component)this).transform.position) > distanceToLoseRats)
					{
						targetPlayer = null;
						SwitchToBehaviorState(State.ReturnToNest);
					}
				}
				else if ((Object)(object)targetEnemy != (Object)null)
				{
					if (rallyRat)
					{
						if (!SetDestinationToPosition(((Component)targetEnemy).transform.position, checkForPath: true))
						{
							rallyRat = false;
							SwitchToBehaviorState(State.ReturnToNest);
						}
					}
					else if (Vector3.Distance(((Component)targetEnemy).transform.position, ((Component)this).transform.position) > distanceToLoseRats)
					{
						targetEnemy = null;
						SwitchToBehaviorState(State.ReturnToNest);
					}
				}
				else
				{
					SwitchToBehaviorState(State.ReturnToNest);
				}
				break;
			default:
				Plugin.LoggerInstance.LogWarning((object)("Invalid state: " + currentBehaviorState));
				break;
			}
		}

		private bool ReachedDestination()
		{
			//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)
			if (!agent.pathPending && agent.remainingDistance <= agent.stoppingDistance)
			{
				if (agent.hasPath)
				{
					Vector3 velocity = agent.velocity;
					if (((Vector3)(ref velocity)).sqrMagnitude != 0f)
					{
						goto IL_006a;
					}
				}
				return true;
			}
			goto IL_006a;
			IL_006a:
			return false;
		}

		private void GrabBody()
		{
			if ((Object)(object)targetPlayer != (Object)null && (Object)(object)targetPlayer.deadBody != (Object)null)
			{
				int attachedLimbIndex = Random.Range(0, targetPlayer.deadBody.bodyParts.Length);
				GrabBodyClientRpc(targetPlayer.actualClientId, attachedLimbIndex);
			}
		}

		private void DropBody(bool deactivate = false)
		{
			if ((Object)(object)heldBody != (Object)null)
			{
				DropBodyClientRpc(deactivate);
			}
		}

		public bool SetDestinationToPosition(Vector3 position, bool checkForPath = false)
		{
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: 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_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_0038: 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_0074: 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_0085: Unknown result type (might be due to invalid IL or missing references)
			if (checkForPath)
			{
				position = RoundManager.Instance.GetNavMeshPosition(position, RoundManager.Instance.navHit, 1.75f, -1);
				path1 = new NavMeshPath();
				if (!agent.CalculatePath(position, path1))
				{
					return false;
				}
				if (Vector3.Distance(path1.corners[path1.corners.Length - 1], RoundManager.Instance.GetNavMeshPosition(position, RoundManager.Instance.navHit, 2.7f, -1)) > 1.55f)
				{
					return false;
				}
			}
			moveTowardsDestination = true;
			destination = RoundManager.Instance.GetNavMeshPosition(position, RoundManager.Instance.navHit, -1f, -1);
			return true;
		}

		private bool CheckLineOfSightForDeadBody()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				DeadBodyInfo deadBody = val.deadBody;
				if (!((Object)(object)deadBody == (Object)null) && !deadBody.deactivated)
				{
					path1 = new NavMeshPath();
					if (CheckLineOfSightForPosition(((Component)deadBody.grabBodyObject).transform.position, 60f, 60, 5f) && agent.CalculatePath(RoundManager.Instance.GetNavMeshPosition(((Component)deadBody.grabBodyObject).transform.position, RoundManager.Instance.navHit, 1.75f, -1), path1))
					{
						targetPlayer = deadBody.playerScript;
						return true;
					}
				}
			}
			return false;
		}

		private void CheckForThreatsInLOS()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (!(timeSinceAddThreat > RatManager.timeToIncreaseThreat))
			{
				return;
			}
			if (CheckLineOfSightForDeadBody())
			{
				Nest = RatManager.GetClosestNest(((Component)this).transform.position);
				StopTaskRoutine();
				grabbingBody = true;
				return;
			}
			PlayerControllerB val = CheckLineOfSightForPlayer(60f, 60, 5);
			if (PlayerIsTargetable(val))
			{
				if ((Object)(object)val.currentlyHeldObjectServer != (Object)null && ((Object)val.currentlyHeldObjectServer.itemProperties).name == "RatCrownItem" && !val.currentlyHeldObjectServer.isPocketed)
				{
					targetPlayer = val;
					targetEnemy = null;
					SwitchToBehaviorState(State.Swarming);
				}
				else
				{
					AddThreat(val);
				}
			}
			else
			{
				EnemyAI val2 = CheckLineOfSightForEnemy(30);
				if ((Object)(object)val2 != (Object)null && val2.enemyType.canDie)
				{
					AddThreat(val2);
				}
			}
		}

		public bool CheckLineOfSightForPosition(Vector3 objectPosition, float width = 45f, int range = 60, float proximityAwareness = -1f, Transform overrideEye = null)
		{
			//IL_002b: 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_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			if (!isOutside)
			{
				if (objectPosition.y > -80f)
				{
					return false;
				}
			}
			else if (objectPosition.y < -100f)
			{
				return false;
			}
			Transform val = (Transform)(((Object)(object)overrideEye != (Object)null) ? overrideEye : ((!((Object)(object)eye == (Object)null)) ? ((object)eye) : ((object)((Component)this).transform)));
			RaycastHit val2 = default(RaycastHit);
			if (Vector3.Distance(val.position, objectPosition) < (float)range && !Physics.Linecast(val.position, objectPosition, ref val2, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1))
			{
				Vector3 val3 = objectPosition - val.position;
				if (Vector3.Angle(val.forward, val3) < width || Vector3.Distance(((Component)this).transform.position, objectPosition) < proximityAwareness)
				{
					return true;
				}
			}
			return false;
		}

		public PlayerControllerB CheckLineOfSightForPlayer(float width = 45f, int range = 60, int proximityAwareness = -1)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			for (int i = 0; i < StartOfRound.Instance.allPlayerScripts.Length; i++)
			{
				Vector3 position = ((Component)StartOfRound.Instance.allPlayerScripts[i].gameplayCamera).transform.position;
				if (Vector3.Distance(position, eye.position) < (float)range && !Physics.Linecast(eye.position, position, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1))
				{
					Vector3 val = position - eye.position;
					if (Vector3.Angle(eye.forward, val) < width || (proximityAwareness != -1 && Vector3.Distance(eye.position, position) < (float)proximityAwareness))
					{
						return StartOfRound.Instance.allPlayerScripts[i];
					}
				}
			}
			return null;
		}

		public EnemyAI? CheckLineOfSightForEnemy(int range)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			foreach (EnemyAI spawnedEnemy in RoundManager.Instance.SpawnedEnemies)
			{
				if (((Object)(object)RatKingAI.Instance != (Object)null && (Object)(object)spawnedEnemy == (Object)(object)RatKingAI.Instance) || !spawnedEnemy.enemyType.canDie || !CheckLineOfSightForPosition(((Component)spawnedEnemy).transform.position, 60f, range, 5f))
				{
					continue;
				}
				return spawnedEnemy;
			}
			return null;
		}

		private void Roam()
		{
			if (ratCoroutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(ratCoroutine);
			}
			ratCoroutine = ((MonoBehaviour)this).StartCoroutine(RoamCoroutine());
		}

		private void RoamStop()
		{
			if (ratCoroutine != null)
			{
				((MonoBehaviour)this).StopAllCoroutines();
				ratCoroutine = null;
			}
		}

		private IEnumerator RoamCoroutine()
		{
			yield return null;
			while (ratCoroutine != null && ((Behaviour)agent).enabled)
			{
				float timeStopped = 0f;
				targetNode = RatManager.GetRandomNode(isOutside);
				if ((Object)(object)targetNode == (Object)null)
				{
					continue;
				}
				Vector3 position = ((Component)targetNode).transform.position;
				if (!SetDestinationToPosition(position))
				{
					continue;
				}
				while (((Behaviour)agent).enabled)
				{
					yield return (object)new WaitForSeconds(AIIntervalTime);
					if (timeStopped > 1f)
					{
						break;
					}
					if (agent.velocity == Vector3.zero)
					{
						timeStopped += AIIntervalTime;
					}
				}
			}
		}

		private IEnumerator SwarmCoroutine(PlayerControllerB player, float radius)
		{
			yield return null;
			Plugin.log("Starting swarm on player");
			while (ratCoroutine != null && (Object)(object)player != (Object)null && !((Object)(object)player == (Object)null) && !player.isPlayerDead)
			{
				float timeStopped = 0f;
				Vector3 position = RoundManager.Instance.GetRandomNavMeshPositionInRadius(((Component)player).transform.position, radius, RoundManager.Instance.navHit);
				SetDestinationToPosition(position);
				while (((Behaviour)agent).enabled)
				{
					yield return (object)new WaitForSeconds(AIIntervalTime);
					if (timeStopped > 1f)
					{
						break;
					}
					if (agent.velocity == Vector3.zero)
					{
						timeStopped += AIIntervalTime;
					}
				}
			}
			SwitchToBehaviorState(State.ReturnToNest);
		}

		private IEnumerator SwarmCoroutine(EnemyAI enemy, float radius)
		{
			yield return null;
			while (ratCoroutine != null && (Object)(object)enemy != (Object)null)
			{
				float timeStopped = 0f;
				Vector3 position = RoundManager.Instance.GetRandomNavMeshPositionInRadius(((Component)enemy).transform.position, radius, RoundManager.Instance.navHit);
				SetDestinationToPosition(position);
				while (((Behaviour)agent).enabled)
				{
					yield return (object)new WaitForSeconds(AIIntervalTime);
					if (timeStopped > 1f)
					{
						break;
					}
					if (agent.velocity == Vector3.zero)
					{
						timeStopped += AIIntervalTime;
					}
				}
			}
			SwitchToBehaviorState(State.ReturnToNest);
		}

		private IEnumerator SwarmCoroutine(Vector3 position, float radius)
		{
			//IL_000e: 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)
			yield return null;
			while (ratCoroutine != null)
			{
				float timeStopped = 0f;
				Vector3 pos2 = position;
				pos2 = RoundManager.Instance.GetRandomNavMeshPositionInRadius(pos2, radius, RoundManager.Instance.navHit);
				SetDestinationToPosition(pos2);
				while (((Behaviour)agent).enabled)
				{
					yield return (object)new WaitForSeconds(AIIntervalTime);
					if (timeStopped > 1f)
					{
						break;
					}
					if (agent.velocity == Vector3.zero)
					{
						timeStopped += AIIntervalTime;
					}
				}
			}
			SwitchToBehaviorState(State.ReturnToNest);
		}

		private IEnumerator SwarmCoroutine(RatNest nest, float radius)
		{
			yield return null;
			while (ratCoroutine != null)
			{
				float timeStopped = 0f;
				Vector3 pos2 = ((Component)nest).transform.position;
				pos2 = RoundManager.Instance.GetRandomNavMeshPositionInRadius(pos2, radius, RoundManager.Instance.navHit);
				SetDestinationToPosition(pos2);
				while (((Behaviour)agent).enabled)
				{
					yield return (object)new WaitForSeconds(AIIntervalTime);
					if (timeStopped > 1f)
					{
						break;
					}
					if (agent.velocity == Vector3.zero)
					{
						timeStopped += AIIntervalTime;
					}
				}
			}
			SwitchToBehaviorState(State.ReturnToNest);
		}

		private IEnumerator ScoutCoroutine()
		{
			yield return null;
			while (ratCoroutine != null && ((Behaviour)agent).enabled)
			{
				float timeStopped = 0f;
				targetNode = RatManager.GetRandomNode(isOutside);
				if ((Object)(object)targetNode == (Object)null)
				{
					continue;
				}
				Vector3 position = ((Component)targetNode).transform.position;
				if (!SetDestinationToPosition(position))
				{
					continue;
				}
				while (((Behaviour)agent).enabled)
				{
					yield return (object)new WaitForSeconds(AIIntervalTime);
					if (timeStopped > 1f)
					{
						SwitchToBehaviorState(State.ReturnToNest);
						ratCoroutine = null;
						yield break;
					}
					if (agent.velocity == Vector3.zero)
					{
						timeStopped += AIIntervalTime;
					}
				}
			}
			SwitchToBehaviorState(State.ReturnToNest);
		}

		public void HitEnemy(int force = 0, PlayerControllerB? playerWhoHit = null, bool playHitSFX = true, int hitID = -1)
		{
			if (isEnemyDead)
			{
				return;
			}
			enemyHP -= force;
			if (enemyHP > 0)
			{
				return;
			}
			DropBody();
			RoundManager.PlayRandomClip(creatureSFX, HitSFX, true, 1f, -1, 1000);
			KillEnemyOnOwnerClient();
			if (Plugin.IsServerOrHost && (Object)(object)playerWhoHit != (Object)null)
			{
				AddThreat(playerWhoHit);
				if (RatManager.PlayerThreatCounter[playerWhoHit] > RatManager.highPlayerThreat && (Object)(object)Nest != (Object)null)
				{
					Nest.SpawnRatKingOnServer(Plugin.configRatKingSummonChanceRatDeath.Value);
				}
			}
		}

		public void HitEnemyOnLocalClient(int force = 1, Vector3 hitDirection = default(Vector3), PlayerControllerB? playerWhoHit = null, bool playHitSFX = false, int hitID = -1)
		{
			int playerWhoHit2 = -1;
			if ((Object)(object)playerWhoHit != (Object)null)
			{
				playerWhoHit2 = (int)playerWhoHit.playerClientId;
				HitEnemy(force, playerWhoHit, playHitSFX, hitID);
			}
			HitEnemyServerRpc(force, playerWhoHit2, playHitSFX, hitID);
		}

		public void HitFromExplosion(float distance)
		{
			RoundManager.PlayRandomClip(creatureSFX, HitSFX, true, 1f, -1, 1000);
			KillEnemyOnOwnerClient();
		}

		public bool PlayerIsTargetable(PlayerControllerB playerScript)
		{
			if ((Object)(object)playerScript == (Object)null)
			{
				return false;
			}
			if (playerScript.isPlayerDead)
			{
				return false;
			}
			if (currentBehaviorState == State.ReturnToNest)
			{
				return false;
			}
			if (!playerScript.isPlayerControlled)
			{
				return false;
			}
			if ((Object)(object)playerScript.inAnimationWithEnemy != (Object)null)
			{
				return false;
			}
			if (playerScript.sinkingValue >= 0.73f)
			{
				return false;
			}
			return true;
		}

		public bool IsPlayerNearANest(PlayerControllerB player)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			foreach (RatNest nest in RatNest.Nests)
			{
				if (Vector3.Distance(((Component)player).transform.position, ((Component)nest).transform.position) < RatManager.defenseRadius)
				{
					return true;
				}
			}
			return false;
		}

		public void OnCollideWithPlayer(Collider other)
		{
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			if (isEnemyDead || !(timeSinceCollision > 1f))
			{
				return;
			}
			timeSinceCollision = 0f;
			PlayerControllerB component = ((Component)other).gameObject.GetComponent<PlayerControllerB>();
			if (!PlayerIsTargetable(component) || ((Object)(object)component.currentlyHeldObjectServer != (Object)null && ((Object)component.currentlyHeldObjectServer).name == "RatCrownItem" && !component.currentlyHeldObjectServer.isPocketed))
			{
				return;
			}
			rallyRat = false;
			if (currentBehaviorState == State.Swarming || IsPlayerNearANest(component))
			{
				RoundManager.PlayRandomClip(creatureSFX, AttackSFX, true, 1f, 0, 1000);
				if (!((Object)(object)component != (Object)(object)Plugin.localPlayer))
				{
					int num = ((Random.Range(0, 2) == 1) ? 7 : 0);
					component.DamagePlayer(ratDamage, true, true, (CauseOfDeath)6, num, false, default(Vector3));
				}
			}
		}

		public void OnCollideWithEnemy(Collider other, EnemyAI? collidedEnemy = null)
		{
			//IL_0259: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.IsServerOrHost)
			{
				rallyRat = false;
				if (isEnemyDead || currentBehaviorState == State.ReturnToNest || (Object)(object)Nest == (Object)null)
				{
					return;
				}
				if (timeSinceCollision > 1f && (Object)(object)collidedEnemy != (Object)null && collidedEnemy.enemyType.canDie)
				{
					if ((Object)(object)RatKingAI.Instance != (Object)null && (Object)(object)RatKingAI.Instance == (Object)(object)collidedEnemy)
					{
						return;
					}
					Plugin.log("Collided with: " + collidedEnemy.enemyType.enemyName);
					timeSinceCollision = 0f;
					if (collidedEnemy.isEnemyDead)
					{
						if (RatNest.EnemyFoodAmount.ContainsKey(collidedEnemy))
						{
							if (RatNest.EnemyFoodAmount[collidedEnemy] <= 1)
							{
								holdingFood = RatNest.EnemyFoodAmount[collidedEnemy] == 1;
								RoundManager.Instance.DespawnEnemyOnServer(((NetworkBehaviour)collidedEnemy).NetworkObject);
								return;
							}
							RatNest.EnemyFoodAmount[collidedEnemy]--;
							holdingFood = true;
						}
						else
						{
							RatManager.EnemyHitCount.Remove(collidedEnemy);
							Nest.AddEnemyFoodAmount(collidedEnemy);
							RatNest.EnemyFoodAmount[collidedEnemy]--;
							holdingFood = true;
						}
						SwitchToBehaviorState(State.ReturnToNest);
					}
					else
					{
						if (!RatManager.EnemyHitCount.ContainsKey(collidedEnemy))
						{
							RatManager.EnemyHitCount.Add(collidedEnemy, RatManager.enemyHitsToDoDamage);
						}
						RatManager.EnemyHitCount[collidedEnemy]--;
						if (RatManager.EnemyHitCount[collidedEnemy] <= 0)
						{
							collidedEnemy.HitEnemy(1, (PlayerControllerB)null, true, -1);
							RatManager.EnemyHitCount[collidedEnemy] = RatManager.enemyHitsToDoDamage;
						}
					}
				}
			}
			if (holdingFood)
			{
				RoundManager.PlayRandomClip(creatureSFX, NibbleSFX, true, 1f, -1, 1000);
				if ((Object)(object)collidedEnemy != (Object)null && Plugin.localPlayer.HasLineOfSightToPosition(((Component)collidedEnemy).transform.position, 45f, 60, -1f))
				{
					Plugin.localPlayer.IncreaseFearLevelOverTime(0.8f, 1f);
				}
			}
			if (currentBehaviorState == State.Swarming)
			{
				RoundManager.PlayRandomClip(creatureSFX, AttackSFX, true, 1f, 0, 1000);
			}
		}

		private void AddThreat(EnemyAI enemy, int amount = 1)
		{
			if (!((Object)(object)enemy == (Object)null) && (Object)(object)Nest != (Object)null)
			{
				timeSinceAddThreat = 0f;
				if (RatManager.EnemyThreatCounter.ContainsKey(enemy))
				{
					RatManager.EnemyThreatCounter[enemy] += amount;
				}
				else
				{
					RatManager.EnemyThreatCounter.Add(enemy, amount);
				}
				int num = RatManager.EnemyThreatCounter[enemy];
				Plugin.log($"{enemy.enemyType.enemyName}: {num} threat");
				if (!defenseRat && (RatManager.EnemyThreatCounter[enemy] > RatManager.threatToAttackEnemy || enemy.isEnemyDead))
				{
					targetPlayer = null;
					targetEnemy = enemy;
					SwitchToBehaviorState(State.Swarming);
				}
			}
		}

		private void AddThreat(PlayerControllerB player, int amount = 1)
		{
			if ((Object)(object)player == (Object)null || !((Object)(object)Nest != (Object)null))
			{
				return;
			}
			timeSinceAddThreat = 0f;
			if (RatManager.PlayerThreatCounter.ContainsKey(player))
			{
				RatManager.PlayerThreatCounter[player] += amount;
			}
			else
			{
				RatManager.PlayerThreatCounter.Add(player, amount);
			}
			int num = RatManager.PlayerThreatCounter[player];
			Plugin.log($"{player.playerUsername}: {num} threat");
			if (!defenseRat)
			{
				if (num > RatManager.highPlayerThreat && (Object)(object)RatKingAI.Instance != (Object)null && ((EnemyAI)RatKingAI.Instance).currentBehaviourStateIndex == 0 && (Object)(object)((EnemyAI)RatKingAI.Instance).targetPlayer == (Object)null)
				{
					Plugin.log("Calling Rat King");
					targetEnemy = null;
					targetPlayer = player;
					PlayRallySFXClientRpc();
					RatKingAI.Instance.AlertHighThreatPlayer(player);
					SwitchToBehaviorState(State.Swarming);
				}
				if (num > RatManager.threatToAttackPlayer || player.isPlayerDead)
				{
					targetEnemy = null;
					targetPlayer = player;
					SwitchToBehaviorState(State.Swarming);
				}
			}
		}

		public void FinishRunCycle()
		{
			if (Random.Range(0f, 1f) < RatManager.squeakChance)
			{
				RoundManager.PlayRandomClip(creatureSFX, SqueakSFX, true, 1f, 0, 1000);
			}
		}

		public void KillEnemyOnOwnerClient()
		{
			if (Plugin.IsServerOrHost && !isEnemyDead)
			{
				Debug.Log((object)"Kill enemy called!");
				KillEnemy();
				if (((NetworkBehaviour)this).NetworkObject.IsSpawned)
				{
					KillEnemyServerRpc();
				}
			}
		}

		public void KillEnemy()
		{
			isEnemyDead = true;
			creatureAnimator.SetTrigger(hashDie);
			creatureAnimator.Update(0f);
			if (Plugin.IsServerOrHost)
			{
				((MonoBehaviour)this).StopAllCoroutines();
				((Behaviour)agent).enabled = false;
				RatManager.Instance.RemoveRat(this);
				ResetRat();
			}
		}

		[ClientRpc]
		public void PlayRallySFXClientRpc()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
				{
					ClientRpcParams val = default(ClientRpcParams);
					FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(2845775495u, val, (RpcDelivery)0);
					((NetworkBehaviour)this).__endSendClientRpc(ref val2, 2845775495u, val, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost))
				{
					creatureVoice.PlayOneShot(ScreamSFX);
				}
			}
		}

		[ServerRpc(RequireOwnership = false)]
		public void HitEnemyServerRpc(int force, int playerWhoHit, bool playHitSFX, int hitID = -1)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: 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_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
				{
					ServerRpcParams val = default(ServerRpcParams);
					FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(3785077483u, val, (RpcDelivery)0);
					BytePacker.WriteValueBitPacked(val2, force);
					BytePacker.WriteValueBitPacked(val2, playerWhoHit);
					((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref playHitSFX, default(ForPrimitives));
					BytePacker.WriteValueBitPacked(val2, hitID);
					((NetworkBehaviour)this).__endSendServerRpc(ref val2, 3785077483u, val, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost) && Plugin.IsServerOrHost)
				{
					HitEnemyClientRpc(force, playerWhoHit, playHitSFX, hitID);
				}
			}
		}

		[ClientRpc]
		public void HitEnemyClientRpc(int force, int playerWhoHit, bool playHitSFX, int hitID = -1)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: 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_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val = default(ClientRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(2762031980u, val, (RpcDelivery)0);
				BytePacker.WriteValueBitPacked(val2, force);
				BytePacker.WriteValueBitPacked(val2, playerWhoHit);
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref playHitSFX, default(ForPrimitives));
				BytePacker.WriteValueBitPacked(val2, hitID);
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 2762031980u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost))
			{
				if (playerWhoHit == -1)
				{
					HitEnemy(force, null, playHitSFX, hitID);
				}
				else
				{
					HitEnemy(force, StartOfRound.Instance.allPlayerScripts[playerWhoHit], playHitSFX, hitID);
				}
			}
		}

		[ClientRpc]
		public void SwitchToBehaviorClientRpc(State state)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: 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)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
				{
					ClientRpcParams val = default(ClientRpcParams);
					FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(2151512038u, val, (RpcDelivery)0);
					((FastBufferWriter)(ref val2)).WriteValueSafe<State>(ref state, default(ForEnums));
					((NetworkBehaviour)this).__endSendClientRpc(ref val2, 2151512038u, val, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost) && currentBehaviorState != state)
				{
					currentBehaviorState = state;
					RoundManager.PlayRandomClip(creatureSFX, SqueakSFX, true, 1f, -1, 1000);
				}
			}
		}

		[ClientRpc]
		public void GrabBodyClientRpc(ulong clientId, int attachedLimbIndex)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: 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_007e: 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)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val = default(ClientRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(3500738837u, val, (RpcDelivery)0);
				BytePacker.WriteValueBitPacked(val2, clientId);
				BytePacker.WriteValueBitPacked(val2, attachedLimbIndex);
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 3500738837u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost))
			{
				targetPlayer = Plugin.PlayerFromId(clientId);
				if ((Object)(object)targetPlayer != (Object)null && (Object)(object)targetPlayer.deadBody != (Object)null)
				{
					heldBody = targetPlayer.deadBody;
					heldBody.attachedTo = RatMouth;
					heldBody.attachedLimb = targetPlayer.deadBody.bodyParts[attachedLimbIndex];
					heldBody.matchPositionExactly = true;
				}
				grabbingBody = false;
				returningBodyToNest = true;
				RoundManager.PlayRandomClip(creatureSFX, NibbleSFX, true, 1f, -1, 1000);
			}
		}

		[ClientRpc]
		public void DropBodyClientRpc(bool deactivate)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: 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)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val = default(ClientRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(1118647984u, val, (RpcDelivery)0);
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref deactivate, default(ForPrimitives));
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 1118647984u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage != 2 || (!networkManager.IsClient && !networkManager.IsHost))
			{
				return;
			}
			returningBodyToNest = false;
			grabbingBody = false;
			targetPlayer = null;
			if ((Object)(object)heldBody != (Object)null)
			{
				heldBody.attachedTo = null;
				heldBody.attachedLimb = null;
				heldBody.matchPositionExactly = false;
				if (deactivate)
				{
					heldBody.DeactivateBody(false);
				}
				heldBody = null;
			}
		}

		[ServerRpc(RequireOwnership = false)]
		public void KillEnemyServerRpc()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
				{
					ServerRpcParams val = default(ServerRpcParams);
					FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(3223101186u, val, (RpcDelivery)0);
					((NetworkBehaviour)this).__endSendServerRpc(ref val2, 3223101186u, val, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost) && Plugin.IsServerOrHost)
				{
					KillEnemyClientRpc();
				}
			}
		}

		[ClientRpc]
		public void KillEnemyClientRpc()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
				{
					ClientRpcParams val = default(ClientRpcParams);
					FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(4064924559u, val, (RpcDelivery)0);
					((NetworkBehaviour)this).__endSendClientRpc(ref val2, 4064924559u, val, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost) && !isEnemyDead)
				{
					KillEnemy();
				}
			}
		}

		protected override void __initializeVariables()
		{
			((NetworkBehaviour)this).__initializeVariables();
		}

		[RuntimeInitializeOnLoadMethod]
		internal static void InitializeRPCS_RatAI()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Expected O, but got Unknown
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Expected O, but got Unknown
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Expected O, but got Unknown
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Expected O, but got Unknown
			NetworkManager.__rpc_func_table.Add(2845775495u, new RpcReceiveHandler(__rpc_handler_2845775495));
			NetworkManager.__rpc_func_table.Add(3785077483u, new RpcReceiveHandler(__rpc_handler_3785077483));
			NetworkManager.__rpc_func_table.Add(2762031980u, new RpcReceiveHandler(__rpc_handler_2762031980));
			NetworkManager.__rpc_func_table.Add(2151512038u, new RpcReceiveHandler(__rpc_handler_2151512038));
			NetworkManager.__rpc_func_table.Add(3500738837u, new RpcReceiveHandler(__rpc_handler_3500738837));
			NetworkManager.__rpc_func_table.Add(1118647984u, new RpcReceiveHandler(__rpc_handler_1118647984));
			NetworkManager.__rpc_func_table.Add(3223101186u, new RpcReceiveHandler(__rpc_handler_3223101186));
			NetworkManager.__rpc_func_table.Add(4064924559u, new RpcReceiveHandler(__rpc_handler_4064924559));
		}

		private static void __rpc_handler_2845775495(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				target.__rpc_exec_stage = (__RpcExecStage)2;
				((RatAI)(object)target).PlayRallySFXClientRpc();
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_3785077483(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0023: 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_0049: 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_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				int force = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref force);
				int playerWhoHit = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref playerWhoHit);
				bool playHitSFX = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref playHitSFX, default(ForPrimitives));
				int hitID = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref hitID);
				target.__rpc_exec_stage = (__RpcExecStage)1;
				((RatAI)(object)target).HitEnemyServerRpc(force, playerWhoHit, playHitSFX, hitID);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_2762031980(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0023: 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_0049: 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_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				int force = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref force);
				int playerWhoHit = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref playerWhoHit);
				bool playHitSFX = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref playHitSFX, default(ForPrimitives));
				int hitID = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref hitID);
				target.__rpc_exec_stage = (__RpcExecStage)2;
				((RatAI)(object)target).HitEnemyClientRpc(force, playerWhoHit, playHitSFX, hitID);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_2151512038(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: 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)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				State state = default(State);
				((FastBufferReader)(ref reader)).ReadValueSafe<State>(ref state, default(ForEnums));
				target.__rpc_exec_stage = (__RpcExecStage)2;
				((RatAI)(object)target).SwitchToBehaviorClientRpc(state);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_3500738837(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0023: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				ulong clientId = default(ulong);
				ByteUnpacker.ReadValueBitPacked(reader, ref clientId);
				int attachedLimbIndex = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref attachedLimbIndex);
				target.__rpc_exec_stage = (__RpcExecStage)2;
				((RatAI)(object)target).GrabBodyClientRpc(clientId, attachedLimbIndex);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_1118647984(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: 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)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				bool deactivate = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref deactivate, default(ForPrimitives));
				target.__rpc_exec_stage = (__RpcExecStage)2;
				((RatAI)(object)target).DropBodyClientRpc(deactivate);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_3223101186(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				target.__rpc_exec_stage = (__RpcExecStage)1;
				((RatAI)(object)target).KillEnemyServerRpc();
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_4064924559(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				target.__rpc_exec_stage = (__RpcExecStage)2;
				((RatAI)(object)target).KillEnemyClientRpc();
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		protected internal override string __getTypeName()
		{
			return "RatAI";
		}
	}
	public class RatKingAI : EnemyAI
	{
		public enum State
		{
			Roaming,
			Hunting,
			Attacking,
			Rampaging
		}

		private static ManualLogSource logger = Plugin.LoggerInstance;

		public bool ratKingCanDie = false;

		public ScanNodeProperties ScanNode;

		public AudioClip[] SqueakSFX;

		public AudioClip[] AttackSFX;

		public AudioClip[] HitSFX;

		public AudioClip[] NibbleSFX;

		public AudioClip ScreamSFX;

		public Transform RatMouth;

		public GameObject NestPrefab;

		public GameObject RatCrownPrefab;

		public GameObject RatMesh;

		public GameObject CrownMesh;

		public NetworkAnimator networkAnimator;

		public Transform NestTransform;

		private bool inRallyAnimation;

		private int hashRunSpeed;

		public RatNest KingNest;

		private float timeSinceCollision;

		private float timeSinceAddThreat;

		private float timeSinceRally;

		private float timeSinceSyncedAIInterval;

		private DeadBodyInfo? heldBody;

		private Coroutine? ratCoroutine;

		public static RatKingAI? Instance { get; private set; }

		public override void OnNetworkSpawn()
		{
			((NetworkBehaviour)this).OnNetworkSpawn();
			if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this)
			{
				if (Plugin.IsServerOrHost)
				{
					Plugin.log("There is already a Rat King in the scene. Removing this one.");
					((NetworkBehaviour)this).NetworkObject.Despawn(true);
				}
				return;
			}
			logger.LogDebug((object)"Setting RatKingAI.Instance to this");
			Instance = this;
			Plugin.log("Finished spawning Rat King");
			if (Plugin.IsServerOrHost)
			{
				Plugin.log("Spawning KingNest");
				KingNest = Object.Instantiate<GameObject>(NestPrefab, NestTransform).GetComponent<RatNest>();
				((NetworkBehaviour)KingNest).NetworkObject.Spawn(true);
				KingNest.SetAsRatKingNestClientRpc();
			}
		}

		public override void OnNetworkDespawn()
		{
			((NetworkBehaviour)this).OnNetworkDespawn();
			if ((Object)(o