Decompiled source of CuriosShenanigans v0.1.0

CuriosityPlugin.dll

Decompiled 4 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using CuriosityPlugin.MonoBehaviours;
using CuriosityPlugin.Patches;
using GameNetcodeStuff;
using HarmonyLib;
using LethalLib.Modules;
using Microsoft.CodeAnalysis;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("CuriosityPlugin")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("My first plugin")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("CuriosityPlugin")]
[assembly: AssemblyTitle("CuriosityPlugin")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace CuriosityPlugin
{
	[BepInPlugin("Yakua.CuriosityPlugin", "CuriosityPlugin", "0.1.0")]
	public class Plugin : BaseUnityPlugin
	{
		private const string pluginGUID = "Yakua.CuriosityPlugin";

		private const string pluginName = "CuriosityPlugin";

		private const string pluginVer = "0.1.0";

		private readonly Harmony harmony = new Harmony("Yakua.CuriosityPlugin");

		public static ManualLogSource Logger;

		public static AssetBundle MainAssets;

		public static ContentLoader ContentLoader;

		public static Dictionary<string, GameObject> Prefabs = new Dictionary<string, GameObject>();

		public static List<Turret> friendlyTurrets;

		public static Plugin Instance { get; private set; }

		public static PluginConfig MyConfig { get; internal set; }

		private void Awake()
		{
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Expected O, but got Unknown
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			Logger = Logger.CreateLogSource("Yakua.CuriosityPlugin");
			Logger.LogInfo((object)"Main: Plugin Yakua.CuriosityPlugin is loaded!");
			MyConfig = new PluginConfig(((BaseUnityPlugin)this).Config);
			friendlyTurrets = new List<Turret>();
			MainAssets = AssetBundle.LoadFromFile(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "curiosityplugin"));
			ContentLoader = new ContentLoader(((BaseUnityPlugin)this).Info, MainAssets, (Action<CustomContent, GameObject>)delegate(CustomContent content, GameObject prefab)
			{
				Prefabs.Add(content.ID, prefab);
			});
			BeerTankard.Init();
			TurretSpawner.Init();
			harmony.PatchAll(typeof(Plugin));
			harmony.PatchAll(typeof(PluginConfig));
			harmony.PatchAll(typeof(TurretSpawner));
			harmony.PatchAll(typeof(TurretWhisperer));
		}

		[HarmonyPatch(typeof(EnemyAI), "KillEnemyServerRpc")]
		[HarmonyPostfix]
		private static void OnEnemyDeath(EnemyAI __instance)
		{
			TurretSpawner.SpawnTurretOnDeath(__instance);
		}

		public void OnDespawnTurret(Vector3 pos)
		{
			//IL_0006: 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)
			NetworkObject component = Object.Instantiate<GameObject>(BeerTankard.tankardPrefab, pos, Quaternion.identity).GetComponent<NetworkObject>();
			component.Spawn(false);
			((GrabbableObject)((Component)component).GetComponent<BeerTankard>()).itemProperties.creditsWorth = 69;
		}

		public void SpawnFriendlyTurret(Vector3 pos, Quaternion rot)
		{
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: 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_0110: Unknown result type (might be due to invalid IL or missing references)
			if (!PluginConfig.imaginaryFriend.Value)
			{
				return;
			}
			Logger.LogInfo((object)("Current level is: " + ((Object)RoundManager.Instance.currentLevel).name));
			GameObject val = null;
			SpawnableMapObject[] spawnableMapObjects = RoundManager.Instance.currentLevel.spawnableMapObjects;
			foreach (SpawnableMapObject val2 in spawnableMapObjects)
			{
				if ((Object)(object)val2.prefabToSpawn.GetComponentInChildren<Turret>() != (Object)null)
				{
					val = val2.prefabToSpawn;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				Logger.LogInfo((object)"Main: No turret found to spawn a friendly turret");
				return;
			}
			Logger.LogInfo((object)"SFT: Found a turret");
			ManualLogSource logger = Logger;
			Vector3 val3 = pos;
			logger.LogInfo((object)("SFT: Pos is: " + ((object)(Vector3)(ref val3)).ToString()));
			ManualLogSource logger2 = Logger;
			Quaternion val4 = rot;
			logger2.LogInfo((object)("SFT: Rot is: " + ((object)(Quaternion)(ref val4)).ToString()));
			NetworkObject networkObject = Object.Instantiate<GameObject>(val, pos, rot).GetComponent<NetworkObject>();
			Logger.LogInfo((object)("NetObj: " + ((Object)networkObject).name));
			friendlyTurrets.Add(((Component)networkObject).GetComponentInChildren<Turret>());
			networkObject.Spawn(true);
			((MonoBehaviour)networkObject).StartCoroutine(WaitForDespawn());
			IEnumerator WaitForDespawn()
			{
				yield return (object)new WaitForSeconds((float)PluginConfig.despawnTurretTimeInSeconds.Value);
				Logger.LogInfo((object)"TS: Turret Should Despawn");
				friendlyTurrets.Remove(((Component)networkObject).GetComponentInChildren<Turret>());
				networkObject.Despawn(true);
			}
		}
	}
	public class PluginConfig : SyncedInstance<PluginConfig>
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static HandleNamedMessageDelegate <0>__OnRequestSync;

			public static HandleNamedMessageDelegate <1>__OnReceiveSync;
		}

		public static ConfigEntry<bool> triggerShenanigans { get; private set; }

		public static ConfigEntry<bool> turretsShenanigans { get; private set; }

		public static ConfigEntry<bool> itemShenanigans { get; private set; }

		public static ConfigEntry<bool> drinkingHurts { get; private set; }

		public static ConfigEntry<bool> imaginaryFriend { get; private set; }

		public static ConfigEntry<int> drinkingDamage { get; private set; }

		public static ConfigEntry<int> tankardRefills { get; private set; }

		public static ConfigEntry<float> tankardDrinkingTime { get; private set; }

		public static ConfigEntry<bool> spawnMultipleTurrets { get; private set; }

		public static ConfigEntry<bool> allowSpawnTurretsOutdoors { get; private set; }

		public static ConfigEntry<int> spawnTurretsChance { get; private set; }

		public static ConfigEntry<bool> despawnTurrets { get; private set; }

		public static ConfigEntry<int> despawnTurretTimeInSeconds { get; private set; }

		public static ConfigEntry<string> bannedCreatures { get; private set; }

		public PluginConfig(ConfigFile cfg)
		{
			InitInstance(this);
			triggerShenanigans = cfg.Bind<bool>("General", "Enable Shenanigans?", true, "Whether or not to trigger shenanigans on enemy death");
			turretsShenanigans = cfg.Bind<bool>("General", "Turrets Shenanigans", true, "Whether or not to spawn turrets shenanigans");
			itemShenanigans = cfg.Bind<bool>("General", "Item Shenanigans", true, "Whether or not to spawn item shenanigans");
			drinkingHurts = cfg.Bind<bool>("General.Items", "Drinking Hurts", false, "Does drinking hurt you?");
			imaginaryFriend = cfg.Bind<bool>("General.Items", "Imaginary Friend", false, "Does drinking spawn a friendly turret?");
			drinkingDamage = ConfigBindClamp("General.Items", "Drinking Damage", 20, "How much does drinking hurt you?", 0, 100);
			tankardRefills = ConfigBindClamp("General.Items", "Tankard Refills", 4, "How much can your drink refill until empty?", 0, 100);
			tankardDrinkingTime = cfg.Bind<float>("General.Items", "Tankard Drinking Time", 2f, "How fast do you drink?(in seconds)");
			allowSpawnTurretsOutdoors = cfg.Bind<bool>("General.Turrets", "AllowSpawnTurretsOutdoors", false, "True to spawn turret outdoors as well. False to spawn only indoors");
			spawnMultipleTurrets = cfg.Bind<bool>("General.Turrets", "SpawnMultipleTurrets", false, "True to spawn turret on one player. False to spawn on all players");
			spawnTurretsChance = ConfigBindClamp("General.Turrets", "SpawnTurretsChance", 20, "Chance to spawn turret on each individual player(in percents from 1 to 100)", 1, 100);
			despawnTurrets = cfg.Bind<bool>("General.Turrets", "DespawnTurrets", true, "Do turrets despawn over time");
			despawnTurretTimeInSeconds = ConfigBindClamp("General.Turrets", "DespawnTurretsTimeInSeconds", 120, "Time that takes turrets to despawn", 0, 3600);
			bannedCreatures = cfg.Bind<string>("General.Misc", "BannedCreatures", "Manticoil, Red Locust Bees, Docile Locust Bees", "List all creatures that don't trigger shenanigans");
			ConfigEntry<int> ConfigBindClamp(string section, string key, int defaultValue, string description, int min, int max)
			{
				ConfigEntry<int> val = cfg.Bind<int>(section, key, defaultValue, description);
				val.Value = Mathf.Clamp(val.Value, min, max);
				return val;
			}
		}

		public static void RequestSync()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (!SyncedInstance<PluginConfig>.IsClient)
			{
				return;
			}
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(SyncedInstance<PluginConfig>.IntSize, (Allocator)2, -1);
			try
			{
				SyncedInstance<PluginConfig>.MessageManager.SendNamedMessage("ModName_OnRequestConfigSync", 0uL, val, (NetworkDelivery)3);
			}
			finally
			{
				((IDisposable)(FastBufferWriter)(ref val)).Dispose();
			}
		}

		public static void OnRequestSync(ulong clientId, FastBufferReader _)
		{
			//IL_0053: 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_0077: Unknown result type (might be due to invalid IL or missing references)
			if (!SyncedInstance<PluginConfig>.IsHost)
			{
				return;
			}
			Plugin.Logger.LogInfo((object)$"Config: Config sync request received from client: {clientId}");
			byte[] array = SyncedInstance<PluginConfig>.SerializeToBytes(SyncedInstance<PluginConfig>.Instance);
			int num = array.Length;
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(num + SyncedInstance<PluginConfig>.IntSize, (Allocator)2, -1);
			try
			{
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteBytesSafe(array, -1, 0);
				SyncedInstance<PluginConfig>.MessageManager.SendNamedMessage("ModName_OnReceiveConfigSync", clientId, val, (NetworkDelivery)3);
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogWarning((object)$"Config: Error occurred syncing config with client: {clientId}\n{arg}");
			}
			finally
			{
				((IDisposable)(FastBufferWriter)(ref val)).Dispose();
			}
		}

		public static void OnReceiveSync(ulong _, FastBufferReader reader)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			if (!((FastBufferReader)(ref reader)).TryBeginRead(SyncedInstance<PluginConfig>.IntSize))
			{
				Plugin.Logger.LogError((object)"Config: Config sync error: Could not begin reading buffer.");
				return;
			}
			int num = default(int);
			((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives));
			if (!((FastBufferReader)(ref reader)).TryBeginRead(num))
			{
				Plugin.Logger.LogError((object)"Config: Config sync error: Host could not sync.");
				return;
			}
			byte[] data = new byte[num];
			((FastBufferReader)(ref reader)).ReadBytesSafe(ref data, num, 0);
			SyncedInstance<PluginConfig>.SyncInstance(data);
			Plugin.Logger.LogInfo((object)"Config: Successfully synced config with host.");
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")]
		public static void InitializeLocalPlayer()
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_0025: 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_0030: Expected O, but got Unknown
			if (SyncedInstance<PluginConfig>.IsHost)
			{
				CustomMessagingManager messageManager = SyncedInstance<PluginConfig>.MessageManager;
				object obj = <>O.<0>__OnRequestSync;
				if (obj == null)
				{
					HandleNamedMessageDelegate val = OnRequestSync;
					<>O.<0>__OnRequestSync = val;
					obj = (object)val;
				}
				messageManager.RegisterNamedMessageHandler("CurYATM_OnRequestConfigSync", (HandleNamedMessageDelegate)obj);
				SyncedInstance<PluginConfig>.Synced = true;
				return;
			}
			SyncedInstance<PluginConfig>.Synced = false;
			CustomMessagingManager messageManager2 = SyncedInstance<PluginConfig>.MessageManager;
			object obj2 = <>O.<1>__OnReceiveSync;
			if (obj2 == null)
			{
				HandleNamedMessageDelegate val2 = OnReceiveSync;
				<>O.<1>__OnReceiveSync = val2;
				obj2 = (object)val2;
			}
			messageManager2.RegisterNamedMessageHandler("CurYATM_OnReceiveConfigSync", (HandleNamedMessageDelegate)obj2);
			RequestSync();
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameNetworkManager), "StartDisconnect")]
		public static void PlayerLeave()
		{
			SyncedInstance<PluginConfig>.RevertSync();
		}
	}
	[Serializable]
	public class SyncedInstance<T>
	{
		[NonSerialized]
		protected static int IntSize = 4;

		internal static CustomMessagingManager MessageManager => NetworkManager.Singleton.CustomMessagingManager;

		internal static bool IsClient => NetworkManager.Singleton.IsClient;

		internal static bool IsHost => NetworkManager.Singleton.IsHost;

		public static T Default { get; private set; }

		public static T Instance { get; private set; }

		public static bool Synced { get; internal set; }

		protected void InitInstance(T instance)
		{
			Default = instance;
			Instance = instance;
			IntSize = 4;
		}

		internal static void SyncInstance(byte[] data)
		{
			Instance = DeserializeFromBytes(data);
			Synced = true;
		}

		internal static void RevertSync()
		{
			Instance = Default;
			Synced = false;
		}

		public static byte[] SerializeToBytes(T val)
		{
			BinaryFormatter binaryFormatter = new BinaryFormatter();
			using MemoryStream memoryStream = new MemoryStream();
			try
			{
				binaryFormatter.Serialize(memoryStream, val);
				return memoryStream.ToArray();
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"Error serializing instance: {arg}");
				return null;
			}
		}

		public static T DeserializeFromBytes(byte[] data)
		{
			BinaryFormatter binaryFormatter = new BinaryFormatter();
			using MemoryStream serializationStream = new MemoryStream(data);
			try
			{
				return (T)binaryFormatter.Deserialize(serializationStream);
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"Error deserializing instance: {arg}");
				return default(T);
			}
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "CuriosityPlugin";

		public const string PLUGIN_NAME = "CuriosityPlugin";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace CuriosityPlugin.Patches
{
	public class TurretSpawner
	{
		public static Random turretSpawnRandom;

		private static List<NetworkObject> spawnedTurrets;

		private static ulong currentEnemy = 9999999uL;

		public static void Init()
		{
			spawnedTurrets = new List<NetworkObject>();
		}

		[HarmonyPatch(typeof(RoundManager), "GenerateNewLevelClientRpc")]
		[HarmonyPostfix]
		private static void updateCurrentTurretSeed(int randomSeed)
		{
			turretSpawnRandom = new Random(randomSeed + 24);
			Plugin.Logger.LogInfo((object)$"TS: Generated a seed for turrets: {randomSeed + 24}");
		}

		public static void SpawnTurretOnDeath(EnemyAI instance)
		{
			Plugin.Logger.LogInfo((object)("TS: Got into Initial Spawn Method called from " + instance.enemyType.enemyName + "."));
			if (!PluginConfig.turretsShenanigans.Value || currentEnemy == ((NetworkBehaviour)instance).NetworkObject.NetworkObjectId || !((NetworkBehaviour)instance).IsHost)
			{
				return;
			}
			string[] array = PluginConfig.bannedCreatures.Value.Split(',');
			string[] array2 = array;
			foreach (string text in array2)
			{
				if (instance.enemyType.enemyName == text)
				{
					return;
				}
			}
			currentEnemy = ((NetworkBehaviour)instance).NetworkObject.NetworkObjectId;
			GameObject val = null;
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			PlayerControllerB[] array3 = allPlayerScripts.Where((PlayerControllerB p) => p.isPlayerControlled && !p.isPlayerDead && (p.isInsideFactory | PluginConfig.allowSpawnTurretsOutdoors.Value)).ToArray();
			Plugin.Logger.LogInfo((object)$"TS: {instance.enemyType.enemyName} has died. Trying to spawn turret on ({array3.Length}) suitable players.");
			SpawnableMapObject[] spawnableMapObjects = RoundManager.Instance.currentLevel.spawnableMapObjects;
			foreach (SpawnableMapObject val2 in spawnableMapObjects)
			{
				if ((Object)(object)val2.prefabToSpawn.GetComponentInChildren<Turret>() != (Object)null)
				{
					val = val2.prefabToSpawn;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Logger.LogInfo((object)"TS: No turret found");
			}
			else
			{
				SpawnTurrets(val, array3);
			}
		}

		private static void SpawnTurrets(GameObject tur, PlayerControllerB[] suitablePlayers)
		{
			if ((Object)(object)tur == (Object)null || suitablePlayers.Length == 0)
			{
				Plugin.Logger.LogInfo((object)"TS: No turret or player found to spawn a hostile turret");
				return;
			}
			if (!PluginConfig.spawnMultipleTurrets.Value)
			{
				Spawn(suitablePlayers[turretSpawnRandom.Next(0, suitablePlayers.Length)]);
				return;
			}
			foreach (PlayerControllerB player2 in suitablePlayers)
			{
				Spawn(player2);
			}
			GameObject Spawn(PlayerControllerB player)
			{
				//IL_0086: Unknown result type (might be due to invalid IL or missing references)
				//IL_008b: Unknown result type (might be due to invalid IL or missing references)
				int num = turretSpawnRandom.Next(1, 101);
				bool flag = ((num <= PluginConfig.spawnTurretsChance.Value) ? true : false);
				Plugin.Logger.LogInfo((object)$"TS: Rolled: {num} out of {PluginConfig.spawnTurretsChance.Value}. Target: {player.playerUsername}");
				NetworkObject networkObject;
				if (flag && (Object)(object)tur != (Object)null)
				{
					networkObject = null;
					try
					{
						networkObject = Object.Instantiate<GameObject>(tur, ((Component)player).transform.position, Quaternion.identity).GetComponent<NetworkObject>();
						networkObject.Spawn(true);
						spawnedTurrets.Add(networkObject);
						if (PluginConfig.despawnTurrets.Value)
						{
							((MonoBehaviour)networkObject).StartCoroutine(WaitForDespawn());
						}
					}
					catch (Exception arg)
					{
						Plugin.Logger.LogWarning((object)$"Exception: {arg}");
					}
					return ((Component)networkObject).gameObject;
				}
				if ((Object)(object)tur == (Object)null)
				{
					Plugin.Logger.LogInfo((object)"TS: No turret object found for this map to spawn a hostile turret");
				}
				return null;
				IEnumerator WaitForDespawn()
				{
					yield return (object)new WaitForSeconds((float)PluginConfig.despawnTurretTimeInSeconds.Value);
					Plugin.Logger.LogInfo((object)"TS: Turret Should Despawn");
					Plugin.Instance.OnDespawnTurret(((Component)networkObject).transform.position);
					Despawn(networkObject);
				}
			}
		}

		public static void Despawn(NetworkObject networkObject)
		{
			spawnedTurrets.Remove(networkObject);
			networkObject.Despawn(true);
		}

		[HarmonyPatch(typeof(StartOfRound), "ShipLeave")]
		[HarmonyPrefix]
		private static void DeleteTurretsOnShipLeave()
		{
			if (spawnedTurrets == null)
			{
				return;
			}
			foreach (NetworkObject spawnedTurret in spawnedTurrets)
			{
				if ((Object)(object)spawnedTurret != (Object)null)
				{
					spawnedTurret.Despawn(true);
				}
			}
			spawnedTurrets = null;
		}
	}
	[HarmonyPatch(typeof(Turret))]
	internal class TurretWhisperer
	{
		public static float viewRadius = 20f;

		public static float viewAngle = 180f;

		public static float missChance = 0.97f;

		[HarmonyPatch("Update")]
		[HarmonyPrefix]
		public static void PatchUpdateBefore(ref Turret __instance)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_003c: 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_0066: 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_0045: Invalid comparison between Unknown and I4
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Invalid comparison between Unknown and I4
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Invalid comparison between Unknown and I4
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Invalid comparison between Unknown and I4
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Invalid comparison between Unknown and I4
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Invalid comparison between Unknown and I4
			if (!Plugin.friendlyTurrets.Contains(__instance))
			{
				return;
			}
			TurretMode val = (TurretMode)AccessTools.Field(typeof(Turret), "turretModeLastFrame").GetValue(__instance);
			TurretMode val2 = val;
			TurretMode val3 = val2;
			if ((int)val3 != 0)
			{
				if ((int)val3 == 1 && (Object)(object)CheckForEnemiesInLOS(__instance, 3f, angleRangeCheck: true) != (Object)null)
				{
					__instance.turretMode = (TurretMode)2;
				}
			}
			else if ((Object)(object)CheckForEnemiesInLOS(__instance, 3f, angleRangeCheck: true) != (Object)null)
			{
				__instance.turretMode = (TurretMode)1;
				SetFieldBase(__instance, "turretInterval", 0f);
			}
			if ((int)__instance.turretMode == 1 || (int)__instance.turretMode == 2 || (int)__instance.turretMode == 3)
			{
				EnemyAI val4 = CheckForEnemiesInLOS(__instance, 3f, angleRangeCheck: true);
				if ((Object)(object)val4 != (Object)null)
				{
					__instance.targetTransform = ((Component)val4).transform;
				}
				else
				{
					__instance.targetTransform = null;
				}
				if ((float)GetFieldBase(__instance, "turretInterval") > 0.1f && !TargetEnemy(__instance, val4) && ((int)val == 2 || (int)val == 3))
				{
					__instance.turretMode = (TurretMode)0;
				}
			}
		}

		[HarmonyPatch("TurnTowardsTargetIfHasLOS")]
		[HarmonyPrefix]
		public static void PatchTurnTowardsTargetIfHasLOS(ref Turret __instance)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00b1: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.friendlyTurrets.Contains(__instance))
			{
				return;
			}
			bool flag = true;
			if (Physics.Linecast(__instance.aimPoint.position, __instance.targetTransform.position, StartOfRound.Instance.collidersAndRoomMask, (QueryTriggerInteraction)1))
			{
				flag = false;
			}
			if (flag)
			{
				SetFieldBase(__instance, "hasLineOfSight", true);
				SetFieldBase(__instance, "lostLOSTimer", 0f);
				__instance.tempTransform.position = __instance.targetTransform.position;
				Transform tempTransform = __instance.tempTransform;
				tempTransform.position -= Vector3.up * 0.15f;
				__instance.turnTowardsObjectCompass.LookAt(__instance.tempTransform);
				return;
			}
			if ((bool)GetFieldBase(__instance, "hasLineOfSight"))
			{
				SetFieldBase(__instance, "hasLineOfSight", false);
				SetFieldBase(__instance, "lostLOSTimer", 0f);
			}
			SetFieldBase(__instance, "lostLOSTimer", (float)GetFieldBase(__instance, "lostLOSTimer") + Time.deltaTime);
			if (!((double)GetFieldBase(__instance, "lostLOSTimer") < 2.0))
			{
				SetFieldBase(__instance, "lostLOSTimer", 0f);
				Debug.Log((object)"Turret: LOS timer ended on server. checking for new player target");
				EnemyAI val = CheckForEnemiesInLOS(__instance);
				if ((Object)(object)val != (Object)null)
				{
					Debug.Log((object)"Turret: Got new enemy target");
				}
				else
				{
					Debug.Log((object)"Turret: No new player to target; returning to detection mode.");
				}
			}
		}

		public static bool TargetEnemy(Turret turret, EnemyAI visibleEnemy)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			bool result = false;
			if ((Object)(object)visibleEnemy != (Object)null)
			{
				if ((double)Random.Range(0f, 1f) > (double)missChance)
				{
					SetFieldBase(turret, "turretInterval", 0f);
					visibleEnemy.HitEnemyOnLocalClient(3, default(Vector3), (PlayerControllerB)null, false, -1);
					Plugin.Logger.LogInfo((object)("TW: " + (visibleEnemy.enemyType.enemyName + " was hit by a friendly turret.")));
					result = true;
				}
				else
				{
					result = false;
				}
			}
			return result;
		}

		public static EnemyAI CheckForEnemiesInLOS(Turret instance, float radius = 2f, bool angleRangeCheck = false)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			Vector3 forward = ((Transform)GetFieldBase(instance, "aimPoint")).forward;
			Vector3 val = Quaternion.Euler(0f, (float)(int)(0f - (float)GetFieldBase(instance, "rotationRange")) / radius, 0f) * forward;
			float num = (float)((double)instance.rotationRange / (double)radius * 2.0);
			SetFieldBase(instance, "shootRay", (object)new Ray(instance.centerPoint.position, val));
			RaycastHit[] array = Physics.RaycastAll((Ray)GetFieldBase(instance, "shootRay"), 30f);
			if (array.Length == 0)
			{
				return null;
			}
			RaycastHit[] array2 = array;
			EnemyAICollisionDetect val3 = default(EnemyAICollisionDetect);
			EnemyAI val4 = default(EnemyAI);
			for (int i = 0; i < array2.Length; i++)
			{
				RaycastHit val2 = array2[i];
				if (((Component)((RaycastHit)(ref val2)).transform).CompareTag("Enemy"))
				{
					SetFieldBase(instance, "hit", val2);
					if (((Component)((RaycastHit)(ref val2)).transform).TryGetComponent<EnemyAICollisionDetect>(ref val3))
					{
						Plugin.Logger.LogWarning((object)("TW: Acquired enemy component from " + ((Object)((RaycastHit)(ref val2)).collider).name));
						if (!((Object)(object)val3 == (Object)null))
						{
							return (angleRangeCheck && (double)Vector3.Angle(((Component)val3).transform.position + Vector3.up * 1.75f - instance.centerPoint.position, instance.forwardFacingPos.forward) > (double)instance.rotationRange) ? null : val3.mainScript;
						}
					}
					else if (((Component)((RaycastHit)(ref val2)).transform).TryGetComponent<EnemyAI>(ref val4))
					{
						Plugin.Logger.LogWarning((object)("TW: Acquired enemy component from " + ((Object)((RaycastHit)(ref val2)).collider).name));
						if (!((Object)(object)val4 == (Object)null))
						{
							return (angleRangeCheck && (double)Vector3.Angle(((Component)val4).transform.position + Vector3.up * 1.75f - instance.centerPoint.position, instance.forwardFacingPos.forward) > (double)instance.rotationRange) ? null : val4;
						}
					}
					else
					{
						Plugin.Logger.LogWarning((object)"TW: Doesn't have the EnemyAI or EnemyAICollisionDetect component.");
						Plugin.Logger.LogWarning((object)("TW: Hit Name: " + ((Object)((RaycastHit)(ref val2)).collider).name));
					}
				}
				else
				{
					val = Quaternion.Euler(0f, num / 6f, 0f) * val;
				}
			}
			return null;
		}

		private static object GetFieldBase(Turret turret, string fieldName)
		{
			return AccessTools.Field(typeof(Turret), fieldName).GetValue(turret);
		}

		private static void SetFieldBase(Turret turret, string fieldName, object fieldValue)
		{
			AccessTools.Field(typeof(Turret), fieldName).SetValue(turret, fieldValue);
		}

		[HarmonyPatch("CheckForPlayersInLineOfSight")]
		[HarmonyPostfix]
		public static void PatchCheckForPlayersInLineOfSight(ref Turret __instance, ref PlayerControllerB __result)
		{
			if (Plugin.friendlyTurrets.Contains(__instance))
			{
				__result = null;
			}
		}
	}
}
namespace CuriosityPlugin.MonoBehaviours
{
	internal class BeerTankard : PhysicsProp
	{
		private static int DamageNumber = 100;

