Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of CuriosShenanigans v0.1.0
CuriosityPlugin.dll
Decompiled 2 years agousing 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); } } }