Rats/Snowlance.Rats.dll

Decompiled 3 weeks 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 GameNetcodeStuff;
using HarmonyLib;
using LethalLib.Extras;
using LethalLib.Modules;
using Microsoft.CodeAnalysis;
using Snowlance.Rats.NetcodePatcher;
using TMPro;
using Unity.Netcode;
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.1.2.0")]
[assembly: AssemblyInformationalVersion("1.1.2+0315001c22fe5763d38b8ef48e1f280b77b6430e")]
[assembly: AssemblyProduct("Rats")]
[assembly: AssemblyTitle("Snowlance.Rats")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.2.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;
		}
	}
}
namespace Rats
{
	internal class TESTING : MonoBehaviour
	{
		private static ManualLogSource logger = Plugin.LoggerInstance;

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

		[HarmonyPrefix]
		[HarmonyPatch(typeof(HUDManager), "SubmitChat_performed")]
		public static void SubmitChat_performedPrefix(HUDManager __instance)
		{
			string text = __instance.chatTextField.text;
			string[] array = text.Split(" ");
			switch (array[0])
			{
			case "/testing":
				RatManager.testing = bool.Parse(array[1]);
				break;
			case "/enemies":
			{
				foreach (SpawnableEnemyWithRarity enemy in GetEnemies())
				{
					logger.LogDebug((object)((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)
				{
					logger.LogDebug((object)((Object)val2).name);
				}
				break;
			}
			case "/dungeon":
				logger.LogDebug((object)((Object)RoundManager.Instance.dungeonGenerator.Generator.DungeonFlow).name);
				break;
			case "/dungeons":
			{
				IndoorMapType[] dungeonFlowTypes = RoundManager.Instance.dungeonFlowTypes;
				foreach (IndoorMapType val in dungeonFlowTypes)
				{
					logger.LogDebug((object)((Object)val.dungeonFlow).name);
				}
				break;
			}
			}
		}

		public static List<SpawnableEnemyWithRarity> GetEnemies()
		{
			logger.LogDebug((object)"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();
			logger.LogDebug((object)$"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.1.2")]
	[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<string> configSewerGrateSpawnWeightCurve;

		public static ConfigEntry<bool> configHideCodeOnTerminal;

		public static ConfigEntry<int> configMinRatSpawnTime;

		public static ConfigEntry<int> configMaxRatSpawnTime;

		public static ConfigEntry<int> configFoodToSpawnRat;

		public static ConfigEntry<int> configEnemyFoodPerHPPoint;

		public static ConfigEntry<int> configMaxRats;

		public static ConfigEntry<float> configAIIntervalTime;

		public static ConfigEntry<bool> configMakeLessSqueaks;

		public static ConfigEntry<float> configDefenseRadius;

		public static ConfigEntry<float> configTimeToIncreaseThreat;

		public static ConfigEntry<int> configThreatToAttackPlayer;

		public static ConfigEntry<int> configThreatToAttackEnemy;

		public static ConfigEntry<float> configSwarmRadius;

		public static ConfigEntry<bool> configCanVent;

		public static ConfigEntry<int> configMaxDefenseRats;

		public static ConfigEntry<int> configRatsNeededToAttack;

		public static ConfigEntry<float> configDistanceNeededToLoseRats;

		public static ConfigEntry<int> configEnemyHitsToDoDamage;

		public static ConfigEntry<int> configPlayerFoodAmount;

		public static ConfigEntry<int> configRatDamage;

		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", true, "Rats spawn with a santa hat");
			configEnableDebugging = ((BaseUnityPlugin)this).Config.Bind<bool>("Debugging", "Enable Debugging", false, "Allows debug logs to show in the logs");
			configSewerGrateSpawnWeightCurve = ((BaseUnityPlugin)this).Config.Bind<string>("Nest", "Spawn Weight Curve", "Vanilla - 0,0 ; 1,3 | Custom - 0,0 ; 1,3", "The MoonName - CurveSpawnWeight for the SewerGrate(Rat nest).");
			configHideCodeOnTerminal = ((BaseUnityPlugin)this).Config.Bind<bool>("Nest", "Hide Code On Terminal", true, "If set to true, will make the code on the ship monitor for the nest be ??, requiring the player to find the nest physically to turn off its spawning.");
			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.");
			configMaxRats = ((BaseUnityPlugin)this).Config.Bind<int>("Nest", "Maximum Rats", 40, "The maximum number of rats that can be on the map. Lowering this can improve performance.");
			configMakeLessSqueaks = ((BaseUnityPlugin)this).Config.Bind<bool>("Rats", "Make Less Squeaks", false, "If set to true, will make the rats squeak less, which can help with performance.");
			configAIIntervalTime = ((BaseUnityPlugin)this).Config.Bind<float>("Rats", "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.");
			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.");
			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", 10f, "The radius in which rats swarm around their target.");
			configCanVent = ((BaseUnityPlugin)this).Config.Bind<bool>("Rats", "Can Vent", true, "If set to true, allows rats to travel through vents. This can also increase performance if set to false.");
			configMaxDefenseRats = ((BaseUnityPlugin)this).Config.Bind<int>("Rats", "Maximum Defense Rats", 10, "The maximum number of defense rats assigned to protect the nest.");
			configRatsNeededToAttack = ((BaseUnityPlugin)this).Config.Bind<int>("Rats", "Rats Needed to Attack", 5, "The minimum number of rats required to start an attack.");
			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.");
			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/RatEnemy.asset");
			if ((Object)(object)val == (Object)null)
			{
				LoggerInstance.LogError((object)"Error: Couldnt get Rat from assets");
				return;
			}
			LoggerInstance.LogDebug((object)"Got Rat prefab");
			SewerGrate.RatEnemyType = val;
			TerminalNode val2 = ModAssets.LoadAsset<TerminalNode>("Assets/ModAssets/Bestiary/RatTN.asset");
			TerminalKeyword val3 = ModAssets.LoadAsset<TerminalKeyword>("Assets/ModAssets/Bestiary/RatTK.asset");
			LoggerInstance.LogDebug((object)"Registering enemy network prefab...");
			NetworkPrefabs.RegisterNetworkPrefab(val.enemyPrefab);
			LoggerInstance.LogDebug((object)"Registering enemy...");
			Enemies.RegisterEnemy(val, (Dictionary<LevelTypes, int>)null, (Dictionary<string, int>)null, 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);
			LoggerInstance.LogDebug((object)"Registering RatSpawn");
			RegisterInsideMapObjectWithConfig(val4, configSewerGrateSpawnWeightCurve.Value);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Snowlance.Rats v1.1.2 has loaded!");
		}

		public static void logIfDebug(string message)
		{
			if (IsLoggingEnabled)
			{
				LoggerInstance.LogDebug((object)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;
		}

		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 : EnemyAI
	{
		public enum RatType
		{
			Unassigned,
			ScoutRat,
			DefenseRat
		}

		public enum State
		{
			Roaming,
			Tasking,
			Swarming,
			Attacking
		}

		public ScanNodeProperties ScanNode = null;

		public AudioClip[] SqueakSFX = null;

		public AudioClip[] AttackSFX = null;

		public AudioClip[] HitSFX = null;

		public AudioClip[] NibbleSFX = null;

		public Transform TurnCompass = null;

		public Transform RatMouth = null;

		public GameObject ChristmasHat = null;

		public SewerGrate? MainNest;

		private DeadBodyInfo? heldBody;

		private EnemyAI? targetEnemy;

		private bool holdingFood;

		private float timeSinceCollision;

		private float timeSinceAddThreat;

		private Vector3 finalDestination;

		private Coroutine? ratCoroutine = null;

		private bool grabbingBody;

		private bool returningBodyToNest;

		private const float timeAgentStopped = 1f;

		private float defenseRadius = 5f;

		private float timeToIncreaseThreat = 3f;

		private int threatToAttackPlayer = 100;

		private int threatToAttackEnemy = 50;

		private float swarmRadius = 10f;

		private bool canVent = true;

		private int maxDefenseRats = 10;

		private int ratsNeededToAttack = 5;

		private float distanceToLoseRats = 25f;

		private int enemyHitsToDoDamage = 10;

		private int playerFoodAmount = 30;

		private int ratDamage = 2;

		private bool makeLessSqueaks = false;

		private RatType RatTypeState = RatType.Unassigned;

		private EnemyVent? FromVent => RatManager.GetClosestVentToPosition(((Component)this).transform.position);

		private EnemyVent? ToVent => RatManager.GetClosestVentToPosition(finalDestination);

		private bool AtNest => ((Behaviour)base.agent).enabled && (Object)(object)MainNest != (Object)null && Vector3.Distance(((Component)this).transform.position, ((Component)MainNest).transform.position) < 1f;

		public void SwitchToBehaviourStateCustom(State state)
		{
			if (base.currentBehaviourStateIndex == (int)state)
			{
				return;
			}
			StopRoutines();
			switch (state)
			{
			case State.Roaming:
				AssignRatType();
				break;
			case State.Tasking:
				AssignRatType();
				break;
			case State.Swarming:
				if ((Object)(object)base.targetPlayer != (Object)null)
				{
					ratCoroutine = ((MonoBehaviour)this).StartCoroutine(SwarmCoroutine(base.targetPlayer, swarmRadius));
				}
				else if ((Object)(object)targetEnemy != (Object)null)
				{
					ratCoroutine = ((MonoBehaviour)this).StartCoroutine(SwarmCoroutine(targetEnemy, swarmRadius));
				}
				else
				{
					Plugin.LoggerInstance.LogError((object)"No target to swarm");
				}
				break;
			case State.Attacking:
				if ((Object)(object)base.targetPlayer != (Object)null)
				{
					ratCoroutine = ((MonoBehaviour)this).StartCoroutine(SwarmCoroutine(base.targetPlayer, 2f));
				}
				else if ((Object)(object)targetEnemy != (Object)null)
				{
					ratCoroutine = ((MonoBehaviour)this).StartCoroutine(SwarmCoroutine(targetEnemy, 2f));
				}
				else
				{
					Plugin.LoggerInstance.LogError((object)"No target to attack");
				}
				break;
			}
			SwitchToBehaviourClientRpc((int)state);
		}

		public override void Start()
		{
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Expected O, but got Unknown
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			makeLessSqueaks = Plugin.configMakeLessSqueaks.Value;
			base.AIIntervalTime = Plugin.configAIIntervalTime.Value;
			defenseRadius = Plugin.configDefenseRadius.Value;
			timeToIncreaseThreat = Plugin.configTimeToIncreaseThreat.Value;
			threatToAttackPlayer = Plugin.configThreatToAttackPlayer.Value;
			threatToAttackEnemy = Plugin.configThreatToAttackEnemy.Value;
			swarmRadius = Plugin.configSwarmRadius.Value;
			canVent = Plugin.configCanVent.Value;
			maxDefenseRats = Plugin.configMaxDefenseRats.Value;
			ratsNeededToAttack = Plugin.configRatsNeededToAttack.Value;
			distanceToLoseRats = Plugin.configDistanceNeededToLoseRats.Value;
			enemyHitsToDoDamage = Plugin.configEnemyHitsToDoDamage.Value;
			playerFoodAmount = Plugin.configPlayerFoodAmount.Value;
			ratDamage = Plugin.configRatDamage.Value;
			ChristmasHat.SetActive(Plugin.configHolidayRats.Value);
			base.updateDestinationInterval = base.AIIntervalTime;
			base.thisNetworkObject = ((NetworkBehaviour)this).NetworkObject;
			base.thisEnemyIndex = RoundManager.Instance.numberOfEnemiesInScene;
			RoundManager instance = RoundManager.Instance;
			instance.numberOfEnemiesInScene++;
			base.allAINodes = RoundManager.Instance.insideAINodes;
			if (!RoundManager.Instance.SpawnedEnemies.Contains((EnemyAI)(object)this))
			{
				RoundManager.Instance.SpawnedEnemies.Add((EnemyAI)(object)this);
			}
			base.path1 = new NavMeshPath();
			base.serverPosition = ((Component)this).transform.position;
			base.ventAnimationFinished = true;
			base.currentBehaviourStateIndex = 1;
			HottestRat();
			RatManager.Rats.Add(this);
			if (Plugin.IsServerOrHost)
			{
				AssignRatType();
			}
			Plugin.logIfDebug("Rat spawned");
		}

		public override void Update()
		{
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			if (base.isEnemyDead || StartOfRound.Instance.allPlayersDead)
			{
				return;
			}
			base.creatureAnimator.SetBool("stunned", base.stunNormalizedTimer > 0f);
			if (base.stunNormalizedTimer >= 0f)
			{
				base.stunNormalizedTimer -= Time.deltaTime / base.enemyType.stunTimeMultiplier;
				base.agent.speed = 0f;
			}
			if (Plugin.IsServerOrHost)
			{
				if (base.updateDestinationInterval >= 0f)
				{
					base.updateDestinationInterval -= Time.deltaTime;
				}
				else
				{
					((EnemyAI)this).DoAIInterval();
					base.updateDestinationInterval = base.AIIntervalTime + Random.Range(-0.015f, 0.015f);
				}
			}
			timeSinceCollision += Time.deltaTime;
			timeSinceAddThreat += Time.deltaTime;
			base.creatureAnimator.SetBool("runBackwards", returningBodyToNest && base.stunNormalizedTimer <= 0f);
			if (returningBodyToNest && (Object)(object)heldBody != (Object)null)
			{
				TurnCompass.LookAt(((Component)heldBody).transform.position);
				((Component)this).transform.rotation = Quaternion.Lerp(((Component)this).transform.rotation, Quaternion.Euler(new Vector3(0f, TurnCompass.eulerAngles.y, 0f)), 10f * Time.deltaTime);
			}
		}

		public override void DoAIInterval()
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_0242: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_036f: Unknown result type (might be due to invalid IL or missing references)
			//IL_037a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0415: Unknown result type (might be due to invalid IL or missing references)
			//IL_0420: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			if (base.isEnemyDead || StartOfRound.Instance.allPlayersDead || base.stunNormalizedTimer > 0f)
			{
				return;
			}
			if (base.moveTowardsDestination)
			{
				base.agent.SetDestination(base.destination);
			}
			if ((Object)(object)MainNest == (Object)null && base.currentBehaviourStateIndex != 0)
			{
				SwitchToBehaviourStateCustom(State.Roaming);
				return;
			}
			switch (base.currentBehaviourStateIndex)
			{
			case 0:
				base.agent.speed = 5f;
				if (AtNest)
				{
					if (returningBodyToNest)
					{
						DropBody(deactivate: true);
						MainNest.AddFood(playerFoodAmount);
					}
					SwitchToBehaviourStateCustom(State.Tasking);
					break;
				}
				if ((Object)(object)MainNest == (Object)null)
				{
					TryGetAnyNest();
				}
				if ((Object)(object)MainNest != (Object)null && SetDestinationToPosition(((Component)MainNest).transform.position))
				{
					StopRoutines();
					SetStatus("Returning to nest");
					break;
				}
				if (returningBodyToNest)
				{
					DropBody();
				}
				Roam();
				break;
			case 1:
				base.agent.speed = 5f;
				if (grabbingBody)
				{
					GrabbableObject grabBodyObject = base.targetPlayer.deadBody.grabBodyObject;
					if (SetDestinationToPosition(((Component)grabBodyObject).transform.position, checkForPath: true))
					{
						if (Vector3.Distance(((Component)this).transform.position, ((Component)grabBodyObject).transform.position) < 1f)
						{
							GrabBody();
							returningBodyToNest = true;
							SwitchToBehaviourStateCustom(State.Roaming);
						}
						break;
					}
				}
				CheckForThreatsInLOS();
				break;
			case 2:
				base.agent.speed = 10f;
				if ((Object)(object)base.targetPlayer != (Object)null)
				{
					if (Vector3.Distance(((Component)base.targetPlayer).transform.position, ((Component)this).transform.position) > distanceToLoseRats)
					{
						base.targetPlayer = null;
						SwitchToBehaviourStateCustom(State.Roaming);
					}
					else if (NearbyRatCount(swarmRadius) >= ratsNeededToAttack)
					{
						SwitchToBehaviourStateCustom(State.Attacking);
					}
				}
				else if ((Object)(object)targetEnemy != (Object)null)
				{
					if (Vector3.Distance(((Component)targetEnemy).transform.position, ((Component)this).transform.position) > distanceToLoseRats)
					{
						targetEnemy = null;
						SwitchToBehaviourStateCustom(State.Roaming);
					}
					else if (NearbyRatCount(swarmRadius) >= ratsNeededToAttack)
					{
						SwitchToBehaviourStateCustom(State.Attacking);
					}
				}
				else
				{
					SwitchToBehaviourStateCustom(State.Roaming);
				}
				break;
			case 3:
				base.agent.speed = 10f;
				if ((Object)(object)base.targetPlayer != (Object)null)
				{
					if (Vector3.Distance(((Component)base.targetPlayer).transform.position, ((Component)this).transform.position) > distanceToLoseRats)
					{
						base.targetPlayer = null;
						SwitchToBehaviourStateCustom(State.Roaming);
					}
					else if (NearbyRatCount(swarmRadius) <= ratsNeededToAttack / 3 && !IsPlayerNearANest(base.targetPlayer))
					{
						base.targetPlayer = null;
						SwitchToBehaviourStateCustom(State.Roaming);
					}
				}
				else if ((Object)(object)targetEnemy != (Object)null)
				{
					if (Vector3.Distance(((Component)targetEnemy).transform.position, ((Component)this).transform.position) > distanceToLoseRats * 2f)
					{
						targetEnemy = null;
						SwitchToBehaviourStateCustom(State.Roaming);
					}
					else if (NearbyRatCount(swarmRadius) <= ratsNeededToAttack / 3)
					{
						targetEnemy = null;
						SwitchToBehaviourStateCustom(State.Roaming);
					}
				}
				else
				{
					SwitchToBehaviourStateCustom(State.Roaming);
				}
				break;
			default:
				Plugin.LoggerInstance.LogWarning((object)("Invalid state: " + base.currentBehaviourStateIndex));
				break;
			}
		}

		private void TryGetAnyNest()
		{
			MainNest = RatManager.Nests.FirstOrDefault();
		}

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

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

		private bool SetDestinationToPosition(Vector3 position)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: 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_00c6: 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_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			position = RoundManager.Instance.GetNavMeshPosition(position, RoundManager.Instance.navHit, 1.75f, -1);
			finalDestination = position;
			base.path1 = new NavMeshPath();
			if (!((Behaviour)base.agent).enabled)
			{
				return false;
			}
			if (!base.agent.CalculatePath(position, base.path1))
			{
				if (canVent && (Object)(object)FromVent != (Object)null && (Object)(object)ToVent != (Object)null)
				{
					Vector3 navMeshPosition = RoundManager.Instance.GetNavMeshPosition(((Component)FromVent.floorNode).transform.position, RoundManager.Instance.navHit, 1.75f, -1);
					if (Vector3.Distance(((Component)this).transform.position, navMeshPosition) < 1f)
					{
						WarpToVent(FromVent, ToVent);
						base.moveTowardsDestination = true;
						base.movingTowardsTargetPlayer = false;
						base.destination = RoundManager.Instance.GetNavMeshPosition(finalDestination, RoundManager.Instance.navHit, -1f, -1);
						return true;
					}
					base.moveTowardsDestination = true;
					base.movingTowardsTargetPlayer = false;
					base.destination = RoundManager.Instance.GetNavMeshPosition(navMeshPosition, RoundManager.Instance.navHit, -1f, -1);
					return true;
				}
				return false;
			}
			base.moveTowardsDestination = true;
			base.movingTowardsTargetPlayer = false;
			base.destination = RoundManager.Instance.GetNavMeshPosition(finalDestination, RoundManager.Instance.navHit, -1f, -1);
			return true;
		}

		private void HottestRat()
		{
			if (Random.Range(0f, 1f) < 0.01f)
			{
				ScanNode.headerText = "HottestRat";
			}
		}

		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)
				{
					base.path1 = new NavMeshPath();
					if (((EnemyAI)this).CheckLineOfSightForPosition(((Component)deadBody.grabBodyObject).transform.position, 60f, 60, 5f, (Transform)null) && base.agent.CalculatePath(RoundManager.Instance.GetNavMeshPosition(((Component)deadBody.grabBodyObject).transform.position, RoundManager.Instance.navHit, 1.75f, -1), base.path1))
					{
						base.targetPlayer = deadBody.playerScript;
						return true;
					}
				}
			}
			return false;
		}

		private void CheckForThreatsInLOS()
		{
			if (!(timeSinceAddThreat > timeToIncreaseThreat))
			{
				return;
			}
			if (CheckLineOfSightForDeadBody())
			{
				StopRoutines();
				grabbingBody = true;
				return;
			}
			PlayerControllerB val = ((EnemyAI)this).CheckLineOfSightForPlayer(60f, 60, 5);
			if (PlayerIsTargetable(val))
			{
				AddThreat(val);
				return;
			}
			EnemyAI val2 = CheckLineOfSightForEnemy(30);
			if ((Object)(object)val2 != (Object)null && val2.enemyType.canDie)
			{
				AddThreat(val2);
			}
		}

		private int NearbyRatCount(float radius)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			foreach (RatAI rat in RatManager.Rats)
			{
				if (Vector3.Distance(((Component)this).transform.position, ((Component)rat).transform.position) <= radius)
				{
					num++;
				}
			}
			return num;
		}

		public void AssignRatType()
		{
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			if (!AtNest)
			{
				RatTypeState = RatType.Unassigned;
				return;
			}
			if (holdingFood)
			{
				holdingFood = false;
				MainNest.AddFood();
			}
			if (MainNest.DefenseRatCount < maxDefenseRats)
			{
				Plugin.logIfDebug("Rat defense assigned");
				RatTypeState = RatType.DefenseRat;
				MainNest.DefenseRatCount++;
				ratCoroutine = ((MonoBehaviour)this).StartCoroutine(SwarmCoroutine(((Component)MainNest).transform.position, defenseRadius));
				SetStatus("Defending");
			}
			else
			{
				Plugin.logIfDebug("Rat scout assigned");
				RatTypeState = RatType.ScoutRat;
				ratCoroutine = ((MonoBehaviour)this).StartCoroutine(ScoutCoroutine());
				SetStatus("Scouting");
			}
		}

		private EnemyVent? GetClosestVentToPosition(Vector3 pos)
		{
			//IL_001f: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			float num = 2000f;
			EnemyVent result = null;
			EnemyVent[] allEnemyVents = RoundManager.Instance.allEnemyVents;
			foreach (EnemyVent val in allEnemyVents)
			{
				float num2 = Vector3.Distance(pos, ((Component)val.floorNode).transform.position);
				if (((Behaviour)base.agent).enabled && RatManager.CalculatePath(pos, ((Component)val.floorNode).transform.position) && num2 < num)
				{
					num = num2;
					result = val;
				}
			}
			return result;
		}

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

		public EnemyAI? GetClosestEnemy(float range)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			EnemyAI result = null;
			float num = range;
			foreach (EnemyAI spawnedEnemy in RoundManager.Instance.SpawnedEnemies)
			{
				if (!((Object)(object)spawnedEnemy.enemyType == (Object)(object)base.enemyType) && spawnedEnemy.enemyType.canDie)
				{
					float num2 = Vector3.Distance(((Component)this).transform.position, ((Component)spawnedEnemy).transform.position);
					if (num2 < num)
					{
						result = spawnedEnemy;
						num = num2;
					}
				}
			}
			return result;
		}