		private static float TimeToEmpty = 2f;

		private static int MaxRefills = 4;

		public static GameObject tankardPrefab;

		private PlayerControllerB previousPlayerHeldBy;

		private Coroutine useTankardCoroutine;

		public AudioSource audioSource;

		public AudioClip interactionSound;

		public AudioClip interactionEndSound;

		public AudioClip interactionEmptySound;

		public AudioClip interactionDeathSound;

		private bool runningOut;

		private float fuel = 1f;

		private int charges;

		public static void Init()
		{
			Item val = Plugin.MainAssets.LoadAsset<Item>("Assets/BeerItem/BeerTankard.asset");
			tankardPrefab = val.spawnPrefab;
			BeerTankard beerTankard = tankardPrefab.AddComponent<BeerTankard>();
			beerTankard.interactionSound = Plugin.MainAssets.LoadAsset<AudioClip>("Assets/BeerItem/BeerInteraction.mp3");
			beerTankard.interactionEndSound = Plugin.MainAssets.LoadAsset<AudioClip>("Assets/BeerItem/BeerClarity.mp3");
			beerTankard.interactionEmptySound = Plugin.MainAssets.LoadAsset<AudioClip>("Assets/BeerItem/BeerEmpty.mp3");
			beerTankard.interactionDeathSound = Plugin.MainAssets.LoadAsset<AudioClip>("Assets/BeerItem/BeerDeath.mp3");
			((GrabbableObject)beerTankard).grabbable = true;
			((GrabbableObject)beerTankard).grabbableToEnemies = true;
			((GrabbableObject)beerTankard).itemProperties = val;
			DamageNumber = PluginConfig.drinkingDamage.Value;
			TimeToEmpty = PluginConfig.tankardDrinkingTime.Value;
			MaxRefills = PluginConfig.tankardRefills.Value;
			NetworkPrefabs.RegisterNetworkPrefab(val.spawnPrefab);
			Utilities.FixMixerGroups(val.spawnPrefab);
			Items.RegisterItem(val);
		}

		public void Awake()
		{
			audioSource = ((Component)this).GetComponent<AudioSource>();
			charges = MaxRefills;
		}

		public override void Update()
		{
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: 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)
			if (runningOut)
			{
				if ((Object)(object)previousPlayerHeldBy == (Object)null || !((GrabbableObject)this).isHeld || (double)fuel <= 0.0)
				{
					RunOutOfFuelServerRpc();
				}
				previousPlayerHeldBy.drunknessInertia = Mathf.Clamp(previousPlayerHeldBy.drunknessInertia + Time.deltaTime / 1.75f * (22f / (TimeToEmpty * (float)MaxRefills)) * previousPlayerHeldBy.drunknessSpeed, 0.1f, 3f);
				previousPlayerHeldBy.increasingDrunknessThisFrame = true;
				if ((double)fuel <= 0.0)
				{
					if (charges <= 0)
					{
						Plugin.Logger.LogInfo((object)"KILL");
						if (((NetworkBehaviour)this).IsOwner)
						{
							((GrabbableObject)this).playerHeldBy.playerBodyAnimator.SetBool("useTZPItem", false);
							((GrabbableObject)this).playerHeldBy.activatingItem = false;
							if (PluginConfig.drinkingHurts.Value)
							{
								((GrabbableObject)this).playerHeldBy.DamagePlayer(DamageNumber, true, true, (CauseOfDeath)0, 1, false, default(Vector3));
							}
						}
						if (((NetworkBehaviour)this).IsHost)
						{
							Plugin.Instance.SpawnFriendlyTurret(((Component)((GrabbableObject)this).playerHeldBy).transform.position, ((Component)((GrabbableObject)this).playerHeldBy).transform.rotation);
						}
						audioSource.PlayOneShot(interactionDeathSound);
						WalkieTalkie.TransmitOneShotAudio(audioSource, interactionDeathSound, 1f);
					}
					else
					{
						Plugin.Logger.LogInfo((object)"Clarity moment");
						if (((NetworkBehaviour)this).IsOwner)
						{
							((GrabbableObject)this).playerHeldBy.playerBodyAnimator.SetBool("useTZPItem", false);
							((GrabbableObject)this).playerHeldBy.activatingItem = false;
							((GrabbableObject)this).playerHeldBy.DamagePlayer(DamageNumber, true, true, (CauseOfDeath)0, 1, false, default(Vector3));
						}
						audioSource.PlayOneShot(interactionEndSound);
						WalkieTalkie.TransmitOneShotAudio(audioSource, interactionEndSound, 1f);
					}
					if (charges > 0)
					{
						charges--;
						fuel = 1f;
					}
					else
					{
						((GrabbableObject)this).itemProperties.creditsWorth = 10;
					}
				}
				else
				{
					fuel -= Time.deltaTime / TimeToEmpty;
				}
			}
			((GrabbableObject)this).Update();
		}

