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 FairAI v1.5.8
FairAI.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using System.Threading.Tasks; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using FairAI; using FairAI.Component; using FairAI.Patches; using GameNetcodeStuff; using HarmonyLib; using LethalThings; using Microsoft.CodeAnalysis; using Unity.Netcode; using UnityEngine; using UnityEngine.AI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("FairAI")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("FairAI")] [assembly: AssemblyCopyright("Copyright © 2023")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("42deea12-f73e-4d63-81e9-5359e98c8d53")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.0.0")] [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; } } } internal class TurretAIPatch { private readonly struct TurretTarget { public readonly PlayerControllerB Player; public readonly EnemyAI Enemy; public static readonly TurretTarget None = default(TurretTarget); public bool IsPlayer => (Object)(object)Player != (Object)null; public bool IsEnemy => (Object)(object)Enemy != (Object)null; public bool IsValid => IsPlayer || IsEnemy; public bool IsDead => (IsPlayer && Player.isPlayerDead) || (IsEnemy && (Enemy.isEnemyDead || Enemy.enemyHP <= 0)); public Vector3 AimPosition => IsPlayer ? ((Component)Player.gameplayCamera).transform.position : (((Component)Enemy).transform.position + Vector3.up * 0.5f); public Transform AimTransform => IsPlayer ? ((Component)Player.gameplayCamera).transform : ((Component)Enemy).transform; public TurretTarget(PlayerControllerB p) { Player = p; Enemy = null; } public TurretTarget(EnemyAI e) { Player = null; Enemy = e; } } private const float DetectRange = 30f; private const int SweepRays = 7; private static readonly Type TurretType = typeof(Turret); private static bool HasCustomSettings => Plugin.turretSettings.Count > 7; private static float FireInterval => HasCustomSettings ? Setting(1) : 0.21f; private static float SwitchInterval => HasCustomSettings ? Setting(3) : 7f; private static float DetectSpeed => HasCustomSettings ? Setting(5) : 28f; private static float ChargeSpeed => HasCustomSettings ? Setting(6) : 95f; private static float BerserkSpeed => HasCustomSettings ? Setting(7) : 77f; private static int PlayerDamage => HasCustomSettings ? ((int)Setting(0)) : Plugin.GetInt("TurretConfig", "Player Damage"); private static T GetField<T>(Turret t, string name) { return (T)TurretType.GetField(name, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(t); } private static void SetField(Turret t, string name, object value) { TurretType.GetField(name, BindingFlags.Instance | BindingFlags.NonPublic).SetValue(t, value); } private static void CallMethod(Turret t, string name, params object[] args) { TurretType.GetMethod(name, BindingFlags.Instance | BindingFlags.NonPublic).Invoke(t, args); } private static float Setting(int index) { return Plugin.turretSettings[index]; } private static FAIR_AI GetAI(Turret turret) { return ((Component)turret).gameObject.GetComponent<FAIR_AI>() ?? ((Component)turret).gameObject.AddComponent<FAIR_AI>(); } private static TurretTarget GetCurrentTarget(Turret turret, FAIR_AI ai) { if ((Object)(object)ai.targetWithRotation != (Object)null && !ai.targetWithRotation.isEnemyDead) { return new TurretTarget(ai.targetWithRotation); } if ((Object)(object)turret.targetPlayerWithRotation != (Object)null && !turret.targetPlayerWithRotation.isPlayerDead) { return new TurretTarget(turret.targetPlayerWithRotation); } return TurretTarget.None; } private static void SetCurrentTarget(Turret turret, FAIR_AI ai, TurretTarget target) { turret.targetPlayerWithRotation = null; ai.targetWithRotation = null; if (target.IsPlayer) { turret.targetPlayerWithRotation = target.Player; } else if (target.IsEnemy) { ai.targetWithRotation = target.Enemy; turret.targetTransform = ((Component)target.Enemy).transform; } } private static void ClearTarget(Turret turret, FAIR_AI ai) { turret.targetPlayerWithRotation = null; ai.targetWithRotation = null; turret.targetTransform = null; ai.targetWithRotation = null; if (((NetworkBehaviour)turret).IsServer) { turret.RemoveTargetedPlayerClientRpc(); ai.RemoveTargetedEnemyClientRpc(); } } public static bool PatchUpdate(ref Turret __instance) { //IL_0012: 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) //IL_010e: 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_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Expected I4, but got Unknown //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_0248: 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) if ((Object)(object)__instance == (Object)null || !Plugin.AllowFairness(((Component)__instance).transform.position)) { return false; } Turret val = __instance; FAIR_AI aI = GetAI(val); if (!val.turretActive) { SetField(val, "wasTargetingPlayerLastFrame", false); val.turretMode = (TurretMode)0; ClearTarget(val, aI); return false; } TurretTarget currentTarget = GetCurrentTarget(val, aI); if (currentTarget.IsValid && !currentTarget.IsDead) { if (!GetField<bool>(val, "wasTargetingPlayerLastFrame")) { SetField(val, "wasTargetingPlayerLastFrame", true); if ((int)val.turretMode == 0) { val.turretMode = (TurretMode)1; } } SyncTargetTransform(val, aI, currentTarget); } else if (currentTarget.IsDead) { ClearTarget(val, aI); SetField(val, "wasTargetingPlayerLastFrame", false); val.turretMode = (TurretMode)0; } else if (GetField<bool>(val, "wasTargetingPlayerLastFrame")) { SetField(val, "wasTargetingPlayerLastFrame", false); val.turretMode = (TurretMode)0; } TurretMode turretMode = val.turretMode; TurretMode val2 = turretMode; switch ((int)val2) { case 0: DetectionFunction(val, aI); break; case 1: ChargingFunction(val, aI); break; case 2: FiringFunction(val, aI); break; case 3: BerserkFunction(val); break; } if (GetField<bool>(val, "rotatingClockwise")) { val.turnTowardsObjectCompass.localEulerAngles = new Vector3(-180f, val.turretRod.localEulerAngles.y - Time.deltaTime * 20f, 180f); } else if (GetField<bool>(val, "rotatingSmoothly")) { val.turnTowardsObjectCompass.localEulerAngles = new Vector3(-180f, Mathf.Clamp(val.targetRotation, 0f - val.rotationRange, val.rotationRange), 180f); } val.turretRod.rotation = Quaternion.RotateTowards(val.turretRod.rotation, val.turnTowardsObjectCompass.rotation, val.rotationSpeed * Time.deltaTime); return false; } private static void DetectionFunction(Turret turret, FAIR_AI ai) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 //IL_028d: Unknown result type (might be due to invalid IL or missing references) if ((int)GetField<TurretMode>(turret, "turretModeLastFrame") > 0) { SetField(turret, "turretModeLastFrame", (object)(TurretMode)0); SetField(turret, "rotatingClockwise", false); SetField(turret, "rotatingSmoothly", true); SetField(turret, "turretInterval", Random.Range(0f, 0.15f)); turret.mainAudio.Stop(); turret.farAudio.Stop(); turret.berserkAudio.Stop(); StopAndStartFadeBulletAudio(turret); turret.bulletParticles.Stop(true, (ParticleSystemStopBehavior)0); turret.rotationSpeed = DetectSpeed; turret.turretAnimator.SetInteger("TurretMode", 0); } if (!((NetworkBehaviour)turret).IsServer) { return; } float field = GetField<float>(turret, "switchRotationTimer"); if (field >= SwitchInterval) { SetField(turret, "switchRotationTimer", 0f); bool flag = !GetField<bool>(turret, "rotatingRight"); turret.SwitchRotationClientRpc(flag); turret.SwitchRotationOnInterval(flag); } else { SetField(turret, "switchRotationTimer", field + Time.deltaTime); } float field2 = GetField<float>(turret, "turretInterval"); if (field2 < 0.25f) { SetField(turret, "turretInterval", field2 + Time.deltaTime); return; } SetField(turret, "turretInterval", 0f); TurretTarget target = FindBestTarget(turret, angleRangeCheck: true); if (target.IsValid && (!target.IsEnemy || Plugin.CanMob("TurretTargetAllMobs", ".Turret Target", target.Enemy.enemyType.enemyName))) { SetCurrentTarget(turret, ai, target); if (target.IsEnemy) { ai.SwitchedTargetedEnemyClientRpc(turret, target.Enemy); Plugin.logger.LogInfo((object)("Turret: Detected enemy '" + target.Enemy.enemyType.enemyName + "', entering charging mode.")); } else { turret.SwitchTargetedPlayerClientRpc((int)target.Player.playerClientId, true); Plugin.logger.LogInfo((object)"Turret: Detected player, entering charging mode."); } CallMethod(turret, "SwitchTurretMode", (object)(TurretMode)1); turret.SetToModeClientRpc(1); turret.turretMode = (TurretMode)1; } } private static void ChargingFunction(Turret turret, FAIR_AI ai) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 if ((int)GetField<TurretMode>(turret, "turretModeLastFrame") != 1) { SetField(turret, "turretModeLastFrame", (object)(TurretMode)1); SetField(turret, "rotatingClockwise", false); SetField(turret, "rotatingSmoothly", false); SetField(turret, "lostLOSTimer", 0f); turret.mainAudio.PlayOneShot(turret.detectPlayerSFX); WalkieTalkie.TransmitOneShotAudio(turret.mainAudio, turret.detectPlayerSFX, 1f); turret.berserkAudio.Stop(); turret.rotationSpeed = ChargeSpeed; turret.turretAnimator.SetInteger("TurretMode", 1); } TurnTowardsTarget(turret, ai); if (!((NetworkBehaviour)turret).IsServer) { return; } float field = GetField<float>(turret, "turretInterval"); if (field < 1.5f) { SetField(turret, "turretInterval", field + Time.deltaTime); return; } SetField(turret, "turretInterval", 0f); TurretTarget target = FindBestTarget(turret, angleRangeCheck: false); if (!target.IsValid) { Plugin.logger.LogInfo((object)"Turret: Lost LOS during charge wind-up, returning to detection."); ClearTarget(turret, ai); return; } if (target.IsEnemy && !Plugin.CanMob("TurretTargetAllMobs", ".Turret Target", target.Enemy.enemyType.enemyName)) { ClearTarget(turret, ai); return; } SetCurrentTarget(turret, ai, target); Plugin.logger.LogInfo((object)"Turret: Charge complete, opening fire."); CallMethod(turret, "SwitchTurretMode", (object)(TurretMode)2); turret.SetToModeClientRpc(2); } private static void FiringFunction(Turret turret, FAIR_AI ai) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 //IL_0070: Unknown result type (might be due to invalid IL or missing references) if ((int)GetField<TurretMode>(turret, "turretModeLastFrame") != 2) { SetField(turret, "turretModeLastFrame", (object)(TurretMode)2); SetField(turret, "rotatingSmoothly", false); SetField(turret, "lostLOSTimer", 0f); turret.berserkAudio.Stop(); RoundManager.Instance.PlayAudibleNoise(((Component)turret.berserkAudio).transform.position, 15f, 0.9f, 0, false, 0); turret.mainAudio.clip = turret.firingSFX; turret.mainAudio.Play(); turret.farAudio.clip = turret.firingFarSFX; turret.farAudio.Play(); turret.bulletParticles.Play(true); turret.bulletCollisionAudio.Play(); StopAndStartFadeBulletAudio(turret); turret.bulletCollisionAudio.volume = 1f; turret.turretAnimator.SetInteger("TurretMode", 2); } TurnTowardsTarget(turret, ai); if (!GetField<bool>(turret, "hasLineOfSight")) { if (!((NetworkBehaviour)turret).IsServer) { return; } float num = GetField<float>(turret, "lostLOSTimer") + Time.deltaTime; SetField(turret, "lostLOSTimer", num); if (num >= 2f) { SetField(turret, "lostLOSTimer", 0f); TurretTarget target = FindBestTarget(turret, angleRangeCheck: false); if (target.IsValid && (!target.IsEnemy || Plugin.CanMob("TurretTargetAllMobs", ".Turret Target", target.Enemy.enemyType.enemyName))) { Plugin.logger.LogInfo((object)"Turret: Re-acquired target after LOS loss."); SetCurrentTarget(turret, ai, target); SetField(turret, "turretInterval", 0f); } else { Plugin.logger.LogInfo((object)"Turret: LOS lost for 2 s, no replacement — returning to detection."); ReturnToDetection(turret, ai); } } return; } SetField(turret, "lostLOSTimer", 0f); float field = GetField<float>(turret, "turretInterval"); if (field < FireInterval) { SetField(turret, "turretInterval", field + Time.deltaTime); return; } SetField(turret, "turretInterval", 0f); ApplyDamageToLocalPlayer(turret); PerformShootRaycast(turret, useCenterPoint: false); TurretTarget currentTarget = GetCurrentTarget(turret, ai); if (!currentTarget.IsValid || currentTarget.IsDead) { TurretTarget target2 = FindBestTarget(turret, angleRangeCheck: false); if (target2.IsValid && (!target2.IsEnemy || Plugin.CanMob("TurretTargetAllMobs", ".Turret Target", target2.Enemy.enemyType.enemyName))) { Plugin.logger.LogInfo((object)"Turret: Target died, acquired new target."); SetCurrentTarget(turret, ai, target2); } else { Plugin.logger.LogInfo((object)"Turret: Target died, no new targets — returning to detection."); ReturnToDetection(turret, ai); } } } private static void BerserkFunction(Turret turret) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 if ((int)GetField<TurretMode>(turret, "turretModeLastFrame") != 3) { SetField(turret, "turretModeLastFrame", (object)(TurretMode)3); SetField(turret, "rotatingClockwise", false); SetField(turret, "rotatingSmoothly", true); SetField(turret, "lostLOSTimer", 0f); SetField(turret, "wasTargetingPlayerLastFrame", false); SetField(turret, "berserkTimer", 1.3f); SetField(turret, "enteringBerserkMode", true); turret.targetPlayerWithRotation = null; turret.rotationSpeed = BerserkSpeed; turret.berserkAudio.Play(); turret.turretAnimator.SetInteger("TurretMode", 1); } if (GetField<bool>(turret, "enteringBerserkMode")) { float num = GetField<float>(turret, "berserkTimer") - Time.deltaTime; SetField(turret, "berserkTimer", num); if (num <= 0f) { SetField(turret, "enteringBerserkMode", false); SetField(turret, "rotatingClockwise", true); SetField(turret, "berserkTimer", 9f); turret.turretAnimator.SetInteger("TurretMode", 2); turret.mainAudio.clip = turret.firingSFX; turret.mainAudio.Play(); turret.farAudio.clip = turret.firingFarSFX; turret.farAudio.Play(); turret.bulletParticles.Play(true); turret.bulletCollisionAudio.Play(); StopAndStartFadeBulletAudio(turret); turret.bulletCollisionAudio.volume = 1f; } return; } float field = GetField<float>(turret, "turretInterval"); if (field >= FireInterval) { SetField(turret, "turretInterval", 0f); ApplyDamageToLocalPlayer(turret); PerformShootRaycast(turret, useCenterPoint: true); } else { SetField(turret, "turretInterval", field + Time.deltaTime); } if (((NetworkBehaviour)turret).IsServer) { float num2 = GetField<float>(turret, "berserkTimer") - Time.deltaTime; SetField(turret, "berserkTimer", num2); if (num2 <= 0f) { CallMethod(turret, "SwitchTurretMode", 0); turret.SetToModeClientRpc(0); } } } private static TurretTarget FindBestTarget(Turret turret, bool angleRangeCheck) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: 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_0040: Unknown result type (might be due to invalid IL or missing references) EnemyAI val = SweepForEnemy(turret); if ((Object)(object)val != (Object)null && !val.isEnemyDead && (!angleRangeCheck || WithinAngleRange(turret, ((Component)val).transform.position + Vector3.up * 0.5f))) { return new TurretTarget(val); } PlayerControllerB val2 = SweepForPlayer(turret, angleRangeCheck); if ((Object)(object)val2 != (Object)null && !val2.isPlayerDead) { return new TurretTarget(val2); } return TurretTarget.None; } private static EnemyAI SweepForEnemy(Turret turret) { //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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: 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_00a1: 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_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0146: 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_014c: Unknown result type (might be due to invalid IL or missing references) float rotationRange = turret.rotationRange; Vector3 val = Quaternion.Euler(0f, 0f - rotationRange, 0f) * turret.aimPoint.forward; float num = rotationRange * 2f / 6f; Ray val2 = default(Ray); for (int i = 0; i < 7; i++) { ((Ray)(ref val2))..ctor(turret.centerPoint.position, val); RaycastHit[] array = Physics.RaycastAll(val2, 30f, -5, (QueryTriggerInteraction)2); Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance)); RaycastHit[] array2 = array; for (int j = 0; j < array2.Length; j++) { RaycastHit val3 = array2[j]; if (Physics.Linecast(turret.centerPoint.position, ((RaycastHit)(ref val3)).point, StartOfRound.Instance.collidersAndRoomMask, (QueryTriggerInteraction)1)) { break; } EnemyAI val4 = ((Component)((RaycastHit)(ref val3)).transform).GetComponent<EnemyAI>() ?? ((Component)((RaycastHit)(ref val3)).transform).GetComponent<EnemyAICollisionDetect>()?.mainScript; if ((Object)(object)val4 != (Object)null && !val4.isEnemyDead && val4.enemyHP > 0) { return val4; } } val = Quaternion.Euler(0f, num, 0f) * val; } return null; } private static PlayerControllerB SweepForPlayer(Turret turret, bool angleRangeCheck) { //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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: 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_016a: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Invalid comparison between Unknown and I4 //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Invalid comparison between Unknown and I4 //IL_00b1: 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_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: 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_014c: Unknown result type (might be due to invalid IL or missing references) float rotationRange = turret.rotationRange; Vector3 val = Quaternion.Euler(0f, 0f - rotationRange, 0f) * turret.aimPoint.forward; float num = rotationRange * 2f / 6f; Ray val2 = default(Ray); RaycastHit val3 = default(RaycastHit); for (int i = 0; i < 7; i++) { ((Ray)(ref val2))..ctor(turret.centerPoint.position, val); if (Physics.Raycast(val2, ref val3, 30f, 1051400, (QueryTriggerInteraction)1)) { if (((Component)((RaycastHit)(ref val3)).transform).CompareTag("Player")) { PlayerControllerB component = ((Component)((RaycastHit)(ref val3)).transform).GetComponent<PlayerControllerB>(); if ((Object)(object)component != (Object)null) { if (angleRangeCheck && !WithinAngleRange(turret, ((Component)component).transform.position + Vector3.up * 1.75f)) { return null; } return component; } } else if (((int)turret.turretMode == 2 || (int)turret.turretMode == 3) && !GetField<bool>(turret, "enteringBerserkMode") && ((Component)((RaycastHit)(ref val3)).transform).tag.StartsWith("PlayerRagdoll")) { Rigidbody component2 = ((Component)((RaycastHit)(ref val3)).transform).GetComponent<Rigidbody>(); if (component2 != null) { component2.AddForce(((Vector3)(ref val)).normalized * 42f, (ForceMode)1); } } } val = Quaternion.Euler(0f, num, 0f) * val; } return null; } private static bool WithinAngleRange(Turret turret, Vector3 worldPos) { //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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) return Vector3.Angle(worldPos - turret.centerPoint.position, turret.forwardFacingPos.forward) <= turret.rotationRange; } private static void TurnTowardsTarget(Turret turret, FAIR_AI ai) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) TurretTarget currentTarget = GetCurrentTarget(turret, ai); if (currentTarget.IsValid && !currentTarget.IsDead) { SyncTargetTransform(turret, ai, currentTarget); bool flag = (Object)(object)turret.targetTransform != (Object)null && WithinAngleRange(turret, turret.targetTransform.position) && !Physics.Linecast(turret.aimPoint.position, currentTarget.AimPosition, StartOfRound.Instance.collidersAndRoomMask, (QueryTriggerInteraction)1); SetField(turret, "hasLineOfSight", flag); if (flag) { turret.tempTransform.position = currentTarget.AimPosition - Vector3.up * 0.15f; turret.turnTowardsObjectCompass.LookAt(turret.tempTransform); } } } private static void SyncTargetTransform(Turret turret, FAIR_AI ai, TurretTarget target) { if (target.IsPlayer) { turret.targetTransform = ((target.Player.isPlayerDead && (Object)(object)target.Player.deadBody != (Object)null) ? ((Component)target.Player.deadBody.bodyParts[5]).transform : ((Component)target.Player.gameplayCamera).transform); } else if (target.IsEnemy) { turret.targetTransform = ((Component)target.Enemy).transform; } } private static void ApplyDamageToLocalPlayer(Turret turret) { //IL_0031: 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_0046: 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_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController; if ((Object)(object)localPlayerController == (Object)null || localPlayerController.isPlayerDead) { return; } Ray val = default(Ray); ((Ray)(ref val))..ctor(turret.centerPoint.position, turret.aimPoint.forward); RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(val, ref val2, 30f, 1051400, (QueryTriggerInteraction)1) && ((Component)((RaycastHit)(ref val2)).transform).CompareTag("Player") && !((Object)(object)((Component)((RaycastHit)(ref val2)).transform).GetComponent<PlayerControllerB>() != (Object)(object)localPlayerController)) { int playerDamage = PlayerDamage; if (playerDamage <= 0) { localPlayerController.MakeCriticallyInjured(false); localPlayerController.DamagePlayer(playerDamage, false, true, (CauseOfDeath)0, 0, false, default(Vector3)); localPlayerController.MakeCriticallyInjured(false); } else if (localPlayerController.health > playerDamage) { localPlayerController.DamagePlayer(playerDamage, true, true, (CauseOfDeath)7, 0, false, default(Vector3)); } else { localPlayerController.KillPlayer(turret.aimPoint.forward * 40f, true, (CauseOfDeath)7, 0, default(Vector3), false); } } } private static void PerformShootRaycast(Turret turret, bool useCenterPoint) { //IL_0009: 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_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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_009d: 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_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: 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_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) Ray val = default(Ray); ((Ray)(ref val))..ctor(turret.aimPoint.position, turret.aimPoint.forward); SetField(turret, "shootRay", val); RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(val, ref val2, 30f, StartOfRound.Instance.collidersAndRoomMask, (QueryTriggerInteraction)1)) { SetField(turret, "hit", val2); ((Component)turret.bulletCollisionAudio).transform.position = ((Ray)(ref val)).GetPoint(((RaycastHit)(ref val2)).distance - 0.5f); } Vector3 aimPoint = (useCenterPoint ? turret.centerPoint.position : turret.aimPoint.position); Vector3 forward = Quaternion.Euler(0f, (float)(-(int)turret.rotationRange) / 3f, 0f) * turret.aimPoint.forward; Plugin.AttackTargets(((Component)turret).GetComponent<FAIR_AI>(), aimPoint, forward, 30f); } private static void ReturnToDetection(Turret turret, FAIR_AI ai) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) ClearTarget(turret, ai); turret.turretMode = (TurretMode)0; turret.SetToModeClientRpc(0); SetField(turret, "wasTargetingPlayerLastFrame", false); SetField(turret, "targetingDeadPlayer", true); turret.turretAnimator.SetInteger("TurretMode", 0); CallMethod(turret, "SwitchTurretMode", (object)(TurretMode)0); } public static bool CheckForTargetsInLOS(ref Turret __instance, float radius = 2f, bool angleRangeCheck = false) { FAIR_AI aI = GetAI(__instance); TurretTarget turretTarget = FindBestTarget(__instance, angleRangeCheck); if (!turretTarget.IsValid) { return false; } aI.targets = new Dictionary<int, GameObject> { { 0, turretTarget.IsPlayer ? ((Component)turretTarget.Player).gameObject : ((Component)turretTarget.Enemy).gameObject } }; return true; } public static bool SetTargetToEnemyBody(ref Turret __instance) { if ((Object)(object)__instance == (Object)null) { return false; } FAIR_AI aI = GetAI(__instance); SyncTargetTransform(__instance, aI, GetCurrentTarget(__instance, aI)); return false; } public static bool TurnTowardsTargetEnemyIfHasLOS(ref Turret __instance) { if ((Object)(object)__instance == (Object)null) { return false; } TurnTowardsTarget(__instance, GetAI(__instance)); return false; } private static void StopAndStartFadeBulletAudio(Turret turret) { FieldInfo field = TurretType.GetField("fadeBulletAudioCoroutine", BindingFlags.Instance | BindingFlags.NonPublic); object? obj = field?.GetValue(turret); Coroutine val = (Coroutine)((obj is Coroutine) ? obj : null); if (val != null) { ((MonoBehaviour)turret).StopCoroutine(val); } MethodInfo method = TurretType.GetMethod("FadeBulletAudio", BindingFlags.Instance | BindingFlags.NonPublic); field?.SetValue(turret, ((MonoBehaviour)turret).StartCoroutine((IEnumerator)method.Invoke(turret, null))); } } namespace FairAI { public class FAIR_AI : NetworkBehaviour { public EnemyAI targetWithRotation; public Dictionary<int, GameObject> targets; private void Awake() { targetWithRotation = null; } [ClientRpc] public void SwitchedTargetedEnemyClientRpc(Turret turret, EnemyAI enemy, bool setModeToCharging = false) { targetWithRotation = enemy; if (setModeToCharging) { Type typeFromHandle = typeof(Turret); MethodInfo method = typeFromHandle.GetMethod("SwitchTurretMode", BindingFlags.Instance | BindingFlags.NonPublic); method.Invoke(turret, new object[1] { 2 }); } } [ClientRpc] public void RemoveTargetedEnemyClientRpc() { targetWithRotation = null; } } [BepInPlugin("GoldenKitten.FairAI", "Fair AI", "1.5.8")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { private const string modGUID = "GoldenKitten.FairAI"; private const string modName = "Fair AI"; private const string modVersion = "1.5.8"; private Harmony harmony = new Harmony("GoldenKitten.FairAI"); private static readonly float onMeshThreshold = 3f; public static Plugin Instance = null; public static ManualLogSource logger; public static List<EnemyType> allEnemies; public static List<EnemyType> enemies; public static List<Item> items; public static List<EnemyType> enemyList; public static List<Item> itemList; public static List<float> turretSettings; public static Dictionary<string, float[]> speeds; public static Dictionary<int, Vector3> positions; public static Dictionary<int, float> sinkingValues; public static Dictionary<int, float> sinkingProgress; public static Assembly codeRebirthAssembly; public static Assembly lethalConfigAssembly; public static Assembly lguAssembly; public static Assembly surfacedAssembly; public static Assembly turretSettingsAssembly; public static Type rubberBootsType; public static PropertyInfo tsBoundConfig; public const string ltModID = "evaisa.lethalthings"; public const string surfacedModID = "Surfaced"; public static bool codeRebirthEnabled = false; public static bool lethalConfigEnabled = false; public static bool lethalThingsEnabled = false; public static bool lguEnabled = false; public static bool playersEnteredInside = false; public static bool roundHasStarted = false; public static bool surfacedEnabled = false; public static bool turretSettingsEnabled = false; public static int wallsAndEnemyLayerMask = 524288; public static int enemyMask = 524288; public static int allHittablesMask; private async void Awake() { if ((Object)(object)Instance == (Object)null) { Instance = this; } logger = Logger.CreateLogSource("GoldenKitten.FairAI"); allEnemies = new List<EnemyType>(); enemies = new List<EnemyType>(); items = new List<Item>(); itemList = new List<Item>(); enemyList = new List<EnemyType>(); speeds = new Dictionary<string, float[]>(); positions = new Dictionary<int, Vector3>(); sinkingProgress = new Dictionary<int, float>(); turretSettings = new List<float>(); sinkingValues = new Dictionary<int, float>(); harmony = new Harmony("GoldenKitten.FairAI"); harmony.PatchAll(typeof(Plugin)); Patch(typeof(RoundManager), "Start", null, typeof(RoundManagerPatch), "PatchStart", isPrefix: false); Patch(typeof(StartOfRound), "Awake", null, typeof(LevelGenManPatch), "PatchAwake", isPrefix: false); Patch(typeof(StartOfRound), "Start", null, typeof(StartOfRoundPatch), "PatchStart", isPrefix: false); Patch(typeof(StartOfRound), "Update", null, typeof(StartOfRoundPatch), "PatchUpdate", isPrefix: false); Patch(typeof(FlowermanAI), "HitEnemy", new Type[4] { typeof(int), typeof(PlayerControllerB), typeof(bool), typeof(int) }, typeof(EnemyAIPatch), "BrackenHitEnemyPatch", isPrefix: true); Patch(typeof(HoarderBugAI), "HitEnemy", new Type[4] { typeof(int), typeof(PlayerControllerB), typeof(bool), typeof(int) }, typeof(EnemyAIPatch), "HoardingBugHitEnemyPatch", isPrefix: true); Patch(typeof(EnemyAI), "KillEnemyOnOwnerClient", new Type[1] { typeof(bool) }, typeof(EnemyAIPatch), "KillEnemyOnOwnerClientPatch", isPrefix: false); Patch(typeof(QuicksandTrigger), "OnTriggerStay", new Type[1] { typeof(Collider) }, typeof(QuickSandPatch), "OnTriggerStayPatch", isPrefix: true); Patch(typeof(QuicksandTrigger), "StopSinkingLocalPlayer", new Type[1] { typeof(PlayerControllerB) }, typeof(QuickSandPatch), "StopSinkingLocalPlayerPatch", isPrefix: true); Patch(typeof(QuicksandTrigger), "OnTriggerExit", new Type[1] { typeof(Collider) }, typeof(QuickSandPatch), "OnTriggerExitPatch", isPrefix: true); Patch(typeof(Turret), "Update", null, typeof(TurretAIPatch), "PatchUpdate", isPrefix: true); Patch(typeof(Turret), "CheckForPlayersInLineOfSight", new Type[2] { typeof(float), typeof(bool) }, typeof(TurretAIPatch), "CheckForTargetsInLOS", isPrefix: true); Patch(typeof(Turret), "SetTargetToPlayerBody", null, typeof(TurretAIPatch), "SetTargetToEnemyBody", isPrefix: true); Patch(typeof(Turret), "TurnTowardsTargetIfHasLOS", null, typeof(TurretAIPatch), "TurnTowardsTargetEnemyIfHasLOS", isPrefix: true); Patch(typeof(Landmine), "SpawnExplosion", new Type[8] { typeof(Vector3), typeof(bool), typeof(float), typeof(float), typeof(int), typeof(float), typeof(GameObject), typeof(bool) }, typeof(MineAIPatch), "PatchSpawnExplosion", isPrefix: false); Patch(typeof(Landmine), "OnTriggerEnter", null, typeof(MineAIPatch), "PatchOnTriggerEnter", isPrefix: false); Patch(typeof(Landmine), "OnTriggerExit", null, typeof(MineAIPatch), "PatchOnTriggerExit", isPrefix: false); Patch(typeof(Landmine), "Detonate", null, typeof(MineAIPatch), "DetonatePatch", isPrefix: false); await WaitForProcess(1); GetTurretSettings(); logger.LogInfo((object)"Fair AI initiated!"); } private void Patch(Type type, string method, Type[] parameters, Type patchType, string patchMethod, bool isPrefix) { CreateHarmonyPatch(harmony, type, method, parameters, patchType, patchMethod, isPrefix); } public static void ImmortalAffected() { if (!GetBool("General", "ImmortalAffected")) { enemies = (from EnemyType e in Resources.FindObjectsOfTypeAll(typeof(EnemyType)) where (Object)(object)e != (Object)null && e.canDie select e).ToList(); } allEnemies = (from EnemyType e in Resources.FindObjectsOfTypeAll(typeof(EnemyType)) where (Object)(object)e != (Object)null select e).ToList(); } public static float[] SpeedAndAccelerationEnemyList(EnemyAICollisionDetect enemy) { if ((Object)(object)enemy?.mainScript?.enemyType == (Object)null) { logger.LogWarning((object)"No valid enemy to get speeds!"); return new float[2] { 1f, 1f }; } string key = RemoveInvalidCharacters(enemy.mainScript.enemyType.enemyName); if (speeds.TryGetValue(key, out var value)) { return value; } NavMeshAgent componentInChildren = ((Component)enemy.mainScript).GetComponentInChildren<NavMeshAgent>(); float[] array = ((!((Object)(object)componentInChildren != (Object)null)) ? new float[2] { 1f, 1f } : new float[2] { componentInChildren.speed, componentInChildren.acceleration }); speeds[key] = array; return array; } public static float[] GetSpeeds(string name) { if (speeds.TryGetValue(name, out var value)) { return value; } logger.LogWarning((object)("Speeds missing on: " + name)); return null; } public static void GetTurretSettings() { if (!turretSettingsEnabled) { turretSettings = new List<float>(8) { 50f, 0.21f, 0f, 7f, 0f, 28f, 95f, 77f }; return; } object value = tsBoundConfig.GetValue(null); if (value == null) { logger.LogInfo((object)"Unable to get BoundConfig"); return; } Type type = value.GetType(); turretSettings.Clear(); string[] array = new string[8] { "turretDamage", "turretFireRate", "turretWarmupTime", "turretRotateTimer", "turretRotationRange", "turretIdleRotationSpeed", "turretFiringRotationSpeed", "turretBerzerkRotationSpeed" }; string[] array2 = array; foreach (string name in array2) { FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public); if (!(field == null)) { object value2 = field.GetValue(value); PropertyInfo propertyInfo = value2?.GetType().GetProperty("Value"); if (!(propertyInfo == null)) { object value3 = propertyInfo.GetValue(value2); turretSettings.Add((value3 is int num) ? ((float)num) : ((float)value3)); } } } logger.LogInfo((object)$"Got Turret Settings: {turretSettings.Count}"); } public static async Task<IEnumerable<int>> WaitForProcess(int waitTime) { await Task.Delay(waitTime); await Instance.DelayedInitialization(); return Array.Empty<int>(); } private async Task DelayedInitialization() { await Task.Run(delegate { TryLoadCodeRebirth(); TryLoadLategameUpgrades(); TryLoadLethalConfig(); TryLoadLethalThings(); TryLoadSurfaced(); TryLoadTurretSettings(); logger.LogInfo((object)"Optional Components initiated!"); }); } private void TryLoadLethalThings() { TryLoadAssembly("LethalThings", ref lethalThingsEnabled, delegate(Assembly assembly) { Type type = assembly.GetType("LethalThings.RoombaAI"); if (!(type == null) && BoombaPatch.enabled) { Patch(type, "Start", null, typeof(BoombaPatch), "PatchStart", isPrefix: false); Patch(type, "DoAIInterval", null, typeof(BoombaPatch), "PatchDoAIInterval", isPrefix: false); lethalThingsEnabled = true; } }); } private void TryLoadSurfaced() { TryLoadAssembly("Surfaced", ref surfacedEnabled, delegate(Assembly assembly) { surfacedAssembly = assembly; if (SurfacedMinePatch.enabled) { Type type = assembly.GetType("Seamine"); if (type != null) { Patch(type, "OnTriggerEnter", new Type[1] { typeof(Collider) }, typeof(SurfacedMinePatch), "PatchOnTriggerEnter", isPrefix: false); surfacedEnabled = true; logger.LogInfo((object)"Surfaced Component Seamine Initiated!"); } Type type2 = assembly.GetType("Bertha"); if (type2 != null) { Patch(type2, "OnTriggerEnter", new Type[1] { typeof(Collider) }, typeof(SurfacedMinePatch), "PatchBerthaOnTriggerEnter", isPrefix: false); surfacedEnabled = true; logger.LogInfo((object)"Surfaced Component Bertha Initiated!"); } } }); } private void TryLoadTurretSettings() { try { Assembly assembly = Assembly.Load("TheNameIsTyler.TurretSettings"); if (!(assembly == null)) { turretSettingsAssembly = assembly; PropertyInfo propertyInfo = assembly.GetType("TurretSettings.TurretSettings")?.GetProperty("BoundConfig", BindingFlags.Static | BindingFlags.NonPublic); if (propertyInfo != null) { tsBoundConfig = propertyInfo; turretSettingsEnabled = true; logger.LogInfo((object)"TurretSettings Component Initiated!"); } } } catch (Exception e) { LogOptionalError("TurretSettings", e); } } private void TryLoadLategameUpgrades() { try { Assembly assembly = Assembly.Load("MoreShipUpgrades"); if (!(assembly == null)) { lguAssembly = assembly; Type type = assembly.GetType("MoreShipUpgrades.UpgradeComponents.TierUpgrades.Player.RubberBoots"); if (type?.GetMethod("ReduceMovementHinderance") != null) { rubberBootsType = type; lguEnabled = true; logger.LogInfo((object)"LategameUpgrades Component Initiated!"); } } } catch (Exception e) { LogOptionalError("LategameUpgrades", e); } } private void TryLoadLethalConfig() { TryLoadAssembly("LethalConfig", ref lethalConfigEnabled, delegate(Assembly assembly) { lethalConfigAssembly = assembly; if (assembly.GetType("LethalConfig.LethalConfigManager") != null) { lethalConfigEnabled = true; logger.LogInfo((object)"LethalConfig Component Initiated!"); } }); } private void TryLoadCodeRebirth() { TryLoadAssembly("CodeRebirth", ref codeRebirthEnabled, delegate(Assembly assembly) { codeRebirthAssembly = assembly; if (assembly.GetType("CodeRebirth.CodeRebirthEnemyKeys.CutieFly") != null) { codeRebirthEnabled = true; logger.LogInfo((object)"CodeRebirth Component Initiated!"); } }); } private void TryLoadAssembly(string assemblyName, ref bool enabledFlag, Action<Assembly> onFound) { try { Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == assemblyName); if (assembly != null) { onFound(assembly); } else { logger.LogWarning((object)(assemblyName + " assembly not found. Skipping optional patch.")); } } catch (Exception e) { LogOptionalError(assemblyName, e); } } private static void LogOptionalError(string name, Exception e) { if (!e.Message.Contains("Could not load the file")) { logger.LogError((object)("An error occurred while trying to apply patches for " + name + ": " + e.Message)); } } public static List<PlayerControllerB> GetActivePlayers() { return StartOfRound.Instance.allPlayerScripts.Where((PlayerControllerB p) => (Object)(object)p != (Object)null && !p.isPlayerDead && ((Behaviour)p).isActiveAndEnabled && p.isPlayerControlled).ToList(); } public static bool AllowFairness(Vector3 position) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)StartOfRound.Instance == (Object)null) { return true; } if (!Can("CheckForPlayersInside")) { return true; } if (!StartOfRound.Instance.shipHasLanded) { return true; } if (!IsAPlayersOutside()) { goto IL_006d; } if (!(position.y > -80f)) { Bounds bounds = StartOfRound.Instance.shipInnerRoomBounds.bounds; if (!((Bounds)(ref bounds)).Contains(position)) { goto IL_006d; } } int result = 1; goto IL_0075; IL_006d: result = (playersEnteredInside ? 1 : 0); goto IL_0075; IL_0075: return (byte)result != 0; } public static bool IsAPlayersOutside() { if (!StartOfRound.Instance.shipHasLanded) { return false; } return GetActivePlayers().Any((PlayerControllerB p) => !p.isInsideFactory); } public static bool IsAPlayerInsideShip() { if (!StartOfRound.Instance.shipHasLanded) { return false; } return GetActivePlayers().Any((PlayerControllerB p) => p.isInHangarShipRoom); } public static bool IsAPlayerInsideDungeon() { if (!StartOfRound.Instance.shipHasLanded) { return false; } return GetActivePlayers().Any((PlayerControllerB p) => p.isInsideFactory); } public static bool CanMob(string parentIdentifier, string identifier, string mobName) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown if (!((BaseUnityPlugin)Instance).Config[new ConfigDefinition("Mobs", parentIdentifier)].BoxedValue.ToString().Equals("TRUE", StringComparison.OrdinalIgnoreCase)) { return false; } string text = RemoveInvalidCharacters(mobName).ToUpper(); string target = RemoveInvalidCharacters(text + identifier).ToUpper(); return ((BaseUnityPlugin)Instance).Config.Keys.Where((ConfigDefinition e) => RemoveInvalidCharacters(e.Key.ToUpper()) == target).Any((ConfigDefinition e) => ((BaseUnityPlugin)Instance).Config[e].BoxedValue.ToString().Equals("TRUE", StringComparison.OrdinalIgnoreCase)); } public static bool Can(string identifier) { string target = RemoveInvalidCharacters(identifier.ToUpper()); return ((BaseUnityPlugin)Instance).Config.Keys.Where((ConfigDefinition e) => RemoveInvalidCharacters(e.Key.ToUpper()) == target).Any((ConfigDefinition e) => ((BaseUnityPlugin)Instance).Config[e].BoxedValue.ToString().Equals("TRUE", StringComparison.OrdinalIgnoreCase)); } public static int GetInt(string parentIdentifier, string identifier) { try { int.TryParse(((BaseUnityPlugin)Instance).Config[parentIdentifier, identifier].BoxedValue.ToString(), out var result); return result; } catch { return 1; } } public static float GetFloat(string parentIdentifier, string identifier) { try { float.TryParse(((BaseUnityPlugin)Instance).Config[parentIdentifier, identifier].BoxedValue.ToString(), out var result); return result; } catch { return 1f; } } public static bool GetBool(string parentIdentifier, string identifier) { return ((BaseUnityPlugin)Instance).Config[parentIdentifier, identifier].BoxedValue.ToString().Equals("TRUE", StringComparison.OrdinalIgnoreCase); } public static string RemoveWhitespaces(string source) { return string.Join("", source.Split((string[]?)null, StringSplitOptions.RemoveEmptyEntries)); } public static string RemoveSpecialCharacters(string source) { StringBuilder stringBuilder = new StringBuilder(); foreach (char c in source) { if (char.IsLetterOrDigit(c)) { stringBuilder.Append(c); } } return stringBuilder.ToString(); } public static string RemoveInvalidCharacters(string source) { return RemoveWhitespaces(RemoveSpecialCharacters(source)); } public static Type FindType(string fullName) { try { return (from a in AppDomain.CurrentDomain.GetAssemblies() where !a.IsDynamic select a).SelectMany((Assembly a) => a.GetTypes()).FirstOrDefault((Type t) => t.FullName.Equals(fullName)); } catch { return null; } } public static void CreateHarmonyPatch(Harmony harmony, Type typeToPatch, string methodToPatch, Type[] parameters, Type patchType, string patchMethod, bool isPrefix, bool isTranspiler = false) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Expected O, but got Unknown //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown if (typeToPatch == null || patchType == null) { logger.LogInfo((object)"Type is either incorrect or does not exist!"); return; } MethodInfo methodInfo = AccessTools.Method(typeToPatch, methodToPatch, parameters, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(patchType, patchMethod, (Type[])null, (Type[])null); if (isTranspiler) { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null); } else if (isPrefix) { harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } else { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } public static bool IsAgentOnNavMesh(GameObject agentObject) { //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_000d: 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_002e: 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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) Vector3 position = agentObject.transform.position; NavMeshHit val = default(NavMeshHit); if (!NavMesh.SamplePosition(position, ref val, onMeshThreshold, -1)) { return false; } return Mathf.Approximately(position.x, ((NavMeshHit)(ref val)).position.x) && Mathf.Approximately(position.z, ((NavMeshHit)(ref val)).position.z) && position.y >= ((NavMeshHit)(ref val)).position.y; } public static List<GameObject> GetTargets(FAIR_AI turret_ai, Vector3 aimPoint, Vector3 forward, float range) { //IL_0038: 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_0064: 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_006c: 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_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) List<GameObject> list = new List<GameObject>(); HashSet<GameObject> hashSet = new HashSet<GameObject>(); float num = ((Component)turret_ai).GetComponent<Turret>()?.rotationRange ?? 45f; int num2 = 7; Vector3 val = Quaternion.Euler(0f, (0f - num) / 3f, 0f) * forward; float num3 = num / 3f * 2f / (float)(num2 - 1); Ray val2 = default(Ray); IHittable val5 = default(IHittable); EnemyAI val7 = default(EnemyAI); for (int i = 0; i < num2; i++) { ((Ray)(ref val2))..ctor(aimPoint, val); RaycastHit[] array = Physics.RaycastAll(val2, range, -5, (QueryTriggerInteraction)2); Array.Sort(array, (RaycastHit x, RaycastHit y) => ((RaycastHit)(ref x)).distance.CompareTo(((RaycastHit)(ref y)).distance)); Vector3 val3 = aimPoint + val * range; RaycastHit[] array2 = array; for (int j = 0; j < array2.Length; j++) { RaycastHit val4 = array2[j]; Transform transform = ((RaycastHit)(ref val4)).transform; if (((Component)transform).TryGetComponent<IHittable>(ref val5)) { EnemyAICollisionDetect val6 = (EnemyAICollisionDetect)(object)((val5 is EnemyAICollisionDetect) ? val5 : null); if (val6 != null) { EnemyAI mainScript = val6.mainScript; if ((Object)(object)mainScript != (Object)null && !mainScript.isEnemyDead && mainScript.enemyHP > 0 && hashSet.Add(((Component)transform).gameObject)) { list.Add(((Component)transform).gameObject); } } else if (!(val5 is PlayerControllerB) && !(val5 is SandSpiderWebTrap) && (!(val5 is Turret) || GetBool("TurretConfig", "HitOtherTurrets"))) { val5.Hit(1, val3, (PlayerControllerB)null, false, -1); } val3 = ((RaycastHit)(ref val4)).point; } else { if (((Component)transform).TryGetComponent<EnemyAI>(ref val7) && !val7.isEnemyDead && val7.enemyHP > 0 && hashSet.Add(((Component)transform).gameObject)) { list.Add(((Component)transform).gameObject); } val3 = ((RaycastHit)(ref val4)).point; } } val = Quaternion.Euler(0f, num3, 0f) * val; } return list; } public static List<EnemyAICollisionDetect> GetEnemyTargets(List<GameObject> originalTargets) { List<EnemyAICollisionDetect> list = new List<EnemyAICollisionDetect>(); EnemyAICollisionDetect item = default(EnemyAICollisionDetect); foreach (GameObject originalTarget in originalTargets) { if ((Object)(object)originalTarget == (Object)null) { continue; } if (originalTarget.TryGetComponent<EnemyAICollisionDetect>(ref item)) { list.Add(item); continue; } EnemyAICollisionDetect componentInChildren = originalTarget.GetComponentInChildren<EnemyAICollisionDetect>(); if ((Object)(object)componentInChildren != (Object)null) { list.Add(componentInChildren); } } return list; } public static bool AttackTargets(FAIR_AI turret_ai, Vector3 aimPoint, Vector3 forward, float range) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) return HitTargets(GetTargets(turret_ai, aimPoint, forward, range), forward); } public static bool HitTargets(List<GameObject> targets, Vector3 forward) { //IL_00d5: 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) //IL_0138: Unknown result type (might be due to invalid IL or missing references) if (!targets.Any()) { return false; } bool result = false; IHittable val3 = default(IHittable); foreach (GameObject target in targets) { if ((Object)(object)target == (Object)null) { continue; } EnemyAI val = target.GetComponent<EnemyAI>() ?? target.GetComponent<EnemyAICollisionDetect>()?.mainScript; if ((Object)(object)val != (Object)null) { if (CanMob("TurretDamageAllMobs", ".Turret Damage", val.enemyType.enemyName)) { int @int = GetInt("TurretConfig", "Enemy Damage"); NutcrackerEnemyAI val2 = (NutcrackerEnemyAI)(object)((val is NutcrackerEnemyAI) ? val : null); if (val2 == null || ((EnemyAI)val2).currentBehaviourStateIndex > 0) { val.HitEnemyOnLocalClient(@int, default(Vector3), (PlayerControllerB)null, false, -1); result = true; } } } else if (target.TryGetComponent<IHittable>(ref val3) && !(val3 is PlayerControllerB) && (!(val3 is Turret) || GetBool("TurretConfig", "HitOtherTurrets"))) { val3.Hit(1, forward, (PlayerControllerB)null, true, -1); result = true; } } return result; } } public class Utils { [CompilerGenerated] private sealed class <WaitForTime>d__2 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Action onComplete; public float timeToWait; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <WaitForTime>d__2(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(timeToWait); <>1__state = 1; return true; case 1: <>1__state = -1; onComplete?.Invoke(); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public static void AddLethalConfigBoolItem(ConfigEntry<bool> tempEntry) { Type type = Plugin.lethalConfigAssembly.GetType("LethalConfig.ConfigItems.BoolCheckBoxConfigItem"); ConstructorInfo constructor = type.GetConstructor(new Type[1] { typeof(ConfigEntry<bool>) }); object obj = constructor.Invoke(new object[1] { tempEntry }); Type type2 = Plugin.lethalConfigAssembly.GetType("LethalConfig.LethalConfigManager"); MethodInfo method = type2.GetMethod("AddConfigItem", new Type[1] { type.BaseType }); method.Invoke(null, new object[1] { obj }); } public static void AddLethalConfigFloatItem(ConfigEntry<float> tempEntry) { Type type = Plugin.lethalConfigAssembly.GetType("LethalConfig.ConfigItems.FloatInputFieldConfigItem"); ConstructorInfo constructor = type.GetConstructor(new Type[1] { typeof(ConfigEntry<float>) }); object obj = constructor.Invoke(new object[1] { tempEntry }); Type type2 = Plugin.lethalConfigAssembly.GetType("LethalConfig.LethalConfigManager"); MethodInfo method = type2.GetMethod("AddConfigItem", new Type[1] { type.BaseType }); method.Invoke(null, new object[1] { obj }); } [IteratorStateMachine(typeof(<WaitForTime>d__2))] public static IEnumerator WaitForTime(Action onComplete, float timeToWait) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <WaitForTime>d__2(0) { onComplete = onComplete, timeToWait = timeToWait }; } public static bool WaitInSeconds(float timeToWait, MonoBehaviour objectToTime = null) { if ((Object)(object)objectToTime == (Object)null) { objectToTime = (MonoBehaviour)(object)Plugin.Instance; } bool done = false; objectToTime.StartCoroutine(WaitForTime(delegate { done = true; }, timeToWait)); return done; } public static void SetupConfig() { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Expected O, but got Unknown //IL_034a: Unknown result type (might be due to invalid IL or missing references) //IL_0354: Expected O, but got Unknown //IL_03ab: Unknown result type (might be due to invalid IL or missing references) //IL_03b5: Expected O, but got Unknown //IL_040c: Unknown result type (might be due to invalid IL or missing references) //IL_0416: Expected O, but got Unknown //IL_046d: Unknown result type (might be due to invalid IL or missing references) //IL_0477: Expected O, but got Unknown //IL_04ce: Unknown result type (might be due to invalid IL or missing references) //IL_04d8: Expected O, but got Unknown //IL_052f: Unknown result type (might be due to invalid IL or missing references) //IL_0539: Expected O, but got Unknown //IL_058c: Unknown result type (might be due to invalid IL or missing references) //IL_0596: Expected O, but got Unknown //IL_05e9: Unknown result type (might be due to invalid IL or missing references) //IL_05f3: Expected O, but got Unknown //IL_0646: Unknown result type (might be due to invalid IL or missing references) //IL_0650: Expected O, but got Unknown //IL_06a3: Unknown result type (might be due to invalid IL or missing references) //IL_06ad: Expected O, but got Unknown //IL_0700: Unknown result type (might be due to invalid IL or missing references) //IL_070a: Expected O, but got Unknown //IL_075d: Unknown result type (might be due to invalid IL or missing references) //IL_0767: Expected O, but got Unknown //IL_07ba: Unknown result type (might be due to invalid IL or missing references) //IL_07c4: Expected O, but got Unknown //IL_0817: Unknown result type (might be due to invalid IL or missing references) //IL_0821: Expected O, but got Unknown //IL_08a5: Unknown result type (might be due to invalid IL or missing references) //IL_08af: Expected O, but got Unknown //IL_09d2: Unknown result type (might be due to invalid IL or missing references) //IL_09dc: Expected O, but got Unknown //IL_0a43: Unknown result type (might be due to invalid IL or missing references) //IL_0a4d: Expected O, but got Unknown //IL_0ab4: Unknown result type (might be due to invalid IL or missing references) //IL_0abe: Expected O, but got Unknown //IL_0b25: Unknown result type (might be due to invalid IL or missing references) //IL_0b2f: Expected O, but got Unknown //IL_0b96: Unknown result type (might be due to invalid IL or missing references) //IL_0ba0: Expected O, but got Unknown //IL_0c07: Unknown result type (might be due to invalid IL or missing references) //IL_0c11: Expected O, but got Unknown if (!Plugin.itemList.SequenceEqual(Plugin.items) || Plugin.items.Count == 0) { Plugin.items = Resources.FindObjectsOfTypeAll<Item>().ToList(); Plugin.itemList = Plugin.items; } Plugin.allHittablesMask = StartOfRound.Instance.collidersRoomMaskDefaultAndPlayers | 0x280008 | Plugin.enemyMask; if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("General", "ImmortalAffected"))) { ConfigEntry<bool> tempEntry = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("General", "ImmortalAffected", false, "If set to on/true immortal enemies will be targeted and trip off traps."); if (Plugin.lethalConfigEnabled) { AddLethalConfigBoolItem(tempEntry); } if (Plugin.enemies.Count == 0) { if (!Plugin.GetBool("General", "ImmortalAffected")) { Plugin.enemies = (from e in Resources.FindObjectsOfTypeAll<EnemyType>() where e.canDie select e).ToList(); Plugin.allEnemies = (from EnemyType e in Resources.FindObjectsOfTypeAll(typeof(EnemyType)) where (Object)(object)e != (Object)null select e).ToList(); Plugin.enemyList = Plugin.enemies; } else { Plugin.enemies = (from e in Resources.FindObjectsOfTypeAll<EnemyType>() where (Object)(object)e != (Object)null select e).ToList(); Plugin.allEnemies = (from EnemyType e in Resources.FindObjectsOfTypeAll(typeof(EnemyType)) where (Object)(object)e != (Object)null select e).ToList(); Plugin.enemyList = Plugin.enemies; } } else if (!Plugin.enemyList.SequenceEqual(Plugin.enemies)) { if (!Plugin.GetBool("General", "ImmortalAffected")) { Plugin.enemies = (from e in Resources.FindObjectsOfTypeAll<EnemyType>() where (Object)(object)e != (Object)null && e.canDie select e).ToList(); Plugin.allEnemies = (from EnemyType e in Resources.FindObjectsOfTypeAll(typeof(EnemyType)) where (Object)(object)e != (Object)null select e).ToList(); Plugin.enemyList = Plugin.enemies; } else { Plugin.enemies = (from e in Resources.FindObjectsOfTypeAll<EnemyType>() where (Object)(object)e != (Object)null select e).ToList(); Plugin.allEnemies = (from EnemyType e in Resources.FindObjectsOfTypeAll(typeof(EnemyType)) where (Object)(object)e != (Object)null select e).ToList(); Plugin.enemyList = Plugin.enemies; } } } if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("ExplosionConfig", "Damage"))) { ConfigEntry<float> tempEntry2 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<float>("ExplosionConfig", "Damage", 1f, "Damage explosions will do outside the kill radius"); if (Plugin.lethalConfigEnabled) { AddLethalConfigFloatItem(tempEntry2); } } if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Quick Sand Config", "Sink Time"))) { ConfigEntry<float> tempEntry3 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<float>("Quick Sand Config", "Sink Time", 5f, "Time Until A Enemy Is Considered Sunk And Will Be Killed"); if (Plugin.lethalConfigEnabled) { AddLethalConfigFloatItem(tempEntry3); } } if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Quick Sand Config", "Slowing Speed"))) { ConfigEntry<float> tempEntry4 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<float>("Quick Sand Config", "Slowing Speed", 33f, "Percentage of Original Speed Enemies Move In Quick Sand"); if (Plugin.lethalConfigEnabled) { AddLethalConfigFloatItem(tempEntry4); } } if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("TurretConfig", "Enemy Damage"))) { ConfigEntry<float> tempEntry5 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<float>("TurretConfig", "Enemy Damage", 1f, "Damage Turrets will Do To Enemies"); if (Plugin.lethalConfigEnabled) { AddLethalConfigFloatItem(tempEntry5); } } if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("TurretConfig", "Player Damage"))) { ConfigEntry<float> tempEntry6 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<float>("TurretConfig", "Player Damage", 50f, "Damage Turrets will Do To Players"); if (Plugin.lethalConfigEnabled) { AddLethalConfigFloatItem(tempEntry6); } } if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("TurretConfig", "HitOtherTurrets"))) { ConfigEntry<bool> tempEntry7 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("TurretConfig", "HitOtherTurrets", false, "If turrets can hit other turrets when firing.(Does not make them target other turrets)"); if (Plugin.lethalConfigEnabled) { AddLethalConfigBoolItem(tempEntry7); } } if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Mobs", "QuicksandAllMobs"))) { ConfigEntry<bool> tempEntry8 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", "QuicksandAllMobs", true, "Leave On To Customise Mobs Below Or Turn Off To Make All Mobs Unable To Set Off Quicksand interactions."); if (Plugin.lethalConfigEnabled) { AddLethalConfigBoolItem(tempEntry8); } } if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Mobs", "ExplodeAllMobs"))) { ConfigEntry<bool> tempEntry9 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", "ExplodeAllMobs", true, "Leave On To Customise Mobs Below Or Turn Off To Make All Mobs Unable To Set Off Mines."); if (Plugin.lethalConfigEnabled) { AddLethalConfigBoolItem(tempEntry9); } } if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Mobs", "BoombaAllMobs"))) { ConfigEntry<bool> tempEntry10 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", "BoombaAllMobs", true, "Leave On To Customise Mobs Below Or Turn Off To Make All Mobs Unable To Set Off Boombas."); if (Plugin.lethalConfigEnabled) { AddLethalConfigBoolItem(tempEntry10); } } if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Mobs", "SeamineAllMobs"))) { ConfigEntry<bool> tempEntry11 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", "SeamineAllMobs", true, "Leave On To Customise Mobs Below Or Turn Off To Make All Mobs Unable To Set Off Seamines."); if (Plugin.lethalConfigEnabled) { AddLethalConfigBoolItem(tempEntry11); } } if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Mobs", "BerthaAllMobs"))) { ConfigEntry<bool> tempEntry12 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", "BerthaAllMobs", true, "Leave On To Customise Mobs Below Or Turn Off To Make All Mobs Unable To Set Off Big Berthas."); if (Plugin.lethalConfigEnabled) { AddLethalConfigBoolItem(tempEntry12); } } if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Mobs", "TurretTargetAllMobs"))) { ConfigEntry<bool> tempEntry13 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", "TurretTargetAllMobs", true, "Leave On To Customise Mobs Below Or Turn Off To Make All Mobs Unable To Be Targeted By Turrets."); if (Plugin.lethalConfigEnabled) { AddLethalConfigBoolItem(tempEntry13); } } if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Mobs", "TurretDamageAllMobs"))) { ConfigEntry<bool> tempEntry14 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", "TurretDamageAllMobs", true, "Leave On To Customise Mobs Below Or Turn Off To Make All Mobs Unable To Be Killed By Turrets."); if (Plugin.lethalConfigEnabled) { AddLethalConfigBoolItem(tempEntry14); } } if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Mobs", "CheckForPlayersInside"))) { ConfigEntry<bool> tempEntry15 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", "CheckForPlayersInside", false, "Whether to check for players inside the dungeon before anything else occurs."); if (Plugin.lethalConfigEnabled) { AddLethalConfigBoolItem(tempEntry15); } } foreach (EnemyType allEnemy in Plugin.allEnemies) { string text = Plugin.RemoveInvalidCharacters(allEnemy.enemyName); if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Mobs", text + ".Quicksand Kill"))) { if (allEnemy.canDie) { ConfigEntry<bool> tempEntry16 = ((!text.ToLower().Equals("cutieflyai") && !text.ToLower().Equals("cutieflyobj") && !text.ToLower().Equals("cutiefly")) ? ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", text + ".Quicksand Kill", true, "Is it killable by quicksand?") : ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", text + ".Quicksand Kill", false, "Is it killable by quicksand?")); if (Plugin.lethalConfigEnabled) { AddLethalConfigBoolItem(tempEntry16); } } else { ConfigEntry<bool> tempEntry16 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", text + ".Quicksand Kill", false, "Is it killable by quicksand?"); if (Plugin.lethalConfigEnabled) { AddLethalConfigBoolItem(tempEntry16); } } } if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Mobs", text + ".Mine"))) { ConfigEntry<bool> tempEntry17 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", text + ".Mine", allEnemy.canDie, "Does it set off the landmine or not?"); if (Plugin.lethalConfigEnabled) { AddLethalConfigBoolItem(tempEntry17); } } if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Mobs", text + ".Seamine"))) { ConfigEntry<bool> tempEntry18 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", text + ".Seamine", allEnemy.canDie, "Does it set off the Surfaced Seamine or not?"); if (Plugin.lethalConfigEnabled) { AddLethalConfigBoolItem(tempEntry18); } } if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Mobs", text + ".Bertha"))) { ConfigEntry<bool> tempEntry19 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", text + ".Bertha", allEnemy.canDie, "Does it set off the Surfaced Big Bertha or not?"); if (Plugin.lethalConfigEnabled) { AddLethalConfigBoolItem(tempEntry19); } } if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Mobs", text + ".Boomba"))) { ConfigEntry<bool> tempEntry20 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", text + ".Boomba", allEnemy.canDie, "Does it set off the LethalThings Boomba or not?"); if (Plugin.lethalConfigEnabled) { AddLethalConfigBoolItem(tempEntry20); } } if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Mobs", text + ".Turret Target"))) { ConfigEntry<bool> tempEntry21 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", text + ".Turret Target", allEnemy.canDie, "Is it targetable by turrets?"); if (Plugin.lethalConfigEnabled) { AddLethalConfigBoolItem(tempEntry21); } } if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Mobs", text + ".Turret Damage"))) { ConfigEntry<bool> tempEntry22 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", text + ".Turret Damage", allEnemy.canDie, "Is it damageable by turrets?"); if (Plugin.lethalConfigEnabled) { AddLethalConfigBoolItem(tempEntry22); } } } } public static int[] GetLateGameUpgradeTier(string upgradeName) { try { Type type = Plugin.lguAssembly.GetType("MoreShipUpgrades.API.UpgradeApi"); if (type == null) { Plugin.logger.LogError((object)"[FairAI] Could not find UpgradeApi type!"); return Array.Empty<int>(); } MethodInfo method = type.GetMethod("GetRankableUpgradeNodes", BindingFlags.Static | BindingFlags.Public); if (method == null) { Plugin.logger.LogError((object)"[FairAI] Could not find GetRankableUpgradeNodes() method!"); return Array.Empty<int>(); } object obj = method.Invoke(null, null); if (!(obj is IEnumerable enumerable)) { Plugin.logger.LogError((object)"[FairAI] Result is not an IEnumerable!"); return Array.Empty<int>(); } foreach (object item in enumerable) { Type type2 = item.GetType(); PropertyInfo property = type2.GetProperty("Name", BindingFlags.Instance | BindingFlags.Public); PropertyInfo property2 = type2.GetProperty("MaxUpgrade", BindingFlags.Instance | BindingFlags.Public); PropertyInfo property3 = type2.GetProperty("CurrentUpgrade", BindingFlags.Instance | BindingFlags.Public); string text = property?.GetValue(item)?.ToString() ?? "(unknown)"; if (!text.Equals("(unknown)") && text.Equals(upgradeName, StringComparison.OrdinalIgnoreCase)) { int num = (int)(property2?.GetValue(item) ?? ((object)0)); int num2 = (int)(property3?.GetValue(item) ?? ((object)0)); Plugin.logger.LogInfo((object)$"[FairAI] {text} — Current: {num2}, Max: {num}"); return new int[2] { num2, num }; } } } catch (Exception arg) { Plugin.logger.LogError((object)$"[FairAI] Error: {arg}"); } return Array.Empty<int>(); } public static bool ReadSyncedEntryBool(object syncedEntry) { if (syncedEntry == null) { return false; } PropertyInfo property = syncedEntry.GetType().GetProperty("Value", BindingFlags.Instance | BindingFlags.Public); return property != null && (bool)property.GetValue(syncedEntry); } public static int ReadSyncedEntryInt(object syncedEntry) { if (syncedEntry == null) { return 0; } PropertyInfo property = syncedEntry.GetType().GetProperty("Value", BindingFlags.Instance | BindingFlags.Public); return (property != null) ? ((int)property.GetValue(syncedEntry)) : 0; } public static float CalculateDecreaseMultiplier() { Type rubberBootsType = Plugin.rubberBootsType; try { Type type = rubberBootsType.Assembly.GetType("MoreShipUpgrades.Misc.Upgrades.BaseUpgrade"); if (type == null) { return 0f; } object obj = type.GetMethod("GetConfiguration", BindingFlags.Static | BindingFlags.Public)?.Invoke(null, null); if (obj == null) { return 0f; } object obj2 = obj.GetType().GetProperty("RubberBootsConfiguration", BindingFlags.Instance | BindingFlags.Public)?.GetValue(obj); if (obj2 == null) { return 0f; } object syncedEntry = obj2.GetType().GetProperty("Enabled")?.GetValue(obj2); if (!ReadSyncedEntryBool(syncedEntry)) { return 0f; } MethodInfo method = type.GetMethod("GetActiveUpgrade", BindingFlags.Static | BindingFlags.Public); if (!(bool)method.Invoke(null, new object[1] { "Rubber Boots" })) { return 0f; } object syncedEntry2 = obj2.GetType().GetProperty("InitialEffect")?.GetValue(obj2); object syncedEntry3 = obj2.GetType().GetProperty("IncrementalEffect")?.GetValue(obj2); int num = ReadSyncedEntryInt(syncedEntry2); int num2 = ReadSyncedEntryInt(syncedEntry3); MethodInfo method2 = type.GetMethod("GetUpgradeLevel", BindingFlags.Static | BindingFlags.Public); int num3 = (int)method2.Invoke(null, new object[1] { "Rubber Boots" }) + 1; Plugin.logger.LogWarning((object)("Decrease: " + (float)(num + num2 * num3) / 100f)); return (float)(num + num2 * num3) / 100f; } catch (Exception arg) { Plugin.logger.LogError((object)$"CalculateDecreaseMultiplier reflection failed: {arg}"); return 0f; } } public static int ClearMovementHinderance(int defaultValue) { if (CalculateDecreaseMultiplier() >= 1f) { return 0; } return defaultValue; } public static float ReduceMovementHinderance(float defaultValue) { float num = CalculateDecreaseMultiplier(); return Mathf.Clamp(Mathf.Clamp(1f - num, 0f, 1f) * defaultValue, 1f, 100f); } } } namespace FairAI.Patches { public static class BoombaPatch { private static bool? _enabled; public static bool enabled { get { if (!_enabled.HasValue) { _enabled = Chainloader.PluginInfos.ContainsKey("evaisa.lethalthings"); } return _enabled.Value; } } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public static void PatchStart(ref RoombaAI __instance) { ((Component)__instance).gameObject.AddComponent<BoombaTimer>(); } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public static void PatchDoAIInterval(ref RoombaAI __instance) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: 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_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.AllowFairness(((Component)__instance).transform.position) || !Plugin.IsAgentOnNavMesh(((Component)__instance).gameObject) || (((EnemyAI)__instance).currentSearch == null && !((EnemyAI)__instance).movingTowardsTargetPlayer) || (!__instance.mineAudio.isPlaying && !__instance.mineFarAudio.isPlaying) || !((Component)__instance).GetComponent<BoombaTimer>().IsActiveBomb()) { return; } Vector3 val = ((Component)__instance).transform.position + Vector3.up; Collider[] array = Physics.OverlapSphere(val, 6f, 2621448, (QueryTriggerInteraction)2); for (int i = 0; i < array.Length; i++) { float num = Vector3.Distance(val, ((Component)array[i]).transform.position); if ((num > 4f && Physics.Linecast(val, ((Component)array[i]).transform.position + Vector3.up * 0.3f, 256, (QueryTriggerInteraction)1)) || !((Object)(object)((Component)array[i]).gameObject.GetComponent<EnemyAICollisionDetect>() != (Object)null)) { continue; } EnemyAICollisionDetect component = ((Component)array[i]).gameObject.GetComponent<EnemyAICollisionDetect>(); if (!((Object)(object)((Component)component.mainScript).gameObject != (Object)(object)((Component)__instance).gameObject) || !Plugin.CanMob("BoombaAllMobs", ".Boomba", component.mainScript.enemyType.enemyName)) { continue; } if ((Object)(object)component != (Object)null && ((NetworkBehaviour)component.mainScript).IsOwner && !component.mainScript.isEnemyDead) { Object.Instantiate<GameObject>(StartOfRound.Instance.explosionPrefab, val, Quaternion.Euler(-90f, 0f, 0f), RoundManager.Instance.mapPropsContainer.transform).SetActive(true); if (num < 3f) { component.mainScript.KillEnemyOnOwnerClient(true); } else if (num < 6f) { component.mainScript.HitEnemyOnLocalClient(2, default(Vector3), (PlayerControllerB)null, false, -1); } } if (((NetworkBehaviour)__instance).IsServer) { ((EnemyAI)__instance).KillEnemy(true); } else { ((EnemyAI)__instance).KillEnemyServerRpc(true); } } } } internal class EnemyAIPatch { private static void BaseHitEnemy(EnemyAI ai, int force, PlayerControllerB playerWhoHit, bool playHitSFX, int hitID) { if (!((Object)(object)ai == (Object)null)) { if (playHitSFX && (Object)(object)ai.enemyType.hitBodySFX != (Object)null && !ai.isEnemyDead) { ai.creatureSFX.PlayOneShot(ai.enemyType.hitBodySFX); WalkieTalkie.TransmitOneShotAudio(ai.creatureSFX, ai.enemyType.hitBodySFX, 1f); } if ((Object)(object)ai.creatureVoice != (Object)null) { ai.creatureVoice.PlayOneShot(ai.enemyType.hitEnemyVoiceSFX); } if (ai.debugEnemyAI) { Debug.Log((object)$"Enemy #{ai.thisEnemyIndex} was hit with force of {force}"); } if ((Object)(object)playerWhoHit != (Object)null) { Debug.Log((object)$"Client #{playerWhoHit.playerClientId} hit enemy {((Object)((Component)ai.agent).transform).name} with force of {force}."); } } } public static void KillEnemyOnOwnerClientPatch(EnemyAI __instance, bool overrideDestroy = false) { if (overrideDestroy) { return; } int id = ((Object)__instance).GetInstanceID(); if (Plugin.sinkingProgress.ContainsKey(id)) { ((MonoBehaviour)__instance).StartCoroutine(Utils.WaitForTime(delegate { Plugin.sinkingProgress.Remove(id); Plugin.sinkingValues.Remove(id); Plugin.positions.Remove(id); __instance.KillEnemyOnOwnerClient(true); }, 1f)); } } public static bool BrackenHitEnemyPatch(ref FlowermanAI __instance, int force = 1, PlayerControllerB playerWhoHit = null, bool playHitSFX = false, int hitID = -1) { BaseHitEnemy((EnemyAI)(object)__instance, force, playerWhoHit, playHitSFX, hitID); if (((EnemyAI)__instance).isEnemyDead) { return false; } FlowermanAI obj = __instance; ((EnemyAI)obj).enemyHP = ((EnemyAI)obj).enemyHP - force; if (((NetworkBehaviour)__instance).IsOwner) { if (((EnemyAI)__instance).enemyHP <= 0) { ((EnemyAI)__instance).KillEnemyOnOwnerClient(false); return false; } if (!Object.op_Implicit((Object)(object)playerWhoHit)) { Plugin.logger.LogDebug((object)"Bracken was hit by another enemy. Not changing its anger meter"); return false; } __instance.angerMeter = 11f; __instance.angerCheckInterval = 1f; __instance.AddToAngerMeter(0.1f); } return false; } public static bool HoardingBugHitEnemyPatch(ref HoarderBugAI __instance, int force = 1, PlayerControllerB playerWhoHit = null, bool playHitSFX = false, int hitID = -1) { BaseHitEnemy((EnemyAI)(object)__instance, force, playerWhoHit, playHitSFX, hitID); if (((EnemyAI)__instance).isEnemyDead) { return false; } ((EnemyAI)__instance).creatureAnimator.SetTrigger("damage"); if (!Object.op_Implicit((Object)(object)playerWhoHit)) { Plugin.logger.LogDebug((object)"Hoarding bug was hit by another enemy. Not changing its anger meter"); } else { __instance.angryAtPlayer = playerWhoHit; HoarderBugAI obj = __instance; obj.angryTimer += 18f; } HoarderBugAI obj2 = __instance; ((EnemyAI)obj2).enemyHP = ((EnemyAI)obj2).enemyHP - force; if (((NetworkBehaviour)__instance).IsOwner && ((EnemyAI)__instance).enemyHP <= 0) { ((EnemyAI)__instance).KillEnemyOnOwnerClient(false); } return false; } } internal class LevelGenManPatch { public static void PatchAwake(ref LevelGenerationManager __instance) { Utils.SetupConfig(); } } internal class MineAIPatch { [CompilerGenerated] private sealed class <WaitForUpdate>d__3 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public float waitTime; public Landmine mine; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <WaitForUpdate>d__3(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(waitTime); <>1__state = 1; return true; case 1: <>1__state = -1; if (!((Object)(object)mine == (Object)null)) { if ((Object)(object)((Component)mine).GetComponent<NetworkObject>() != (Object)null) { ((Component)mine).GetComponent<NetworkObject>().Despawn(true); } else { Object.Destroy((Object)(object)((Component)mine).gameObject); } } return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public static void PatchOnTriggerEnter(ref Landmine __instance, Collider other, ref float ___pressMineDebounceTimer) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) if (Plugin.AllowFairness(((Component)__instance).transform.position)) { EnemyAICollisionDetect component = ((Component)other).gameObject.GetComponent<EnemyAICollisionDetect>(); if ((Object)(object)component != (Object)null && !component.mainScript.isEnemyDead && Plugin.CanMob("ExplodeAllMobs", ".Mine", component.mainScript.enemyType.enemyName.ToUpper())) { ___pressMineDebounceTimer = 0.5f; __instance.PressMineServerRpc(); } } } public static void PatchOnTriggerExit(ref Landmine __instance, Collider other, ref bool ___sendingExplosionRPC) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) if (Plugin.AllowFairness(((Component)__instance).transform.position)) { EnemyAICollisionDetect component = ((Component)other).gameObject.GetComponent<EnemyAICollisionDetect>(); if ((Object)(object)component != (Object)null && !component.mainScript.isEnemyDead && Plugin.CanMob("ExplodeAllMobs", ".Mine", component.mainScript.enemyType.enemyName.ToUpper()) && !__instance.hasExploded) { __instance.SetOffMineAnimation(); ___sendingExplosionRPC = true; __instance.ExplodeMineServerRpc(); } } } public static void DetonatePatch(ref Landmine __instance) { if (!((Object)(object)__instance == (Object)null)) { ((MonoBehaviour)__instance).StartCoroutine(WaitForUpdate(1.5f, __instance)); } } [IteratorStateMachine(typeof(<WaitForUpdate>d__3))] public static IEnumerator WaitForUpdate(float waitTime, Landmine mine) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <WaitForUpdate>d__3(0) { waitTime = waitTime, mine = mine }; } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public static void PatchSpawnExplosion(Vector3 explosionPosition, bool spawnExplosionEffect = false, float killRange = 1f, float damageRange = 1f, int nonLethalDamage = 50, float physicsForce = 0f, GameObject overridePrefab = null, bool goThroughCar = false) { //IL_0004: 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_0027: 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_0043: 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) //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) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) bool flag = true; Collider[] array = Physics.OverlapSphere(explosionPosition, 6f, 2621448, (QueryTriggerInteraction)2); for (int i = 0; i < array.Length; i++) { float num = Vector3.Distance(explosionPosition, ((Component)array[i]).transform.position); if (num > 4f && Physics.Linecast(explosionPosition, ((Component)array[i]).transform.position + Vector3.up * 0.3f, 256, (QueryTriggerInteraction)1)) { continue; } if (Plugin.surfacedEnabled && Plugin.surfacedAssembly != null) { Type type = Plugin.surfacedAssembly.GetType("Seamine"); if (type != null && (Object)(object)((Component)array[i]).gameObject.GetComponent(type) != (Object)null) { Component component = ((Component)array[i]).gameObject.GetComponent(type); FieldInfo field = type.GetField("mineActivated", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo field2 = type.GetField("hasExploded", BindingFlags.Instance | BindingFlags.Public); if (!(bool)field2.GetValue(component) || !(bool)field.GetValue(component)) { break; } if (Plugin.AllowFairness(component.transform.position)) { MethodInfo method = type.GetMethod("TriggerMineOnLocalClientByExiting", BindingFlags.Instance | BindingFlags.NonPublic); method.Invoke(component, new object[0]); } } } if (!((Object)(object)((Component)array[i]).gameObject.GetComponent<EnemyAICollisionDetect>() != (Object)null)) { continue; } EnemyAICollisionDetect component2 = ((Component)array[i]).gameObject.GetComponent<EnemyAICollisionDetect>(); if ((Object)(object)component2 != (Object)null && ((NetworkBehaviour)component2.mainScript).IsOwner && !component2.mainScript.isEnemyDead) { if (num < killRange) { component2.mainScript.HitEnemyOnLocalClient(component2.mainScript.enemyHP, default(Vector3), (PlayerControllerB)null, false, -1); } else if (num < damageRange) { component2.mainScript.HitEnemyOnLocalClient(Mathf.RoundToInt(Plugin.GetFloat("ExplosionConfig", "Damage")), default(Vector3), (PlayerControllerB)null, false, -1); } } } } } internal class QuickSandPatch { public static bool OnTriggerStayPatch(ref QuicksandTrigger __instance, Collider other) { if (!__instance.isWater && (Object)(object)((Component)other).gameObject.GetComponent<EnemyAICollisionDetect>() != (Object)null && Plugin.GetBool("Mobs", "QuicksandAllMobs")) { EnemyAICollisionDetect component = ((Component)other).gameObject.GetComponent<EnemyAICollisionDetect>(); if ((Object)(object)component != (Object)null) { EnemyAI mainScript = component.mainScript; if ((Object)(object)mainScript != (Object)null) { string enemyName = mainScript.enemyType.enemyName; if ((Object)(object)mainScript.agent != (Object)null && (Plugin.GetBool("Mobs", Plugin.RemoveInvalidCharacters(enemyName) + ".Quicksand Kill") || !enemyName.ToLower().Contains("cutiefly"))) { NavMeshAgent agent = mainScript.agent; float[] array = Plugin.SpeedAndAccelerationEnemyList(component); float num = (float)Plugin.GetInt("Quick Sand Config", "Slowing Speed") * 0.01f; if (array.Length != 0) { if (array[0] * num != agent.speed) { agent.speed = array[0] * num; } if (array[1] * num != agent.acceleration) { agent.acceleration = array[1] * num; } } } if (Plugin.GetBool("Mobs", Plugin.RemoveInvalidCharacters(mainScript.enemyType.enemyName) + ".Quicksand Kill")) { SetSinking(component); } } } } QuicksandEventsForPlayer(__instance, other); return false; } public static bool OnTriggerExitPatch(ref QuicksandTrigger __instance, Collider other) { //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)((Component)other).gameObject.GetComponent<EnemyAICollisionDetect>() != (Object)null && Plugin.GetBool("Mobs", "QuicksandAllMobs")) { EnemyAICollisionDetect component = ((Component)other).gameObject.GetComponent<EnemyAICollisionDetect>(); EnemyAI mainScript = component.mainScript; int instanceID = ((Object)mainScript).GetInstanceID(); string enemyName = mainScript.enemyType.enemyName; if (!Plugin.positions.TryGetValue(instanceID, out var value)) { return false; } if (Plugin.GetBool("Mobs", Plugin.RemoveInvalidCharacters(enemyName) + ".Quicksand Kill") || !enemyName.ToLower().Contains("cutiefly")) { float[] array = Plugin.SpeedAndAccelerationEnemyList(component); if (array.Length != 0) { mainScript.agent.speed = array[0]; mainScript.agent.acceleration = array[1]; } } if (Plugin.GetBool("Mobs", Plugin.RemoveInvalidCharacters(enemyName) + ".Quicksand Kill")) { ((Component)mainScript).transform.position = new Vector3(((Component)mainScript).transform.position.x, value.y, ((Component)mainScript).transform.position.z); mainScript.SyncPositionToClients(); Plugin.sinkingValues[instanceID] = 0f; Plugin.sinkingProgress[instanceID] = 0f; } } else { __instance.OnExit(other); } return false; } public static bool StopSinkingLocalPlayerPatch(ref QuicksandTrigger __instance, PlayerControllerB playerScript) { if (__instance.sinkingLocalPlayer) { __instance.sinkingLocalPlayer = false; playerScript.sourcesCausingSinking = Mathf.Clamp(playerScript.sourc