Decompiled source of TheArchive Essentials v2025.2.0
plugins/TheArchive.Essentials.dll
Decompiled 3 weeks 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.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using AK; using Agents; using AirParticleSystem; using BepInEx.Unity.IL2CPP.Utils.Collections; using BoosterImplants; using CellMenu; using ChainedPuzzles; using Clonesoft.Json; using Clonesoft.Json.Linq; using Enemies; using FX_EffectSystem; using GameData; using Gear; using HarmonyLib; using IRF; using Il2CppInterop.Runtime.Attributes; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppInterop.Runtime.Runtime; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using Il2CppSystem.Reflection; using LevelGeneration; using Localization; using Microsoft.CodeAnalysis; using Player; using SNetwork; using StateMachines; using Steamworks; using TMPro; using TheArchive.Core; using TheArchive.Core.Attributes; using TheArchive.Core.Attributes.Feature; using TheArchive.Core.Attributes.Feature.Members; using TheArchive.Core.Attributes.Feature.Patches; using TheArchive.Core.Attributes.Feature.Settings; using TheArchive.Core.FeaturesAPI; using TheArchive.Core.FeaturesAPI.Components; using TheArchive.Core.FeaturesAPI.Settings; using TheArchive.Core.Localization; using TheArchive.Core.Managers; using TheArchive.Core.Models; using TheArchive.Features.Accessibility; using TheArchive.Features.Dev; using TheArchive.Interfaces; using TheArchive.Loader; using TheArchive.Utilities; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyFileVersion("2025.2.0")] [assembly: AssemblyInformationalVersion("2025.2.0")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("TheArchive.Essentials")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyProduct("TheArchive.Essentials")] [assembly: AssemblyTitle("TheArchive.Essentials")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2025.2.0.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } internal class ThisAssembly { public class Git { public class BaseVersion { public const string Major = "2025"; public const string Minor = "2"; public const string Patch = "0"; } public class SemVer { public const string Major = "2025"; public const string Minor = "2"; public const string Patch = "1"; public const string Label = ""; public const string DashLabel = ""; public const string Source = "Tag"; } public const bool IsDirty = false; public const string IsDirtyString = "false"; public const string RepositoryUrl = "https://github.com/AuriRex/GTFO_TheArchive.git"; public const string Branch = "main"; public const string Commit = "6d23fe4"; public const string Sha = "6d23fe4e8bc046d994648b8c7855588348eff63c"; public const string CommitDate = "2025-08-23T17:58:53+02:00"; public const string Commits = "1"; public const string Tag = "v2025.2.0-1-g6d23fe4"; public const string BaseTag = "v2025.2.0"; } } internal class ManifestInfo { internal const string TSName = "TheArchive_Essentials"; internal const string TSDescription = "That one massive GTFO Quality of Life mod."; internal const string TSVersion = "2025.2.0"; internal const string TSAuthor = "AuriRex"; internal const string TSWebsite = "https://github.com/AuriRex/GTFO_TheArchive"; } namespace TheArchive { [ArchiveModule("dev.AuriRex.gtfo.TheArchive.Essentials", "TheArchive_Essentials", "2025.2.0")] public class ArchiveEssentialsModule : IArchiveModule { public const string GUID = "dev.AuriRex.gtfo.TheArchive.Essentials"; public const string MOD_NAME = "TheArchive_Essentials"; public const string VERSION = "2025.2.0"; public ILocalizationService LocalizationService { get; set; } public IArchiveLogger Logger { get; set; } public void Init() { } } } namespace TheArchive.Features.Special { [RundownConstraint(/*Could not decode attribute arguments.*/)] public class AdBlock : Feature { [ArchivePatch(/*Could not decode attribute arguments.*/)] internal static class CM_PageRundown_New_ABC_Patch { public static void Postfix(CM_PageRundown_New __instance) { ToggleDOWImage(__instance); } } public override string Name => "AdBlock"; public override FeatureGroup Group => FeatureGroups.Special; public override string Description => "Removes the Den of Wolves button from the rundown screen."; public static bool IsEnabled { get; set; } public override void OnEnable() { if (Feature.DataBlocksReady) { ToggleDOWImage(MainMenuGuiLayer.Current.PageRundownNew); } } public override void OnDisable() { if (!Feature.IsApplicationQuitting) { ToggleDOWImage(MainMenuGuiLayer.Current.PageRundownNew, setActive: true); } } private static void ToggleDOWImage(CM_PageRundown_New __instance, bool setActive = false) { RectTransform movingContentHolder = ((CM_PageBase)__instance).m_movingContentHolder; object obj; if (movingContentHolder == null) { obj = null; } else { Transform childWithExactName = SharedUtils.GetChildWithExactName((Transform)(object)movingContentHolder, "PasteAndJoinOnLobbyID"); if (childWithExactName == null) { obj = null; } else { Transform childWithExactName2 = SharedUtils.GetChildWithExactName(childWithExactName, "ButtonGIF"); obj = ((childWithExactName2 != null) ? ((Component)childWithExactName2).gameObject : null); } } GameObject val = (GameObject)obj; if (!((Object)(object)val == (Object)null)) { OnEnabledListener component = val.GetComponent<OnEnabledListener>(); if ((Object)(object)component != (Object)null && setActive) { Object.Destroy((Object)(object)component); } else if ((Object)(object)component == (Object)null) { component = val.AddComponent<OnEnabledListener>(); OnEnabledListener obj2 = component; obj2.OnEnabledSelf = (Action<GameObject>)Delegate.Combine(obj2.OnEnabledSelf, new Action<GameObject>(OnButtonEnabled)); } val.SetActive(setActive); } } private static void OnButtonEnabled(GameObject go) { if (IsEnabled) { go.SetActive(false); } } } [EnableFeatureByDefault] internal class AltTabCounter : Feature { public class AltTabCounterSettings { public class AltTabCounterSettingsForReal { [FSHeader("ALT + TABs <3", true)] [FSReadOnly(true)] [FSDisplayName("Total Count")] [FSDescription("All time total of ALT + TABs")] public int TotalCount { get; set; } [FSReadOnly(true)] [FSDisplayName("This Session Count")] [FSDescription("ALT + TABs accumulated this session")] public int CurrentSessionCount { get; set; } [FSReadOnly(true)] [FSDisplayName("This Level Count")] [FSDescription("ALT + TABs accumulated this level")] public int CurrentWhileInLevelCount { get; set; } } [FSUseDynamicSubmenu] [FSDisplayName("ALT + TAB Counts")] public AltTabCounterSettingsForReal AltTabCounts { get; set; } = new AltTabCounterSettingsForReal(); } public override string Name => "Alt Tab Counter"; public override FeatureGroup Group => FeatureGroups.Special; public override string Description => "Counts the amount of times that the game went out of focus. (ALT + TAB)"; [FeatureConfig] public static AltTabCounterSettings Settings { get; set; } public static bool InLevel { get; private set; } public override void Init() { Settings.AltTabCounts.CurrentSessionCount = 0; } public override void OnApplicationFocusChanged(bool focus) { if (!focus) { Settings.AltTabCounts.TotalCount++; Settings.AltTabCounts.CurrentSessionCount++; if (InLevel) { Settings.AltTabCounts.CurrentWhileInLevelCount++; } Feature.MarkSettingsAsDirty<AltTabCounterSettings>(Settings); } } public void OnGameStateChanged(eGameStateName state) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 InLevel = (int)state == 10; if (InLevel) { Settings.AltTabCounts.CurrentWhileInLevelCount = 0; Feature.MarkSettingsAsDirty<AltTabCounterSettings>(Settings); } } } public class HideFirstPersonItem : Feature { public class HideFirstPersonItemSettings { [FSDisplayName("Model Toggle Key")] [FSDescription("Key used to toggle the model.")] public KeyCode Key { get; set; } = (KeyCode)283; } public override string Name => "Weapon Model Toggle"; public override FeatureGroup Group => FeatureGroups.Special; public override string Description => "Forces the held item to be hidden.\nIntended for taking pictures.\n<color=orange>(Warning! This makes you unable to use or switch items until unhidden!)</color>"; [FeatureConfig] public static HideFirstPersonItemSettings Settings { get; set; } public override void Update() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 //IL_000e: Unknown result type (might be due to invalid IL or missing references) if ((int)FocusStateManager.CurrentState == 4 && Input.GetKeyDown(Settings.Key)) { PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent(); if ((Object)(object)localPlayerAgent != (Object)null && (Object)(object)localPlayerAgent.FPItemHolder != (Object)null) { localPlayerAgent.FPItemHolder.ForceItemHidden = !localPlayerAgent.FPItemHolder.ForceItemHidden; } } } } [RundownConstraint(/*Could not decode attribute arguments.*/)] public class MuteSpeak : Feature { private static PlayerAgent _localPlayerAgent; public override string Name => "Mute Speak"; public override FeatureGroup Group => FeatureGroups.Special; public override string Description => "Binds a few voice lines to keyboard keys.\n\nArrow keys\n[P, L, K, J, H] toggleable by hitting F8; off by default\nHold [Right Control] for alternate lines"; public static IArchiveLogger FeatureLogger { get; set; } public static bool EnableOtherVoiceBinds { get; set; } public static void IfKeySay(KeyCode key, uint soundId) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if (Input.GetKeyDown(key)) { PlayerVoiceManager.WantToSay(_localPlayerAgent.CharacterID, soundId); } } public static void IfKeySay(KeyCode key, uint soundId, int characterID) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if (Input.GetKeyDown(key)) { PlayerVoiceManager.WantToSay(characterID, soundId); } } public override void Update() { if (Input.GetKeyDown((KeyCode)289)) { EnableOtherVoiceBinds = !EnableOtherVoiceBinds; FeatureLogger.Notice($"Voice binds enabled: {EnableOtherVoiceBinds}"); } if (PlayerChatManager.InChatMode || SharedUtils.LocalPlayerIsInTerminal || !PlayerManager.TryGetLocalPlayerAgent(ref _localPlayerAgent) || (Object)(object)_localPlayerAgent == (Object)null) { return; } if (Input.GetKey((KeyCode)305)) { IfKeySay((KeyCode)303, SoundEventCache.Resolve("PLAY_BIGSPACEENTER01", false)); IfKeySay((KeyCode)273, SoundEventCache.Resolve("PLAY_CL_NORTH", false)); IfKeySay((KeyCode)275, SoundEventCache.Resolve("PLAY_CL_EAST", false)); IfKeySay((KeyCode)274, SoundEventCache.Resolve("PLAY_CL_SOUTH", false)); IfKeySay((KeyCode)276, SoundEventCache.Resolve("PLAY_CL_WEST", false)); if (EnableOtherVoiceBinds) { IfKeySay((KeyCode)112, SoundEventCache.Resolve("PLAY_CL_WELLDONE", false)); IfKeySay((KeyCode)108, SoundEventCache.Resolve("PLAY_CL_SHH", false)); IfKeySay((KeyCode)107, SoundEventCache.Resolve("PLAY_CL_WILLDO", false)); IfKeySay((KeyCode)106, SoundEventCache.Resolve("PLAY_CL_YOUTAKE", false)); IfKeySay((KeyCode)104, SoundEventCache.Resolve("PLAY_FALLDAMAGEGRUNT02_5A", false), 2); } } else { IfKeySay((KeyCode)276, SoundEventCache.Resolve("PLAY_CL_LEFT", false)); IfKeySay((KeyCode)275, SoundEventCache.Resolve("PLAY_CL_RIGHT", false)); IfKeySay((KeyCode)273, SoundEventCache.Resolve("PLAY_CL_YES", false)); IfKeySay((KeyCode)274, SoundEventCache.Resolve("PLAY_CL_NO", false)); if (EnableOtherVoiceBinds) { IfKeySay((KeyCode)112, SoundEventCache.Resolve("PLAY_CL_SORRY", false)); IfKeySay((KeyCode)108, SoundEventCache.Resolve("PLAY_CL_HURRY", false)); IfKeySay((KeyCode)106, SoundEventCache.Resolve("PLAY_CL_THREETWOONEGO", false)); IfKeySay((KeyCode)107, SoundEventCache.Resolve("PLAY_CL_SYNCHRONIZE", false)); IfKeySay((KeyCode)104, SoundEventCache.Resolve("PLAY_FALLDAMAGEGRUNT02_5A", false)); } } } } [EnableFeatureByDefault] public class ProcessPriority : Feature { public class ProcessPrioritySettings { [Localized] public enum PriorityClass { High, AboveNormal, Normal, BelowNormal } [FSDisplayName("Priority")] public PriorityClass Priority { get; set; } = PriorityClass.AboveNormal; } private static readonly Dictionary<ProcessPrioritySettings.PriorityClass, ProcessPriorityClass> _prioMap = new Dictionary<ProcessPrioritySettings.PriorityClass, ProcessPriorityClass> { { ProcessPrioritySettings.PriorityClass.High, ProcessPriorityClass.High }, { ProcessPrioritySettings.PriorityClass.AboveNormal, ProcessPriorityClass.AboveNormal }, { ProcessPrioritySettings.PriorityClass.Normal, ProcessPriorityClass.Normal }, { ProcessPrioritySettings.PriorityClass.BelowNormal, ProcessPriorityClass.BelowNormal } }; public override string Name => "Process Priority"; public override FeatureGroup Group => FeatureGroups.Special; public override string Description => $"Set the games process priority.\n\nThis does the same thing as opening up <color=orange>Taskmanager</color>, going into the 'Details' tab and right clicking on GTFO.exe > [Set Priority]\n\nWarning! Your system might lag / stutter while the game is loading if set to <color=orange>{1}</color> or higher!"; [FeatureConfig] public static ProcessPrioritySettings Settings { get; set; } public override void OnEnable() { SetPriority(Settings.Priority); } public override void OnDisable() { SetPriority(ProcessPrioritySettings.PriorityClass.Normal); } public override void OnFeatureSettingChanged(FeatureSetting setting) { SetPriority(Settings.Priority); } public void SetPriority(ProcessPrioritySettings.PriorityClass settingsPriority) { if (_prioMap.TryGetValue(settingsPriority, out var value)) { using (Process process = Process.GetCurrentProcess()) { process.PriorityClass = value; } ((Feature)this).FeatureLogger.Success($"Set ProcessPriority to {settingsPriority}!"); } } } [RundownConstraint(/*Could not decode attribute arguments.*/)] public class RemoveChatRestrictions : Feature { [ArchivePatch(/*Could not decode attribute arguments.*/)] internal static class PlayerChatManager_SetupPatch { public static void Postfix(ref PlayerChatManager __instance) { try { SetValues(__instance); } catch (Exception ex) { FeatureLogger.Exception(ex); } } } private static PropertyAccessor<PlayerChatManager, Il2CppStructArray<int>> A_PlayerChatManager_m_forbiddenChars; private readonly int[] _forbiddenChars = new int[3] { 60, 61, 62 }; public override string Name => "Remove Chat Restrictions"; public override FeatureGroup Group => FeatureGroups.Special; public override string Description => "Allows the usage of '>' and '<' characters in chat.\n\n(Also enables TextMeshPro RichText tags to be used in chat, don't do stupid things!)"; public static IArchiveLogger FeatureLogger { get; set; } public override void OnEnable() { SetValues(PlayerChatManager.Current); } public override void OnDisable() { SetValues(PlayerChatManager.Current, _forbiddenChars); } public override void Init() { A_PlayerChatManager_m_forbiddenChars = PropertyAccessor<PlayerChatManager, Il2CppStructArray<int>>.GetAccessor("m_forbiddenChars", false); } public static void SetValues(PlayerChatManager instance, int[] values = null) { if (!((Object)(object)instance == (Object)null)) { A_PlayerChatManager_m_forbiddenChars.Set(instance, Il2CppStructArray<int>.op_Implicit(values ?? Array.Empty<int>())); } } } } namespace TheArchive.Features.Security { [EnableFeatureByDefault] public class AntiBoosterHack : Feature { public class AntiBoosterHackSettings { [Localized] public enum PunishmentMode { NoneAndLog, Kick, KickAndBan } [FSDisplayName("Punish Friends")] [FSDescription("If (Steam) Friends should be affected as well.")] public bool PunishFriends { get; set; } [FSDisplayName("Punishment")] [FSDescription("What to do with griefers that are using modified boosters.")] public PunishmentMode Punishment { get; set; } = PunishmentMode.Kick; } [ArchivePatch(/*Could not decode attribute arguments.*/)] private class BoosterImplantManager__OnSyncBoosterImplants__Patch { private static void Postfix(SNet_Player player, pBoosterImplantsWithOwner pBoosterImplantsWithOwner) { SNet_Player player2 = default(SNet_Player); if (SNet.IsMaster && pBoosterImplantsWithOwner != null && (player == null || !player.IsLocal) && SNet.Replication.TryGetLastSender(ref player2, false) && ((pBoosterImplantsWithOwner.BasicImplant.BoosterEffectCount != 0 && !BoosterImplantTemplateManager.TryGetBoosterImplantTemplate(pBoosterImplantsWithOwner.BasicImplant, (BoosterImplantCategory)0)) || (pBoosterImplantsWithOwner.AdvancedImplant.BoosterEffectCount != 0 && !BoosterImplantTemplateManager.TryGetBoosterImplantTemplate(pBoosterImplantsWithOwner.AdvancedImplant, (BoosterImplantCategory)1)) || (pBoosterImplantsWithOwner.SpecializedImplant.BoosterEffectCount != 0 && !BoosterImplantTemplateManager.TryGetBoosterImplantTemplate(pBoosterImplantsWithOwner.SpecializedImplant, (BoosterImplantCategory)2)))) { PunishPlayer(player2); } } } public static class BoosterImplantTemplateManager { public class LocalizedTextJsonConverter : JsonConverter { public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { writer.WriteValue(string.Empty); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { return BoosterImplantTemplateDataBlock.UNKNOWN_BLOCK.PublicName; } public override bool CanConvert(Type objectType) { return objectType == typeof(LocalizedText); } } public class ListOfTConverter<T> : JsonConverter<List<T>> { public override List<T> ReadJson(JsonReader reader, Type objectType, List<T> existingValue, bool hasExistingValue, JsonSerializer serializer) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 JToken val = JToken.Load(reader); if ((int)val.Type == 2) { return SharedUtils.ToIL2CPPListIfNecessary<T>(val.ToObject<List<T>>(serializer)); } return null; } public override void WriteJson(JsonWriter writer, List<T> value, JsonSerializer serializer) { JToken.FromObject((object)value).WriteTo(writer, Array.Empty<JsonConverter>()); } public ListOfTConverter() { ((JsonConverter<List<List<T>>>)(object)this)..ctor(); } } public class ListOfListOfTConverter<T> : JsonConverter<List<List<T>>> { public override List<List<T>> ReadJson(JsonReader reader, Type objectType, List<List<T>> existingValue, bool hasExistingValue, JsonSerializer serializer) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Invalid comparison between Unknown and I4 //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Invalid comparison between Unknown and I4 //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) JToken val = JToken.Load(reader); List<List<T>> val2 = (List<List<T>>)(object)new List<List<List<T>>>(); if ((int)val.Type == 2) { foreach (JToken item in val.Children()) { if ((int)item.Type != 2) { continue; } List<T> val3 = new List<T>(); foreach (JToken item2 in item.Children()) { T val4 = item2.ToObject<T>(serializer); val3.Add(val4); } ((List<List<List<T>>>)(object)val2).Add((List<List<T>>)(object)val3); } } return val2; } public override void WriteJson(JsonWriter writer, List<List<T>> value, JsonSerializer serializer) { JToken.FromObject((object)value).WriteTo(writer, Array.Empty<JsonConverter>()); } public ListOfListOfTConverter() { ((JsonConverter<List<List<List<List<T>>>>>)(object)this)..ctor(); } } public class BoosterImplantEffectTemplate { public uint BoosterImplantEffect { get; set; } public float EffectMaxValue { get; set; } public float EffectMinValue { get; set; } public BoosterImplantEffectTemplate(BoosterImplantEffectInstance effect) { EffectMaxValue = effect.MaxValue; EffectMinValue = effect.MinValue; BoosterImplantEffect = effect.BoosterImplantEffect; } } public class BoosterImplantTemplate { public uint BoosterImplantID { get; set; } public BoosterImplantCategory ImplantCategory { get; set; } [JsonIgnore] public List<BoosterImplantEffectTemplate> Effects { get; set; } = new List<BoosterImplantEffectTemplate>(); [JsonIgnore] public List<List<BoosterImplantEffectTemplate>> RandomEffects { get; set; } = new List<List<BoosterImplantEffectTemplate>>(); [JsonIgnore] public List<uint> Conditions { get; set; } = new List<uint>(); [JsonIgnore] public List<uint> RandomConditions { get; set; } = new List<uint>(); [JsonIgnore] public BoosterImplantTemplateDataBlock TemplateDataBlock { get; private set; } public List<List<BoosterImplantEffectTemplate>> EffectGroups { get; set; } = new List<List<BoosterImplantEffectTemplate>>(); public List<List<uint>> ConditionGroups { get; set; } = new List<List<uint>>(); public BoosterImplantTemplate(BoosterImplantTemplateDataBlock block) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) TemplateDataBlock = block; BoosterImplantID = ((GameDataBlockBase<BoosterImplantTemplateDataBlock>)(object)block).persistentID; ImplantCategory = block.ImplantCategory; for (int i = 0; i < block.Effects.Count; i++) { Effects.Add(new BoosterImplantEffectTemplate(block.Effects[i])); } for (int j = 0; j < block.RandomEffects.Count; j++) { List<BoosterImplantEffectTemplate> list = new List<BoosterImplantEffectTemplate>(); for (int k = 0; k < block.RandomEffects[j].Count; k++) { list.Add(new BoosterImplantEffectTemplate(block.RandomEffects[j][k])); } RandomEffects.Add(list); } Conditions.AddRange((IEnumerable<uint>)block.Conditions.ToArray()); RandomConditions.AddRange((IEnumerable<uint>)block.RandomConditions.ToArray()); EffectGroups = GenerateEffectGroups(); ConditionGroups = GenerateConditionGroups(); } private List<List<BoosterImplantEffectTemplate>> GenerateEffectGroups() { List<List<BoosterImplantEffectTemplate>> list = new List<List<BoosterImplantEffectTemplate>>(); List<List<BoosterImplantEffectTemplate>> nElementCombinations = GetNElementCombinations(RandomEffects); for (int i = 0; i < nElementCombinations.Count; i++) { List<BoosterImplantEffectTemplate> list2 = Effects.ToList(); list2.AddRange(nElementCombinations[i]); list.Add(list2); } return list; } private List<List<uint>> GenerateConditionGroups() { return GetNElementCombinations(new List<List<uint>> { Conditions, RandomConditions }); } } private static string _r5BoosterTemplatesJson; private static List<BoosterImplantTemplateDataBlock> OldBoosterImplantTemplateDataBlocks = new List<BoosterImplantTemplateDataBlock>(); public static List<BoosterImplantTemplate> BoosterImplantTemplates { get; } = new List<BoosterImplantTemplate>(); private static string R5BoosterTemplatesJson { get { if (!string.IsNullOrWhiteSpace(_r5BoosterTemplatesJson)) { return _r5BoosterTemplatesJson; } byte[] bytes = Utils.LoadFromResource("TheArchive.Resources.RundownFiveBoosterTemplates.json"); _r5BoosterTemplatesJson = Encoding.UTF8.GetString(bytes); return _r5BoosterTemplatesJson; } } public static void LoadTemplateData() { OldBoosterImplantTemplateDataBlocks.Clear(); OldBoosterImplantTemplateDataBlocks.AddRange(JsonConvert.DeserializeObject<List<BoosterImplantTemplateDataBlock>>(R5BoosterTemplatesJson, (JsonConverter[])(object)new JsonConverter[4] { new LocalizedTextJsonConverter(), (JsonConverter)new ListOfTConverter<uint>(), (JsonConverter)new ListOfTConverter<BoosterImplantEffectInstance>(), (JsonConverter)new ListOfListOfTConverter<BoosterImplantEffectInstance>() })); BoosterImplantTemplates.Clear(); Il2CppArrayBase<BoosterImplantTemplateDataBlock> allBlocksForEditor = GameDataBlockBase<BoosterImplantTemplateDataBlock>.GetAllBlocksForEditor(); for (int i = 0; i < allBlocksForEditor.Count; i++) { BoosterImplantTemplates.Add(new BoosterImplantTemplate(allBlocksForEditor[i])); } for (int j = 0; j < OldBoosterImplantTemplateDataBlocks.Count; j++) { BoosterImplantTemplates.Add(new BoosterImplantTemplate(OldBoosterImplantTemplateDataBlocks[j])); } } public static bool TryGetBoosterImplantTemplate(pBoosterImplantData boosterImplant, BoosterImplantCategory category) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_02ec: Unknown result type (might be due to invalid IL or missing references) if (boosterImplant == null) { return false; } uint persistenID = boosterImplant.BoosterImplantID; List<BoosterImplantTemplate> list = BoosterImplantTemplates.FindAll((BoosterImplantTemplate p) => p.BoosterImplantID == persistenID && p.ImplantCategory == category); for (int k = 0; k < list.Count; k++) { BoosterImplantTemplate boosterImplantTemplate = list[k]; if (boosterImplantTemplate == null || boosterImplantTemplate.TemplateDataBlock == null) { continue; } List<List<uint>> conditionGroups = boosterImplantTemplate.ConditionGroups; int conditionCount = boosterImplant.ConditionCount; bool flag = false; IEnumerable<uint> conditions = ((IEnumerable<uint>)boosterImplant.Conditions).Take(conditionCount); int j; for (j = 0; j < conditionGroups.Count; j++) { if (conditionCount != conditionGroups[j].Count) { continue; } bool num = conditions.All((uint p) => conditionGroups[j].Any((uint q) => q == p)); bool flag2 = conditionGroups[j].All((uint p) => conditions.Any((uint q) => q == p)); if (num && flag2) { flag = true; break; } } if (!flag) { continue; } int boosterEffectCount = boosterImplant.BoosterEffectCount; bool flag3 = false; List<List<BoosterImplantEffectTemplate>> effectGroups = boosterImplantTemplate.EffectGroups; IEnumerable<pBoosterEffectData> effects = ((IEnumerable<pBoosterEffectData>)boosterImplant.BoosterEffectDatas).Take(boosterEffectCount); int i; for (i = 0; i < effectGroups.Count; i++) { if (effectGroups[i].Count != boosterEffectCount) { continue; } for (int l = 0; l < effectGroups[i].Count; l++) { bool num2 = effects.All((pBoosterEffectData p) => effectGroups[i].Any((BoosterImplantEffectTemplate q) => q.BoosterImplantEffect == p.BoosterEffectID && p.EffectValue >= q.EffectMinValue && p.EffectValue <= q.EffectMaxValue)); bool flag4 = effectGroups[i].All((BoosterImplantEffectTemplate p) => effects.Any((pBoosterEffectData q) => q.BoosterEffectID == p.BoosterImplantEffect && q.EffectValue >= p.EffectMinValue && q.EffectValue <= p.EffectMaxValue)); if (num2 && flag4) { flag3 = true; break; } } if (flag3) { break; } } if (flag3) { bool flag5 = boosterImplant.UseCount <= (int)boosterImplantTemplate.TemplateDataBlock.DurationRange.y && boosterImplant.UseCount >= 0; if (flag && flag3 && flag5) { return true; } } } return false; } private static List<List<T>> GetNElementCombinations<T>(List<List<T>> lists) { List<List<T>> list = new List<List<T>>(); GetNElementCombinationsHelper(lists, new List<T>(), 0, list); return list; } private static void GetNElementCombinationsHelper<T>(List<List<T>> lists, List<T> currentCombination, int currentIndex, List<List<T>> combinations) { if (currentIndex == lists.Count) { combinations.Add(new List<T>(currentCombination)); return; } List<T> list = lists[currentIndex]; if (list.Count == 0) { GetNElementCombinationsHelper(lists, currentCombination, currentIndex + 1, combinations); return; } foreach (T item in list) { currentCombination.Add(item); GetNElementCombinationsHelper(lists, currentCombination, currentIndex + 1, combinations); currentCombination.RemoveAt(currentCombination.Count - 1); } } } public override string Name => "Anti Booster Hack"; public override string Description => "Prevents clients from using modified boosters."; public override FeatureGroup Group => FeatureGroups.Security; public static IArchiveLogger FeatureLogger { get; set; } [FeatureConfig] public static AntiBoosterHackSettings Settings { get; set; } public override void Init() { if (ArchiveMod.IsPlayingModded) { ((Feature)this).RequestDisable("Playing Modded"); } } public override void OnGameDataInitialized() { BoosterImplantTemplateManager.LoadTemplateData(); } public static bool PunishPlayer(SNet_Player player) { if ((Object)(object)player == (Object)null) { return true; } if (SharedUtils.IsFriend(player) && !Settings.PunishFriends) { FeatureLogger.Notice($"Friend \"{player.NickName}\" \"{player.Lookup}\" is using modified boosters!"); return false; } switch (Settings.Punishment) { case AntiBoosterHackSettings.PunishmentMode.KickAndBan: PlayerLobbyManagement.BanPlayer(player); break; case AntiBoosterHackSettings.PunishmentMode.Kick: PlayerLobbyManagement.KickPlayer(player); break; } FeatureLogger.Notice($"Player \"{player.NickName}\" \"{player.Lookup}\" is using modified boosters! ({Settings.Punishment})"); return true; } } [EnableFeatureByDefault] public class AntiGearHack : Feature { public class AntiGearHackSettings { [Localized] public enum PunishmentMode { NoneAndLog, Kick, KickAndBan } [FSDisplayName("Punish Friends")] [FSDescription("If (Steam) Friends should be affected as well.")] public bool PunishFriends { get; set; } [FSDisplayName("Punishment")] [FSDescription("What to do with griefers that are using modified gears.")] public PunishmentMode Punishment { get; set; } = PunishmentMode.Kick; } [ArchivePatch(/*Could not decode attribute arguments.*/)] private class PlayerBackpackManager__ReceiveInventorySync__Patch { private static void Prefix(pInventorySync data) { //IL_0008: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown if (!SNet.IsMaster) { return; } pPlayer sourcePlayer = data.sourcePlayer; SNet_Player val = default(SNet_Player); SNet_Player val2 = default(SNet_Player); if (!((pPlayer)(ref sourcePlayer)).TryGetPlayer(ref val) || val.IsLocal || val.IsBot || !SNet.Replication.TryGetLastSender(ref val2, false) || val2.IsLocal || val2.IsBot) { return; } foreach (GearIDRange item in new List<GearIDRange> { new GearIDRange(data.gearStandard), new GearIDRange(data.gearSpecial), new GearIDRange(data.gearMelee), new GearIDRange(data.gearClass), new GearIDRange(data.gearHacking) }) { if (!CheckGearIDRange(item)) { PunishPlayer(val2); break; } } } } private static Dictionary<string, string> GearCompsHashLookup = new Dictionary<string, string>(); public override string Name => "Anti Gear Hack"; public override string Description => "Prevents clients from using modified gear."; public override FeatureGroup Group => FeatureGroups.Security; public static IArchiveLogger FeatureLogger { get; set; } [FeatureConfig] public static AntiGearHackSettings Settings { get; set; } public override void Init() { if (ArchiveMod.IsPlayingModded) { ((Feature)this).RequestDisable("Playing Modded"); } } public override void OnGameDataInitialized() { LoadData(); } public static bool PunishPlayer(SNet_Player player) { if ((Object)(object)player == (Object)null) { return true; } if (SharedUtils.IsFriend(player) && !Settings.PunishFriends) { FeatureLogger.Notice($"Friend \"{player.NickName}\" \"{player.Lookup}\" is using modified gears!"); return false; } switch (Settings.Punishment) { case AntiGearHackSettings.PunishmentMode.KickAndBan: PlayerLobbyManagement.BanPlayer(player); break; case AntiGearHackSettings.PunishmentMode.Kick: PlayerLobbyManagement.KickPlayer(player); break; } FeatureLogger.Notice($"Player \"{player.NickName}\" \"{player.Lookup}\" is using modified gears! ({Settings.Punishment})"); return true; } public static bool CheckIsValidWeaponGearIDRangeDataForPlayer(SNet_Player player) { if (!player.HasCharacterSlot) { return false; } Enumerator<GearIDRange> enumerator = ((Il2CppArrayBase<List<GearIDRange>>)(object)GearManager.Current.m_gearPerSlot)[player.PlayerSlotIndex()].GetEnumerator(); while (enumerator.MoveNext()) { if (CheckGearIDRange(enumerator.Current)) { return false; } } return true; } public static bool CheckGearIDRange(GearIDRange gearIDRange) { string input = gearIDRange.ToJSON(); string pattern = "(?<=Comps\":)(.*?)(?=,\"MatTrans\")"; string key = Utils.HashString(Regex.Match(input, pattern).Value); return GearCompsHashLookup.ContainsKey(key); } public static void LoadData() { GearCompsHashLookup.Clear(); foreach (PlayerOfflineGearDataBlock allBlock in GameDataBlockBase<PlayerOfflineGearDataBlock>.GetAllBlocks()) { string gearJSON = allBlock.GearJSON; string pattern = "(?<=Comps\":)(.*?)(?=,\"MatTrans\")"; string key = Utils.HashString(Regex.Match(gearJSON, pattern).Value); GearCompsHashLookup[key] = gearJSON; } } } [EnableFeatureByDefault] [RundownConstraint(/*Could not decode attribute arguments.*/)] public class AntiSpawn : Feature { public class AntiSpawnSettings { [Localized] public enum PunishmentMode { NoneAndLog, Kick, KickAndBan } [FSDisplayName("Punish Friends")] [FSDescription("If (Steam) Friends should be affected as well.")] public bool PunishFriends { get; set; } [FSDisplayName("Punishment")] [FSDescription("What to do with griefers that are trying to spawn in enemies.")] public PunishmentMode Punishment { get; set; } = PunishmentMode.Kick; } public unsafe delegate void Original_InternalSpawnRequestFromSlaveCallback(IntPtr self, IntPtr spawnData, Il2CppMethodInfo* methodInfo); private static bool _hasBeenPatched = false; private static Original_InternalSpawnRequestFromSlaveCallback _originalMethod_InternalSpawnRequestFromSlaveCallback_pEnemySpawnData; private unsafe static Original_InternalSpawnRequestFromSlaveCallback _detourMethod_InternalSpawnRequestFromSlaveCallback_pEnemySpawnData = InternalSpawnRequestFromSlaveCallback_pEnemySpawnData_Replacement; private static Original_InternalSpawnRequestFromSlaveCallback _originalMethod_InternalSpawnRequestFromSlaveCallback_pEnemyGroupSpawnData; private unsafe static Original_InternalSpawnRequestFromSlaveCallback _detourMethod_InternalSpawnRequestFromSlaveCallback_pEnemyGroupSpawnData = InternalSpawnRequestFromSlaveCallback_pEnemyGroupSpawnData_Replacement; public override string Name => "Anti Spawn"; public override FeatureGroup Group => FeatureGroups.Security; public override string Description => "Prevents clients from spawning in enemies."; public static IArchiveLogger FeatureLogger { get; set; } public static bool IsEnabled { get; set; } [FeatureConfig] public static AntiSpawnSettings Settings { get; set; } public override void OnEnable() { OneTimePatch(); } private static void OneTimePatch() { if (!_hasBeenPatched) { LoaderWrapper.ApplyNativeHook<SNet_ReplicationManager<pEnemySpawnData, EnemyReplicator>, Original_InternalSpawnRequestFromSlaveCallback>("InternalSpawnRequestFromSlaveCallback", typeof(void).FullName, new string[1] { typeof(pEnemySpawnData).FullName }, _detourMethod_InternalSpawnRequestFromSlaveCallback_pEnemySpawnData, ref _originalMethod_InternalSpawnRequestFromSlaveCallback_pEnemySpawnData); LoaderWrapper.ApplyNativeHook<SNet_ReplicationManager<pEnemyGroupSpawnData, SNet_DynamicReplicator<pEnemyGroupSpawnData>>, Original_InternalSpawnRequestFromSlaveCallback>("InternalSpawnRequestFromSlaveCallback", typeof(void).FullName, new string[1] { typeof(pEnemyGroupSpawnData).FullName }, _detourMethod_InternalSpawnRequestFromSlaveCallback_pEnemyGroupSpawnData, ref _originalMethod_InternalSpawnRequestFromSlaveCallback_pEnemyGroupSpawnData); _hasBeenPatched = true; } } public unsafe static void InternalSpawnRequestFromSlaveCallback_pEnemyGroupSpawnData_Replacement(IntPtr self, IntPtr spawnData, Il2CppMethodInfo* methodInfo) { if (IsEnabled && SNet.IsMaster && !SNet.Capture.IsCheckpointRecall) { bool flag = true; SNet_Player player = default(SNet_Player); if (SNet.Replication.TryGetLastSender(ref player, false)) { flag = PunishPlayer(player); } if (flag) { FeatureLogger.Fail("Cancelled enemy spawn!"); return; } } _originalMethod_InternalSpawnRequestFromSlaveCallback_pEnemyGroupSpawnData(self, spawnData, methodInfo); } public unsafe static void InternalSpawnRequestFromSlaveCallback_pEnemySpawnData_Replacement(IntPtr self, IntPtr spawnData, Il2CppMethodInfo* methodInfo) { if (IsEnabled && SNet.IsMaster && !SNet.Capture.IsCheckpointRecall) { bool flag = true; SNet_Player player = default(SNet_Player); if (SNet.Replication.TryGetLastSender(ref player, false)) { flag = PunishPlayer(player); } if (flag) { FeatureLogger.Fail("Cancelled enemy spawn!"); return; } } _originalMethod_InternalSpawnRequestFromSlaveCallback_pEnemySpawnData(self, spawnData, methodInfo); } public static bool PunishPlayer(SNet_Player player) { if ((Object)(object)player == (Object)null) { return true; } if (SharedUtils.IsFriend(player) && !Settings.PunishFriends) { FeatureLogger.Notice("Friend \"" + player.NickName + "\" is spawning something in!"); return false; } switch (Settings.Punishment) { case AntiSpawnSettings.PunishmentMode.KickAndBan: PlayerLobbyManagement.BanPlayer(player); break; case AntiSpawnSettings.PunishmentMode.Kick: PlayerLobbyManagement.KickPlayer(player); break; } FeatureLogger.Notice($"Player \"{player.NickName}\" tried to spawn something! ({Settings.Punishment})"); return true; } } [EnableFeatureByDefault] public class PlayerLobbyManagement : Feature { public class LobbyManagementSettings { public class LobbyColorSettings { [FSDisplayName("Color the Square")] [FSDescription("Use the colors/settings below to color the square on the loadout screen next to the player names.")] public bool ColorizeLobbyBullet { get; set; } = true; [FSDisplayName("Use Nickname Color for Self")] public bool UseNicknameColorForSelf { get; set; } = true; [FSDisplayName("Random Colors for Self")] public bool RainbowPukeSelf { get; set; } [FSDisplayName("Random Colors for Others")] public bool RainbowPukeFriends { get; set; } [FSHeader("Colors", true)] [FSDisplayName("Default")] public SColor Default { get; set; } = new SColor(1f, 1f, 1f, (float?)null); [FSDisplayName("Friends")] public SColor Friends { get; set; } = new SColor(0.964f, 0.921f, 0.227f, (float?)null); [FSDisplayName("Bots")] public SColor Bots { get; set; } = new SColor(0.949f, 0.58f, 0f, (float?)null); [FSDisplayName("Banned")] public SColor Banned { get; set; } = new SColor(0.545f, 0f, 0f, (float?)null); [FSDisplayName("Self")] public SColor Self { get; set; } = new SColor(1f, 1f, 1f, (float?)null); } public class BanListEntry { [FSSeparator] [FSReadOnly(true)] [FSDisplayName("Name")] public string Name { get; set; } [FSReadOnly(true)] [FSDisplayName("SteamID")] public ulong SteamID { get; set; } [FSReadOnly(true)] [FSTimestamp("U")] [FSDisplayName("Banned on:")] public long Timestamp { get; set; } } public class RecentlyPlayedWithEntry { [FSSeparator] [FSReadOnly(true)] [FSDisplayName("Name")] public string Name { get; set; } [FSReadOnly(true)] [FSDisplayName("SteamID")] public ulong SteamID { get; set; } [FSReadOnly(true)] [FSTimestamp("U")] [FSDisplayName("First time played with:")] public long TimestampFirst { get; set; } [FSReadOnly(true)] [FSTimestamp("U")] [FSDisplayName("Last time played with:")] public long TimestampLast { get; set; } } [FSDisplayName("Names on Map open Steam Profile")] [FSDescription("If clicking a players name on the map screen should open their Steam Profile in your default browser.")] public bool NamesOnMapOpenSteamProfile { get; set; } [FSDisplayName("Open Profiles in Steam Overlay")] [FSDescription("Wheter to open profile links in the overlay or in the default OS browser.")] public bool PreferOpeningProfileLinksInSteamOverlay { get; set; } = true; [FSHeader("Lobby Color Settings", true)] [FSDisplayName("Lobby Colors")] public LobbyColorSettings LobbyColors { get; set; } = new LobbyColorSettings(); [FSHeader("Other", true)] [FSDisplayName("Recently Played With")] public List<RecentlyPlayedWithEntry> RecentlyPlayedWith { get; set; } = new List<RecentlyPlayedWithEntry>(); [FSDisplayName("Banned Players")] [FSDescription("Players who are on this list will not be able to join any games <b>you host</b>.")] public List<BanListEntry> BanList { get; set; } = new List<BanListEntry>(); } [Localized] public enum PlayerRelationShip { None, Self, Friend, Banned, Bot } [ArchivePatch(/*Could not decode attribute arguments.*/)] internal static class SNet_SessionHub_SlaveWantsToJoin_Patch { public static bool Prefix(SNet_Player player) { if (SNet.IsMaster && IsPlayerBanned(player.Lookup)) { FeatureLogger.Notice("Banned player \"" + player.GetName() + "\" tried to join, their join request has been ignored!"); KickPlayer(player); return false; } return true; } } [ArchivePatch(/*Could not decode attribute arguments.*/)] internal static class SNet_OnPlayerJoinedSessionHub_Patch { public static void Postfix(SNet_Player player) { AddRecentlyPlayedWith(player, joined: true); } } [ArchivePatch(/*Could not decode attribute arguments.*/)] internal static class SNet_OnPlayerLeftSessionHub_Patch { public static void Prefix(SNet_Player player) { AddRecentlyPlayedWith(player, joined: false); } } [ArchivePatch(/*Could not decode attribute arguments.*/)] internal static class CM_PlayerLobbyBar_UpdatePlayer_Patch { internal static Dictionary<int, BoxCollider2D> colliderMap = new Dictionary<int, BoxCollider2D>(); private static MethodAccessor<GUIX_ElementSprite> A_Unregister; private static MethodAccessor<GUIX_ElementSprite> A_Start; private static IValueAccessor<GUIX_ElementSprite, GUIX_Layer> A_layer; public static void Init() { A_Start = MethodAccessor<GUIX_ElementSprite>.GetAccessor("Start", (Type[])null, false); A_Unregister = MethodAccessor<GUIX_ElementSprite>.GetAccessor("Unregister", (Type[])null, false); A_layer = AccessorBase.GetValueAccessor<GUIX_ElementSprite, GUIX_Layer>("layer", false); } public static void ColorizeNickNameGUIX(GameObject nickNameGuix, PlayerRelationShip rel = PlayerRelationShip.None) { //IL_0051: 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_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)nickNameGuix == (Object)null) { return; } foreach (Transform item in SharedUtils.DirectChildren(nickNameGuix.transform)) { GUIX_ElementSprite component = ((Component)item).GetComponent<GUIX_ElementSprite>(); SpriteRenderer component2 = ((Component)item).GetComponent<SpriteRenderer>(); if ((Object)(object)component2 != (Object)null) { if (!Settings.LobbyColors.ColorizeLobbyBullet) { component2.color = Color.white; } else if (rel != PlayerRelationShip.Self) { if (rel != PlayerRelationShip.Friend || !Settings.LobbyColors.RainbowPukeFriends) { goto IL_00cf; } component2.color = Random.ColorHSV(); } else if (Settings.LobbyColors.RainbowPukeSelf) { component2.color = Random.ColorHSV(); } else { if (!Settings.LobbyColors.UseNicknameColorForSelf || !FeatureManager.IsFeatureEnabled<Nickname>() || !Nickname.IsNicknameColorEnabled) { goto IL_00cf; } component2.color = Nickname.CurrentNicknameColor; } } goto IL_00db; IL_00cf: component2.color = GetRelationshipColor(rel); goto IL_00db; IL_00db: if (!((Object)(object)A_layer.Get(component) == (Object)null) && ((Component)component).gameObject.activeInHierarchy) { A_Unregister.Invoke(component); component.DynamicIndex = -1; A_layer.Set(component, (GUIX_Layer)null); A_Start.Invoke(component); } } } public static void Postfix(CM_PlayerLobbyBar __instance, SNet_Player player) { //IL_0094: 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) if (player == null) { return; } SNet_Slot characterSlot = player.CharacterSlot; if (characterSlot == null) { return; } _ = characterSlot.index; if (false) { return; } int playerLobbyBarIndex = SharedUtils.GetPlayerLobbyBarIndex(__instance); GameObject gameObject = ((Component)__instance.m_nickText).gameObject; CM_Item CM_Item = gameObject.GetComponent<CM_Item>(); if ((Object)(object)CM_Item == (Object)null) { FeatureLogger.Debug($"Setting up player name button for slot index {playerLobbyBarIndex}"); BoxCollider2D val = gameObject.AddComponent<BoxCollider2D>(); val.size = new Vector2(447.2f, 52.8f); ((Collider2D)val).offset = new Vector2(160f, 1.6f); if (colliderMap.ContainsKey(playerLobbyBarIndex)) { colliderMap.Remove(playerLobbyBarIndex); } colliderMap.Add(playerLobbyBarIndex, val); CM_Item = gameObject.AddComponent<CM_Item>(); CM_Item.ID = playerLobbyBarIndex + 1; SharedUtils.SetCMItemEvents(CM_Item, (Action<int>)delegate(int id) { if (!((RectTransformComp)PopupWindow).IsVisible || ((CM_PopupOverlay)PopupWindow).ID != id) { SetupAndPlaceWindow(id, ((Component)CM_Item).transform); } else { ((RectTransformComp)PopupWindow).SetVisible(false); } }, (Action<int, bool>)null); } ColorizeNickNameGUIX(__instance.m_nickNameGuix, GetRelationship(player)); } } [ArchivePatch(/*Could not decode attribute arguments.*/)] internal static class PUI_Inventory_UpdateAllSlots_Patch { internal static Dictionary<int, BoxCollider2D> colliderMap = new Dictionary<int, BoxCollider2D>(); public static void Postfix(PUI_Inventory __instance, SNet_Player player) { //IL_008c: 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) if (player == null) { return; } SNet_Slot characterSlot = player.CharacterSlot; if (characterSlot == null) { return; } _ = characterSlot.index; if (false) { return; } int index = player.CharacterSlot.index; GameObject headerRoot = __instance.m_headerRoot; if ((Object)(object)headerRoot.GetComponent<CM_Item>() == (Object)null) { FeatureLogger.Debug($"Setting up player name button (map) for index {player.CharacterSlot.index}"); BoxCollider2D val = headerRoot.AddComponent<BoxCollider2D>(); val.size = new Vector2(400f, 40f); ((Collider2D)val).offset = new Vector2(-200f, 0f); if (colliderMap.ContainsKey(index)) { colliderMap.Remove(index); } colliderMap.Add(index, val); CM_Item obj = headerRoot.AddComponent<CM_Item>(); obj.ID = player.CharacterSlot.index + 1; SharedUtils.SetCMItemEvents(obj, (Action<int>)OnMapNameButtonPressed, (Action<int, bool>)null); } } } private static Dictionary<PlayerRelationShip, Color> _colorMap = new Dictionary<PlayerRelationShip, Color>(); private static CM_ScrollWindow _popupWindow = null; public override string Name => "Player Lobby Management"; public override FeatureGroup Group => FeatureGroups.Security; public override string Description => "Allows you to open a players steam profile by clicking on their name as well as kick and ban players as host."; public static ILocalizationService Localization { get; set; } public static IArchiveLogger FeatureLogger { get; set; } [FeatureConfig] public static LobbyManagementSettings Settings { get; set; } private static CM_ScrollWindow PopupWindow { get { //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: 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_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_popupWindow == (Object)null) { FeatureLogger.Debug("Creating PopupWindow ..."); _popupWindow = Object.Instantiate<CM_ScrollWindow>(PageSettingsData.PopupWindow, (Transform)(object)((CM_PageBase)CM_PageLoadout.Current).m_movingContentHolder); Object.DontDestroyOnLoad((Object)(object)_popupWindow); ((Object)_popupWindow).name = "PlayerLobbyManagement_PopupWindow_PlayerManagement"; ((RectTransformComp)PopupWindow).Setup(); OpenSteamItem = CreatePopupItem(Localization.Get(1u), OnNameButtonPressed); SharedUtils.ChangeColorCMItem(OpenSteamItem, ModSettings.GREEN, (Color?)null); SharedUtils.SetHoldDuration(SharedUtils.TryCastTo<CM_TimedButton>((Il2CppObjectBase)(object)OpenSteamItem), 0.5f); IsFriendItem = CreatePopupItem(Localization.Get(2u), delegate { }); SharedUtils.ChangeColorCMItem(IsFriendItem, GetRelationshipColor(PlayerRelationShip.Friend), (Color?)null); SharedUtils.SetHoldDuration(SharedUtils.TryCastTo<CM_TimedButton>((Il2CppObjectBase)(object)IsFriendItem), 100f); ((Behaviour)((Component)IsFriendItem).GetComponent<Collider2D>()).enabled = false; KickPlayerItem = CreatePopupItem(Localization.Get(3u), KickPlayerButtonPressed); SharedUtils.ChangeColorCMItem(KickPlayerItem, ModSettings.ORANGE, (Color?)null); SharedUtils.SetHoldDuration(SharedUtils.TryCastTo<CM_TimedButton>((Il2CppObjectBase)(object)KickPlayerItem), 2f); BanPlayerItem = CreatePopupItem(Localization.Get(4u), BanPlayerButtonPressed); SharedUtils.ChangeColorCMItem(BanPlayerItem, ModSettings.RED, (Color?)null); SharedUtils.SetHoldDuration(SharedUtils.TryCastTo<CM_TimedButton>((Il2CppObjectBase)(object)BanPlayerItem), 4f); CM_Item val = CreatePopupItem("Spacer, should not be visible", delegate { }); List<iScrollWindowContent> val2 = SharedUtils.NewListForGame<iScrollWindowContent>(); val2.Add(((Component)OpenSteamItem).GetComponentInChildren<iScrollWindowContent>()); val2.Add(((Component)IsFriendItem).GetComponentInChildren<iScrollWindowContent>()); val2.Add(((Component)val).GetComponentInChildren<iScrollWindowContent>()); val2.Add(((Component)KickPlayerItem).GetComponentInChildren<iScrollWindowContent>()); val2.Add(((Component)BanPlayerItem).GetComponentInChildren<iScrollWindowContent>()); PopupWindow.SetContentItems(val2, 5f); ((Component)val).gameObject.SetActive(false); ((Component)val).transform.position = new Vector3(-5000f, 0f, 0f); ((RectTransformComp)PopupWindow).SetSize(new Vector2(350f, (float)(58 * val2.Count))); ((RectTransformComp)PopupWindow).SetVisible(false); PopupWindow.SetHeader("Player options"); } return _popupWindow; } } internal static CM_Item OpenSteamItem { get; set; } internal static CM_Item IsFriendItem { get; set; } internal static CM_Item KickPlayerItem { get; set; } internal static CM_Item BanPlayerItem { get; set; } public override void OnEnable() { foreach (BoxCollider2D value in CM_PlayerLobbyBar_UpdatePlayer_Patch.colliderMap.Values) { if ((Object)(object)value != (Object)null) { ((Behaviour)value).enabled = true; } } foreach (BoxCollider2D value2 in PUI_Inventory_UpdateAllSlots_Patch.colliderMap.Values) { if ((Object)(object)value2 != (Object)null) { ((Behaviour)value2).enabled = true; } } SetupColorMap(); } public override void OnDisable() { foreach (BoxCollider2D value in CM_PlayerLobbyBar_UpdatePlayer_Patch.colliderMap.Values) { if ((Object)(object)value != (Object)null) { ((Behaviour)value).enabled = false; } } foreach (BoxCollider2D value2 in PUI_Inventory_UpdateAllSlots_Patch.colliderMap.Values) { if ((Object)(object)value2 != (Object)null) { ((Behaviour)value2).enabled = false; } } } public override void OnFeatureSettingChanged(FeatureSetting setting) { SetupColorMap(); } public static void SetupColorMap() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) _colorMap.Clear(); PlayerRelationShip[] array = Enum.GetValues(typeof(PlayerRelationShip)) as PlayerRelationShip[]; foreach (PlayerRelationShip playerRelationShip in array) { _colorMap.Add(playerRelationShip, GetRelationshipColor(playerRelationShip)); } } public static PlayerRelationShip GetRelationship(PlayerAgent player) { return GetRelationship((player != null) ? player.Owner : null); } public static PlayerRelationShip GetRelationship(SNet_Player player) { if ((Object)(object)player == (Object)null) { return PlayerRelationShip.None; } if (SharedUtils.SafeIsBot(player)) { return PlayerRelationShip.Bot; } if (player.IsLocal) { return PlayerRelationShip.Self; } if (IsPlayerBanned(player.Lookup)) { return PlayerRelationShip.Banned; } if (SharedUtils.IsFriend(player)) { return PlayerRelationShip.Friend; } return PlayerRelationShip.None; } public static Color GetRelationshipColor(PlayerRelationShip rel) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_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) if (_colorMap.TryGetValue(rel, out var value)) { return value; } return (Color)(rel switch { PlayerRelationShip.Self => SColorExtensions.ToUnityColor(Settings.LobbyColors.Self), PlayerRelationShip.Bot => SColorExtensions.ToUnityColor(Settings.LobbyColors.Bots), PlayerRelationShip.Friend => SColorExtensions.ToUnityColor(Settings.LobbyColors.Friends), PlayerRelationShip.Banned => SColorExtensions.ToUnityColor(Settings.LobbyColors.Banned), _ => SColorExtensions.ToUnityColor(Settings.LobbyColors.Default), }); } public static bool IsPlayerBanned(ulong lookup) { return Settings.BanList.Any((LobbyManagementSettings.BanListEntry bp) => bp.SteamID == lookup); } internal static void OnMapNameButtonPressed(int id) { if (Settings.NamesOnMapOpenSteamProfile) { SNet_Player player = default(SNet_Player); if (!SharedUtils.TryGetPlayerByCharacterIndex(id, ref player)) { FeatureLogger.Debug($"No player found for character index {id - 1}."); } else { OpenSteamProfileFor(player); } } } internal static void OnNameButtonPressed(int id) { ((RectTransformComp)PopupWindow).SetVisible(false); SNet_Player player = default(SNet_Player); if (!SharedUtils.TryGetPlayerByPlayerLobbyBarIndex(id - 1, ref player)) { FeatureLogger.Debug($"No player found for index {id - 1}."); } else { OpenSteamProfileFor(player); } } public static void OpenSteamProfileFor(SNet_Player player) { if ((Object)(object)player == (Object)null) { FeatureLogger.Debug("Player was null!"); return; } if (SharedUtils.SafeIsBot(player)) { FeatureLogger.Notice("The Bot has no steam profile!"); return; } FeatureLogger.Info($"Opening Steam profile for player \"{player.NickName}\" ({player.Lookup})"); string text = $"https://steamcommunity.com/profiles/{player.Lookup}"; if (Settings.PreferOpeningProfileLinksInSteamOverlay && SteamUtils.IsOverlayEnabled()) { SteamFriends.ActivateGameOverlayToWebPage(text, (EActivateGameOverlayToWebPageMode)0); } else { Application.OpenURL(text); } } internal static void KickPlayerButtonPressed(int playerID) { ((RectTransformComp)PopupWindow).SetVisible(false); SNet_Player val = default(SNet_Player); if (SNet.IsMaster && SharedUtils.TryGetPlayerByPlayerLobbyBarIndex(playerID - 1, ref val)) { if (SharedUtils.SafeIsBot(val)) { FeatureLogger.Notice("Use the built in button below to remove bots!"); return; } FeatureLogger.Notice($"Kicking player \"{val.GetName()}\" Nick:\"{val.NickName}\" ..."); KickPlayer(val); } } internal static void BanPlayerButtonPressed(int playerID) { SNet_Player val = default(SNet_Player); if (!SharedUtils.TryGetPlayerByPlayerLobbyBarIndex(playerID - 1, ref val)) { return; } if (val.IsLocal) { BanPlayerItem.SetText(" You can't ban yourself, silly!"); return; } ((RectTransformComp)PopupWindow).SetVisible(false); if (SharedUtils.SafeIsBot(val)) { FeatureLogger.Notice("You can't ban a bot!"); } else if (!IsPlayerBanned(val.Lookup)) { BanPlayer(val); } else { UnbanPlayer(val); } } public static bool BanPlayer(SNet_Player player, bool kickPlayer = true) { if ((Object)(object)player == (Object)null) { return false; } if (!IsPlayerBanned(player.Lookup)) { Settings.BanList.Add(new LobbyManagementSettings.BanListEntry { Name = player.GetName(), SteamID = player.Lookup, Timestamp = DateTime.UtcNow.Ticks }); FeatureLogger.Fail($"Player has been added to list of banned players: Name:\"{player.GetName()}\" SteamID:\"{player.Lookup}\""); Feature.MarkSettingsAsDirty<LobbyManagementSettings>(Settings); if (kickPlayer) { KickPlayer(player); } return true; } return false; } public static bool UnbanPlayer(SNet_Player player) { return UnbanPlayer((player != null) ? player.Lookup : ulong.MaxValue); } public static bool UnbanPlayer(ulong playerID) { if (playerID == ulong.MaxValue) { return false; } LobbyManagementSettings.BanListEntry banListEntry = Settings.BanList.FirstOrDefault((LobbyManagementSettings.BanListEntry entry) => entry.SteamID == playerID); if (banListEntry != null) { Settings.BanList.Remove(banListEntry); FeatureLogger.Success($"Player has been removed from the list of banned players: Name:\"{banListEntry.Name}\" SteamID:\"{banListEntry.SteamID}\""); Feature.MarkSettingsAsDirty<LobbyManagementSettings>(Settings); return true; } return false; } public static void KickPlayer(SNet_Player player) { if (SNet.IsMaster) { SNet.Sync.KickPlayer(player, (SNet_PlayerEventReason)2); } } private static CM_Item CreatePopupItem(string text, Action<int> onClick, int id = 0) { CM_Item val = SharedUtils.TryCastTo<CM_Item>((Il2CppObjectBase)(object)GOUtil.SpawnChildAndGetComp<iScrollWindowContent>(UIHelper.PopupItemPrefab, ((Component)_popupWindow).transform)); val.SetupCMItem(); if (id != 0) { val.ID = id; } val.SetText(text); SharedUtils.SetCMItemEvents(val, onClick, (Action<int, bool>)null); ((RectTransformComp)val).ForcePopupLayer(true, (GameObject)null); return val; } public static void SetupAndPlaceWindow(int playerID, Transform pos) { //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Expected O, but got Unknown //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Unknown result type (might be due to invalid IL or missing references) SNet_Player val = default(SNet_Player); if (!SharedUtils.TryGetPlayerByPlayerLobbyBarIndex(playerID - 1, ref val)) { return; } string name = val.GetName(); bool flag = SharedUtils.SafeIsBot(val); ((Component)KickPlayerItem).gameObject.SetActive(!flag); ((Component)BanPlayerItem).gameObject.SetActive(!flag); ((Component)OpenSteamItem).gameObject.SetActive(!flag); if (flag) { ((Component)IsFriendItem).gameObject.SetActive(true); IsFriendItem.SetText(Localization.Get(6u)); SharedUtils.ChangeColorCMItem(IsFriendItem, GetRelationshipColor(PlayerRelationShip.Bot), (Color?)null); ShowWindow(name, pos, playerID); return; } ((CM_PopupOverlay)PopupWindow).SetupFromButton(new iCellMenuPopupController(((Il2CppObjectBase)CM_PageLoadout.Current).Pointer), (CM_PageBase)(object)CM_PageLoadout.Current); SNet_Friend val2 = default(SNet_Friend); bool flag2 = SNet.Friends.TryGetFriend(val.Lookup, ref val2); bool flag3 = IsPlayerBanned(val.Lookup); ((Component)IsFriendItem).gameObject.SetActive(flag2 || flag3); if (flag3) { IsFriendItem.SetText(Localization.Get(5u)); SharedUtils.ChangeColorCMItem(IsFriendItem, GetRelationshipColor(PlayerRelationShip.Banned), (Color?)null); } else if (flag2) { IsFriendItem.SetText(Localization.Get(2u)); SharedUtils.ChangeColorCMItem(IsFriendItem, GetRelationshipColor(PlayerRelationShip.Friend), (Color?)null); } KickPlayerItem.SetText(Localization.Format(7u, new object[1] { name })); if (val.IsMaster || !SNet.IsMaster) { ((Behaviour)((Component)KickPlayerItem).GetComponent<Collider2D>()).enabled = false; SharedUtils.ChangeColorCMItem(KickPlayerItem, ModSettings.DISABLED, (Color?)null); BanPlayerItem.SetText(Localization.Format(8u, new object[1] { name })); } else { ((Behaviour)((Component)KickPlayerItem).GetComponent<Collider2D>()).enabled = true; SharedUtils.ChangeColorCMItem(KickPlayerItem, ModSettings.ORANGE, (Color?)null); BanPlayerItem.SetText(Localization.Format(9u, new object[1] { name })); } if (val.IsLocal) { SharedUtils.ChangeColorCMItem(BanPlayerItem, ModSettings.DISABLED, (Color?)null); } else if (flag3) { BanPlayerItem.SetText(Localization.Format(10u, new object[1] { name })); SharedUtils.ChangeColorCMItem(BanPlayerItem, ModSettings.GREEN, (Color?)null); } else { SharedUtils.ChangeColorCMItem(BanPlayerItem, ModSettings.RED, (Color?)null); } ShowWindow(name, pos, playerID); } private static void ShowWindow(string header, Transform pos, int playerID) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) PopupWindow.SetHeader(header); ((CM_PopupOverlay)PopupWindow).ID = playerID; ((Component)PopupWindow).transform.position = pos.position + new Vector3(200f, 0f, 0f); OpenSteamItem.ID = playerID; KickPlayerItem.ID = playerID; BanPlayerItem.ID = playerID; ((RectTransformComp)PopupWindow).SetVisible(true); } private static void AddRecentlyPlayedWith(SNet_Player player, bool joined) { LobbyManagementSettings.RecentlyPlayedWithEntry recentlyPlayedWithEntry = Settings.RecentlyPlayedWith.FirstOrDefault((LobbyManagementSettings.RecentlyPlayedWithEntry entry) => entry.SteamID == player.Lookup); if (recentlyPlayedWithEntry != null) { if (joined) { FeatureLogger.Notice($"{player.NickName} joined Session, last time played with them {DateTime.UtcNow - new DateTime(recentlyPlayedWithEntry.TimestampLast):d' day(s) and 'hh':'mm':'ss} ago."); } else { FeatureLogger.Debug(player.NickName + " left Session, saving Timestamp."); } recentlyPlayedWithEntry.TimestampLast = DateTime.UtcNow.Ticks; Feature.MarkSettingsAsDirty<LobbyManagementSettings>(Settings); } else { long ticks = DateTime.UtcNow.Ticks; Settings.RecentlyPlayedWith.Add(new LobbyManagementSettings.RecentlyPlayedWithEntry { Name = player.NickName, SteamID = player.Lookup, TimestampFirst = ticks, TimestampLast = ticks }); Feature.MarkSettingsAsDirty<LobbyManagementSettings>(Settings); } } } } namespace TheArchive.Features.QoL { public class IntroSkip : Feature { [ArchivePatch(/*Could not decode attribute arguments.*/)] internal static class CM_PageIntro_Update_Patch { private static bool _injectPressed; private static MethodAccessor<CM_PageIntro> _onSkip; public static void Init() { _onSkip = MethodAccessor<CM_PageIntro>.GetAccessor("OnSkip", (Type[])null, false); } [IsPostfix] [RundownConstraint(/*Could not decode attribute arguments.*/)] public static void PostfixR4OrLater(CM_PageIntro __instance) { CheckAndSkipIfReady(__instance, __instance.m_startupLoaded, __instance.m_enemiesLoaded, __instance.m_sharedLoaded); } public static void CheckAndSkipIfReady(CM_PageIntro __instance, bool ___m_startupLoaded, bool ___m_enemiesLoaded, bool ___m_sharedLoaded) { if (___m_startupLoaded && ___m_enemiesLoaded && ___m_sharedLoaded && ItemSpawnManager.ReadyToSpawnItems && IsProgressionFileReady() && !_injectPressed) { FeatureLogger.Notice("Automatically pressing the Inject button ..."); _onSkip.Invoke(__instance); __instance.EXT_PressInject(-1); _injectPressed = true; } } } public override string Name => "Skip Intro"; public override FeatureGroup Group => FeatureGroups.QualityOfLife; public override string Description => "Automatically presses inject at the start of the game"; public static IArchiveLogger FeatureLogger { get; set; } public static bool IsProgressionFileReady() { return RundownManager.RundownProgressionReady; } } public class L4DStylePacks : Feature { [ArchivePatch(/*Could not decode attribute arguments.*/)] internal static class ResourcePackFirstPerson_UpdateInteraction_Patch { private static MethodAccessor<ResourcePackFirstPerson> A_UpdateInteractionActionName; private static IValueAccessor<Interact_Timed, PlayerAgent> A_m_interactionSourceAgent; private static IValueAccessor<Interact_Timed, float> A_m_interactionTimer; public static void Init() { A_UpdateInteractionActionName = MethodAccessor<ResourcePackFirstPerson>.GetAccessor("UpdateInteractionActionName", (Type[])null, false); if (!Is.R6OrLater) { A_m_interactionSourceAgent = AccessorBase.GetValueAccessor<Interact_Timed, PlayerAgent>("m_interactionSourceAgent", false); A_m_interactionTimer = AccessorBase.GetValueAccessor<Interact_Timed, float>("m_interactionTimer", false); } } public static bool Prefix(ResourcePackFirstPerson __instance) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_006a: 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_008f: 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_0127: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_026b: Unknown result type (might be due to invalid IL or missing references) iResourcePackReceiver val = __instance.m_actionReceiver; iResourcePackReceiver lastActionReceiver = __instance.m_lastActionReceiver; eResourceContainerSpawnType packType = __instance.m_packType; Interact_ManualTimedWithCallback interactApplyResource = __instance.m_interactApplyResource; bool flag = false; bool flag2 = false; InputAction input = (InputAction)0; if (InputMapper.GetButtonDown.Invoke((InputAction)8, ((Item)__instance).Owner.InputFilter)) { flag = true; if (!((Interact_Timed)interactApplyResource).TimerIsActive) { val = (__instance.m_actionReceiver = SharedUtils.CastTo<iResourcePackReceiver>((Il2CppObjectBase)(object)((Item)__instance).Owner)); } input = (InputAction)8; } if (InputMapper.GetButton.Invoke((InputAction)7, ((Item)__instance).Owner.InputFilter)) { flag2 = true; flag = true; RaycastHit val3 = default(RaycastHit); if (!((Interact_Timed)interactApplyResource).TimerIsActive && Physics.Raycast(((Item)__instance).Owner.FPSCamera.Position, ((Item)__instance).Owner.FPSCamera.Forward, ref val3, 2.4f, LayerManager.MASK_GIVE_RESOURCE_PACK)) { iResourcePackReceiver componentInParent = ((Component)((RaycastHit)(ref val3)).collider).GetComponentInParent<iResourcePackReceiver>(); if (componentInParent != null) { val = (__instance.m_actionReceiver = componentInParent); } } input = ((!val.IsLocallyOwned) ? ((InputAction)7) : ((InputAction)8)); } if (val == null || (!((Interact_Timed)interactApplyResource).TimerIsActive && !flag)) { val = (__instance.m_actionReceiver = SharedUtils.CastTo<iResourcePackReceiver>((Il2CppObjectBase)(object)((Item)__instance).Owner)); if (Is.R6OrLater) { OnInteractorStateChangedR6Plus(interactApplyResource, ((Item)__instance).Owner, state: false); } ((Interact_Base)interactApplyResource).PlayerSetSelected(false, ((Item)__instance).Owner); } bool flag3 = NeedsResource(val, packType); if (!((Interact_Timed)interactApplyResource).TimerIsActive && val != lastActionReceiver) { if (val.IsLocallyOwned) { A_UpdateInteractionActionName.Invoke(__instance, new object[2] { Localization.Get(7u), true }); interactApplyResource.m_input = input; } else { A_UpdateInteractionActionName.Invoke(__instance, new object[2] { val.InteractionName, false }); interactApplyResource.m_input = input; if (flag3) { if (Is.R6OrLater) { OnInteractorStateChangedR6Plus(interactApplyResource, ((Item)__instance).Owner, state: true); } else { ActivateTimerR5AndBelow(interactApplyResource, ((Item)__instance).Owner); } } } __instance.m_lastActionReceiver = val; } bool timerIsActive = ((Interact_Timed)interactApplyResource).TimerIsActive; interactApplyResource.ManualUpdateWithCondition(flag3, ((Item)__instance).Owner, flag3 && !val.IsLocallyOwned); bool timerIsActive2 = ((Interact_Timed)interactApplyResource).TimerIsActive; if (!timerIsActive && timerIsActive2 && Is.R6OrLater) { SendGenericInteractR6Plus(__instance, val); } if (timerIsActive && !timerIsActive2) { PlayerAgent owner = ((Item)__instance).Owner; __instance.m_actionReceiver = ((owner != null) ? SharedUtils.CastTo<iResourcePackReceiver>((Il2CppObjectBase)(object)owner) : null); } if (!flag3 && flag && __instance.m_lastButtonDown != flag && (!flag2 || !val.IsLocallyOwned)) { SharedUtils.SafePost(((ItemEquippable)__instance).Sound, EVENTS.BUTTONGENERICBLIPDENIED, true); ShowDoesNotNeedResourcePrompt(val, packType); } __instance.m_lastButtonDown = flag; return false; } private static void ActivateTimerR5AndBelow(Interact_ManualTimedWithCallback timer, PlayerAgent agent) { A_m_interactionSourceAgent.Set((Interact_Timed)(object)timer, agent); ((Interact_Timed)timer).SetTimerActive(true); A_m_interactionTimer.Set((Interact_Timed)(object)timer, Clock.Delta); } [MethodImpl(MethodImplOptions.NoInlining)] private static void SendGenericInteractR6Plus(ResourcePackFirstPerson __instance, iResourcePackReceiver packReceiver) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) TypeEnum val = (TypeEnum)(packReceiver.IsLocallyOwned ? 6 : 5); ((Item)__instance).Owner.Sync.SendGenericInteract(val, false); } [MethodImpl(MethodImplOptions.NoInlining)] private static void OnInteractorStateChangedR6Plus(Interact_ManualTimedWithCallback timer, PlayerAgent sourceAgent, bool state) { ((Interact_Timed)timer).OnInteractorStateChanged(sourceAgent, state); } } private static MethodAccessor<InteractionGuiLayer> A_SetTimedMessage; public override string Name => "L4D Style Resource Packs"; public override FeatureGroup Group => FeatureGroups.QualityOfLife; public override string Description => "Use left and right mouse buttons to apply resource packs instead of E.\n\nLeft mouse = yourself\nRight mouse = other players\n\n<color=orange>[R4+]</color> You're able to hold down M2 and it will start applying to a receiver under your croshair if in range automatically\n\n<#f00><u>/!\\</u> Make sure to <color=orange><u>disable</u></color> the vanilla game setting <color=orange>Gameplay > Separate Use Keybinds</color> for this Feature to work!</color>"; public static ILocalizationService Localization { get; set; } public static IArchiveLogger FeatureLogger { get; set; } public override void Init() { if (!Is.R2OrLater) { A_SetTimedMessage = MethodAccessor<InteractionGuiLayer>.GetAccessor("SetTimedMessage", (Type[])null, false); } } public static bool NeedsResource(iResourcePackReceiver receiver, eResourceContainerSpawnType packType) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected I4, but got Unknown //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Invalid comparison between Unknown and I4 if (receiver == null) { return false; } switch ((int)packType) { default: if ((int)packType == 9) { if (Is.R2OrLater) { return NeedsDisinfect(receiver); } return false; } return false; case 0: return receiver.NeedHealth(); case 1: return receiver.NeedWeaponAmmo(); case 2: return receiver.NeedToolAmmo(); } } [MethodImpl(MethodImplOptions.NoInlining)] private static bool NeedsDisinfect(iResourcePackReceiver receiver) { return receiver.NeedDisinfection(); } public static void ShowDoesNotNeedResourcePrompt(iResourcePackReceiver receiver, eResourceContainerSpawnType packType) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected I4, but got Unknown //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Invalid comparison between Unknown and I4 string text = (receiver.IsLocallyOwned ? Localization.Get(1u) : Localization.Format(2u, new object[1] { receiver.InteractionName })); switch ((int)packType) { default: if ((int)packType == 9) { text += Localization.Get(6u); } break; case 1: text += Localization.Get(3u); break; case 2: text += Localization.Get(4u); break; case 0: text += Localization.Get(5u); break; } SetTimedInteractionPrompt(text, 1.4f); } private static void SetTimedInteractionPrompt(string text, float time) { if (Is.R2OrLater) { TimedInteractionPromptR2Plus(text, time); return; } A_SetTimedMessage.Invoke(GuiManager.InteractionLayer, new object[3] { text, time, (object)(ePUIMessageStyle)1 }); } [MethodImpl(MethodImplOptions.NoInlining)] private static void TimedInteractionPromptR2Plus(string text, float time) { GuiManager.InteractionLayer.SetTimedInteractionPrompt(text, time, (ePUIMessageStyle)0); } } public class LastUsedGearSwitcher : Feature { public class LastUsedGearSwitcherSettings { [FSDisplayName("Quick Swap Key")] [FSDescription("Press this key to switch to the previously wielded gear.")] public KeyCode QuickSwitchKey { get; set; } = (KeyCode)120; [FSHide] [FSDisplayName("Prints Debug Info")] [FSDescription("Prints debug info to the console")] public bool DebugLog { get; set; } } [ArchivePatch(/*Could not decode attribute arguments.*/)] internal static class PlayerSync_WantsToWieldSlot_Patch { public static void Prefix(PlayerSync __instance, InventorySlot slot) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: 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) IReplicator replicator = __instance.Replicator; bool? obj; if (replicator == null) { obj = null; } else { SNet_Player owningPlayer = replicator.OwningPlayer; obj = ((owningPlayer != null) ? new bool?(owningPlayer.IsLocal) : null); } bool? flag = obj; if (flag.GetValueOrDefault()) { InventorySlot wieldedSlot = __instance.GetWieldedSlot(); if (Settings.DebugLog) { FeatureLogger.Debug($"PlayerSync.WantsToWieldSlot: currentSlot:{wieldedSlot} -> slot:{slot} | _previousInventorySlot:{_previousInventorySlot}"); } if (wieldedSlot != slot) { _previousInventorySlot = wieldedSlot; } } } } private static readonly eFocusState _eFocusState_FPS = Utils.GetEnumFromName<eFocusState>("FPS"); private static eFocusState _eFocusState_FPS_CommunicationDialog; private static InventorySlot _previousInventorySlot = (InventorySlot)10; public override string Name => "Last Used Gear Switcher"; public override FeatureGroup Group => FeatureGroups.QualityOfLife; public override string Description => "Allows you to swap between the last two used weapons via a keypress"; public static IArchiveLogger FeatureLogger { get; set; } [FeatureConfig] public static LastUsedGearSwitcherSettings Settings { get; set; } public override void Init() { if (Is.R6OrLater) { Utils.TryGetEnumFromName<eFocusState>("FPS_CommunicationDialog", ref _eFocusState_FPS_CommunicationDialog); } } public override void Update() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) if ((FocusStateManager.CurrentState == _eFocusState_FPS || (Is.R6OrLater && FocusStateManager.CurrentState == _eFocusState_FPS_CommunicationDialog)) && Input.GetKeyDown(Settings.QuickSwitchKey)) { SwitchToPreviousSlot(); } } public static void SwitchToPreviousSlot() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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) //IL_0054: Unknown result type (might be due to invalid IL or missing references) PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent(); InventorySlot previousInventorySlot = _previousInventorySlot; InventorySlot wieldedSlot = localPlayerAgent.Inventory.WieldedSlot; if (Settings.DebugLog) { FeatureLogger.Debug($"Switching to previous slot: {wieldedSlot} -> {previousInventorySlot}"); } localPlayerAgent.Sync.WantsToWieldSlot(previousInventorySlot, false); } } public class LoadoutRandomizer : Feature { public class LoadoutRandomizerSettings { [Localized] public enum InventorySlots { Primary, Special, Tool, Melee } [Localized] public enum RandomizerMode { True, NoDuplicate } [FSDisplayName("Do not randomize")] public List<InventorySlots> ExcludedSlots { get; set; } = new List<InventorySlots>(); [FSDisplayName("Mode")] public RandomizerMode Mode { get; set; } = RandomizerMode.NoDuplicate; } [ArchivePatch(/*Could not decode attribute arguments.*/)] public static class CM_PageLoadout_SetupPatch { public static void Postfix(CM_PageLoadout __instance) { SetupViaInstance(__instance); } } private static CM_TimedButton _loadoutRandomizerButton; private static bool _hasBeenSetup = false; private static eGameStateName _eGameStateName_Lobby; private static readonly Dictionary<InventorySlot, LoadoutRandomizerSettings.InventorySlots> _invSlotMap = new Dictionary<InventorySlot, LoadoutRandomizerSettings.InventorySlots> { { Utils.GetEnumFromName<InventorySlot>("GearMelee"), LoadoutRandomizerSettings.InventorySlots.Melee }, { Utils.GetEnumFromName<InventorySlot>("GearStandard"), LoadoutRandomizerSettings.InventorySlots.Primary }, { Utils.GetEnumFromName<InventorySlot>("GearSpecial"), LoadoutRandomizerSettings.InventorySlots.Special }, { Utils.GetEnumFromName<InventorySlot>("GearClass"), LoadoutRandomizerSettings.InventorySlots.Tool } }; public override string Name => "Loadout Randomizer"; public override FeatureGroup Group => FeatureGroups.QualityOfLife; public override string Description => "Adds a Loadout Randomizer button onto the loadout screen.\nSelect which gear to randomize via the settings below."; public static IArchiveLogger FeatureLogger { get; set; } [FeatureConfig] public static LoadoutRandomizerSettings Config { get; set; } public static bool IsEnabled { get; set; } public override void Init() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) _eGameStateName_Lobby = Utils.GetEnumFromName<eGameStateName>("Lobby"); } public override void OnEnable() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Invalid comparison between I4 and Unknown if (!_hasBeenSetup) { SetupViaInstance(CM_PageLoadout.Current); } if ((byte)Feature.CurrentGameState == (int)_eGameStateName_Lobby) { SetButtonActive(); } } public override void OnDisable() { CM_TimedButton loadoutRandomizerButton = _loadoutRandomizerButton; if (loadoutRandomizerButton != null) { GameObject gameObject = ((Component)loadoutRandomizerButton).gameObject; if (gameObject != null) { gameObject.SetActive(false); } } } public void OnGameStateChanged(eGameStateName state) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) if (state == _eGameStateName_Lobby) { SetButtonActive(); } else { SetButtonInactive(); } } public static void SetupViaInstance(CM_PageLoadout pageLoadout) { //IL_0012: 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) //IL_001a: 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) if (!((Object)(object)pageLoadout == (Object)null)) { CM_TimedButton readyButton = pageLoadout.m_readyButton; CM_Item changeLoadoutButton = null; GameBuildInfo buildInfo = Feature.BuildInfo; if (RundownFlagsExtensions.IsIncludedIn(((GameBuildInfo)(ref buildInfo)).Rundown, RundownFlagsExtensions.ToLatest((RundownFlags)32))) { GetChangeLoadoutButtonR6Plus(pageLoadout, out changeLoadoutButton); } SetupButton(readyButton, changeLoadoutButton); } } [MethodImpl(MethodImplOptions.NoInlining)] public static void GetChangeLoadoutButtonR6Plus(CM_PageLoadout pageLoadout, out CM_Item changeLoadoutButton) { changeLoadoutButton = pageLoadout.m_changeLoadoutButton; } private static void SetupButton(CM_TimedButton readyUpButton, CM_Item changeLoadoutButton = null) { //IL_0008: 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_0010: 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) if (_hasBeenSetup) { return; } GameBuildInfo buildInfo = Feature.BuildInfo; if (RundownFlagsExtensions.IsIncludedIn(((GameBuildInfo)(ref buildInfo)).Rundown, RundownFlagsExtensions.ToLatest((RundownFlags)32))) { SharedUtils.AddCMItemEvents((CM_Item)(object)readyUpButton, (Action<int>)SetButtonInactive, (Action<int, bool>)null); if (changeLoadoutButton != null) { SharedUtils.AddCMItemEvents(changeLoadoutButton, (Action<int>)SetButtonActive, (Action<int, bool>)null); } } CreateButton(readyUpButton); _hasBeenSetup = true; } private static CM_TimedButton CreateButton(CM_TimedButton prefab) { //IL_0061: 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_008a: Unknown result type (might be due to invalid IL or missing references) _loadoutRandomizerButton = Object.Instantiate<GameObject>(((Component)prefab).gameObject, ((Component)prefab).transform.parent).GetComponent<CM_TimedButton>(); SharedUtils.SetCMItemEvents((CM_Item)(object)_loadoutRandomizerButton, (Action<int>)OnRandomizeLoadoutButtonPressed, (Action<int, bool>)OnButtonHoverChanged); ((Component)_loadoutRandomizerButton).gameObject.transform.Translate(new Vector3(-500f, 0f, 0f)); BoxCollider2D component = ((Component)_loadoutRandomizerButton).GetComponent<BoxCollider2D>(); if ((Object)(object)component != (Object)null) { ((Collider2D)component).offset = new Vector2(0f, -40f); } ((CM_Item)_loadoutRandomizerButton).SetText("Randomize Loadout"); SharedUtils.ChangeColorTimedExpeditionButton(_loadoutRandomizerButton, new Color(1f, 1f, 1f, 0.5f)); SetButtonActive(); return _loadoutRandomizerButton; } private static void SetButtonActive(int _ = 0) { CM_TimedButton loadoutRandomizerButton = _loadoutRandomizerButton; if (loadoutRandomizerButton != null) { GameObject gameObject = ((Component)loadoutRandomizerButton).gameObject; if (gameObject != null) { gameObject.SetActive(IsEnabled); } } } public static void SetButtonInactive(int _ = 0) { CM_TimedButton loadoutRandomizerButton = _loadoutRandomizerButton; if (loadoutRandomizerButton != null) { GameObject gameObject = ((Component)loadoutRandomizerButton).gameObject; if (gameObject != null) { gameObject.SetActive(false); } } } public static void OnRandomizeLoadoutButtonPressed(int _) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) FeatureLogger.Notice("Randomizer Button has been pressed!"); CM_PlayerLobbyBar val = null; val = ((IEnumerable<CM_PlayerLobbyBar>)((IEnumerable<CM_PlayerLobbyBar>)CM_PageLoadout.Current.m_playerLobbyBars).ToArray()).FirstOrDefault((Func<CM_PlayerLobbyBar, bool>)delegate(CM_PlayerLobbyBar plb) { SNet_Player player = plb.m_player; int? num = ((player != null) ? new int?(player.CharacterIndex) : null); PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent(); return num == ((localPlayerAgent != null) ? new int?(localPlayerAgent.CharacterID) : null); }); if ((Object)(object)val == (Object)null) { FeatureLogger.Error("Couldn't find the local players CM_PlayerLobbyBar, aborting randomization of loadout!"); return; } Enumerator<InventorySlot, CM_InventorySlotItem> enumerator = val.m_inventorySlotItems.GetEnumerator(); BackpackItem val2 = default(BackpackItem); while (enumerator.MoveNext()) { KeyValuePair<InventorySlot, CM_InventorySlotItem> current = enumerator.Current; InventorySlot key = current.Key; if (!_invSlotMap.TryGetValue(key, out var value) || !Config.ExcludedSlots.Contains(value)) { GearIDRange[] array = Il2CppArrayBase<GearIDRange>.op_Implicit((Il2CppArrayBase<GearIDRange>)(object)GearManager.GetAllGearForSlot(key)); PlayerBackpackManager.LocalBackpack.TryGetBackpackItem(key, ref val2); GearIDRange currentGearIdForSlot = val2.GearIDRange; LoadoutRandomizerSettings.RandomizerMode mode = Config.Mode; GearIDRange val3 = ((mode == LoadoutRandomizerSettings.RandomizerMode.True || mode != LoadoutRandomizerSettings.RandomizerMode.NoDuplicate) ? Utils.PickRandom<GearIDRange>(array) : Utils.PickRandomExcept<GearIDRange>(array, (Func<GearIDRange, bool>)((GearIDRange random) => !currentGearIdForSlot.GetChecksum().Equals(random.GetChecksum())))); if (val3 == null) { FeatureLogger.Error($"Tried to randomize Gear for slot {key} but received null!"); continue; } FeatureLogger.Notice($"Picked random gear \"{val3.PublicGearName}\" for slot {key}!"); PlayerBackpackManager.ResetLocalAmmoStorage(false); PlayerBackpackManager.EquipLocalGear(val3); GearManager.RegisterGearInSlotAsEquipped(val3.PlayfabItemInstanceId, key); } } } public static void OnButtonHoverChanged(int i, bool b) { } } [RundownConstraint(/*Could not decode attribute arguments.*/)] internal class NoDroppedMagazineSounds : Feature { public override string Name => "No Magazine Drop Sound"; public override FeatureGroup Group => FeatureGroups.QualityOfLife; public override string Description => "Removes the <i>globally audible</i> sound whenever a magazine drops on the floor after a reload."; public override bool RequiresRestart => true; public override void OnGameDataInitialized() { if (!((Feature)this).Enabled) { return; } foreach (GearMagPartDataBlock allBlock in GameDataBlockBase<GearMagPartDataBlock>.GetAllBlocks()) { allBlock.DropSoundType = (MagazineDropSoundType)0; } } } [EnableFeatureByDefault] public class NoNavMarkerHideInChat : Feature { [ArchivePatch(/*Could not decode attribute arguments.*/)] internal static class GuiManager_OnFocusStateChanged_Patch { private static eFocusState _eFocusState_FPS_TypingInChat; public static void Init() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) _eFocusState_FPS_TypingInChat = Utils.GetEnumFromName<eFocusState>("FPS_TypingInChat"); } public static void Postfix(eFocusState state) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) if (state == _eFocusState_FPS_TypingInChat) { ((GuiLayer)GuiManager.NavMarkerLayer).SetVisible(true); } } } public override string Name => "See NavMarkers in Chat"; public override FeatureGroup Group => FeatureGroups.QualityOfLife; public override string Description => "Prevent enemy pings from hiding whenever the chat is open."; } [RundownConstraint(/*Could not decode attribute arguments.*/)] public class NoStoryDialog : Feature { [ArchivePatch(/*Could not decode attribute arguments.*/)] internal static class WardenObjectiveManager_CheckAndExecuteEventsOnTrigger_Patch { [IsPrefix] [RundownConstraint(/*Could not decode attribute arguments.*/)] public static void PrefixR7(WardenObjectiveEventData eventToTrigger) { if (eventToTrigger.SoundSubtitle.HasValue) { FeatureLogger.Notice($"SoundEvent about to execute was: {eventToTrigger.SoundID} ({SoundEventCache.ReverseResolve(eventToTrigger.SoundID, false)})"); eventToTrigger.SoundID = 0u; } } [IsPrefix] [RundownConstraint(/*Could not decode attribute arguments.*/)] public static void PrefixR6(WardenObjectiveEventData eventToTrigger) { if (eventToTrigger.SoundID != 0) { FeatureLogger.Notice($"SoundEvent about to execute was: {eventToTrigger.SoundID} ({SoundEventCache.ReverseResolve(eventToTrigger.SoundID, false)})"); eventToTrigger.SoundID = 0u; } } } public override string Name => "Remove Story Dialog"; public override FeatureGroup Group => FeatureGroups.QualityOfLife; public override string Description => "Removes all level-based voice events that come with subtitles.\naka Schaeffer-be-gone"; public static IArchiveLogger FeatureLogger { get; set; } } public class ReloadSoundCue : Feature { public class ReloadSoundCueSettings { [FSDisplayName("Test Sound Event")] [FSDescription("Plays the sound event below,\nit's a little janky and might not work depending on the sound, sorry!")] public FButton TestSoundButton { get; set; } = new FButton("Play Sound", (string)null, (Action)null, false); [FSDisplayName("Sound Event")] [FSDescription("The sound event to play whenever the reload has happened.")] public string SoundEvent { get; set; } = "HACKING_PUZZLE_CORRECT"; [