		public override void ItemActivate(bool used, bool buttonDown = true)
		{
			((GrabbableObject)this).ItemActivate(used, buttonDown);
			if (!((GrabbableObject)this).isBeingUsed)
			{
				((GrabbableObject)this).isBeingUsed = true;
				if ((double)fuel <= 0.0)
				{
					((GrabbableObject)this).isBeingUsed = false;
					audioSource.PlayOneShot(interactionEmptySound);
					WalkieTalkie.TransmitOneShotAudio(audioSource, interactionEmptySound, 1f);
					previousPlayerHeldBy.playerBodyAnimator.SetTrigger("shakeItem");
				}
				else
				{
					previousPlayerHeldBy = ((GrabbableObject)this).playerHeldBy;
					audioSource.PlayOneShot(interactionSound);
					WalkieTalkie.TransmitOneShotAudio(audioSource, interactionSound, 1f);
					runningOut = true;
					useTankardCoroutine = ((MonoBehaviour)this).StartCoroutine(TankardAnimation());
				}
			}
		}

		public override void EquipItem()
		{
			((PhysicsProp)this).EquipItem();
			StartOfRound.Instance.RefreshPlayerVoicePlaybackObjects();
			if ((Object)(object)((GrabbableObject)this).playerHeldBy != (Object)null)
			{
				previousPlayerHeldBy = ((GrabbableObject)this).playerHeldBy;
			}
		}

