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 FairGiants v1.1.2
FairGiants.dll
Decompiled 2 years agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BlindGiants; using BlindGiants.Patches; using FairGiants; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using Unity.Collections; using Unity.Netcode; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: AssemblyCompany("FairGiants")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright (c) 2024 LegoMaster3650")] [assembly: AssemblyDescription("Makes forest keepers/giants fairer in lethal company.")] [assembly: AssemblyFileVersion("1.1.1")] [assembly: AssemblyInformationalVersion("1.1.1")] [assembly: AssemblyProduct("FairGiants")] [assembly: AssemblyTitle("FairGiants")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace FairGiants { [Serializable] public class ConfigSync { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnRequestSync; public static HandleNamedMessageDelegate <1>__OnRecieveSync; } public static bool Synced; public bool reduceVisionFog; public bool reduceVisionSnow; public int giantFogDivisor; public string snowyPlanets; public bool enhancedAntiCamp; public bool randomWander; public PatchApplyLevel stealthDecaysWhen; public float passiveStealthDecay; public ConfigSync() { reduceVisionFog = Config.file_reduceVisionFog.Value; reduceVisionSnow = Config.file_reduceVisionSnow.Value; giantFogDivisor = Config.file_giantFogDivisor.Value; snowyPlanets = Config.file_snowyPlanets.Value; enhancedAntiCamp = Config.file_enhancedAntiCamp.Value; randomWander = Config.file_randomWander.Value; stealthDecaysWhen = Config.file_stealthDecaysWhen.Value; passiveStealthDecay = Config.file_passiveStealthDecay.Value; } [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] [HarmonyPostfix] public static void Init() { //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown if (Synced) { return; } Plugin.Log("Syncing configs..."); if (NetworkManager.Singleton.IsHost) { Plugin.Log("Client is host, no need to sync configs!"); CustomMessagingManager customMessagingManager = NetworkManager.Singleton.CustomMessagingManager; object obj = <>O.<0>__OnRequestSync; if (obj == null) { HandleNamedMessageDelegate val = OnRequestSync; <>O.<0>__OnRequestSync = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler("FairGiants-OnRequestSync", (HandleNamedMessageDelegate)obj); Synced = true; } else { Plugin.Log("Requesting config sync"); CustomMessagingManager customMessagingManager2 = NetworkManager.Singleton.CustomMessagingManager; object obj2 = <>O.<1>__OnRecieveSync; if (obj2 == null) { HandleNamedMessageDelegate val2 = OnRecieveSync; <>O.<1>__OnRecieveSync = val2; obj2 = (object)val2; } customMessagingManager2.RegisterNamedMessageHandler("FairGiants-OnRecieveSync", (HandleNamedMessageDelegate)obj2); RequestSync(); } } [HarmonyPatch(typeof(GameNetworkManager), "StartDisconnect")] [HarmonyPostfix] public static void Reset() { Synced = false; Config.Instance = Config.Default; Config.ConfigChanged(); } public static void RequestSync() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) if (NetworkManager.Singleton.IsClient) { FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(0, (Allocator)2, -1); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("FairGiants-OnRequestSync", 0uL, val, (NetworkDelivery)3); } } public static void OnRequestSync(ulong clientId, FastBufferReader reader) { //IL_005f: 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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) if (!NetworkManager.Singleton.IsHost) { return; } Plugin.Log($"Client {clientId} requested config sync"); BinaryFormatter binaryFormatter = new BinaryFormatter(); using MemoryStream memoryStream = new MemoryStream(); try { binaryFormatter.Serialize(memoryStream, Config.Default); } catch (Exception arg) { Plugin.LogError($"Error serializing config: {arg}"); return; } byte[] array = memoryStream.ToArray(); FastBufferWriter val = new FastBufferWriter(array.Length + 4, (Allocator)2, -1); try { int num = array.Length; ((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteBytesSafe(array, -1, 0); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("FairGiants-OnRecieveSync", clientId, val, (NetworkDelivery)3); } finally { ((IDisposable)(FastBufferWriter)(ref val)).Dispose(); } } public static void OnRecieveSync(ulong clientId, FastBufferReader reader) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (!NetworkManager.Singleton.IsClient) { return; } Plugin.Log("Recieved config data from host."); if (!((FastBufferReader)(ref reader)).TryBeginRead(4)) { Plugin.LogError("Config sync failed: Could not read size of buffer"); return; } int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives)); if (!((FastBufferReader)(ref reader)).TryBeginRead(num)) { Plugin.LogError("Config sync failed: Could not read buffer"); return; } byte[] buffer = new byte[num]; ((FastBufferReader)(ref reader)).ReadBytesSafe(ref buffer, num, 0); BinaryFormatter binaryFormatter = new BinaryFormatter(); using MemoryStream serializationStream = new MemoryStream(buffer); try { Config.Instance = (ConfigSync)binaryFormatter.Deserialize(serializationStream); } catch (Exception arg) { Plugin.LogError($"Error deserializing config: {arg}"); return; } Plugin.Log("Config values synced with host!"); Synced = true; Config.ConfigChanged(); } } public enum PatchApplyLevel { Never, Solo, Always } public static class PluginInfo { public const string PLUGIN_GUID = "FairGiants"; public const string PLUGIN_NAME = "FairGiants"; public const string PLUGIN_VERSION = "1.1.1"; } } namespace BlindGiants { public class Config { public static ConfigSync Default; public static ConfigSync Instance; public static ConfigEntry<bool> file_reduceVisionFog; public static ConfigEntry<bool> file_reduceVisionSnow; public static ConfigEntry<int> file_giantFogDivisor; public static ConfigEntry<string> file_snowyPlanets; public static string[] snowyPlanetsList = new string[3] { "Dine", "Rend", "Titan" }; public static ConfigEntry<bool> file_enhancedAntiCamp; public static ConfigEntry<bool> file_randomWander; public static ConfigEntry<PatchApplyLevel> file_stealthDecaysWhen; public static ConfigEntry<float> file_passiveStealthDecay; public static void Bind(ConfigFile config) { //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Expected O, but got Unknown file_reduceVisionFog = config.Bind<bool>("Vision", "ReduceVisionFog", true, "If true, divides giant sight range by GiantFogDivisor when a moon is foggy"); file_reduceVisionSnow = config.Bind<bool>("Vision", "ReduceVisionSnow", true, "If true, divides giant sight range by GiantFogDivisor when a moon is snowy"); file_giantFogDivisor = config.Bind<int>("Vision", "GiantFogDivisor", 3, "The amount to divide giant sight range by"); file_snowyPlanets = config.Bind<string>("Vision", "SnowyPlanets", "Dine,Rend,Titan", "Names of planets that should be considered snowy to giants. (Separate with commas, spaces around commas are allowed but will be ignored)"); file_enhancedAntiCamp = config.Bind<bool>("Ship", "EnhancedAntiCamp", true, "If true, fixes some issues with the base game's anti-camp when losing a player near the ship."); file_randomWander = config.Bind<bool>("Ship", "RandomWander", true, "If true, uses custom logic to wander to a random point away from the ship. If false, uses the vanilla point of the furthest point from the ship."); file_stealthDecaysWhen = config.Bind<PatchApplyLevel>("Aggro", "StealthDecaysWhen", PatchApplyLevel.Solo, "When to allow all stealth meters to passively decay when a giant sees no players."); file_passiveStealthDecay = config.Bind<float>("Aggro", "PassiveStealthDecay", 0.2f, new ConfigDescription("How much stealth decays each second when a giant sees no players. Vanilla decay is 0.33", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); Default = new ConfigSync(); Instance = new ConfigSync(); ConfigChanged(); config.SettingChanged += OnSettingChanged; } private static void OnSettingChanged(object sender, SettingChangedEventArgs e) { SetConfigChanged(); } private static void SetConfigChanged() { if (NetworkManager.Singleton.IsHost) { Instance = new ConfigSync(); } ConfigChanged(); } public static void ConfigChanged() { string[] array = Instance.snowyPlanets.Split(','); for (int i = 0; i < array.Length; i++) { array[i] = array[i].Trim(); } snowyPlanetsList = array; } public static bool IsSnowyPlanet(string name) { string[] array = snowyPlanetsList; foreach (string value in array) { if (name.Contains(value)) { return true; } } return false; } } [BepInPlugin("3650.FairGiants", "FairGiants", "1.0.0")] public class Plugin : BaseUnityPlugin { public const string pluginGuid = "3650.FairGiants"; public const string pluginName = "FairGiants"; public const string pluginVersion = "1.0.0"; private static Plugin Instance; private void Awake() { //IL_0022: 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) if (Instance == null) { Instance = this; } ((BaseUnityPlugin)this).Logger.LogInfo((object)"Patching giants..."); Harmony val = new Harmony("3650.FairGiants"); val.PatchAll(typeof(ForestGiantAIPatch)); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Giants patched!"); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Loading config..."); Config.Bind(((BaseUnityPlugin)this).Config); val.PatchAll(typeof(ConfigSync)); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Config loaded!"); } public static void Log(string msg) { ((BaseUnityPlugin)Instance).Logger.LogInfo((object)msg); } public static void LogError(string msg) { ((BaseUnityPlugin)Instance).Logger.LogError((object)msg); } public static void LogDebug(string msg) { ((BaseUnityPlugin)Instance).Logger.LogDebug((object)msg); } } } namespace BlindGiants.Patches { [HarmonyPatch(typeof(ForestGiantAI))] public class ForestGiantAIPatch { [HarmonyPatch("LookForPlayers")] [HarmonyTranspiler] public static IEnumerable<CodeInstruction> SearchDistancePatch(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_0002: 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_0037: Expected O, but got Unknown //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown return new CodeMatcher(instructions, (ILGenerator)null).MatchForward(true, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(EnemyAI), "GetAllPlayersInLineOfSight", (Type[])null, (Type[])null), (string)null) }).MatchBack(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldc_I4_S, (object)null, (string)null) }).Advance(1) .InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ForestGiantAIPatch), "ClampRange", (Type[])null, (Type[])null)) }) .InstructionEnumeration(); } [HarmonyPatch("GiantSeePlayerEffect")] [HarmonyTranspiler] public static IEnumerable<CodeInstruction> FearDistancePatch(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_0002: 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_0037: Expected O, but got Unknown //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown return new CodeMatcher(instructions, (ILGenerator)null).MatchForward(true, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(EnemyAI), "CheckLineOfSightForPosition", (Type[])null, (Type[])null), (string)null) }).MatchBack(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldc_I4_S, (object)null, (string)null) }).Advance(1) .InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ForestGiantAIPatch), "ClampRange", (Type[])null, (Type[])null)) }) .InstructionEnumeration(); } public static int ClampRange(int range) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Invalid comparison between Unknown and I4 if ((!Config.Instance.reduceVisionFog || (int)TimeOfDay.Instance.currentLevelWeather != 3) && (!Config.Instance.reduceVisionSnow || !Config.IsSnowyPlanet(TimeOfDay.Instance.currentLevel.PlanetName))) { return range; } return range / Config.Instance.giantFogDivisor; } [HarmonyPatch("DoAIInterval")] [HarmonyTranspiler] public static IEnumerable<CodeInstruction> GiantRoamPatch(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_0002: 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_0037: Expected O, but got Unknown //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Expected O, but got Unknown //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Expected O, but got Unknown return new CodeMatcher(instructions, (ILGenerator)null).MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(EnemyAI), "ChooseFarthestNodeFromPosition", (Type[])null, (Type[])null), (string)null) }).Advance(3).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[6] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ForestGiantAIPatch), "LeaveShipPatch", (Type[])null, (Type[])null)), new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldloc_1, (object)null), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ForestGiantAIPatch), "ChooseFarNodeFromShip", (Type[])null, (Type[])null)), new CodeInstruction(OpCodes.Stloc_1, (object)null) }) .InstructionEnumeration(); } public static Vector3 ChooseFarNodeFromShip(ForestGiantAI ai, Vector3 farPosition) { //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_0031: 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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0223: 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) //IL_02b4: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_028a: Unknown result type (might be due to invalid IL or missing references) //IL_028f: Unknown result type (might be due to invalid IL or missing references) if (!Config.Instance.randomWander) { return farPosition; } Vector3 ship = StartOfRound.Instance.elevatorTransform.position; Random random = new Random(((EnemyAI)ai).RoundUpToNearestFive(((Component)ai).transform.position.x) + ((EnemyAI)ai).RoundUpToNearestFive(((Component)ai).transform.position.z)); IEnumerable<(GameObject, float)> source = from node in ((EnemyAI)ai).allAINodes select (node, Vector3.Distance(ship, node.transform.position)) into x where x.dist >= 102f orderby x.dist + (float)random.Next(-12, 12) descending select x; List<GameObject> list = new List<GameObject>(); foreach (GameObject item in source.Select<(GameObject, float), GameObject>(((GameObject node, float dist) x) => x.node)) { list.Add(item); } ((EnemyAI)ai).nodesTempArray = list.ToArray(); List<float> list2 = new List<float>(); foreach (float item2 in source.Select<(GameObject, float), float>(((GameObject node, float dist) x) => x.dist)) { list2.Add(item2); } float[] source2 = list2.ToArray(); if (((EnemyAI)ai).nodesTempArray.Length == 0) { return farPosition; } float num = 0.7f * source2.Sum() / (float)((EnemyAI)ai).nodesTempArray.Length + 0.3f * (source2.First() + source2.Last()); double num2 = (double)(Mathf.Clamp(((double)num < 152.5) ? (-0.8f * (num - 100f) + 50f) : (-0.125f * (num - 152.5f) + 8f), 1f, 50f) * (float)Mathf.Clamp(130 - ((EnemyAI)ai).nodesTempArray.Length, 50, 100)) * 0.0001; Vector3 result = farPosition; for (int i = 1; i < ((EnemyAI)ai).nodesTempArray.Length; i++) { if (random.NextDouble() < num2) { break; } if (!((EnemyAI)ai).PathIsIntersectedByLineOfSight(((EnemyAI)ai).nodesTempArray[i].transform.position, false, false, false)) { ((EnemyAI)ai).mostOptimalDistance = Vector3.Distance(ship, ((EnemyAI)ai).nodesTempArray[i].transform.position); result = ((EnemyAI)ai).nodesTempArray[i].transform.position; if (i >= ((EnemyAI)ai).nodesTempArray.Length - 1) { break; } } } return result; } public static void LeaveShipPatch(ForestGiantAI ai) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown if (Config.Instance.enhancedAntiCamp) { Plugin.Log("Roaming Away"); if (ai.roamPlanet == null) { ai.roamPlanet = new AISearchRoutine(); } ((EnemyAI)ai).StopSearch(ai.roamPlanet, true); ai.roamPlanet.searchWidth = 35f; } } [HarmonyPatch("FinishedCurrentSearchRoutine")] [HarmonyPrefix] public static void GiantFinishSearch(ForestGiantAI __instance) { if (Config.Instance.enhancedAntiCamp) { Plugin.LogDebug("Giant Finished a Search"); if (__instance.roamPlanet != null && __instance.roamPlanet.searchWidth < 200f) { __instance.roamPlanet.searchWidth = 200f; } } } [HarmonyPatch("LookForPlayers")] [HarmonyTranspiler] public static IEnumerable<CodeInstruction> AggroPatch(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown return new CodeMatcher(instructions, (ILGenerator)null).End().MatchBack(false, (CodeMatch[])(object)new CodeMatch[3] { new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldc_R4, (object)0f, (string)null), new CodeMatch((OpCode?)OpCodes.Stfld, (object)AccessTools.Field(typeof(ForestGiantAI), "timeSpentStaring"), (string)null) }).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[2] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ForestGiantAIPatch), "LowerAllAggro", (Type[])null, (Type[])null)) }) .InstructionEnumeration(); } public static void LowerAllAggro(ForestGiantAI ai) { if (((EnemyAI)ai).currentBehaviourStateIndex != 0 || Config.Instance.stealthDecaysWhen == PatchApplyLevel.Always || (Config.Instance.stealthDecaysWhen == PatchApplyLevel.Solo && StartOfRound.Instance.connectedPlayersAmount <= 0)) { for (int i = 0; i < StartOfRound.Instance.allPlayerScripts.Length; i++) { ai.playerStealthMeters[i] = Mathf.Clamp(ai.playerStealthMeters[i] - Time.deltaTime * Config.Instance.passiveStealthDecay, 0f, 1f); } } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }