Decompiled source of LethalMon v0.4.7

plugins/LethalMon/LethalMon.dll

Decompiled 2 years 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.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using DigitalRuby.ThunderAndLightning;
using GameNetcodeStuff;
using HarmonyLib;
using LethalCompanyInputUtils.Api;
using LethalCompanyInputUtils.BindingPathEnums;
using LethalLib.Modules;
using LethalMon;
using LethalMon.Behaviours;
using LethalMon.CatchableEnemy;
using LethalMon.Compatibility;
using LethalMon.CustomPasses;
using LethalMon.Items;
using LethalMon.NetcodePatcher;
using LethalMon.Patches;
using LethalMon.Throw;
using Microsoft.CodeAnalysis;
using ModelReplacement;
using ModelReplacement.Monobehaviors.Enemies;
using Newtonsoft.Json;
using TMPro;
using TerminalApi;
using TerminalApi.Classes;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition;
using UnityEngine.Rendering.RendererUtils;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("LethalMon")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+4aca66cbd2fa774e84486d5ec3c4493a5dd7efe3")]
[assembly: AssemblyProduct("LethalMon")]
[assembly: AssemblyTitle("LethalMon")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[module: NetcodePatchedAssembly]
internal class <Module>
{
	static <Module>()
	{
		NetworkVariableSerializationTypes.InitializeSerializer_FixedString<FixedString64Bytes>();
		NetworkVariableSerializationTypes.InitializeEqualityChecker_UnmanagedIEquatable<FixedString64Bytes>();
		NetworkVariableSerializationTypes.InitializeSerializer_FixedString<FixedString512Bytes>();
		NetworkVariableSerializationTypes.InitializeEqualityChecker_UnmanagedIEquatable<FixedString512Bytes>();
		NetworkVariableSerializationTypes.InitializeSerializer_UnmanagedByMemcpy<float>();
		NetworkVariableSerializationTypes.InitializeEqualityChecker_UnmanagedIEquatable<float>();
	}
}
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;
		}
	}
}
internal class SeeThroughCustomPass : CustomPass
{
	public Material seeThroughMaterial = new Material(Utils.WireframeMaterial);

	public LayerMask seeThroughLayer;

	public float maxVisibilityDistance = 20f;

	[SerializeField]
	private Shader stencilShader = Utils.SeeThroughShader;

	private Material stencilMaterial;

	private ShaderTagId[] shaderTags;

	protected override bool executeInSceneView => true;

	public void ConfigureMaterial(Color edgeColor, Color fillColor, float thickness)
	{
		//IL_000b: 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)
		seeThroughMaterial.SetColor("_EdgeColor", edgeColor);
		seeThroughMaterial.SetColor("_MainColor", fillColor);
		seeThroughMaterial.SetFloat("_WireframeVal", thickness);
	}

	protected override void Setup(ScriptableRenderContext renderContext, CommandBuffer cmd)
	{
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: 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_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		stencilMaterial = CoreUtils.CreateEngineMaterial(stencilShader);
		shaderTags = (ShaderTagId[])(object)new ShaderTagId[4]
		{
			new ShaderTagId("Forward"),
			new ShaderTagId("ForwardOnly"),
			new ShaderTagId("SRPDefaultUnlit"),
			new ShaderTagId("FirstPass")
		};
	}

	protected override void Execute(CustomPassContext ctx)
	{
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		stencilMaterial.SetInt("_StencilWriteMask", 64);
		seeThroughMaterial.SetFloat("_MaxVisibilityDistance", maxVisibilityDistance);
		RenderObjects(ctx.renderContext, ctx.cmd, stencilMaterial, 0, (CompareFunction)4, ctx.cullingResults, ctx.hdCamera);
		StencilState value = default(StencilState);
		((StencilState)(ref value))..ctor(true, (byte)64, byte.MaxValue, (CompareFunction)3, (StencilOp)0, (StencilOp)0, (StencilOp)0);
		RenderObjects(ctx.renderContext, ctx.cmd, seeThroughMaterial, seeThroughMaterial.FindPass("ForwardOnly"), (CompareFunction)7, ctx.cullingResults, ctx.hdCamera, value);
	}

	public override IEnumerable<Material> RegisterMaterialForInspector()
	{
		yield return seeThroughMaterial;
	}

	private void RenderObjects(ScriptableRenderContext renderContext, CommandBuffer cmd, Material overrideMaterial, int passIndex, CompareFunction depthCompare, CullingResults cullingResult, HDCamera hdCamera, StencilState? overrideStencil = null)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: 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_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		RendererListDesc val = default(RendererListDesc);
		((RendererListDesc)(ref val))..ctor(shaderTags, cullingResult, hdCamera.camera);
		val.rendererConfiguration = (PerObjectData)0;
		val.renderQueueRange = RenderQueueRange.all;
		val.sortingCriteria = (SortingCriteria)4;
		val.excludeObjectMotionVectors = false;
		val.overrideMaterial = overrideMaterial;
		val.overrideMaterialPassIndex = passIndex;
		val.layerMask = LayerMask.op_Implicit(seeThroughLayer);
		RenderStateBlock value = default(RenderStateBlock);
		((RenderStateBlock)(ref value))..ctor((RenderStateMask)4);
		((RenderStateBlock)(ref value)).depthState = new DepthState(true, depthCompare);
		val.stateBlock = value;
		RendererListDesc val2 = val;
		if (overrideStencil.HasValue)
		{
			RenderStateBlock value2 = val2.stateBlock.Value;
			((RenderStateBlock)(ref value2)).mask = (RenderStateMask)(((RenderStateBlock)(ref value2)).mask | 8);
			((RenderStateBlock)(ref value2)).stencilState = overrideStencil.Value;
			val2.stateBlock = value2;
		}
		CoreUtils.DrawRendererList(renderContext, cmd, ((ScriptableRenderContext)(ref renderContext)).CreateRendererList(val2));
	}

	protected override void Cleanup()
	{
	}
}
namespace LethalMon
{
	public sealed class ModConfig : LcInputActions
	{
		public struct ConfigValues
		{
			public int Tier1BallSpawnWeight { get; set; }

			public int Tier2BallSpawnWeight { get; set; }

			public int Tier3BallSpawnWeight { get; set; }

			public int Tier4BallSpawnWeight { get; set; }

			public int Tier1BallCost { get; set; }

			public int Tier2BallCost { get; set; }

			public int Tier3BallCost { get; set; }

			public int Tier4BallCost { get; set; }

			public string KeepBallsIfAllPlayersDead { get; set; }

			public int CaptureRateModifier { get; set; }

			public string[] DisabledMonsters { get; set; }

			public bool MonstersReactToFailedCaptures { get; set; }

			public float BrackenGrabCooldown { get; set; }

			public float DressGirlTeleportCooldown { get; set; }

			public float HoardingBugBringItemCooldown { get; set; }

			public float FoxTongueHitCooldown { get; set; }

			public float EyelessDogHowlCooldown { get; set; }

			public float MaskedLendCooldown { get; set; }
		}

		[HarmonyPatch]
		public class SyncHandshake
		{
			private const string REQUEST_MESSAGE = "LethalMon_HostConfigRequested";

			private const string RECEIVE_MESSAGE = "LethalMon_HostConfigReceived";

			[HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")]
			[HarmonyPostfix]
			public static void Initialize(PlayerControllerB __instance)
			{
				//IL_0078: Unknown result type (might be due to invalid IL or missing references)
				//IL_0082: Expected O, but got Unknown
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				//IL_003e: Expected O, but got Unknown
				if ((Object)(object)Utils.CurrentPlayer == (Object)(object)__instance)
				{
					if (Utils.IsHost)
					{
						Debug.Log((object)"Current player is the host.");
						NetworkManager.Singleton.CustomMessagingManager.RegisterNamedMessageHandler("LethalMon_HostConfigRequested", new HandleNamedMessageDelegate(HostConfigRequested));
						Instance.values = Instance.originalValues;
						ProcessValues();
					}
					else
					{
						Debug.Log((object)"Current player is not the host.");
						NetworkManager.Singleton.CustomMessagingManager.RegisterNamedMessageHandler("LethalMon_HostConfigReceived", new HandleNamedMessageDelegate(HostConfigReceived));
						RequestHostConfig();
					}
				}
			}

			public static void RequestHostConfig()
			{
				//IL_0025: Unknown result type (might be due to invalid IL or missing references)
				if (!Utils.IsHost)
				{
					Debug.Log((object)"Sending config request to host.");
					NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("LethalMon_HostConfigRequested", 0uL, new FastBufferWriter(0, (Allocator)2, -1), (NetworkDelivery)3);
				}
				else
				{
					Debug.Log((object)"Config request not required. No other player available.");
				}
			}

			public static void HostConfigRequested(ulong clientId, FastBufferReader reader)
			{
				//IL_0064: Unknown result type (might be due to invalid IL or missing references)
				if (!Utils.IsHost)
				{
					return;
				}
				string text = JsonConvert.SerializeObject((object)Instance.values);
				Debug.Log((object)("Client [" + clientId + "] requested host config. Sending own config: " + text));
				int writeSize = FastBufferWriter.GetWriteSize(text, false);
				FastBufferWriter val = default(FastBufferWriter);
				((FastBufferWriter)(ref val))..ctor(writeSize, (Allocator)2, -1);
				try
				{
					((FastBufferWriter)(ref val)).WriteValueSafe(text, false);
					NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("LethalMon_HostConfigReceived", clientId, val, (NetworkDelivery)4);
				}
				finally
				{
					((IDisposable)(FastBufferWriter)(ref val)).Dispose();
				}
			}

			public static void HostConfigReceived(ulong clientId, FastBufferReader reader)
			{
				string text = default(string);
				((FastBufferReader)(ref reader)).ReadValueSafe(ref text, false);
				Debug.Log((object)("Received host config: " + text));
				ConfigValues values = JsonConvert.DeserializeObject<ConfigValues>(text);
				Instance.values = values;
				ProcessValues();
			}
		}

		public ConfigValues values;

		public ConfigValues originalValues;

		private static ModConfig instance;

		public InputAction RetrieveBallKey => ((LcInputActions)this).Asset["retreiveBallKey"];

		public InputAction ActionKey1 => ((LcInputActions)this).Asset["actionKey1"];

		public static ModConfig Instance
		{
			get
			{
				if (instance == null)
				{
					instance = new ModConfig();
				}
				return instance;
			}
		}

		public void Setup()
		{
			values.Tier1BallCost = ((BaseUnityPlugin)LethalMon.Instance).Config.Bind<int>("Items", "Tier1BallCost", 40, "The cost of the tier 1 ball (pokeball) item in the shop. -1 to disable").Value;
			values.Tier2BallCost = ((BaseUnityPlugin)LethalMon.Instance).Config.Bind<int>("Items", "Tier2BallCost", 125, "The cost of the tier 1 ball (great ball) item in the shop. -1 to disable").Value;
			values.Tier3BallCost = ((BaseUnityPlugin)LethalMon.Instance).Config.Bind<int>("Items", "Tier3BallCost", 375, "The cost of the tier 1 ball (ultra ball) item in the shop. -1 to disable").Value;
			values.Tier4BallCost = ((BaseUnityPlugin)LethalMon.Instance).Config.Bind<int>("Items", "Tier4BallCost", 700, "The cost of the tier 1 ball (master ball) item in the shop. -1 to disable").Value;
			values.Tier1BallSpawnWeight = ((BaseUnityPlugin)LethalMon.Instance).Config.Bind<int>("Items", "Tier1BallSpawnWeight", 20, "The spawn weight of the tier 1 ball (pokeball). Higher = more common").Value;
			values.Tier2BallSpawnWeight = ((BaseUnityPlugin)LethalMon.Instance).Config.Bind<int>("Items", "Tier2BallSpawnWeight", 10, "The spawn weight of the tier 2 ball (great ball). Higher = more common").Value;
			values.Tier3BallSpawnWeight = ((BaseUnityPlugin)LethalMon.Instance).Config.Bind<int>("Items", "Tier3BallSpawnWeight", 6, "The spawn weight of the tier 3 ball (ultra ball). Higher = more common").Value;
			values.Tier4BallSpawnWeight = ((BaseUnityPlugin)LethalMon.Instance).Config.Bind<int>("Items", "Tier4BallSpawnWeight", 2, "The spawn weight of the tier 4 ball (master ball). Higher = more common").Value;
			values.KeepBallsIfAllPlayersDead = ((BaseUnityPlugin)LethalMon.Instance).Config.Bind<string>("Items", "KeepBallsIfAllPlayersDead", "no", "Make the balls don't despawn even if all the players are dead. Values are: no, fullOnly, all").Value;
			values.DisabledMonsters = ((BaseUnityPlugin)LethalMon.Instance).Config.Bind<string>("Monsters", "DisabledMonsters", "", "Disabled monsters types. Separate with a comma and don't put spaces. Example: Monster1,Monster2. Available monsters: " + string.Join(", ", Enum.GetNames(typeof(Utils.Enemy)))).Value.Split(",");
			values.MonstersReactToFailedCaptures = ((BaseUnityPlugin)LethalMon.Instance).Config.Bind<bool>("Monsters", "MonstersReactToFailedCaptures", true, "Make the monsters react aggressively if a capture fails").Value;
			values.CaptureRateModifier = ((BaseUnityPlugin)LethalMon.Instance).Config.Bind<int>("Monsters", "CaptureRateModifier", 0, "Modifier for the capture rate. Each monster have a difficulty to catch between 1 and 10. You can modify all the monsters difficulty by adding this modifier to the base difficulty. Negative = easier to catch, positive = harder to catch").Value;
			values.BrackenGrabCooldown = ((BaseUnityPlugin)LethalMon.Instance).Config.Bind<float>("Cooldowns", "BrackenGrabCooldown", 20f, "Grab cooldown time in seconds for the bracken").Value;
			values.DressGirlTeleportCooldown = ((BaseUnityPlugin)LethalMon.Instance).Config.Bind<float>("Cooldowns", "DressGirlTeleportCooldown", 60f, "Teleport cooldown time in seconds for the dress girl").Value;
			values.HoardingBugBringItemCooldown = ((BaseUnityPlugin)LethalMon.Instance).Config.Bind<float>("Cooldowns", "HoardingBugBringItemCooldown", 5f, "Bring item cooldown time in seconds for the hoarder bug").Value;
			values.FoxTongueHitCooldown = ((BaseUnityPlugin)LethalMon.Instance).Config.Bind<float>("Cooldowns", "FoxTongueHitCooldown", 5f, "Tongue hit cooldown time in seconds for the fox").Value;
			values.EyelessDogHowlCooldown = ((BaseUnityPlugin)LethalMon.Instance).Config.Bind<float>("Cooldowns", "EyelessDogHowlCooldown", 5f, "Howl cooldown time in seconds for the eyeless dog").Value;
			values.MaskedLendCooldown = ((BaseUnityPlugin)LethalMon.Instance).Config.Bind<float>("Cooldowns", "MaskedLendCooldown", 7f, "Mask lending cooldown time in seconds for the masked").Value;
			originalValues = values;
		}

		public override void CreateInputActions(in InputActionMapBuilder builder)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			ConfigFile config = ((BaseUnityPlugin)LethalMon.Instance).Config;
			KeyboardControl val = (KeyboardControl)36;
			string value = config.Bind<string>("Controls", "RetrieveBallKeyKeyboard", "<Keyboard>/" + ((object)(KeyboardControl)(ref val)).ToString(), "Key for retrieving the tamed enemy inside its ball. Requires a restart after changing.").Value;
			ConfigFile config2 = ((BaseUnityPlugin)LethalMon.Instance).Config;
			GamepadControl val2 = (GamepadControl)7;
			string value2 = config2.Bind<string>("Controls", "RetrieveBallKeyGamepad", "<Gamepad>/" + ((object)(GamepadControl)(ref val2)).ToString(), "Gamepad key for retrieving the tamed enemy inside its ball. Requires a restart after changing.").Value;
			builder.NewActionBinding().WithActionId("retreiveBallKey").WithActionType((InputActionType)1)
				.WithBindingName("RetrieveBallKey")
				.WithKbmPath(value)
				.WithGamepadPath(value2)
				.Finish();
			ConfigFile config3 = ((BaseUnityPlugin)LethalMon.Instance).Config;
			val = (KeyboardControl)22;
			string value3 = config3.Bind<string>("Controls", "ActionKey1Keyboard", "<Keyboard>/" + ((object)(KeyboardControl)(ref val)).ToString(), "Key for the first custom action on a tamed enemy. Requires a restart after changing.").Value;
			ConfigFile config4 = ((BaseUnityPlugin)LethalMon.Instance).Config;
			val2 = (GamepadControl)9;
			string value4 = config4.Bind<string>("Controls", "ActionKey1Gamepad", "<Gamepad>/" + ((object)(GamepadControl)(ref val2)).ToString(), "Gamepad key for the first custom action on a tamed enemy. Requires a restart after changing.").Value;
			builder.NewActionBinding().WithActionId("actionKey1").WithActionType((InputActionType)1)
				.WithBindingName("ActionKey1")
				.WithKbmPath(value3)
				.WithGamepadPath(value4)
				.Finish();
		}

		public static void ProcessValues()
		{
			LethalMon.Log("Processing config");
			if ((Object)(object)Pokeball.BallItem != (Object)null)
			{
				if (Instance.values.Tier1BallCost >= 0)
				{
					Items.UpdateShopItemPrice(Pokeball.BallItem, Instance.values.Tier1BallCost);
				}
				else
				{
					Items.RemoveShopItem(Pokeball.BallItem);
				}
			}
			if ((Object)(object)Greatball.BallItem != (Object)null)
			{
				if (Instance.values.Tier2BallCost >= 0)
				{
					Items.UpdateShopItemPrice(Greatball.BallItem, Instance.values.Tier2BallCost);
				}
				else
				{
					Items.RemoveShopItem(Greatball.BallItem);
				}
			}
			if ((Object)(object)Ultraball.BallItem != (Object)null)
			{
				if (Instance.values.Tier3BallCost >= 0)
				{
					Items.UpdateShopItemPrice(Ultraball.BallItem, Instance.values.Tier3BallCost);
				}
				else
				{
					Items.RemoveShopItem(Ultraball.BallItem);
				}
			}
			if ((Object)(object)Masterball.BallItem != (Object)null)
			{
				if (Instance.values.Tier4BallCost >= 0)
				{
					Items.UpdateShopItemPrice(Masterball.BallItem, Instance.values.Tier4BallCost);
				}
				else
				{
					Items.RemoveShopItem(Masterball.BallItem);
				}
			}
			string[] disabledMonsters = Instance.values.DisabledMonsters;
			foreach (string key in disabledMonsters)
			{
				Data.CatchableMonsters.Remove(key);
			}
			if (Chainloader.PluginInfos.ContainsKey("atomic.terminalapi"))
			{
				LethalDex.Register();
			}
		}
	}
	public static class Data
	{
		public static readonly Random Random = new Random();

		public static readonly float[][] CaptureProbabilities = new float[4][]
		{
			new float[10] { 0.95f, 0.9f, 0.8f, 0.65f, 0.5f, 0.3f, 0.1f, 0.05f, 0.02f, 0.01f },
			new float[10] { 1f, 0.97f, 0.95f, 0.85f, 0.7f, 0.5f, 0.3f, 0.2f, 0.15f, 0.1f },
			new float[10] { 1f, 1f, 1f, 0.97f, 0.95f, 0.9f, 0.8f, 0.7f, 0.6f, 0.5f },
			new float[10] { 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f }
		};

		public static readonly Dictionary<string, global::LethalMon.CatchableEnemy.CatchableEnemy> CatchableMonsters = new Dictionary<string, global::LethalMon.CatchableEnemy.CatchableEnemy>
		{
			{
				Utils.Enemy.Flowerman.ToString(),
				new CatchableFlowerman()
			},
			{
				Utils.Enemy.HoarderBug.ToString(),
				new CatchableHoarderBug()
			},
			{
				Utils.Enemy.RedLocustBees.ToString(),
				new CatchableRedLocustBees()
			},
			{
				Utils.Enemy.Puffer.ToString(),
				new CatchableSporeLizard()
			},
			{
				Utils.Enemy.MouthDog.ToString(),
				new CatchableMouthDog()
			},
			{
				Utils.Enemy.FlowerSnake.ToString(),
				new CatchableTulipSnake()
			},
			{
				Utils.Enemy.DressGirl.ToString(),
				new CatchableGhostGirl()
			},
			{
				Utils.Enemy.Nutcracker.ToString(),
				new CatchableNutcracker()
			},
			{
				Utils.Enemy.Butler.ToString(),
				new CatchableButler()
			},
			{
				Utils.Enemy.BushWolf.ToString(),
				new CatchableKidnapperFox()
			},
			{
				Utils.Enemy.Crawler.ToString(),
				new CatchableCrawler()
			},
			{
				Utils.Enemy.MaskedPlayerEnemy.ToString(),
				new CatchableMasked()
			}
		};
	}
	public class LethalDex
	{
		private const string TopLeftJoint = "+";

		private const string TopRightJoint = "+";

		private const string BottomLeftJoint = "+";

		private const string BottomRightJoint = "+";

		private const string TopJoint = "+";

		private const string BottomJoint = "+";

		private const string LeftJoint = "+";

		private const string MiddleJoint = "+";

		private const string RightJoint = "+";

		private const char HorizontalLine = '-';

		private const string VerticalLine = "|";

		private static string _commandText = "Something went wrong :(";

		public static void Register()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: 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_002a: 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_0061: Expected O, but got Unknown
			_commandText = InitCommandText();
			TerminalApi.AddCommand("lethaldex", new CommandInfo
			{
				Title = "LethalDex",
				Category = "Other",
				Description = "Shows LethalMon's monsters details",
				DisplayTextSupplier = () => _commandText
			}, (string)null, true);
			LethalMon.Log("Registered LethalDex terminal command");
		}

		private static string InitCommandText()
		{
			string text = "Capture probabilities:\n\nPB = Pokeball, GB = Great ball, UB = Ultra ball, MB = Master ball\n";
			global::LethalMon.CatchableEnemy.CatchableEnemy[] array = Data.CatchableMonsters.Values.OrderBy((global::LethalMon.CatchableEnemy.CatchableEnemy enemy) => enemy.CatchDifficulty).ToArray();
			int num = array.Max((global::LethalMon.CatchableEnemy.CatchableEnemy enemy) => enemy.DisplayName.Length);
			string text2 = " PB ";
			string text3 = " GB ";
			string text4 = " UB ";
			string text5 = " MB ";
			text = text + "+" + new string('-', num + 2) + "+" + new string('-', text2.Length + 2) + "+" + new string('-', text3.Length + 2) + "+" + new string('-', text4.Length + 2) + "+" + new string('-', text5.Length + 2) + "+\n";
			text = text + "|" + new string(' ', num + 2) + "| " + text2 + " | " + text3 + " | " + text4 + " | " + text5 + " |\n";
			string text6 = "+" + new string('-', num + 2) + "+" + new string('-', text2.Length + 2) + "+" + new string('-', text3.Length + 2) + "+" + new string('-', text4.Length + 2) + "+" + new string('-', text5.Length + 2) + "+";
			foreach (global::LethalMon.CatchableEnemy.CatchableEnemy catchableEnemy in array)
			{
				text = text + text6 + "\n";
				string text7 = ((int)Mathf.Floor(catchableEnemy.GetCaptureProbability(0) * 100f)).ToString();
				string text8 = ((int)Mathf.Floor(catchableEnemy.GetCaptureProbability(1) * 100f)).ToString();
				string text9 = ((int)Mathf.Floor(catchableEnemy.GetCaptureProbability(2) * 100f)).ToString();
				string text10 = ((int)Mathf.Floor(catchableEnemy.GetCaptureProbability(3) * 100f)).ToString();
				text = text + "| " + catchableEnemy.DisplayName + new string(' ', num - catchableEnemy.DisplayName.Length) + " | " + new string(' ', Math.Clamp(3 - text7.Length, 0, 3)) + text7 + "% | " + new string(' ', Math.Clamp(3 - text8.Length, 0, 3)) + text8 + "% | " + new string(' ', Math.Clamp(3 - text9.Length, 0, 3)) + text9 + "% | " + new string(' ', Math.Clamp(3 - text10.Length, 0, 3)) + text10 + "% |\n";
			}
			return text + "+" + new string('-', num + 2) + "+" + new string('-', text2.Length + 2) + "+" + new string('-', text3.Length + 2) + "+" + new string('-', text4.Length + 2) + "+" + new string('-', text5.Length + 2) + "+\n\n";
		}
	}
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("LethalMon", "LethalMon", "1.0.0")]
	public class LethalMon : BaseUnityPlugin
	{
		public enum LogType
		{
			Message,
			Warning,
			Error,
			Fatal,
			Debug
		}

		internal static GameObject hudPrefab;

		internal static Dictionary<string, Sprite> monstersSprites = new Dictionary<string, Sprite>();

		public static LethalMon Instance { get; private set; } = null;


		internal static ManualLogSource Logger { get; private set; } = null;


		internal static Harmony? Harmony { get; set; }

		private void Awake()
		{
			Logger = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			ModConfig.Instance.Setup();
			LoadAssetBundle();
			NetcodePatching();
			ApplyHarmonyPatches();
			PlayerControllerBPatch.InitializeRPCS();
			Logger.LogInfo((object)"LethalMon v1.0.0 has loaded!");
		}

		private void NetcodePatching()
		{
			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);
					}
				}
			}
		}

		private void LoadAssetBundle()
		{
			AssetBundle assetBundle = AssetBundle.LoadFromFile(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "lethalmon"));
			Pokeball.Setup(assetBundle);
			Greatball.Setup(assetBundle);
			Ultraball.Setup(assetBundle);
			Masterball.Setup(assetBundle);
			Utils.LoadSeeThroughShader(assetBundle);
			Utils.LoadWireframeMaterial(assetBundle);
			MaskedTamedBehaviour.LoadGhostAudio(assetBundle);
			HoarderBugTamedBehaviour.LoadAudio(assetBundle);
			hudPrefab = assetBundle.LoadAsset<GameObject>("Assets/UI/MonsterInfo.prefab");
			monstersSprites = (from assetName in assetBundle.GetAllAssetNames()
				where assetName.StartsWith("assets/ui/monstersicons/") && assetName.EndsWith(".png")
				select assetName).ToDictionary((string assetName) => assetName.Substring("assets/ui/monstersicons/".Length, assetName.Length - "assets/ui/monstersicons/".Length - 4), (string assetName) => assetBundle.LoadAsset<Sprite>(assetName));
		}

		private void ApplyHarmonyPatches()
		{
			Harmony = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null);
			Harmony.PatchAll(typeof(DebugPatches));
			Harmony.PatchAll(typeof(ModConfig.SyncHandshake));
			Harmony.PatchAll(typeof(PlayerControllerBPatch));
			Harmony.PatchAll(typeof(StartOfRoundPatch));
			Harmony.PatchAll(typeof(RoundManagerPatch));
			Harmony.PatchAll(typeof(HUDManagerPatch));
			Harmony.PatchAll(typeof(EnemyAIPatch));
			Harmony.PatchAll(typeof(RedLocustBeesPatch));
			Harmony.PatchAll(typeof(MouthDogPatch));
			Harmony.PatchAll(typeof(FlowermanAIPatch));
			Harmony.PatchAll(typeof(BushWolfEnemyPatch));
			Harmony.PatchAll(typeof(MaskedPlayerEnemyPatch));
			Harmony.PatchAll(typeof(TamedEnemyBehaviour));
			Harmony.PatchAll(typeof(KidnapperFoxTamedBehaviour));
		}

		private static void Unpatch()
		{
			Logger.LogDebug((object)"Unpatching...");
			Harmony? harmony = Harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			Logger.LogDebug((object)"Finished unpatching!");
		}

		internal static void Log(string message, LogType type = LogType.Debug)
		{
			switch (type)
			{
			case LogType.Debug:
				break;
			case LogType.Warning:
				Logger.LogWarning((object)message);
				break;
			case LogType.Error:
				Logger.LogError((object)message);
				break;
			case LogType.Fatal:
				Logger.LogFatal((object)message);
				break;
			default:
				Logger.LogMessage((object)message);
				break;
			}
		}
	}
	public class Utils
	{
		public enum Enemy
		{
			BaboonHawk,
			Blob,
			BushWolf,
			Butler,
			ButlerBees,
			Centipede,
			ClaySurgeon,
			Crawler,
			DocileLocustBees,
			Doublewing,
			FlowerSnake,
			RedLocustBees,
			DressGirl,
			Flowerman,
			ForestGiant,
			HoarderBug,
			Jester,
			LassoMan,
			MaskedPlayerEnemy,
			MouthDog,
			Nutcracker,
			Puffer,
			RadMech,
			RedPillEnemyType,
			SandSpider,
			SandWorm,
			SpringMan
		}

		internal class LayerMasks
		{
			internal enum Mask
			{
				All = -1,
				Default,
				TransparentFX,
				Ignore_Raycast,
				Player,
				Water,
				UI,
				Props,
				HelmetVisor,
				Room,
				InteractableObject,
				Foliage,
				Colliders,
				PhysicsObject,
				Triggers,
				MapRadar,
				NavigationSurface,
				RoomLight,
				Anomaly,
				LineOfSight,
				Enemies,
				PlayerRagdoll,
				MapHazards,
				ScanNode,
				EnemiesNotRendered,
				MiscLevelGeometry,
				Terrain,
				PlaceableShipObjects,
				PlacementBlocker,
				Railing,
				DecalStickableSurface,
				CompanyCruiser
			}

			internal static int ToInt(Mask[] masks)
			{
				int num = 0;
				foreach (Mask mask in masks)
				{
					num |= 1 << (int)mask;
				}
				return num;
			}
		}

		public static readonly Random Random = new Random();

		private static Dictionary<string, TerminalNode> infoNodes = new Dictionary<string, TerminalNode>();

		public static readonly float DefaultJumpForce = 13f;

		private static Item? _giftBoxItem;

		public static Shader? SeeThroughShader;

		public static readonly Color EnemyHighlightOutline = Color.red;

		public static readonly Color EnemyHighlightInline = new Color(0.8f, 0f, 0f, 0.8f);

		public static readonly Color ItemHighlightOutline = Color.yellow;

		public static readonly Color ItemHighlightInline = new Color(0.8f, 0.8f, 0f, 0.5f);

		public static readonly Color PlayerHighlightOutline = Color.green;

		public static readonly Color PlayerHighlightInline = new Color(0f, 0.8f, 0f, 0.6f);

		public static Material? WireframeMaterial;

		private static readonly string GlassName = "LethalMonGlass";

		private static Material? _glassMaterial = null;

		private static Material? _ghostMaterial = null;

		private static Material? _ghostEyesMaterial = null;

		public static List<PlayerControllerB>? AllPlayers => StartOfRound.Instance?.allPlayerScripts?.Where((PlayerControllerB pcb) => (Object)(object)pcb != (Object)null && (pcb.isPlayerControlled || pcb.isPlayerDead)).ToList();

		public static List<PlayerControllerB>? AlivePlayers => AllPlayers?.Where((PlayerControllerB pcb) => !pcb.isPlayerDead).ToList();

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

		public static ulong? CurrentPlayerID => CurrentPlayer?.playerClientId;

		public static bool IsHost
		{
			get
			{
				if ((Object)(object)NetworkManager.Singleton != (Object)null)
				{
					if (!NetworkManager.Singleton.IsHost)
					{
						return NetworkManager.Singleton.IsServer;
					}
					return true;
				}
				if (CurrentPlayerID.HasValue)
				{
					return CurrentPlayerID.Value == 0;
				}
				return false;
			}
		}

		public static float DefaultPlayerSpeed
		{
			get
			{
				if (!CurrentPlayer.isSprinting)
				{
					return 1f;
				}
				return 2.25f;
			}
		}

		public static List<EnemyType> EnemyTypes => Resources.FindObjectsOfTypeAll<EnemyType>().ToList();

		public static Item? GiftBoxItem
		{
			get
			{
				if ((Object)(object)_giftBoxItem != (Object)null)
				{
					return _giftBoxItem;
				}
				_giftBoxItem = ((IEnumerable<Item>)Resources.FindObjectsOfTypeAll<Item>()).FirstOrDefault((Func<Item, bool>)((Item item) => item.itemName == "Gift"));
				return _giftBoxItem;
			}
		}

		public static Material Glass
		{
			get
			{
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0024: Expected O, but got Unknown
				//IL_003d: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)_glassMaterial == (Object)null)
				{
					_glassMaterial = new Material(Shader.Find("HDRP/Lit"));
					_glassMaterial.color = new Color(0.5f, 0.5f, 0.6f, 0.6f);
					_glassMaterial.renderQueue = 3300;
					_glassMaterial.shaderKeywords = new string[5] { "_SURFACE_TYPE_TRANSPARENT", "_DISABLE_SSR_TRANSPARENT", "_REFRACTION_THIN", "_NORMALMAP_TANGENT_SPACE", "_ENABLE_FOG_ON_TRANSPARENT" };
					((Object)_glassMaterial).name = GlassName;
				}
				return _glassMaterial;
			}
		}

		internal static Material GhostMaterial
		{
			get
			{
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_001c: Expected O, but got Unknown
				//IL_003a: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)_ghostMaterial == (Object)null)
				{
					_ghostMaterial = new Material(WireframeMaterial);
					_ghostMaterial.SetColor("_EdgeColor", new Color(0.8f, 0.9f, 1f, 0.15f));
					_ghostMaterial.SetFloat("_WireframeVal", 1f);
					_ghostMaterial.SetFloat("_MaxVisibilityDistance", 15f);
				}
				return _ghostMaterial;
			}
		}

		internal static Material GhostEyesMaterial
		{
			get
			{
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_0021: Expected O, but got Unknown
				//IL_0035: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)_ghostEyesMaterial == (Object)null)
				{
					_ghostEyesMaterial = new Material(Shader.Find("HDRP/Unlit"));
					_ghostEyesMaterial.color = new Color(0.8f, 0.9f, 1f);
				}
				return _ghostEyesMaterial;
			}
		}

		public static void CallNextFrame(Action action)
		{
			((MonoBehaviour)GameNetworkManager.Instance).StartCoroutine(CallNextFrameCoroutine(action));
		}

		public static IEnumerator CallNextFrameCoroutine(Action action)
		{
			yield return null;
			action();
		}

		public static TamedEnemyBehaviour? GetPlayerPet(PlayerControllerB player)
		{
			PlayerControllerB player2 = player;
			return Object.FindObjectsOfType<TamedEnemyBehaviour>().FirstOrDefault((TamedEnemyBehaviour tamedBehaviour) => (Object)(object)tamedBehaviour.ownerPlayer == (Object)(object)player2);
		}

		public static Vector3 GetPositionInFrontOfPlayerEyes(PlayerControllerB player)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			return player.playerEye.position + player.playerEye.forward * 2.5f;
		}

		public static Vector3 GetPositionBehindPlayer(PlayerControllerB player)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			return ((Component)player).transform.position + ((Component)player).transform.forward * -2f;
		}

		public static EnemyAI? GetMostProbableAttackerEnemy(PlayerControllerB player, StackTrace stackTrace)
		{
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			StackFrame[] frames = stackTrace.GetFrames();
			StackFrame[] subArray = frames[1..];
			foreach (StackFrame stackFrame in subArray)
			{
				Type declaringType = stackFrame.GetMethod().DeclaringType;
				LethalMon.Log("Stackframe type: " + declaringType);
				if (!declaringType.IsSubclassOf(typeof(EnemyAI)))
				{
					continue;
				}
				LethalMon.Log("Class is assignable from EnemyAI");
				EnemyAI val = null;
				float? num = float.MaxValue;
				Collider[] array = Physics.OverlapSphere(((Component)player).transform.position, 10f);
				Collider[] array2 = array;
				foreach (Collider val2 in array2)
				{
					EnemyAI componentInParent = ((Component)val2).GetComponentInParent<EnemyAI>();
					if ((Object)(object)componentInParent != (Object)null && ((object)componentInParent).GetType() == declaringType)
					{
						float num2 = Vector3.Distance(((Component)player).transform.position, ((Component)componentInParent).transform.position);
						if (num > num2)
						{
							val = componentInParent;
							num = num2;
						}
					}
				}
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		public static TerminalNode CreateTerminalNode(string name, string description)
		{
			if (infoNodes.TryGetValue(name, out TerminalNode value))
			{
				return value;
			}
			TerminalNode val = ScriptableObject.CreateInstance<TerminalNode>();
			Object.DontDestroyOnLoad((Object)(object)val);
			val.clearPreviousText = true;
			((Object)val).name = name + "InfoNode";
			val.displayText = description + "\n\n";
			infoNodes.Add(name, val);
			return val;
		}

		public static Vector3 GetRandomNavMeshPositionOnRadius(Vector3 pos, float radius, NavMeshHit navHit = default(NavMeshHit))
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: 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_0036: 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)
			float y = pos.y;
			pos = Random.onUnitSphere * radius + pos;
			pos.y = y;
			if (NavMesh.SamplePosition(pos, ref navHit, radius, -1))
			{
				return ((NavMeshHit)(ref navHit)).position;
			}
			return pos;
		}

		public static void PlaySoundAtPosition(Vector3 position, AudioClip clip, float volume = 1f)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			AudioSource val = (SoundManager.Instance.tempAudio1.isPlaying ? SoundManager.Instance.tempAudio2 : SoundManager.Instance.tempAudio1);
			((Component)val).transform.position = position;
			val.PlayOneShot(clip, volume);
		}

		public static void PlaySoundAtPosition(Vector3 position, AudioClip clip)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			((Component)SoundManager.Instance.tempAudio1).transform.position = position;
			SoundManager.Instance.tempAudio1.PlayOneShot(clip);
		}

		public static void EnableShotgunHeldByEnemyAi(EnemyAI enemyAI, bool enable)
		{
			ShotgunItem[] array = Object.FindObjectsOfType<ShotgunItem>();
			ShotgunItem[] array2 = array;
			foreach (ShotgunItem val in array2)
			{
				if ((Object)(object)val.heldByEnemy == (Object)(object)enemyAI)
				{
					((GrabbableObject)val).EnableItemMeshes(enable);
				}
			}
		}

		public static void DestroyShotgunHeldByEnemyAi(EnemyAI enemyAI)
		{
			ShotgunItem[] array = Object.FindObjectsOfType<ShotgunItem>();
			ShotgunItem[] array2 = array;
			foreach (ShotgunItem val in array2)
			{
				if ((Object)(object)val.heldByEnemy == (Object)(object)enemyAI)
				{
					((Component)val).GetComponent<NetworkObject>().Despawn(true);
				}
			}
		}

		public static void OpenDoorsAsEnemyAroundPosition(Vector3 position)
		{
			//IL_0000: 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)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			Collider[] array = Physics.OverlapSphere(position, 0.5f);
			Collider[] array2 = array;
			AnimatedObjectTrigger val3 = default(AnimatedObjectTrigger);
			foreach (Collider val in array2)
			{
				DoorLock componentInParent = ((Component)val).GetComponentInParent<DoorLock>();
				if ((Object)(object)componentInParent != (Object)null && !componentInParent.isDoorOpened && !componentInParent.isLocked)
				{
					Vector3 val2 = position;
					LethalMon.Log("Door opened at " + ((object)(Vector3)(ref val2)).ToString());
					if (((Component)componentInParent).gameObject.TryGetComponent<AnimatedObjectTrigger>(ref val3))
					{
						val3.TriggerAnimationNonPlayer(false, true, false);
					}
					componentInParent.OpenDoorAsEnemyServerRpc();
				}
			}
		}

		public static bool TryGetRealEnemyBounds(EnemyAI enemy, out Bounds bounds)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: 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)
			bounds = default(Bounds);
			if ((Object)(object)enemy == (Object)null)
			{
				return false;
			}
			Renderer[] componentsInChildren = ((Component)enemy).gameObject.GetComponentsInChildren<Renderer>();
			if (componentsInChildren == null)
			{
				return false;
			}
			bounds = componentsInChildren[0].bounds;
			for (int i = 1; i < componentsInChildren.Length; i++)
			{
				((Bounds)(ref bounds)).Encapsulate(componentsInChildren[i].bounds);
			}
			return true;
		}

		private static GameObject? TrySpawnItemAtPosition(SpawnableItemWithRarity spawnableItemWithRarity, Vector3 position)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			if (!IsHost)
			{
				LethalMon.Log("TrySpawnItemAtPosition: Not a valid item or not the host.");
				return null;
			}
			LethalMon.Log("Instantiating item " + ((Object)spawnableItemWithRarity.spawnableItem).name);
			GameObject val = Object.Instantiate<GameObject>(spawnableItemWithRarity.spawnableItem.spawnPrefab, position, Quaternion.identity, StartOfRound.Instance.elevatorTransform);
			NetworkObject component = val.GetComponent<NetworkObject>();
			if (component != null)
			{
				component.Spawn(false);
			}
			return val;
		}

		public static GameObject? TrySpawnRandomItemAtPosition(Vector3 position, out SpawnableItemWithRarity spawnableItemWithRarity)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			LethalMon.Log("Spawnable items: " + RoundManager.Instance.currentLevel.spawnableScrap.Count);
			spawnableItemWithRarity = RoundManager.Instance.currentLevel.spawnableScrap[Random.RandomRangeInt(0, RoundManager.Instance.currentLevel.spawnableScrap.Count)];
			return TrySpawnItemAtPosition(spawnableItemWithRarity, position);
		}

		public static void SpawnPoofCloudAt(Vector3 position)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			Item giftBoxItem = GiftBoxItem;
			if ((Object)(object)giftBoxItem != (Object)null && (Object)(object)giftBoxItem.spawnPrefab != (Object)null)
			{
				GiftBoxItem component = giftBoxItem.spawnPrefab.GetComponent<GiftBoxItem>();
				ParticleSystem val = Object.Instantiate<ParticleSystem>(component.PoofParticle);
				((Component)val).transform.position = position;
				val.Play();
			}
		}

		public static List<Renderer> GetRenderers(GameObject? g)
		{
			List<Renderer> list = new List<Renderer>();
			if ((Object)(object)g != (Object)null)
			{
				Renderer[] componentsInChildren = g.GetComponentsInChildren<Renderer>();
				foreach (Renderer item in componentsInChildren)
				{
					list.Add(item);
				}
			}
			return list;
		}

		public static void ReplaceAllMaterialsWith(GameObject g, Func<Material, Material> materialReplacer)
		{
			List<Renderer> renderers = GetRenderers(g);
			foreach (Renderer item in renderers)
			{
				ReplaceAllMaterialsWith(item, materialReplacer);
			}
		}

		public static Material[] ReplaceAllMaterialsWith(Renderer mr, Func<Material, Material> materialReplacer)
		{
			List<Material> list = new List<Material>();
			Material[] materials = mr.materials;
			foreach (Material arg in materials)
			{
				list.Add(materialReplacer(arg));
			}
			Material[] materials2 = mr.materials;
			mr.materials = list.ToArray();
			return materials2;
		}

		public static void LoadSeeThroughShader(AssetBundle assetBundle)
		{
			SeeThroughShader = assetBundle.LoadAsset<Shader>("Assets/SeeThrough/SeeThroughStencil.shader");
			if ((Object)(object)SeeThroughShader == (Object)null)
			{
				LethalMon.Log("Unable to load seethrough shader!", LethalMon.LogType.Error);
			}
		}

		public static void LoadWireframeMaterial(AssetBundle assetBundle)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			Shader val = assetBundle.LoadAsset<Shader>("Assets/SeeThrough/wireframe.shader");
			if ((Object)(object)val == (Object)null)
			{
				LethalMon.Log("Unable to load wireframe shader!", LethalMon.LogType.Error);
			}
			else
			{
				WireframeMaterial = new Material(val);
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "LethalMon";

		public const string PLUGIN_NAME = "LethalMon";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace LethalMon.Throw
{
	public class FallCurve
	{
		internal static readonly Keyframe[] fallCurveKeyframes = (Keyframe[])(object)new Keyframe[2]
		{
			new Keyframe(0f, 0f, 2f, 2f),
			new Keyframe(1f, 1f, 0f, 0f)
		};

		internal static readonly Keyframe[] verticalFallCurveKeyframes = (Keyframe[])(object)new Keyframe[5]
		{
			new Keyframe(0f, 0f, 0.116908506f, 0.116908506f, 0f, 0.27230743f),
			new Keyframe(0.49081117f, 1f, 4.1146584f, -1.81379f, 0.07234045f, 0.28319725f),
			new Keyframe(0.7587703f, 1f, 1.4123471f, -1.3678839f, 0.31997186f, 0.56917864f),
			new Keyframe(0.9393898f, 1f, 0.82654804f, -0.029021755f, 0.53747445f, 1f),
			new Keyframe(1f, 1f)
		};

		internal static readonly Keyframe[] verticalFallCurveNoBounceKeyFrames = (Keyframe[])(object)new Keyframe[4]
		{
			new Keyframe(0f, 0f, 0.116908506f, 0.116908506f, 0f, 0.27230743f),
			new Keyframe(0.69081116f, 1f, 0.1146584f, 0.06098772f, 0.07234045f, 0.20768756f),
			new Keyframe(0.9393898f, 1f, 0.06394797f, -0.029021755f, 0.1980713f, 1f),
			new Keyframe(1f, 1f)
		};

		internal static readonly AnimationCurve fallCurve = new AnimationCurve(fallCurveKeyframes);

		internal static readonly AnimationCurve verticalFallCurve = new AnimationCurve(verticalFallCurveKeyframes);

		internal static readonly AnimationCurve verticalFallCurveNoBounce = new AnimationCurve(verticalFallCurveNoBounceKeyFrames);
	}
	public abstract class ThrowableItem : GrabbableObject
	{
		public AnimationCurve itemFallCurve;

		public AnimationCurve itemVerticalFallCurve;

		public AnimationCurve itemVerticalFallCurveNoBounce;

		public RaycastHit itemHit;

		public Ray itemThrowRay;

		public PlayerControllerB playerThrownBy;

		public PlayerControllerB lastThrower;

		[ServerRpc(RequireOwnership = false)]
		public void ThrowServerRpc(NetworkObjectReference playerThrownByReference)
		{
			//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)
			//IL_00d7: 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(2923164452u, val, (RpcDelivery)0);
					((FastBufferWriter)(ref val2)).WriteValueSafe<NetworkObjectReference>(ref playerThrownByReference, default(ForNetworkSerializable));
					((NetworkBehaviour)this).__endSendServerRpc(ref val2, 2923164452u, val, (RpcDelivery)0);
				}
				if ((int)((NetworkBehaviour)this).__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost))
				{
					ThrowClientRpc(playerThrownByReference);
				}
			}
		}

		[ClientRpc]
		public void ThrowClientRpc(NetworkObjectReference playerThrownByReference)
		{
			//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(3841692620u, val, (RpcDelivery)0);
				((FastBufferWriter)(ref val2)).WriteValueSafe<NetworkObjectReference>(ref playerThrownByReference, default(ForNetworkSerializable));
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 3841692620u, val, (RpcDelivery)0);
			}
			if ((int)((NetworkBehaviour)this).__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost))
			{
				LethalMon.Log("SendThrowRpc server rpc received");
				NetworkObject val3 = default(NetworkObject);
				PlayerControllerB val4 = default(PlayerControllerB);
				if (!((NetworkObjectReference)(ref playerThrownByReference)).TryGet(ref val3, (NetworkManager)null))
				{
					LethalMon.Log(((Object)((Component)this).gameObject).name + ": Failed to get player component (SendThrowRpc)", LethalMon.LogType.Error);
				}
				else if (((Component)val3).TryGetComponent<PlayerControllerB>(ref val4))
				{
					playerThrownBy = val4;
					lastThrower = playerThrownBy;
				}
			}
		}

		public override void ItemActivate(bool used, bool buttonDown = true)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			((GrabbableObject)this).ItemActivate(used, buttonDown);
			if (((NetworkBehaviour)this).IsOwner)
			{
				playerThrownBy = base.playerHeldBy;
				lastThrower = playerThrownBy;
				base.playerHeldBy.DiscardHeldObject(true, (NetworkObject)null, GetItemThrowDestination(), true);
				ThrowServerRpc(NetworkObjectReference.op_Implicit(((Component)playerThrownBy).GetComponent<NetworkObject>()));
			}
		}

		public override void EquipItem()
		{
			((GrabbableObject)this).EnableItemMeshes(true);
			base.isPocketed = false;
		}

		public abstract void TouchGround();

		public override void FallWithCurve()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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_007e: 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_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: 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_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = base.startFallingPosition - base.targetFloorPosition;
			float magnitude = ((Vector3)(ref val)).magnitude;
			((Component)this).transform.rotation = Quaternion.Lerp(((Component)this).transform.rotation, Quaternion.Euler(base.itemProperties.restingRotation.x, ((Component)this).transform.eulerAngles.y, base.itemProperties.restingRotation.z), 14f * Time.deltaTime / magnitude);
			((Component)this).transform.localPosition = Vector3.Lerp(base.startFallingPosition, base.targetFloorPosition, FallCurve.fallCurve.Evaluate(base.fallTime));
			if (magnitude > 5f)
			{
				((Component)this).transform.localPosition = Vector3.Lerp(new Vector3(((Component)this).transform.localPosition.x, base.startFallingPosition.y, ((Component)this).transform.localPosition.z), new Vector3(((Component)this).transform.localPosition.x, base.targetFloorPosition.y, ((Component)this).transform.localPosition.z), FallCurve.verticalFallCurveNoBounce.Evaluate(base.fallTime));
			}
			else
			{
				((Component)this).transform.localPosition = Vector3.Lerp(new Vector3(((Component)this).transform.localPosition.x, base.startFallingPosition.y, ((Component)this).transform.localPosition.z), new Vector3(((Component)this).transform.localPosition.x, base.targetFloorPosition.y, ((Component)this).transform.localPosition.z), FallCurve.verticalFallCurve.Evaluate(base.fallTime));
			}
			base.fallTime += Mathf.Abs(Time.deltaTime * 12f / magnitude);
			if (base.fallTime > 1f)
			{
				TouchGround();
				playerThrownBy = null;
			}
		}

		public override void Update()
		{
			((GrabbableObject)this).Update();
		}

		public Vector3 GetItemThrowDestination()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: 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_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = ((Component)this).transform.position;
			itemThrowRay = new Ray(((Component)base.playerHeldBy.gameplayCamera).transform.position, ((Component)base.playerHeldBy.gameplayCamera).transform.forward);
			position = ((!Physics.Raycast(itemThrowRay, ref itemHit, 12f, 268437761, (QueryTriggerInteraction)1)) ? ((Ray)(ref itemThrowRay)).GetPoint(10f) : ((Ray)(ref itemThrowRay)).GetPoint(((RaycastHit)(ref itemHit)).distance - 0.05f));
			itemThrowRay = new Ray(position, Vector3.down);
			if (Physics.Raycast(itemThrowRay, ref itemHit, 30f, 268437761, (QueryTriggerInteraction)1))
			{
				return ((RaycastHit)(ref itemHit)).point + Vector3.up * (base.itemProperties.verticalOffset + 0.05f);
			}
			return ((Ray)(ref itemThrowRay)).GetPoint(30f);
		}

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

		[RuntimeInitializeOnLoadMethod]
		internal static void InitializeRPCS_ThrowableItem()
		{
			//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
			NetworkManager.__rpc_func_table.Add(2923164452u, new RpcReceiveHandler(__rpc_handler_2923164452));
			NetworkManager.__rpc_func_table.Add(3841692620u, new RpcReceiveHandler(__rpc_handler_3841692620));
		}

		private static void __rpc_handler_2923164452(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_004f: 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)
			{
				NetworkObjectReference playerThrownByReference = default(NetworkObjectReference);
				((FastBufferReader)(ref reader)).ReadValueSafe<NetworkObjectReference>(ref playerThrownByReference, default(ForNetworkSerializable));
				target.__rpc_exec_stage = (__RpcExecStage)1;
				((ThrowableItem)(object)target).ThrowServerRpc(playerThrownByReference);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_3841692620(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_004f: 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)
			{
				NetworkObjectReference playerThrownByReference = default(NetworkObjectReference);
				((FastBufferReader)(ref reader)).ReadValueSafe<NetworkObjectReference>(ref playerThrownByReference, default(ForNetworkSerializable));
				target.__rpc_exec_stage = (__RpcExecStage)2;
				((ThrowableItem)(object)target).ThrowClientRpc(playerThrownByReference);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		protected internal override string __getTypeName()
		{
			return "ThrowableItem";
		}
	}
}
namespace LethalMon.Patches
{
	public class BushWolfEnemyPatch
	{
		[HarmonyPatch(typeof(BushWolfEnemy), "Start")]
		[HarmonyPostfix]
		public static void OnStartPostfix(BushWolfEnemy __instance)
		{
			KidnapperFoxTamedBehaviour component = ((Component)__instance).GetComponent<KidnapperFoxTamedBehaviour>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.ownerPlayer != (Object)null)
			{
				((EnemyAI)__instance).inSpecialAnimation = false;
				((EnemyAI)__instance).EnableEnemyMesh(true, false);
				((Behaviour)((EnemyAI)__instance).agent).enabled = true;
				((EnemyAI)__instance).agent.speed = 5f;
			}
		}
	}
	[HarmonyPatch]
	internal class DebugPatches : NetworkBehaviour
	{
		protected override void __initializeVariables()
		{
			((NetworkBehaviour)this).__initializeVariables();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		protected internal override string __getTypeName()
		{
			return "DebugPatches";
		}
	}
	public class EnemyAIPatch
	{
		[HarmonyPatch(typeof(EnemyAI), "OnDestroy")]
		[HarmonyPrefix]
		private static void OnDestroyPreFix(EnemyAI __instance)
		{
			TamedEnemyBehaviour component = ((Component)__instance).GetComponent<TamedEnemyBehaviour>();
			if ((Object)(object)component != (Object)null)
			{
				LethalMon.Log("Destroying TamedEnemyBehaviour component");
				Object.Destroy((Object)(object)component);
			}
			else
			{
				LethalMon.Log("No TamedEnemyBehaviour component found before EnemyAI OnDestroy", LethalMon.LogType.Warning);
			}
		}

		[HarmonyPatch(typeof(EnemyAI), "SwitchToBehaviourStateOnLocalClient")]
		[HarmonyPrefix]
		private static void SwitchToBehaviourStateOnLocalClientPrefix(EnemyAI __instance)
		{
			TamedEnemyBehaviour component = ((Component)__instance).GetComponent<TamedEnemyBehaviour>();
			if ((Object)(object)component != (Object)null && __instance.currentBehaviourStateIndex > component.LastDefaultBehaviourIndex)
			{
				if (__instance.currentBehaviourStateIndex <= component.LastDefaultBehaviourIndex + TamedEnemyBehaviour.TamedBehaviourCount)
				{
					component.LeaveTamingBehaviour((TamedEnemyBehaviour.TamingBehaviour)(__instance.currentBehaviourStateIndex - component.LastDefaultBehaviourIndex));
				}
				else
				{
					component.LeaveCustomBehaviour(__instance.currentBehaviourStateIndex - TamedEnemyBehaviour.TamedBehaviourCount - component.LastDefaultBehaviourIndex);
				}
			}
		}

		[HarmonyPatch(typeof(EnemyAI), "SwitchToBehaviourStateOnLocalClient")]
		[HarmonyPostfix]
		private static void SwitchToBehaviourStateOnLocalClientPostfix(EnemyAI __instance, int stateIndex)
		{
			TamedEnemyBehaviour component = ((Component)__instance).GetComponent<TamedEnemyBehaviour>();
			if ((Object)(object)component != (Object)null)
			{
				if (stateIndex > component.LastDefaultBehaviourIndex)
				{
					if (stateIndex <= component.LastDefaultBehaviourIndex + TamedEnemyBehaviour.TamedBehaviourCount)
					{
						component.InitTamingBehaviour((TamedEnemyBehaviour.TamingBehaviour)(stateIndex - component.LastDefaultBehaviourIndex));
					}
					else
					{
						component.InitCustomBehaviour(stateIndex - TamedEnemyBehaviour.TamedBehaviourCount - component.LastDefaultBehaviourIndex);
					}
				}
				if ((Object)(object)component.ownerPlayer == (Object)(object)Utils.CurrentPlayer)
				{
					HUDManagerPatch.UpdateTamedMonsterAction(component.GetCurrentStateDescription());
				}
			}
			else
			{
				LethalMon.Log("No TamedEnemyBehaviour component found after EnemyAI SwitchToBehaviourStateOnLocalClient", LethalMon.LogType.Warning);
			}
		}

		[HarmonyPatch(typeof(EnemyAI), "HitEnemy")]
		[HarmonyPrefix]
		private static bool HitEnemyPrefix(EnemyAI __instance, int force = -1, PlayerControllerB playerWhoHit = null, bool playHitSFX = false, int hitID = -1)
		{
			TamedEnemyBehaviour component = ((Component)__instance).GetComponent<TamedEnemyBehaviour>();
			if (!((Object)(object)component == (Object)null))
			{
				return (Object)(object)component.ownerPlayer == (Object)null;
			}
			return true;
		}

		[HarmonyPatch(typeof(EnemyAI), "KillEnemy")]
		[HarmonyPrefix]
		private static bool KillEnemyPrefix(EnemyAI __instance, bool destroy = false)
		{
			TamedEnemyBehaviour component = ((Component)__instance).GetComponent<TamedEnemyBehaviour>();
			if (!((Object)(object)component == (Object)null))
			{
				return (Object)(object)component.ownerPlayer == (Object)null;
			}
			return true;
		}

		[HarmonyPatch(typeof(EnemyAI), "KillEnemyClientRpc")]
		[HarmonyPrefix]
		private static bool KillEnemyClientRpcPrefix(EnemyAI __instance, bool destroy)
		{
			TamedEnemyBehaviour component = ((Component)__instance).GetComponent<TamedEnemyBehaviour>();
			if (!((Object)(object)component == (Object)null))
			{
				return (Object)(object)component.ownerPlayer == (Object)null;
			}
			return true;
		}

		[HarmonyPatch(typeof(EnemyAI), "KillEnemyServerRpc")]
		[HarmonyPrefix]
		private static bool KillEnemyServerRpcPrefix(EnemyAI __instance, bool destroy)
		{
			TamedEnemyBehaviour component = ((Component)__instance).GetComponent<TamedEnemyBehaviour>();
			if (!((Object)(object)component == (Object)null))
			{
				return (Object)(object)component.ownerPlayer == (Object)null;
			}
			return true;
		}

		[HarmonyPatch(typeof(EnemyAI), "KillEnemyOnOwnerClient")]
		[HarmonyPrefix]
		private static bool KillEnemyOnOwnerClientPrefix(EnemyAI __instance, bool overrideDestroy = false)
		{
			TamedEnemyBehaviour component = ((Component)__instance).GetComponent<TamedEnemyBehaviour>();
			if (!((Object)(object)component == (Object)null))
			{
				return (Object)(object)component.ownerPlayer == (Object)null;
			}
			return true;
		}
	}
	public class FlowermanAIPatch
	{
		[HarmonyPatch(typeof(FlowermanAI), "HitEnemy")]
		[HarmonyPrefix]
		private static bool HitEnemyPrefix(FlowermanAI __instance, int force = -1, PlayerControllerB playerWhoHit = null, bool playHitSFX = false, int hitID = -1)
		{
			TamedEnemyBehaviour component = ((Component)__instance).GetComponent<TamedEnemyBehaviour>();
			if (!((Object)(object)component == (Object)null))
			{
				return (Object)(object)component.ownerPlayer == (Object)null;
			}
			return true;
		}
	}
	public class HUDManagerPatch
	{
		private static HUDElement monsterHudElement;

		private static Image monsterIcon;

		private static TextMeshProUGUI monsterName;

		private static TextMeshProUGUI pressKeyTip;

		private static TextMeshProUGUI monsterAction;

		private static Image cooldownCircle1;

		private static TextMeshProUGUI cooldownTime1;

		private static TextMeshProUGUI cooldownName1;

		private static Image cooldownCircle2;

		private static TextMeshProUGUI cooldownTime2;

		private static TextMeshProUGUI cooldownName2;

		public static void UpdatePressKeyTip()
		{
			if ((Object)(object)pressKeyTip != (Object)null)
			{
				((TMP_Text)pressKeyTip).text = "[" + InputActionRebindingExtensions.GetBindingDisplayString(ModConfig.Instance.RetrieveBallKey, (DisplayStringOptions)0, (string)null) + "]\nto retrieve";
			}
		}

		public static void ChangeToTamedBehaviour(TamedEnemyBehaviour behaviour)
		{
			string name = ((Object)behaviour.Enemy.enemyType).name;
			monsterIcon.sprite = (Sprite)(LethalMon.monstersSprites.TryGetValue(name.ToLower(), out Sprite value) ? ((object)value) : ((object)LethalMon.monstersSprites["unknown"]));
			((TMP_Text)monsterName).text = Data.CatchableMonsters[name].DisplayName;
			CooldownNetworkBehaviour[] components = ((Component)behaviour).GetComponents<CooldownNetworkBehaviour>();
			if (components.Length >= 1)
			{
				((Component)cooldownCircle1).gameObject.SetActive(true);
				((Component)cooldownTime1).gameObject.SetActive(true);
				((Component)cooldownName1).gameObject.SetActive(true);
				components[0].BindToHUD(cooldownCircle1, cooldownTime1, cooldownName1);
			}
			else
			{
				((Component)cooldownCircle1).gameObject.SetActive(false);
				((Component)cooldownTime1).gameObject.SetActive(false);
				((Component)cooldownName1).gameObject.SetActive(false);
			}
			if (components.Length >= 2)
			{
				((Component)cooldownCircle2).gameObject.SetActive(true);
				((Component)cooldownTime2).gameObject.SetActive(true);
				((Component)cooldownName2).gameObject.SetActive(true);
				components[1].BindToHUD(cooldownCircle2, cooldownTime2, cooldownName2);
			}
			else
			{
				((Component)cooldownCircle2).gameObject.SetActive(false);
				((Component)cooldownTime2).gameObject.SetActive(false);
				((Component)cooldownName2).gameObject.SetActive(false);
			}
		}

		public static void EnableHUD(bool enable)
		{
			((Component)monsterHudElement.canvasGroup).gameObject.SetActive(enable);
		}

		public static void UpdateTamedMonsterAction(string action)
		{
			((TMP_Text)monsterAction).text = action;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(HUDManager), "Awake")]
		private static void AwakePostfix(HUDManager __instance)
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Expected O, but got Unknown
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0301: Unknown result type (might be due to invalid IL or missing references)
			//IL_030f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0314: Unknown result type (might be due to invalid IL or missing references)
			FieldInfo field = typeof(HUDManager).GetField("HUDElements", BindingFlags.Instance | BindingFlags.NonPublic);
			if (field == null)
			{
				LethalMon.Log("Unable to instantiate HUD, HUDElements array not found", LethalMon.LogType.Error);
				return;
			}
			HUDElement[] array = (HUDElement[])field.GetValue(__instance);
			if (array.Length == 0)
			{
				LethalMon.Log("NO HUD element found (probably because of another mod), cannot instantiate LethalMon HUD", LethalMon.LogType.Error);
				return;
			}
			HUDElement val = ((IEnumerable<HUDElement>)array).FirstOrDefault((Func<HUDElement, bool>)((HUDElement e) => ((Component)e.canvasGroup).GetComponents<Component>().Any((Component c) => ((Object)c).name == "TopRightCorner")));
			if (val == null)
			{
				LethalMon.Log("Top left corner HUDElement not found, cannot instantiate LethalMon HUD", LethalMon.LogType.Error);
				return;
			}
			GameObject val2 = Object.Instantiate<GameObject>(LethalMon.hudPrefab, ((Component)val.canvasGroup).transform.parent);
			monsterHudElement = new HUDElement
			{
				canvasGroup = val2.GetComponent<CanvasGroup>(),
				targetAlpha = val.targetAlpha,
				fadeCoroutine = val.fadeCoroutine
			};
			Component[] componentsInChildren = val2.GetComponentsInChildren<Component>();
			monsterIcon = componentsInChildren.First((Component c) => ((Object)c).name == "Icon").GetComponent<Image>();
			monsterName = componentsInChildren.First((Component c) => ((Object)c).name == "Name").GetComponent<TextMeshProUGUI>();
			pressKeyTip = componentsInChildren.First((Component c) => ((Object)c).name == "PressKeyTip").GetComponent<TextMeshProUGUI>();
			monsterAction = componentsInChildren.First((Component c) => ((Object)c).name == "Action").GetComponent<TextMeshProUGUI>();
			cooldownCircle1 = componentsInChildren.First((Component c) => ((Object)c).name == "CooldownCircle1").GetComponent<Image>();
			cooldownName1 = componentsInChildren.First((Component c) => ((Object)c).name == "CooldownName1").GetComponent<TextMeshProUGUI>();
			cooldownTime1 = componentsInChildren.First((Component c) => ((Object)c).name == "CooldownTime1").GetComponent<TextMeshProUGUI>();
			cooldownCircle2 = componentsInChildren.First((Component c) => ((Object)c).name == "CooldownCircle2").GetComponent<Image>();
			cooldownName2 = componentsInChildren.First((Component c) => ((Object)c).name == "CooldownName2").GetComponent<TextMeshProUGUI>();
			cooldownTime2 = componentsInChildren.First((Component c) => ((Object)c).name == "CooldownTime2").GetComponent<TextMeshProUGUI>();
			UpdatePressKeyTip();
			EnableHUD(enable: false);
			field.SetValue(__instance, new List<HUDElement>(array) { monsterHudElement }.ToArray());
			Transform transform = ((Component)val.canvasGroup).transform;
			Vector3 localPosition = transform.localPosition;
			Rect rect = ((Component)monsterHudElement.canvasGroup).GetComponent<RectTransform>().rect;
			transform.localPosition = localPosition - new Vector3(0f, ((Rect)(ref rect)).height, 0f);
			LethalMon.Log("HUD initialized");
		}
	}
	internal class MaskedPlayerEnemyPatch
	{
		internal static Dictionary<int, int> lastColliderIDs = new Dictionary<int, int>();

		[HarmonyPrefix]
		[HarmonyPatch(typeof(MaskedPlayerEnemy), "OnCollideWithPlayer")]
		public static void OnCollideWithPlayerPrefix(MaskedPlayerEnemy __instance, Collider other)
		{
			if (lastColliderIDs.GetValueOrDefault(((Object)__instance).GetInstanceID(), -1) == ((Object)other).GetInstanceID())
			{
				return;
			}
			lastColliderIDs[((Object)__instance).GetInstanceID()] = ((Object)other).GetInstanceID();
			PlayerControllerB component = ((Component)other).gameObject.GetComponent<PlayerControllerB>();
			MaskedTamedBehaviour maskedTamedBehaviour = default(MaskedTamedBehaviour);
			if ((Object)(object)component == (Object)null || !((Component)__instance).TryGetComponent<MaskedTamedBehaviour>(ref maskedTamedBehaviour) || (Object)(object)maskedTamedBehaviour.targetPlayer == (Object)null)
			{
				return;
			}
			if (maskedTamedBehaviour.CurrentCustomBehaviour.GetValueOrDefault(-1) == 2)
			{
				LethalMon.Log("Ghost hitting player " + component.playerClientId);
				maskedTamedBehaviour.Masked.startingKillAnimationLocalClient = true;
				maskedTamedBehaviour.GhostHitPlayerServerRpc(component.playerClientId);
			}
			else if (maskedTamedBehaviour.escapeFromBallEventRunning && (Object)(object)component == (Object)(object)maskedTamedBehaviour.targetPlayer)
			{
				LethalMon.Log("Player " + component.playerClientId + " ran into the masked that does the escape event.");
				maskedTamedBehaviour.CleanUp();
				maskedTamedBehaviour.Masked.maskEyesGlowLight.intensity = 0.6f;
				if ((Object)(object)((EnemyAI)maskedTamedBehaviour.Masked).agent != (Object)null)
				{
					((Behaviour)((EnemyAI)maskedTamedBehaviour.Masked).agent).enabled = true;
				}
				((Behaviour)maskedTamedBehaviour.Masked).enabled = true;
				maskedTamedBehaviour.EscapeFromBallEventEndedServerRpc();
				if (Time.realtimeSinceStartup - maskedTamedBehaviour.Masked.timeAtLastUsingEntrance < 1.75f)
				{
					maskedTamedBehaviour.Masked.timeAtLastUsingEntrance = Time.realtimeSinceStartup - 2f;
				}
			}
		}
	}
	public class MouthDogPatch
	{
		[HarmonyPatch(typeof(MouthDogAI), "ReactToOtherDogHowl")]
		[HarmonyPrefix]
		private static bool ReactToOtherDogHowlPreFix(MouthDogAI __instance, Vector3 howlPosition)
		{
			return !((Object)(object)((Component)__instance).GetComponentInParent<MouthDogTamedBehaviour>()?.ownerPlayer != (Object)null);
		}
	}
	public class PlayerControllerBPatch
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static RpcReceiveHandler <0>____rpc_handler_346187524u;

			public static Action<CallbackContext> <1>__RetrieveBallKeyPressed;

			public static Action<CallbackContext> <2>__ActionKey1Pressed;
		}

		private static bool lastTestPressed = false;

		private static int currentTestEnemyTypeIndex = 0;

		private static string[] testEnemyTypes = new List<string>(Data.CatchableMonsters.Keys).ToArray();

		private static bool SentBallScanTip = false;

		internal static void InitializeRPCS()
		{
			//IL_001a: 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_0025: Expected O, but got Unknown
			Dictionary<uint, RpcReceiveHandler> _rpc_func_table = NetworkManager.__rpc_func_table;
			object obj = <>O.<0>____rpc_handler_346187524u;
			if (obj == null)
			{
				RpcReceiveHandler val = __rpc_handler_346187524u;
				<>O.<0>____rpc_handler_346187524u = val;
				obj = (object)val;
			}
			_rpc_func_table.Add(346187524u, (RpcReceiveHandler)obj);
		}

		public static void SendPetRetrievePacket(PlayerControllerB player)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			ServerRpcParams val = default(ServerRpcParams);
			FastBufferWriter val2 = (FastBufferWriter)((object)player).GetType().GetMethod("__beginSendServerRpc", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(player, new object[3]
			{
				346187524u,
				val,
				(object)(RpcDelivery)0
			});
			NetworkObjectReference val3 = NetworkObjectReference.op_Implicit(((Component)player).GetComponent<NetworkObject>());
			((object)player).GetType().GetMethod("__endSendServerRpc", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(player, new object[4]
			{
				val2,
				346187524u,
				val,
				(object)(RpcDelivery)0
			});
			LethalMon.Log("Send pet retrieve server rpc send finished");
		}

		private static void __rpc_handler_346187524u(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			NetworkManager networkManager = target.NetworkManager;
			if ((Object)(object)networkManager != (Object)null && networkManager.IsListening)
			{
				LethalMon.Log("Execute RPC handler " + MethodBase.GetCurrentMethod().Name);
				PlayerControllerB val = (PlayerControllerB)target;
				TamedEnemyBehaviour playerPet = Utils.GetPlayerPet(val);
				if ((Object)(object)playerPet != (Object)null)
				{
					PetRetrieve(val, playerPet);
				}
				else
				{
					LethalMon.Log("No tamed enemy found for " + ((object)val)?.ToString() + " but they sent a retrieve ball RPC");
				}
			}
		}

		private static void PetRetrieve(PlayerControllerB player, TamedEnemyBehaviour tamedEnemyBehaviour)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			Vector3 positionInFrontOfPlayerEyes = Utils.GetPositionInFrontOfPlayerEyes(player);
			PokeballItem pokeballItem = tamedEnemyBehaviour.RetrieveInBall(positionInFrontOfPlayerEyes);
			if (!((Object)(object)pokeballItem == (Object)null))
			{
				Bounds bounds = StartOfRound.Instance.shipBounds.bounds;
				bool flag = ((Bounds)(ref bounds)).Contains(positionInFrontOfPlayerEyes);
				player.SetItemInElevator(flag, flag, (GrabbableObject)(object)pokeballItem);
				((Component)pokeballItem).transform.SetParent(StartOfRound.Instance.elevatorTransform, true);
			}
		}

		[HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")]
		[HarmonyPostfix]
		public static void ConnectPlayerPostfix(PlayerControllerB __instance)
		{
			ModConfig.Instance.RetrieveBallKey.performed += RetrieveBallKeyPressed;
			ModConfig.Instance.ActionKey1.performed += ActionKey1Pressed;
		}

		[HarmonyPatch(typeof(GameNetworkManager), "Disconnect")]
		[HarmonyPrefix]
		public static void DisconnectPlayerPrefix()
		{
			ModConfig.Instance.RetrieveBallKey.performed -= RetrieveBallKeyPressed;
			ModConfig.Instance.ActionKey1.performed -= ActionKey1Pressed;
		}

		internal static void RetrieveBallKeyPressed(CallbackContext dashContext)
		{
			if (Utils.IsHost)
			{
				LethalMon.Log("RetrieveBallKeyPressed");
				TamedEnemyBehaviour playerPet = Utils.GetPlayerPet(Utils.CurrentPlayer);
				if ((Object)(object)playerPet != (Object)null)
				{
					PetRetrieve(Utils.CurrentPlayer, playerPet);
				}
			}
			else
			{
				SendPetRetrievePacket(Utils.CurrentPlayer);
			}
		}

		internal static void ActionKey1Pressed(CallbackContext dashContext)
		{
			LethalMon.Log("ActionKey1Pressed");
			TamedEnemyBehaviour playerPet = Utils.GetPlayerPet(Utils.CurrentPlayer);
			if ((Object)(object)playerPet != (Object)null)
			{
				playerPet.ActionKey1Pressed();
			}
		}

		[HarmonyPatch(typeof(PlayerControllerB), "Update")]
		[HarmonyPostfix]
		private static void UpdatePostfix(PlayerControllerB __instance)
		{
			if (__instance == null || !__instance.isPlayerControlled || !((NetworkBehaviour)__instance).IsOwner || !((Object)(object)StartOfRound.Instance.testRoom != (Object)null) || (!((NetworkBehaviour)__instance).IsHost && !((NetworkBehaviour)__instance).IsServer))
			{
				return;
			}
			bool flag = InputControlExtensions.IsPressed((InputControl)(object)Keyboard.current[(Key)29], 0f);
			if (flag && !lastTestPressed)
			{
				lastTestPressed = true;
				GrabbableObject val = __instance.ItemSlots[__instance.currentItemSlot];
				if (!((Object)(object)val != (Object)null))
				{
					return;
				}
				PokeballItem component = ((Component)val).GetComponent<PokeballItem>();
				if ((Object)(object)component != (Object)null)
				{
					EnemyType val2 = Resources.FindObjectsOfTypeAll<EnemyType>().First((EnemyType enemyType) => ((Object)enemyType).name == testEnemyTypes[currentTestEnemyTypeIndex]);
					component.SetCaughtEnemyServerRpc(((Object)val2).name);
					HUDManager.Instance.AddTextMessageClientRpc("Caught enemy: " + ((Object)val2).name);
					currentTestEnemyTypeIndex++;
					if (currentTestEnemyTypeIndex >= testEnemyTypes.Length)
					{
						currentTestEnemyTypeIndex = 0;
					}
				}
			}
			else if (!flag)
			{
				lastTestPressed = false;
			}
		}

		[HarmonyPatch(typeof(PlayerControllerB), "TeleportPlayer")]
		[HarmonyPostfix]
		private static void TeleportPlayer(PlayerControllerB __instance, Vector3 pos)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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)
			TamedEnemyBehaviour playerPet = Utils.GetPlayerPet(__instance);
			if ((Object)(object)playerPet != (Object)null && playerPet.CanBeTeleported())
			{
				Vector3 val = pos;
				LethalMon.Log("Teleport tamed enemy to " + ((object)(Vector3)(ref val)).ToString());
				((Behaviour)playerPet.Enemy.agent).enabled = false;
				((Component)playerPet.Enemy).transform.position = pos;
				((Behaviour)playerPet.Enemy.agent).enabled = true;
				playerPet.Enemy.serverPosition = pos;
				playerPet.Enemy.SetEnemyOutside(!__instance.isInsideFactory);
			}
		}

		[HarmonyPatch(typeof(PlayerControllerB), "KillPlayerServerRpc")]
		[HarmonyPostfix]
		private static void KillPlayerServerRpcPostfix(PlayerControllerB __instance)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			TamedEnemyBehaviour playerPet = Utils.GetPlayerPet(__instance);
			if ((Object)(object)playerPet != (Object)null && Utils.IsHost && !playerPet.hasBeenRetrieved)
			{
				LethalMon.Log("Owner is dead, go back to the ball");
				playerPet.RetrieveInBall(((Component)playerPet.Enemy).transform.position);
			}
		}

		[HarmonyPatch(typeof(PlayerControllerB), "DamagePlayer")]
		[HarmonyPostfix]
		private static void DamagePlayerPostfix(PlayerControllerB __instance, int damageNumber, bool hasDamageSFX, bool callRPC, CauseOfDeath causeOfDeath, int deathAnimation, bool fallDamage, Vector3 force)
		{
			TamedEnemyBehaviour playerPet = Utils.GetPlayerPet(__instance);
			if ((Object)(object)playerPet != (Object)null && playerPet.CanDefend)
			{
				EnemyAI mostProbableAttackerEnemy = Utils.GetMostProbableAttackerEnemy(__instance, new StackTrace());
				TamedEnemyBehaviour componentInParent = ((Component)mostProbableAttackerEnemy).GetComponentInParent<TamedEnemyBehaviour>();
				if ((Object)(object)mostProbableAttackerEnemy != (Object)null && (Object)(object)mostProbableAttackerEnemy != (Object)(object)playerPet.Enemy && ((Object)(object)componentInParent == (Object)null || (Object)(object)componentInParent.ownerPlayer == (Object)null))
				{
					playerPet.targetEnemy = mostProbableAttackerEnemy;
					playerPet.SwitchToTamingBehaviour(TamedEnemyBehaviour.TamingBehaviour.TamedDefending);
				}
			}
		}

		[HarmonyPatch(typeof(PlayerControllerB), "DamagePlayerFromOtherClientServerRpc")]
		[HarmonyPostfix]
		private static void DamagePlayerFromOtherClientServerRpcPostFix(PlayerControllerB __instance, Vector3 hitDirection, int playerWhoHit)
		{
			//IL_0070: 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)
			if ((int)__instance.playerClientId == playerWhoHit)
			{
				return;
			}
			TamedEnemyBehaviour playerPet = Utils.GetPlayerPet(__instance);
			if ((Object)(object)playerPet != (Object)null && (((NetworkBehaviour)__instance).IsServer || ((NetworkBehaviour)__instance).IsHost) && playerPet.CanDefend)
			{
				PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[playerWhoHit];
				LethalMon.Log("Player " + val.playerUsername + " hit " + __instance.playerUsername);
				if ((Object)(object)__instance != (Object)(object)val && Vector3.Distance(((Component)__instance).transform.position, ((Component)val).transform.position) < 5f)
				{
					playerPet.targetPlayer = val;
					playerPet.SwitchToTamingBehaviour(TamedEnemyBehaviour.TamingBehaviour.TamedDefending);
				}
			}
		}

		[HarmonyPatch(typeof(PlayerControllerB), "SwitchToItemSlot")]
		[HarmonyPostfix]
		private static void SwitchToItemSlotPostFix(PlayerControllerB __instance, int slot, GrabbableObject fillSlotWithItem = null)
		{
			if (!SentBallScanTip && StartOfRound.Instance.shipHasLanded && !((Object)(object)__instance != (Object)(object)Utils.CurrentPlayer))
			{
				GrabbableObject val = __instance.ItemSlots[slot];
				if ((Object)(object)val != (Object)null && ((object)val).GetType().IsSubclassOf(typeof(PokeballItem)) && !((PokeballItem)(object)val).enemyCaptured)
				{
					HUDManager.Instance.DisplayTip("LethalMon Tip", "Scan base game enemies to know if they are catchable or not. Modded enemies are not catchable.", false, false, "LC_Tip1");
					SentBallScanTip = true;
				}
			}
		}
	}
	public class RedLocustBeesPatch
	{
		public static readonly Dictionary<int, DateTime> AngryUntil = new Dictionary<int, DateTime>();

		[HarmonyPatch(typeof(RedLocustBees), "IsHivePlacedAndInLOS")]
		[HarmonyPrefix]
		private static bool IsHivePlacedAndInLOSPrefix(RedLocustBees __instance, ref bool __result)
		{
			int instanceID = ((Object)__instance).GetInstanceID();
			if (AngryUntil.TryGetValue(instanceID, out var value))
			{
				if (value < DateTime.Now)
				{
					AngryUntil.Remove(instanceID);
					return true;
				}
				__result = false;
				LethalMon.Log("ANGRY BEES!!!!");
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(RedLocustBees), "SpawnHiveNearEnemy")]
		[HarmonyPrefix]
		public static bool SpawnHiveNearEnemyPrefix(RedLocustBees __instance)
		{
			TamedEnemyBehaviour component = ((Component)__instance).GetComponent<TamedEnemyBehaviour>();
			if ((Object)(object)component != (Object)null)
			{
				return !component.IsOwnedByAPlayer();
			}
			return true;
		}
	}
	public class RoundManagerPatch
	{
		private static void ChangeIsScrapForBalls(bool isScrap, bool fullOnly)
		{
			GrabbableObject[] array = Object.FindObjectsOfType<GrabbableObject>();
			GrabbableObject[] array2 = array;
			foreach (GrabbableObject val in array2)
			{
				if (((object)val).GetType().IsSubclassOf(typeof(PokeballItem)) && (!fullOnly || ((PokeballItem)(object)val).enemyCaptured))
				{
					val.itemProperties.isScrap = isScrap;
				}
			}
		}

		[HarmonyPatch(typeof(RoundManager), "DespawnPropsAtEndOfRound")]
		[HarmonyPrefix]
		private static void DespawnPropsAtEndOfRoundPrefix(RoundManager __instance, bool despawnAllItems = false)
		{
			if (ModConfig.Instance.values.KeepBallsIfAllPlayersDead != "no")
			{
				ChangeIsScrapForBalls(isScrap: false, ModConfig.Instance.values.KeepBallsIfAllPlayersDead == "fullOnly");
			}
		}

		[HarmonyPatch(typeof(RoundManager), "DespawnPropsAtEndOfRound")]
		[HarmonyPostfix]
		private static void DespawnPropsAtEndOfRoundPostfix(RoundManager __instance, bool despawnAllItems = false)
		{
			if (ModConfig.Instance.values.KeepBallsIfAllPlayersDead != "no")
			{
				ChangeIsScrapForBalls(isScrap: true, ModConfig.Instance.values.KeepBallsIfAllPlayersDead == "fullOnly");
			}
		}
	}
	public class StartOfRoundPatch
	{
		[HarmonyPatch(typeof(StartOfRound), "ShipHasLeft")]
		[HarmonyPrefix]
		private static void OnShipHasLeftPreFix(StartOfRound __instance)
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			TamedEnemyBehaviour[] array = Object.FindObjectsOfType<TamedEnemyBehaviour>();
			LethalMon.Log($"End of game, processing {array.Length} tamed enemies");
			TamedEnemyBehaviour[] array2 = array;
			foreach (TamedEnemyBehaviour tamedEnemyBehaviour in array2)
			{
				if (!((Object)(object)tamedEnemyBehaviour.ownerPlayer == (Object)null))
				{
					LethalMon.Log("Player is in hangar ship room: " + tamedEnemyBehaviour.ownerPlayer.isInHangarShipRoom);
					if (tamedEnemyBehaviour.ownerPlayer.isInHangarShipRoom)
					{
						PokeballItem pokeballItem = tamedEnemyBehaviour.RetrieveInBall(((Component)tamedEnemyBehaviour.ownerPlayer).transform.position);
						tamedEnemyBehaviour.ownerPlayer.SetItemInElevator(true, true, (GrabbableObject)(object)pokeballItem);
						((Component)pokeballItem).transform.SetParent(__instance.elevatorTransform, true);
					}
				}
			}
		}

		[HarmonyPatch(typeof(StartOfRound), "OnPlayerDC")]
		[HarmonyPrefix]
		private static void OnPlayerDCPrefix(StartOfRound __instance, int playerObjectNumber, ulong clientId)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			LethalMon.Log($"Client with ID {clientId} disconnected. Starting to delete its pets");
			TamedEnemyBehaviour[] array = Object.FindObjectsOfType<TamedEnemyBehaviour>();
			TamedEnemyBehaviour[] array2 = array;
			foreach (TamedEnemyBehaviour tamedEnemyBehaviour in array2)
			{
				if (tamedEnemyBehaviour.ownClientId == clientId)
				{
					LethalMon.Log("Found " + ((Object)tamedEnemyBehaviour.Enemy.enemyType).name + ", retrieving in ball");
					tamedEnemyBehaviour.RetrieveInBall(((Component)tamedEnemyBehaviour.Enemy).transform.position);
				}
			}
		}
	}
}
namespace LethalMon.Items
{
	public enum BallType
	{
		POKEBALL,
		GREAT_BALL,
		ULTRA_BALL,
		MASTER_BALL
	}
	public class BallTypeMethods
	{
		public static GameObject? GetPrefab(BallType ballType)
		{
			return (GameObject?)(ballType switch
			{
				BallType.GREAT_BALL => Greatball.SpawnPrefab, 
				BallType.ULTRA_BALL => Ultraball.SpawnPrefab, 
				BallType.MASTER_BALL => Masterball.SpawnPrefab, 
				_ => Pokeball.SpawnPrefab, 
			});
		}
	}
	public class Greatball : PokeballItem
	{
		public static GameObject? SpawnPrefab;

		public static Item? BallItem;

		public Greatball()
			: base(BallType.GREAT_BALL, 1)
		{
		}

		internal static void Setup(AssetBundle assetBundle)
		{
			Item val = PokeballItem.InitBallPrefab<Greatball>(assetBundle, "Greatball/Greatball.asset", ModConfig.Instance.values.Tier2BallSpawnWeight);
			if (!((Object)(object)val == (Object)null))
			{
				BallItem = val;
				SpawnPrefab = val.spawnPrefab;
				Item? ballItem = BallItem;
				int tier2BallCost = ModConfig.Instance.values.Tier2BallCost;
				Items.RegisterShopItem(ballItem, (TerminalNode)null, (TerminalNode)null, Utils.CreateTerminalNode("Great ball", "Use it to capture monsters. Second ball tier with a medium capture rate."), tier2BallCost);
				LethalMon.Log("Great ball added to shop");
			}
		}

		protected override void __initializeVariables()
		{
			base.__initializeVariables();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		protected internal override string? __getTypeName()
		{
			return "Greatball";
		}
	}
	public class Masterball : PokeballItem
	{
		public static GameObject? SpawnPrefab;

		public static Item? BallItem;

		public Masterball()
			: base(BallType.MASTER_BALL, 3)
		{
		}

		internal static void Setup(AssetBundle assetBundle)
		{
			Item val = PokeballItem.InitBallPrefab<Masterball>(assetBundle, "Masterball/Masterball.asset", ModConfig.Instance.values.Tier4BallSpawnWeight);
			if (!((Object)(object)val == (Object)null))
			{
				BallItem = val;
				SpawnPrefab = val.spawnPrefab;
				Item? ballItem = BallItem;
				int tier4BallCost = ModConfig.Instance.values.Tier4BallCost;
				Items.RegisterShopItem(ballItem, (TerminalNode)null, (TerminalNode)null, Utils.CreateTerminalNode("Master ball", "Use it to capture monsters. Fourth ball tier with a 100% capture rate."), tier4BallCost);
				LethalMon.Log("Master ball added to shop");
			}
		}

		protected override void __initializeVariables()
		{
			base.__initializeVariables();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		protected internal override string? __getTypeName()
		{
			return "Masterball";
		}
	}
	public class Pokeball : PokeballItem
	{
		public static GameObject? SpawnPrefab;

		public static Item? BallItem;

		public Pokeball()
			: base(BallType.POKEBALL, 0)
		{
		}

		internal static void Setup(AssetBundle assetBundle)
		{
			Item val = PokeballItem.InitBallPrefab<Pokeball>(assetBundle, "Pokeball/Pokeball.asset", ModConfig.Instance.values.Tier1BallSpawnWeight);
			if (!((Object)(object)val == (Object)null))
			{
				BallItem = val;
				SpawnPrefab = val.spawnPrefab;
				Item? ballItem = BallItem;
				int tier1BallCost = ModConfig.Instance.values.Tier1BallCost;
				Items.RegisterShopItem(ballItem, (TerminalNode)null, (TerminalNode)null, Utils.CreateTerminalNode("Pokeball", "Use it to capture monsters. First ball tier with a low capture rate."), tier1BallCost);
				LethalMon.Log("Pokeball added to shop");
			}
		}

		protected override void __initializeVariables()
		{
			base.__initializeVariables();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		protected internal override string? __getTypeName()
		{
			return "Pokeball";
		}
	}
	public abstract class PokeballItem : ThrowableItem
	{
		private EnemyAI? enemyAI;

		private EnemyType? enemyType;

		private global::LethalMon.CatchableEnemy.CatchableEnemy? catchableEnemy;

		private bool captureSuccess;

		private int captureRounds = 1;

		private int currentCaptureRound;

		internal bool enemyCaptured;

		private int captureStrength;

		private BallType ballType;

		public Dictionary<string, Tuple<float, DateTime>> cooldowns = new Dictionary<string, Tuple<float, DateTime>>();

		public PokeballItem(BallType ballType, int captureStrength)
		{
			this.ballType = ballType;
			this.captureStrength = captureStrength;
		}

		internal static Item? InitBallPrefab<T>(AssetBundle assetBundle, string assetPath, int scrapRarity = 1) where T : PokeballItem
		{
			if ((Object)(object)assetBundle == (Object)null)
			{
				return null;
			}
			Item val = assetBundle.LoadAsset<Item>(Path.Combine("As