		private bool TargetPlayerNearNest()
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)MainNest == (Object)null)
			{
				return false;
			}
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				if (PlayerIsTargetable(val) && Vector3.Distance(((Component)val).transform.position, ((Component)MainNest).transform.position) < defenseRadius)
				{
					base.targetPlayer = val;
				}
			}
			return (Object)(object)base.targetPlayer != (Object)null;
		}

		private void WarpToVent(EnemyVent fromVent, EnemyVent toVent)
		{
			//IL_001f: 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)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			OpenVents(fromVent, toVent);
			Vector3 navMeshPosition = RoundManager.Instance.GetNavMeshPosition(((Component)ToVent.floorNode).transform.position, RoundManager.Instance.navHit, 1.75f, -1);
			((Component)this).transform.position = navMeshPosition;
			base.agent.Warp(navMeshPosition);
		}

		private int GetVentIndex(EnemyVent? vent)
		{
			for (int i = 0; i < RoundManager.Instance.allEnemyVents.Length; i++)
			{
				if ((Object)(object)RoundManager.Instance.allEnemyVents[i] == (Object)(object)vent)
				{
					return i;
				}
			}
			return -1;
		}

		private void OpenVents(EnemyVent? vent, EnemyVent? vent2 = null)
		{
			if (!((Object)(object)vent == (Object)null))
			{
				int num = -1;
				int num2 = -1;
				if (!vent.ventIsOpen)
				{
					num = GetVentIndex(vent);
				}
				if ((Object)(object)vent2 != (Object)null && !vent2.ventIsOpen)
				{
					num2 = GetVentIndex(vent2);
				}
				if (num != -1 || num2 != -1)
				{
					OpenVentsClientRpc(num, num2);
				}
			}
		}

		private void SetStatus(string status)
		{
			if (Plugin.configEnableDebugging.Value)
			{
				ScanNode.subText = status;
			}
		}

		private void Roam()
		{
			if (ratCoroutine == null)
			{
				SetStatus("Lost");
				ratCoroutine = ((MonoBehaviour)this).StartCoroutine(RoamCoroutine());
			}
		}

		private IEnumerator RoamCoroutine()
		{
			yield return null;
			while (ratCoroutine != null)
			{
				float timeStuck = 0f;
				TargetRandomNode();
				if ((Object)(object)base.targetNode == (Object)null)
				{
					continue;
				}
				Vector3 position = RoundManager.Instance.GetNavMeshPosition(base.targetNode.position, RoundManager.Instance.navHit, 1.75f, base.agent.areaMask);
				if (!SetDestinationToPosition(position))
				{
					continue;
				}
				while (((Behaviour)base.agent).enabled)
				{
					yield return (object)new WaitForSeconds(base.AIIntervalTime);
					if (!base.agent.hasPath || timeStuck > 1f)
					{
						PlaySqueakSFX(longSqueak: true);
						break;
					}
					if (base.agent.velocity == Vector3.zero)
					{
						timeStuck += base.AIIntervalTime;
					}
				}
			}
			SwitchToBehaviourStateCustom(State.Roaming);
		}

		private IEnumerator SwarmCoroutine(PlayerControllerB player, float radius)
		{
			yield return null;
			Plugin.logIfDebug("Starting swarm on player");
			while (ratCoroutine != null && (Object)(object)player != (Object)null && !((Object)(object)player == (Object)null) && !player.isPlayerDead)
			{
				float timeStuck = 0f;
				Vector3 position = RoundManager.Instance.GetRandomNavMeshPositionInRadius(((Component)player).transform.position, radius, RoundManager.Instance.navHit);
				SetDestinationToPosition(position, checkForPath: false);
				while (((Behaviour)base.agent).enabled)
				{
					yield return (object)new WaitForSeconds(base.AIIntervalTime);
					if (!base.agent.hasPath || timeStuck > 1f)
					{
						PlaySqueakSFX();
						break;
					}
					if (base.agent.velocity == Vector3.zero)
					{
						timeStuck += base.AIIntervalTime;
					}
				}
			}
			SwitchToBehaviourStateCustom(State.Roaming);
		}

		private IEnumerator SwarmCoroutine(EnemyAI enemy, float radius)
		{
			yield return null;
			while (ratCoroutine != null && (Object)(object)enemy != (Object)null)
			{
				float timeStuck = 0f;
				Vector3 position = RoundManager.Instance.GetRandomNavMeshPositionInRadius(((Component)enemy).transform.position, radius, RoundManager.Instance.navHit);
				SetDestinationToPosition(position, checkForPath: false);
				while (((Behaviour)base.agent).enabled)
				{
					yield return (object)new WaitForSeconds(base.AIIntervalTime);
					if (!base.agent.hasPath || timeStuck > 1f)
					{
						PlaySqueakSFX();
						break;
					}
					if (base.agent.velocity == Vector3.zero)
					{
						timeStuck += base.AIIntervalTime;
					}
				}
			}
			SwitchToBehaviourStateCustom(State.Roaming);
		}

		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 timeStuck = 0f;
				Vector3 pos2 = position;
				pos2 = RoundManager.Instance.GetRandomNavMeshPositionInRadius(pos2, radius, RoundManager.Instance.navHit);
				SetDestinationToPosition(pos2, checkForPath: false);
				while (((Behaviour)base.agent).enabled)
				{
					yield return (object)new WaitForSeconds(base.AIIntervalTime);
					if (!base.agent.hasPath || timeStuck > 1f)
					{
						PlaySqueakSFX();
						break;
					}
					if (base.agent.velocity == Vector3.zero)
					{
						timeStuck += base.AIIntervalTime;
					}
				}
			}
			SwitchToBehaviourStateCustom(State.Roaming);
		}

		private IEnumerator ScoutCoroutine()
		{
			yield return null;
			while (ratCoroutine != null && ((Behaviour)base.agent).enabled)
			{
				float timeStuck = 0f;
				TargetRandomNode();
				if ((Object)(object)base.targetNode == (Object)null)
				{
					continue;
				}
				Vector3 position = ((Component)base.targetNode).transform.position;
				if (!SetDestinationToPosition(position))
				{
					continue;
				}
				while (((Behaviour)base.agent).enabled)
				{
					yield return (object)new WaitForSeconds(base.AIIntervalTime);
					if (!base.agent.hasPath || timeStuck > 1f)
					{
						PlaySqueakSFX(longSqueak: true);
						SwitchToBehaviourStateCustom(State.Roaming);
						ratCoroutine = null;
						yield break;
					}
					if (base.agent.velocity == Vector3.zero)
					{
						timeStuck += base.AIIntervalTime;
					}
				}
			}
			SwitchToBehaviourStateCustom(State.Roaming);
		}

		private void PlaySqueakSFX(bool longSqueak = false)
		{
			if (!Plugin.configMakeLessSqueaks.Value)
			{
				PlaySqueakSFXClientRpc(longSqueak);
			}
		}

		private void TargetRandomNode()
		{
			try
			{
				GameObject[] allAINodes = base.allAINodes;
				int num = Random.Range(0, allAINodes.Length);
				base.targetNode = allAINodes[num].transform;
			}
			catch
			{
				base.targetNode = null;
			}
		}

		public override void HitEnemy(int force = 0, PlayerControllerB playerWhoHit = null, bool playHitSFX = true, int hitID = -1)
		{
			if (!base.isEnemyDead)
			{
				base.enemyHP -= force;
				if (base.enemyHP <= 0)
				{
					DropBody();
					RoundManager.PlayRandomClip(base.creatureSFX, HitSFX, true, 1f, -1, 1000);
					((EnemyAI)this).KillEnemyOnOwnerClient(false);
				}
			}
		}

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

		public override void CancelSpecialAnimationWithPlayer()
		{
			StopRoutines();
		}

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

		public bool PlayerIsTargetable(PlayerControllerB playerScript)
		{
			if ((Object)(object)playerScript == (Object)null)
			{
				return false;
			}
			if (playerScript.isPlayerDead)
			{
				return false;
			}
			if (base.currentBehaviourStateIndex == 0)
			{
				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 (SewerGrate nest in RatManager.Nests)
			{
				if (Vector3.Distance(((Component)player).transform.position, ((Component)nest).transform.position) < defenseRadius)
				{
					return true;
				}
			}
			return false;
		}

		public override void OnCollideWithPlayer(Collider other)
		{
			//IL_007f: 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 (!base.isEnemyDead && timeSinceCollision > 1f)
			{
				timeSinceCollision = 0f;
				PlayerControllerB val = ((EnemyAI)this).MeetsStandardPlayerCollisionConditions(other, false, false);
				if (!((Object)(object)val == (Object)null) && (base.currentBehaviourStateIndex == 3 || IsPlayerNearANest(val)))
				{
					int num = ((Random.Range(0, 2) == 1) ? 7 : 0);
					val.DamagePlayer(ratDamage, true, true, (CauseOfDeath)6, num, false, default(Vector3));
					PlayAttackSFXServerRpc();
				}
			}
		}

		public override void OnCollideWithEnemy(Collider other, EnemyAI? collidedEnemy = null)
		{
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			((EnemyAI)this).OnCollideWithEnemy(other, collidedEnemy);
			if (Plugin.IsServerOrHost)
			{
				if (base.isEnemyDead || base.currentBehaviourStateIndex == 0 || (Object)(object)MainNest == (Object)null)
				{
					return;
				}
				if (timeSinceCollision > 1f && (Object)(object)collidedEnemy != (Object)null && (Object)(object)collidedEnemy.enemyType != (Object)(object)base.enemyType && collidedEnemy.enemyType.canDie && !(base.stunNormalizedTimer > 0f))
				{
					Plugin.logIfDebug("Collided with: " + collidedEnemy.enemyType.enemyName);
					timeSinceCollision = 0f;
					if (collidedEnemy.isEnemyDead)
					{
						if (SewerGrate.EnemyFoodAmount.ContainsKey(collidedEnemy))
						{
							if (SewerGrate.EnemyFoodAmount[collidedEnemy] <= 1)
							{
								holdingFood = SewerGrate.EnemyFoodAmount[collidedEnemy] == 1;
								RoundManager.Instance.DespawnEnemyOnServer(((NetworkBehaviour)collidedEnemy).NetworkObject);
								return;
							}
							SewerGrate.EnemyFoodAmount[collidedEnemy]--;
							holdingFood = true;
						}
						else
						{
							RatManager.EnemyHitCount.Remove(collidedEnemy);
							MainNest.AddEnemyFoodAmount(collidedEnemy);
							SewerGrate.EnemyFoodAmount[collidedEnemy]--;
							holdingFood = true;
						}
						SwitchToBehaviourStateCustom(State.Roaming);
					}
					else
					{
						if (!RatManager.EnemyHitCount.ContainsKey(collidedEnemy))
						{
							RatManager.EnemyHitCount.Add(collidedEnemy, enemyHitsToDoDamage);
						}
						RatManager.EnemyHitCount[collidedEnemy]--;
						if (RatManager.EnemyHitCount[collidedEnemy] <= 0)
						{
							collidedEnemy.HitEnemy(1, (PlayerControllerB)null, true, -1);
							RatManager.EnemyHitCount[collidedEnemy] = enemyHitsToDoDamage;
						}
					}
				}
			}
			if (holdingFood)
			{
				RoundManager.PlayRandomClip(base.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);
				}
			}
		}

		private void AddThreat(EnemyAI enemy, int amount = 1)
		{
			if (!((Object)(object)enemy == (Object)null) && (Object)(object)MainNest != (Object)null)
			{
				timeSinceAddThreat = 0f;
				if (RatManager.EnemyThreatCounter.ContainsKey(enemy))
				{
					RatManager.EnemyThreatCounter[enemy] += amount;
				}
				else
				{
					RatManager.EnemyThreatCounter.Add(enemy, amount);
				}
				PlaySqueakSFXClientRpc();
				int num = RatManager.EnemyThreatCounter[enemy];
				Plugin.logIfDebug($"{enemy.enemyType.enemyName}: {num} threat");
				if (RatTypeState != RatType.DefenseRat && (RatManager.EnemyThreatCounter[enemy] > threatToAttackEnemy || enemy.isEnemyDead))
				{
					SetTarget(enemy);
					SwitchToBehaviourStateCustom(State.Swarming);
				}
			}
		}

		private void AddThreat(PlayerControllerB player, int amount = 1)
		{
			if (!((Object)(object)player == (Object)null) && (Object)(object)MainNest != (Object)null)
			{
				timeSinceAddThreat = 0f;
				if (RatManager.PlayerThreatCounter.ContainsKey(player))
				{
					RatManager.PlayerThreatCounter[player] += amount;
				}
				else
				{
					RatManager.PlayerThreatCounter.Add(player, amount);
				}
				PlaySqueakSFXClientRpc();
				int num = RatManager.PlayerThreatCounter[player];
				Plugin.logIfDebug($"{player.playerUsername}: {num} threat");
				if (RatTypeState != RatType.DefenseRat && (RatManager.PlayerThreatCounter[player] > threatToAttackPlayer || player.isPlayerDead))
				{
					SetTarget(player);
					SwitchToBehaviourStateCustom(State.Swarming);
				}
			}
		}

		public void SetTarget(PlayerControllerB player)
		{
			targetEnemy = null;
			base.targetPlayer = player;
		}

		public void SetTarget(EnemyAI enemy)
		{
			base.targetPlayer = null;
			targetEnemy = enemy;
		}

		public override void SetEnemyStunned(bool setToStunned, float setToStunTime = 1f, PlayerControllerB? setStunnedByPlayer = null)
		{
			if (base.isEnemyDead)
			{
				return;
			}
			if (setToStunned)
			{
				if (!(base.postStunInvincibilityTimer >= 0f))
				{
					base.stunnedByPlayer = setStunnedByPlayer;
					base.postStunInvincibilityTimer = 0.5f;
					base.stunNormalizedTimer = 5f;
				}
			}
			else
			{
				base.stunnedByPlayer = null;
				if (base.stunNormalizedTimer > 0f)
				{
					base.stunNormalizedTimer = 0f;
				}
			}
		}

		public override void KillEnemy(bool destroy = false)
		{
			if (destroy && base.enemyType.canBeDestroyed)
			{
				Debug.Log((object)"Destroy enemy called");
				if (((NetworkBehaviour)this).IsServer)
				{
					Debug.Log((object)"Despawn network object in kill enemy called!");
					if (base.thisNetworkObject.IsSpawned)
					{
						base.thisNetworkObject.Despawn(true);
					}
				}
				return;
			}
			if ((Object)(object)ScanNode != (Object)null && Object.op_Implicit((Object)(object)((Component)ScanNode).gameObject.GetComponent<Collider>()))
			{
				((Component)ScanNode).gameObject.GetComponent<Collider>().enabled = false;
			}
			base.isEnemyDead = true;
			try
			{
				if ((Object)(object)base.creatureAnimator != (Object)null)
				{
					base.creatureAnimator.SetBool("stunned", false);
					base.creatureAnimator.SetTrigger("KillEnemy");
				}
			}
			catch (Exception arg)
			{
				Debug.LogError((object)$"enemy did not have bool in animator in KillEnemy, error returned; {arg}");
			}
			((MonoBehaviour)this).StopAllCoroutines();
			((Behaviour)base.agent).enabled = false;
			RatManager.Rats.Remove(this);
			if (RatTypeState == RatType.DefenseRat)
			{
				MainNest.DefenseRatCount--;
			}
		}

		public override void OnDestroy()
		{
			((Behaviour)base.agent).enabled = false;
			((MonoBehaviour)this).StopAllCoroutines();
			if ((Object)(object)((NetworkBehaviour)this).NetworkObject != (Object)null && ((NetworkBehaviour)this).NetworkObject.IsSpawned && ((NetworkBehaviour)this).IsSpawned)
			{
				((NetworkBehaviour)this).NetworkObject.OnNetworkBehaviourDestroyed((NetworkBehaviour)(object)this);
			}
			if (!((NetworkBehaviour)this).m_VarInit)
			{
				((NetworkBehaviour)this).InitializeVariables();
			}
			for (int i = 0; i < ((NetworkBehaviour)this).NetworkVariableFields.Count; i++)
			{
				((NetworkBehaviour)this).NetworkVariableFields[i].Dispose();
			}
			if (RoundManager.Instance.SpawnedEnemies.Contains((EnemyAI)(object)this))
			{
				RoundManager.Instance.SpawnedEnemies.Remove((EnemyAI)(object)this);
			}
			RatManager.Rats.Remove(this);
		}

		public bool SetDestinationToPosition(Vector3 position, bool checkForPath = false)
		{
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_006d: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			if (checkForPath)
			{
				position = RoundManager.Instance.GetNavMeshPosition(position, RoundManager.Instance.navHit, 1.75f, -1);
				base.path1 = new NavMeshPath();
				if (!base.agent.CalculatePath(position, base.path1))
				{
					return false;
				}
				if (Vector3.Distance(base.path1.corners[base.path1.corners.Length - 1], RoundManager.Instance.GetNavMeshPosition(position, RoundManager.Instance.navHit, 2.7f, -1)) > 1.55f)
				{
					return false;
				}
			}
			base.moveTowardsDestination = true;
			base.movingTowardsTargetPlayer = false;
			base.destination = RoundManager.Instance.GetNavMeshPosition(position, RoundManager.Instance.navHit, -1f, -1);
			return true;
		}

		[ServerRpc(RequireOwnership = false)]
		public void PlayAttackSFXServerRpc()
		{
			//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)((NetworkBehaviour)this).__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
				{
					ServerRpcParams val = default(ServerRpcParams);
					FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(4136324962u, val, (RpcDelivery)0);
					((NetworkBehaviour)this).__endSendServerRpc(ref val2, 4136324962u, val, (RpcDelivery)0);
				}
				if ((int)((NetworkBehaviour)this).__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost) && Plugin.IsServerOrHost)
				{
					PlayAttackSFXClientRpc();
				}
			}
		}

		[ClientRpc]
		public void PlayAttackSFXClientRpc()
		{
			//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)((NetworkBehaviour)this).__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
				{
					ClientRpcParams val = default(ClientRpcParams);
					FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(2132714291u, val, (RpcDelivery)0);
					((NetworkBehaviour)this).__endSendClientRpc(ref val2, 2132714291u, val, (RpcDelivery)0);
				}
				if ((int)((NetworkBehaviour)this).__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost))
				{
					RoundManager.PlayRandomClip(base.creatureSFX, AttackSFX, true, 1f, -1, 1000);
				}
			}
		}

		[ClientRpc]
		public void SwitchToBehaviourClientRpc(int stateIndex)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: 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_0089: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)((NetworkBehaviour)this).__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
				{
					ClientRpcParams val = default(ClientRpcParams);
					FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(2453761421u, val, (RpcDelivery)0);
					BytePacker.WriteValueBitPacked(val2, stateIndex);
					((NetworkBehaviour)this).__endSendClientRpc(ref val2, 2453761421u, val, (RpcDelivery)0);
				}
				if ((int)((NetworkBehaviour)this).__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost) && base.currentBehaviourStateIndex != stateIndex)
				{
					base.currentBehaviourStateIndex = stateIndex;
					base.currentBehaviourState = base.enemyBehaviourStates[stateIndex];
					RoundManager.PlayRandomClip(base.creatureSFX, SqueakSFX, true, 1f, -1, 1000);
				}
			}
		}

		[ClientRpc]
		public void PlaySqueakSFXClientRpc(bool longSqueak = false)
		{
			//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)((NetworkBehaviour)this).__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val = default(ClientRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(2878241198u, val, (RpcDelivery)0);
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref longSqueak, default(ForPrimitives));
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 2878241198u, val, (RpcDelivery)0);
			}
			if ((int)((NetworkBehaviour)this).__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost))
			{
				if (longSqueak)
				{
					RoundManager.PlayRandomClip(base.creatureSFX, SqueakSFX, true, 1f, -1, 1000);
				}
				else
				{
					RoundManager.PlayRandomClip(base.creatureSFX, HitSFX, true, 1f, -1, 1000);
				}
			}
		}

		[ClientRpc]
		public void OpenVentsClientRpc(int ventIndex, int ventIndex2)
		{
			//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)((NetworkBehaviour)this).__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val = default(ClientRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(550538699u, val, (RpcDelivery)0);
				BytePacker.WriteValueBitPacked(val2, ventIndex);
				BytePacker.WriteValueBitPacked(val2, ventIndex2);
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 550538699u, val, (RpcDelivery)0);
			}
			if ((int)((NetworkBehaviour)this).__rpc_exec_stage != 2 || (!networkManager.IsClient && !networkManager.IsHost))
			{
				return;
			}
			if (ventIndex != -1)
			{
				EnemyVent val3 = RoundManager.Instance.allEnemyVents[ventIndex];
				if ((Object)(object)val3 == (Object)null)
				{
					RoundManager.Instance.RefreshEnemyVents();
					val3 = RoundManager.Instance.allEnemyVents[ventIndex];
					if ((Object)(object)val3 == (Object)null)
					{
						Plugin.LoggerInstance.LogError((object)"Cant get vent to open on client");
						return;
					}
				}
				val3.ventIsOpen = true;
				val3.ventAnimator.SetTrigger("openVent");
				val3.lowPassFilter.lowpassResonanceQ = 0f;
			}
			if (ventIndex2 == -1)
			{
				return;
			}
			EnemyVent val4 = RoundManager.Instance.allEnemyVents[ventIndex2];
			if ((Object)(object)val4 == (Object)null)
			{
				RoundManager.Instance.RefreshEnemyVents();
				val4 = RoundManager.Instance.allEnemyVents[ventIndex2];
				if ((Object)(object)val4 == (Object)null)
				{
					Plugin.LoggerInstance.LogError((object)"Cant get vent to open on client");
					return;
				}
			}
			val4.ventIsOpen = true;
			val4.ventAnimator.SetTrigger("openVent");
			val4.lowPassFilter.lowpassResonanceQ = 0f;
		}

		[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)((NetworkBehaviour)this).__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)((NetworkBehaviour)this).__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost))
			{
				base.targetPlayer = Plugin.PlayerFromId(clientId);
				if ((Object)(object)base.targetPlayer != (Object)null && (Object)(object)base.targetPlayer.deadBody != (Object)null)
				{
					heldBody = base.targetPlayer.deadBody;
					heldBody.attachedTo = RatMouth;
					heldBody.attachedLimb = base.targetPlayer.deadBody.bodyParts[attachedLimbIndex];
					heldBody.matchPositionExactly = true;
				}
				grabbingBody = false;
				returningBodyToNest = true;
				RoundManager.PlayRandomClip(base.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)((NetworkBehaviour)this).__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)((NetworkBehaviour)this).__rpc_exec_stage != 2 || (!networkManager.IsClient && !networkManager.IsHost))
			{
				return;
			}
			returningBodyToNest = false;
			grabbingBody = false;
			base.targetPlayer = null;
			if ((Object)(object)heldBody != (Object)null)
			{
				heldBody.attachedTo = null;
				heldBody.attachedLimb = null;
				heldBody.matchPositionExactly = false;
				if (deactivate)
				{
					heldBody.DeactivateBody(false);
				}
				heldBody = null;
			}
		}

		protected override void __initializeVariables()
		{
			((EnemyAI)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
			NetworkManager.__rpc_func_table.Add(4136324962u, new RpcReceiveHandler(__rpc_handler_4136324962));
			NetworkManager.__rpc_func_table.Add(2132714291u, new RpcReceiveHandler(__rpc_handler_2132714291));
			NetworkManager.__rpc_func_table.Add(2453761421u, new RpcReceiveHandler(__rpc_handler_2453761421));
			NetworkManager.__rpc_func_table.Add(2878241198u, new RpcReceiveHandler(__rpc_handler_2878241198));
			NetworkManager.__rpc_func_table.Add(550538699u, new RpcReceiveHandler(__rpc_handler_550538699));
			NetworkManager.__rpc_func_table.Add(3500738837u, new RpcReceiveHandler(__rpc_handler_3500738837));
			NetworkManager.__rpc_func_table.Add(1118647984u, new RpcReceiveHandler(__rpc_handler_1118647984));
		}

		private static void __rpc_handler_4136324962(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).PlayAttackSFXServerRpc();
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_2132714291(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).PlayAttackSFXClientRpc();
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_2453761421(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				int stateIndex = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref stateIndex);
				target.__rpc_exec_stage = (__RpcExecStage)2;
				((RatAI)(object)target).SwitchToBehaviourClientRpc(stateIndex);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_2878241198(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 longSqueak = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref longSqueak, default(ForPrimitives));
				target.__rpc_exec_stage = (__RpcExecStage)2;
				((RatAI)(object)target).PlaySqueakSFXClientRpc(longSqueak);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_550538699(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)
			{
				int ventIndex = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref ventIndex);
				int ventIndex2 = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref ventIndex2);
				target.__rpc_exec_stage = (__RpcExecStage)2;
				((RatAI)(object)target).OpenVentsClientRpc(ventIndex, ventIndex2);
				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;
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		protected internal override string __getTypeName()
		{
			return "RatAI";
		}
	}
	public static class RatManager
	{
		public static bool testing = false;

		public static List<RatAI> Rats = new List<RatAI>();

		public static List<SewerGrate> Nests = new List<SewerGrate>();

		public static Dictionary<EnemyAI, int> EnemyHitCount = new Dictionary<EnemyAI, int>();

		public static Dictionary<PlayerControllerB, int> PlayerThreatCounter = new Dictionary<PlayerControllerB, int>();

		public static Dictionary<EnemyAI, int> EnemyThreatCounter = new Dictionary<EnemyAI, int>();

		public static List<EnemyVent> Vents => RoundManager.Instance.allEnemyVents.ToList();

		public static EnemyVent? GetClosestVentToPosition(Vector3 pos)
		{
			//IL_0020: 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_0038: 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)
			float num = 2000f;
			EnemyVent result = null;
			foreach (EnemyVent vent in Vents)
			{
				float num2 = Vector3.Distance(pos, ((Component)vent.floorNode).transform.position);
				if (CalculatePath(pos, ((Component)vent.floorNode).transform.position) && num2 < num)
				{
					num = num2;
					result = vent;
				}
			}
			return result;
		}

		public static bool CalculatePath(Vector3 fromPos, Vector3 toPos)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: 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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_003f: 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_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: 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_0075: Unknown result type (might be due to invalid IL or missing references)
			Vector3 navMeshPosition = RoundManager.Instance.GetNavMeshPosition(fromPos, RoundManager.Instance.navHit, 1.75f, -1);
			Vector3 navMeshPosition2 = RoundManager.Instance.GetNavMeshPosition(toPos, RoundManager.Instance.navHit, 1.75f, -1);
			NavMeshPath val = new NavMeshPath();
			return NavMesh.CalculatePath(navMeshPosition, navMeshPosition2, -1, val) && Vector3.Distance(val.corners[val.corners.Length - 1], RoundManager.Instance.GetNavMeshPosition(navMeshPosition2, RoundManager.Instance.navHit, 2.7f, -1)) <= 1.55f;
		}
	}
	public class SewerGrate : NetworkBehaviour
	{
		public static EnemyType RatEnemyType = null;

		public GameObject RatPrefab = null;

		public TextMeshPro[] TerminalCodes = null;

		public TerminalAccessibleObject TerminalAccessibleObj = null;

		public static LungProp? Apparatus;

		public EnemyVent? NestVent;

		public int DefenseRatCount;

		public static Dictionary<EnemyAI, int> EnemyFoodAmount = new Dictionary<EnemyAI, int>();

		private float timeSinceSpawnRat;

		private float nextRatSpawnTime;

		public bool open = true;

		private bool codeOnGrateSet = false;

		private int food;

		private bool hideCodeOnTerminal = true;

		private float minRatSpawnTime = 10f;

		private float maxRatSpawnTime = 30f;

		private int foodToSpawnRat = 5;

		private int enemyFoodPerHPPoint = 10;

		private int maxRats = 40;

		public bool accessible => (Object)(object)NestVent != (Object)null;

		public void Start()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = ((Component)this).transform.position;
			Plugin.logIfDebug("Sewer grate spawned at: " + ((object)(Vector3)(ref position)).ToString());
			RatManager.Nests.Add(this);
			hideCodeOnTerminal = Plugin.configHideCodeOnTerminal.Value;
			minRatSpawnTime = Plugin.configMinRatSpawnTime.Value;
			maxRatSpawnTime = Plugin.configMaxRatSpawnTime.Value;
			foodToSpawnRat = Plugin.configFoodToSpawnRat.Value;
			enemyFoodPerHPPoint = Plugin.configEnemyFoodPerHPPoint.Value;
			maxRats = Plugin.configMaxRats.Value;
			Plugin.IsLoggingEnabled = Plugin.configEnableDebugging.Value;
			if ((Object)(object)Apparatus == (Object)null)
			{
				Apparatus = (from x in Object.FindObjectsOfType<LungProp>()
					where x.isLungDocked
					select x).FirstOrDefault();
			}
			if (Plugin.IsServerOrHost)
			{
				nextRatSpawnTime = Random.Range(minRatSpawnTime, maxRatSpawnTime);
			}
		}

		public void Update()
		{
			if (!codeOnGrateSet && TerminalAccessibleObj.objectCode != "")
			{
				codeOnGrateSet = true;
				SetCodes();
				if (hideCodeOnTerminal)
				{
					((TMP_Text)TerminalAccessibleObj.mapRadarText).text = "??";
				}
			}
			if ((Object)(object)Apparatus != (Object)null && !Apparatus.isLungDocked)
			{
				open = true;
			}
			if (Plugin.IsServerOrHost && open && RatManager.Rats.Count < maxRats)
			{
				timeSinceSpawnRat += Time.unscaledDeltaTime;
				if (timeSinceSpawnRat > nextRatSpawnTime)
				{
					timeSinceSpawnRat = 0f;
					nextRatSpawnTime = Random.Range(minRatSpawnTime, maxRatSpawnTime);
					SpawnRat();
				}
			}
		}

		private void SetCodes()
		{
			TextMeshPro[] terminalCodes = TerminalCodes;
			foreach (TextMeshPro val in terminalCodes)
			{
				((TMP_Text)val).text = TerminalAccessibleObj.objectCode;
			}
		}

		public void AddEnemyFoodAmount(EnemyAI enemy)
		{
			int enemyHP = enemy.enemyType.enemyPrefab.GetComponent<EnemyAI>().enemyHP;
			int value = enemyHP * enemyFoodPerHPPoint;
			EnemyFoodAmount.Add(enemy, value);
		}

		public void AddFood(int amount = 1)
		{
			food += amount;
			int amount2 = food / foodToSpawnRat;
			int num = food % foodToSpawnRat;
			food = num;
			Plugin.logIfDebug("Spawning rats from food: " + amount2);
			SpawnRats(amount2);
		}

		private void SpawnRats(int amount)
		{
			if (amount != 0)
			{
				for (int i = 0; i < amount; i++)
				{
					SpawnRat();
				}
			}
		}

		private void SpawnRat()
		{
			//IL_0024: 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)
			if (RatManager.Rats.Count < maxRats)
			{
				GameObject val = Object.Instantiate<GameObject>(RatPrefab, ((Component)this).transform.position, Quaternion.identity);
				RatAI component = val.GetComponent<RatAI>();
				((NetworkBehaviour)component).NetworkObject.Spawn(true);
				component.MainNest = this;
			}
		}

		public void ToggleVent()
		{
			if (!((Object)(object)Apparatus != (Object)null) || Apparatus.isLungDocked)
			{
				open = !open;
			}
		}

		public override void OnDestroy()
		{
			RatManager.EnemyHitCount.Clear();
			RatManager.EnemyThreatCounter.Clear();
			RatManager.PlayerThreatCounter.Clear();
			EnemyFoodAmount.Clear();
			Apparatus = null;
			((MonoBehaviour)this).StopAllCoroutines();
			((NetworkBehaviour)this).OnDestroy();
		}

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

		[MethodImpl(MethodImplOptions.NoInlining)]
		protected internal override string __getTypeName()
		{
			return "SewerGrate";
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "Snowlance.Rats";

		public const string PLUGIN_NAME = "Rats";

		public const string PLUGIN_VERSION = "1.1.2";
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}
namespace Snowlance.Rats.NetcodePatcher
{
	[AttributeUsage(AttributeTargets.Module)]
	internal class NetcodePatchedAssemblyAttribute : Attribute
	{
	}
}