		[ServerRpc]
		public void RunOutOfFuelServerRpc()
		{
			RunOutOfFuelClientRpc();
		}

		[ClientRpc]
		public void RunOutOfFuelClientRpc()
		{
			previousPlayerHeldBy.playerBodyAnimator.SetBool("useTZPItem", false);
			((MonoBehaviour)this).StopCoroutine(useTankardCoroutine);
			previousPlayerHeldBy.activatingItem = false;
			((GrabbableObject)this).itemUsedUp = true;
			((GrabbableObject)this).isBeingUsed = false;
			runningOut = false;
			fuel = 0f;
		}

		public override void DiscardItem()
		{
			runningOut = false;
			((GrabbableObject)this).playerHeldBy.playerBodyAnimator.ResetTrigger("shakeItem");
			previousPlayerHeldBy.playerBodyAnimator.SetBool("useTZPItem", false);
			if ((Object)(object)previousPlayerHeldBy != (Object)null)
			{
				previousPlayerHeldBy.activatingItem = false;
			}
			((GrabbableObject)this).DiscardItem();
		}

		public IEnumerator TankardAnimation()
		{
			((GrabbableObject)this).playerHeldBy.activatingItem = true;
			((GrabbableObject)this).playerHeldBy.playerBodyAnimator.SetBool("useTZPItem", true);
			yield return (object)new WaitForSeconds(0.75f);
			HUDManager.Instance.gasHelmetAnimator.SetBool("gasEmitting", true);
		}
	}
}