using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using AIGraph; using Agents; using CellMenu; using Clonesoft.Json; using DiscordRPC; using DiscordRPC.Events; using DiscordRPC.IO; using DiscordRPC.Logging; using DiscordRPC.Message; using GameData; using Gear; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using LevelGeneration; using Player; using SNetwork; 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.Groups; using TheArchive.Core.Localization; using TheArchive.Core.Managers; using TheArchive.Core.Models; using TheArchive.Core.Settings; using TheArchive.Interfaces; using TheArchive.Loader; using TheArchive.Utilities; using UnityEngine; [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.RichPresence")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyProduct("TheArchive.RichPresence")] [assembly: AssemblyTitle("TheArchive.RichPresence")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2025.2.0.0")] [module: UnverifiableCode] internal class ThisAssembly { public class Git { public class BaseVersion { public const string Major = "0"; public const string Minor = "0"; public const string Patch = "0"; } public class SemVer { public const string Major = "0"; public const string Minor = "0"; public const string Patch = "838"; public const string Label = ""; public const string DashLabel = ""; public const string Source = "Default"; } public const bool IsDirty = false; public const string IsDirtyString = "false"; public const string RepositoryUrl = "https://github.com/Tuesday1028/GTFO_TheArchive"; public const string Branch = "doing-things"; public const string Commit = "a4eb55a"; public const string Sha = "a4eb55a7e97569a44df6831acc6074b0f084b6eb"; public const string CommitDate = "2026-05-07T19:14:52+08:00"; public const string Commits = "838"; public const string Tag = ""; public const string BaseTag = ""; } } internal class ManifestInfo { internal const string TSName = "TheArchive_RichPresence"; internal const string TSDescription = "Custom Discord Rich Presence Add-on for TheArchive."; 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.RichPresence", "TheArchive_RichPresence", "2025.2.0")] public class ArchiveRichPresenceModule : IArchiveModule { public const string GUID = "dev.AuriRex.gtfo.TheArchive.RichPresence"; public const string MOD_NAME = "TheArchive_RichPresence"; public const string VERSION = "2025.2.0"; public ILocalizationService LocalizationService { get; set; } public IArchiveLogger Logger { get; set; } public void Init() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown ArchiveMod.GameDataInitialized += OnGameDataInitialized; try { string @string = Encoding.UTF8.GetString(Utils.GetResource(Assembly.GetExecutingAssembly(), "TheArchive.DiscordGameSDK.LICENSE_DiscordRPC")); AttributionInfo val = new AttributionInfo("DiscordRPC License", @string, "", ""); val.set_Comment("<#fff18e>Huge shoutouts to <#88e2e9>Lachee for her re-implementation of the discord_game_sdks functions in C#!"); val.set_Origin("TheArchive_RichPresence".Replace("_", ".")); Attribution.Add(val); } catch (Exception ex) { Logger.Error("Something went wrong while trying to add Attribution."); Logger.Exception(ex); } } private void OnGameDataInitialized(RundownID _) { try { PresenceFormatter.RegisterAllPresenceFormatProviders(typeof(PresenceManager), false); PresenceFormatter.Setup(); } catch (Exception ex) { Logger.Exception(ex); } } } } namespace TheArchive.Features.Presence { [EnableFeatureByDefault] public class CustomLobbyCodeString : Feature { public class CustomLobbyCodeStringConfig { [FSMaxLength(120)] [FSDisplayName("Format")] public string Format { get; set; } = "LF%OpenSlots% %Rundown%%Expedition% \"%ExpeditionName%\": `%LobbyID%`"; } [ArchivePatch(/*Could not decode attribute arguments.*/)] internal static class CM_PageSettings_SetupPatch { public static void Postfix(CM_PageSettings __instance) { SetupViaInstance(__instance); } } [ArchivePatch(/*Could not decode attribute arguments.*/)] internal static class CM_PageLoadout_SetupPatch { public static void Postfix(CM_PageLoadout __instance) { SetupViaInstance(__instance); } } public const string DefaultFormat = "LF%OpenSlots% %Rundown%%Expedition% \"%ExpeditionName%\": `%LobbyID%`"; private static CM_Item _CM_PageLoadout_coppyLobbyIDButton; private static CM_Item _CM_PageSettings_coppyLobbyIDButton; public override string Name => "Copy Lobby ID Format"; public override GroupBase Group => (GroupBase)(object)GroupManager.Presence; public override string Description => "Customize copied lobby code from the 'Copy Lobby ID'-Button on the loadout and settings screens with a custom format."; public static IArchiveLogger FeatureLogger { get; set; } [FeatureConfig] public static CustomLobbyCodeStringConfig Config { get; set; } [SetEnabledStatus] public static bool IsEnabled { get; set; } public override void OnEnable() { if ((Object)(object)_CM_PageLoadout_coppyLobbyIDButton == (Object)null) { SetupViaInstance(CM_PageLoadout.Current); } } public static void CopyLobbyIdToClipboard(int _) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) if (!IsEnabled) { string text2 = (GUIUtility.systemCopyBuffer = PresenceFormatter.FormatPresenceString("%LobbyID%")); FeatureLogger.Notice("Copied lobby id to clipboard: " + text2); return; } GameBuildInfo buildInfo = Feature.BuildInfo; if ((!RundownFlagsExtensions.IsIncludedIn(((GameBuildInfo)(ref buildInfo)).Rundown, RundownFlagsExtensions.ToLatest((RundownFlags)16)) || !IsExternalMatchMakingActive()) && SNet.IsInLobby) { if (string.IsNullOrWhiteSpace(Config.Format)) { Config.Format = "LF%OpenSlots% %Rundown%%Expedition% \"%ExpeditionName%\": `%LobbyID%`"; } string text4 = (GUIUtility.systemCopyBuffer = PresenceFormatter.FormatPresenceString(Config.Format)); FeatureLogger.Notice("Copied lobby id to clipboard: " + text4); } } [MethodImpl(MethodImplOptions.NoInlining)] private static bool IsExternalMatchMakingActive() { return SNet.IsExternalMatchMakingActive; } public static void SetupViaInstance(CM_PageSettings pageSettings) { if (!((Object)(object)pageSettings == (Object)null)) { _CM_PageSettings_coppyLobbyIDButton = pageSettings.m_copyLobbyIdButton; if ((Object)(object)_CM_PageSettings_coppyLobbyIDButton != (Object)null) { FeatureLogger.Info("Hooking CM_PageSettings Copy Lobby ID Button ..."); SharedUtils.SetCMItemEvents(SharedUtils.RemoveCMItemEvents(_CM_PageSettings_coppyLobbyIDButton, true), (Action)CopyLobbyIdToClipboard, (Action)null); } else { FeatureLogger.Warning("[CustomLobbyCodeString] copy lobby id button in CM_PageSettings wasn't found!!!"); } } } public static void SetupViaInstance(CM_PageLoadout pageLoadout) { if (!((Object)(object)pageLoadout == (Object)null)) { _CM_PageLoadout_coppyLobbyIDButton = pageLoadout.m_copyLobbyIdButton; if ((Object)(object)_CM_PageLoadout_coppyLobbyIDButton != (Object)null) { FeatureLogger.Info("Hooking CM_PageLoadout Copy Lobby ID Button ..."); SharedUtils.SetCMItemEvents(SharedUtils.RemoveCMItemEvents(_CM_PageLoadout_coppyLobbyIDButton, true), (Action)CopyLobbyIdToClipboard, (Action)null); } else { FeatureLogger.Warning("[CustomLobbyCodeString] copy lobby id button in CM_PageLoadout wasn't found!!!"); } } } } [RundownConstraint(/*Could not decode attribute arguments.*/)] public class DisableBasePresence : Feature { private bool _firstTime = true; public override string Name => "Disable Built-in Rich Presence"; public override GroupBase Group => (GroupBase)(object)GroupManager.Presence; public override string Description => "Disables the Discord Rich Presence added to the game in Rundown 8."; public override void OnEnable() { if (Feature.DataBlocksReady) { DisableBaseDiscord(); } } public void OnGameStateChanged(eGameStateName state) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 if ((int)state == 4 && _firstTime) { DisableBaseDiscord(); _firstTime = false; } } public override void OnDisable() { if (!Feature.IsApplicationQuitting && Feature.DataBlocksReady) { EnableBaseDiscord(); } } public static void DisableBaseDiscord() { DiscordManager.Current.ToggleDiscord(false); } public static void EnableBaseDiscord() { DiscordManager.Current.ToggleDiscord(true); } } [EnableFeatureByDefault] public class DiscordRichPresence : Feature { public override string Name => "Archive Discord Rich Presence"; public override GroupBase Group => (GroupBase)(object)GroupManager.Presence; public override string Description => "Show the current game state in detail on discord."; public static IArchiveLogger FeatureLogger { get; set; } public override bool InlineSettingsIntoParentMenu => true; public override bool SkipInitialOnEnable => true; public override Type[] ExternalLocalizedTypes => new Type[1] { typeof(RichPresenceSettings) }; [FeatureConfig] public static RichPresenceSettings DiscordRPCSettings { get; set; } public override void Init() { DiscordRPCSettings = DiscordRPCSettings?.FillDefaultDictValues(); PresenceManager.UpdateGameState((PresenceGameState)0); } public override void OnEnable() { if (!Feature.DataBlocksReady || ArchiveDiscordManager.IsEnabled) { return; } try { ArchiveDiscordManager.RenewPartyGuid(); ArchiveDiscordManager.OnActivityJoin += DiscordManager_OnActivityJoin; ArchiveDiscordManager.Enable(DiscordRPCSettings); } catch (Exception ex) { FeatureLogger.Exception(ex); } } public void OnGameStateChanged(eGameStateName state) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 if ((int)state == 4) { FeatureLogger.Debug("Creating a new Party GUID."); ArchiveDiscordManager.RenewPartyGuid(); } } public override void OnDatablocksReady() { ((Feature)this).OnEnable(); } private static void DiscordManager_OnActivityJoin(string secret) { if (ulong.TryParse(secret, out var result) && result != 0L) { CM_Utils.JoinLobby(result, Action.op_Implicit((Action)delegate { FeatureLogger.Success("Successfully joined lobby \"" + secret + "\"!"); }), Action.op_Implicit((Action)delegate { FeatureLogger.Fail("Failed to join lobby \"" + secret + "\"."); })); } } public override void OnDisable() { if (!ArchiveDiscordManager.IsEnabled) { return; } try { ArchiveDiscordManager.OnActivityJoin -= DiscordManager_OnActivityJoin; ArchiveDiscordManager.Disable(); } catch (Exception ex) { FeatureLogger.Exception(ex); } } public override void Update() { ArchiveDiscordManager.Update(); } } [EnableFeatureByDefault] [HideInModSettings] public class ReactorDiscordRPC : Feature { public enum ReactorTypes { Error, Startup, Shutdown } [ArchivePatch(/*Could not decode attribute arguments.*/)] internal static class LG_WardenObjective_Reactor_Start_Patch { public static void Postfix(LG_WardenObjective_Reactor __instance) { ReactorsInLevel.Add(__instance); FeatureLogger.Debug("Added Reactor to Set: " + GetReactorItemKey(__instance)); } } [ArchivePatch(/*Could not decode attribute arguments.*/)] internal static class LG_WardenObjective_Reactor_OnDestroy_Patch { public static void Postfix(LG_WardenObjective_Reactor __instance) { LG_WardenObjective_Reactor val = ((IEnumerable)ReactorsInLevel).FirstOrDefault((Func)((LG_WardenObjective_Reactor reactor) => GetReactorItemKey(reactor) == GetReactorItemKey(__instance))); ReactorsInLevel.Remove(val); FeatureLogger.Debug("Removed Reactor from Set: " + GetReactorItemKey(val)); } } private static IValueAccessor A_m_currentWaveProgress; private static IValueAccessor A_m_currentDuration; private static IValueAccessor A_m_currentWaveCount; private static IValueAccessor A_m_waveCountMax; private static IValueAccessor A_m_itemKey; private static IValueAccessor A_m_currentWaveData; private static IValueAccessor A_m_currentState; private static readonly HashSet _idleReactorStatuses = new HashSet { Utils.GetEnumFromName("Inactive_Idle"), Utils.GetEnumFromName("Active_Idle") }; private static int _lastFrameCount = 0; private static LG_WardenObjective_Reactor _lastReturnedActiveReactor; public override string Name => "ReactorDiscordRPC"; public override GroupBase Group => (GroupBase)(object)GroupManager.Presence; public static IArchiveLogger FeatureLogger { get; set; } [PresenceFormatProvider("ReactorWaveCountMax")] public static int ReactorWaveCountMax => GetWaveCountMax(GetActiveReactor()); [PresenceFormatProvider("ReactorWaveCountCurrent")] public static int ReactorWaveCountCurrent => GetCurrentWaveCount(GetActiveReactor()); [PresenceFormatProvider("ReactorWaveSecondsRemaining")] public static float ReactorWaveSecondsRemaining => GetWaveSecondsRemaining(GetActiveReactor()); [PresenceFormatProvider("ReactorType")] public static string ReactorType => GetReactorType(GetActiveReactor()).ToString(); [PresenceFormatProvider("ReactorWaveEndTime")] public static long ReactorWaveEndTime => DateTimeOffset.UtcNow.ToUnixTimeSeconds() + (long)GetWaveSecondsRemaining(GetActiveReactor()); [PresenceFormatProvider("IsReactorActive")] public static bool IsReactorActive { get { LG_WardenObjective_Reactor activeReactor; return TryGetActiveReactor(out activeReactor); } } [PresenceFormatProvider("IsReactorInIntro")] public static bool IsReactorInIntro => IsReactorInStatus(GetActiveReactor(), (eReactorStatus)2, (eReactorStatus)6); [PresenceFormatProvider("IsReactorWaveOrChaosActive")] public static bool IsReactorWaveOrChaosActive => IsReactorInStatus(GetActiveReactor(), (eReactorStatus)3, (eReactorStatus)8); [PresenceFormatProvider("IsReactorAwaitingVerify")] public static bool IsReactorAwaitingVerify => IsReactorInStatus(GetActiveReactor(), (eReactorStatus)4, (eReactorStatus)7); [PresenceFormatProvider("IsReactorCompleted")] public static bool IsReactorCompleted => IsReactorInStatus(GetActiveReactor(), (eReactorStatus)5, (eReactorStatus)9); [PresenceFormatProvider("IsReactorTypeStartup")] public static bool IsReactorTypeStartup => GetReactorType(GetActiveReactor()) == ReactorTypes.Startup; [PresenceFormatProvider("IsReactorInVerifyFailState")] public static bool IsReactorInVerifyFailState { get { //IL_0010: Unknown result type (might be due to invalid IL or missing references) if (!TryGetReactorState(GetActiveReactor(), out var state)) { return false; } return state.verifyFailed; } } [PresenceFormatProvider("ReactorVerificationString")] public static string ReactorVerificationString { get { bool isTerminal; string nextCodeOrTerminalSerial = GetNextCodeOrTerminalSerial(GetActiveReactor(), out isTerminal); if (isTerminal) { return "LOG in " + nextCodeOrTerminalSerial; } return "Free Code: " + nextCodeOrTerminalSerial.ToUpper(); } } public static HashSet ReactorsInLevel { get; } = new HashSet(); public override void Init() { //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_0008: Unknown result type (might be due to invalid IL or missing references) GameBuildInfo buildInfo = Feature.BuildInfo; if (RundownFlagsExtensions.IsIncludedIn(((GameBuildInfo)(ref buildInfo)).Rundown, (RundownFlags)1)) { A_m_currentWaveProgress = AccessorBase.GetValueAccessor("m_currentStateProgress", false); A_m_currentDuration = AccessorBase.GetValueAccessor("m_currentStateDuration", false); A_m_currentWaveCount = AccessorBase.GetValueAccessor("m_currentStateCount", false); A_m_waveCountMax = AccessorBase.GetValueAccessor("m_stateCountMax", false); } else { A_m_currentWaveProgress = AccessorBase.GetValueAccessor("m_currentWaveProgress", false); A_m_currentDuration = AccessorBase.GetValueAccessor("m_currentDuration", false); A_m_currentWaveCount = AccessorBase.GetValueAccessor("m_currentWaveCount", false); A_m_waveCountMax = AccessorBase.GetValueAccessor("m_waveCountMax", false); } A_m_itemKey = AccessorBase.GetValueAccessor("m_itemKey", false); A_m_currentWaveData = AccessorBase.GetValueAccessor("m_currentWaveData", false); A_m_currentState = AccessorBase.GetValueAccessor("m_currentState", false); PresenceFormatter.RegisterAllPresenceFormatProviders(typeof(ReactorDiscordRPC), true); } public static string GetNextCodeOrTerminalSerial(LG_WardenObjective_Reactor reactor, out bool isTerminal) { //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_0020: Unknown result type (might be due to invalid IL or missing references) isTerminal = false; if ((Object)(object)reactor == (Object)null) { return "Error"; } GameBuildInfo buildInfo = Feature.BuildInfo; if (RundownFlagsExtensions.IsIncludedIn(((GameBuildInfo)(ref buildInfo)).Rundown, RundownFlagsExtensions.ToLatest((RundownFlags)2))) { return GetNextCodeOrTerminalR2(reactor, out isTerminal); } return reactor.CurrentStateOverrideCode; } public static string GetNextCodeOrTerminalR2(LG_WardenObjective_Reactor reactor, out bool isTerminal) { isTerminal = false; if ((Object)(object)reactor == (Object)null) { return "Error"; } ReactorWaveData val = A_m_currentWaveData.Get(reactor); if (val.HasVerificationTerminal) { isTerminal = true; return val.VerificationTerminalSerial; } return reactor.CurrentStateOverrideCode; } public static bool IsReactorInStatus(LG_WardenObjective_Reactor reactor, params eReactorStatus[] statuses) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between I4 and Unknown if (!TryGetReactorStatus(reactor, out var status)) { return false; } for (int i = 0; i < statuses.Length; i++) { if ((int)statuses[i] == (int)status) { return true; } } return false; } public static bool TryGetReactorStatus(LG_WardenObjective_Reactor reactor, out eReactorStatus status) { //IL_0019: 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_0020: Expected I4, but got Unknown if ((Object)(object)reactor == (Object)null || !TryGetReactorState(reactor, out var state)) { status = (eReactorStatus)0; return false; } status = (eReactorStatus)(int)state.status; return true; } public static int GetCurrentWaveCount(LG_WardenObjective_Reactor reactor) { if ((Object)(object)reactor == (Object)null) { return -1; } return A_m_currentWaveCount.Get(reactor); } public static int GetWaveCountMax(LG_WardenObjective_Reactor reactor) { if ((Object)(object)reactor == (Object)null) { return -1; } return A_m_waveCountMax.Get(reactor); } public static float GetWaveSecondsRemaining(LG_WardenObjective_Reactor reactor) { if ((Object)(object)reactor == (Object)null) { return -1f; } return (1f - A_m_currentWaveProgress.Get(reactor)) * A_m_currentDuration.Get(reactor); } public static ReactorTypes GetReactorType(LG_WardenObjective_Reactor reactor) { if (TryGetReactorState(reactor, out var state)) { if (((object)(eReactorStatus)(ref state.status)).ToString().StartsWith("Start")) { return ReactorTypes.Startup; } if (((object)(eReactorStatus)(ref state.status)).ToString().StartsWith("Shut")) { return ReactorTypes.Shutdown; } } return ReactorTypes.Error; } public static bool TryGetReactorState(LG_WardenObjective_Reactor reactor, out pReactorState state) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)reactor == (Object)null) { state = default(pReactorState); return false; } state = A_m_currentState.Get(reactor); return true; } public static LG_WardenObjective_Reactor GetActiveReactor() { int frameCount = Time.frameCount; if (_lastFrameCount == frameCount) { return _lastReturnedActiveReactor; } pReactorState state; LG_WardenObjective_Reactor? obj = ((IEnumerable)ReactorsInLevel).FirstOrDefault((Func)((LG_WardenObjective_Reactor reactor) => TryGetReactorState(reactor, out state) && !_idleReactorStatuses.Contains(state.status))); _lastFrameCount = frameCount; _lastReturnedActiveReactor = obj; return obj; } public static bool TryGetActiveReactor(out LG_WardenObjective_Reactor activeReactor) { activeReactor = GetActiveReactor(); return (Object)(object)activeReactor != (Object)null; } public static string GetReactorItemKey(LG_WardenObjective_Reactor reactor) { return A_m_itemKey.Get(reactor); } } [EnableFeatureByDefault] [HideInModSettings] public class RichPresenceCore : Feature { [ArchivePatch(/*Could not decode attribute arguments.*/)] internal static class RundownManager__GetUniqueExpeditionKey__Patch { public static void Postfix(string rundownKey, eRundownTier tier, int expIndex) { ExpeditionNumber = expIndex + 1; } } public override string Name => "Rich Presence Core"; public override GroupBase Group => (GroupBase)(object)GroupManager.Presence; public override string Description => "Updates the Presence Game State and provides some values via patches."; [PresenceFormatProvider("EquippedMeleeWeaponName")] public static string EquippedMeleeWeaponName => ItemNameForSlot((InventorySlot)10); [PresenceFormatProvider("EquippedMeleeWeaponID")] public static string EquippedMeleeWeaponID => ItemIDForSlot((InventorySlot)10); [PresenceFormatProvider("EquippedToolName")] public static string EquippedToolName => ItemNameForSlot((InventorySlot)3); [PresenceFormatProvider("EquippedToolID")] public static string EquippedToolID => ItemIDForSlot((InventorySlot)3); private static PlayerAmmoStorage LocalAmmo { get { PlayerBackpack localBackpack = PlayerBackpackManager.LocalBackpack; if (localBackpack == null) { return null; } return localBackpack.AmmoStorage; } } [PresenceFormatProvider("HealthRaw")] public static float HealthRaw { get { PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent(); float? obj; if (localPlayerAgent == null) { obj = null; } else { Dam_PlayerDamageBase damage = localPlayerAgent.Damage; obj = ((damage != null) ? new float?(((Dam_SyncedDamageBase)damage).Health) : null); } float? num = obj; return num.GetValueOrDefault(-1f); } } [PresenceFormatProvider("MaxHealthRaw")] public static float MaxHealthRaw { get { PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent(); float? obj; if (localPlayerAgent == null) { obj = null; } else { Dam_PlayerDamageBase damage = localPlayerAgent.Damage; obj = ((damage != null) ? new float?(((Dam_SyncedDamageBase)damage).HealthMax) : null); } float? num = obj; return num.GetValueOrDefault(-1f); } } [PresenceFormatProvider("ToolAmmo")] public static int ToolAmmo { get { PlayerAmmoStorage localAmmo = LocalAmmo; int? obj; if (localAmmo == null) { obj = null; } else { InventorySlotAmmo classAmmo = localAmmo.ClassAmmo; obj = ((classAmmo != null) ? new int?(classAmmo.BulletsInPack) : null); } int? num = obj; return num.GetValueOrDefault(-1); } } [PresenceFormatProvider("MaxToolAmmo")] public static int MaxToolAmmo { get { PlayerAmmoStorage localAmmo = LocalAmmo; int? obj; if (localAmmo == null) { obj = null; } else { InventorySlotAmmo classAmmo = localAmmo.ClassAmmo; obj = ((classAmmo != null) ? new int?(classAmmo.BulletsMaxCap) : null); } int? num = obj; return num.GetValueOrDefault(-1); } } [PresenceFormatProvider("PrimaryAmmo")] public static int PrimaryAmmo { get { PlayerAmmoStorage localAmmo = LocalAmmo; int? obj; if (localAmmo == null) { obj = null; } else { InventorySlotAmmo standardAmmo = localAmmo.StandardAmmo; obj = ((standardAmmo != null) ? new int?(standardAmmo.BulletsInPack) : null); } int? num = obj; return num.GetValueOrDefault(-1) + GetClip((InventorySlot)1); } } [PresenceFormatProvider("MaxPrimaryAmmo")] public static int MaxPrimaryAmmo { get { PlayerAmmoStorage localAmmo = LocalAmmo; int? obj; if (localAmmo == null) { obj = null; } else { InventorySlotAmmo standardAmmo = localAmmo.StandardAmmo; obj = ((standardAmmo != null) ? new int?(standardAmmo.BulletsMaxCap) : null); } int? num = obj; return num.GetValueOrDefault(-1); } } [PresenceFormatProvider("SpecialAmmo")] public static int SpecialAmmo { get { PlayerAmmoStorage localAmmo = LocalAmmo; int? obj; if (localAmmo == null) { obj = null; } else { InventorySlotAmmo specialAmmo = localAmmo.SpecialAmmo; obj = ((specialAmmo != null) ? new int?(specialAmmo.BulletsInPack) : null); } int? num = obj; return num.GetValueOrDefault(-1) + GetClip((InventorySlot)2); } } [PresenceFormatProvider("MaxSpecialAmmo")] public static int MaxSpecialAmmo { get { PlayerAmmoStorage localAmmo = LocalAmmo; int? obj; if (localAmmo == null) { obj = null; } else { InventorySlotAmmo specialAmmo = localAmmo.SpecialAmmo; obj = ((specialAmmo != null) ? new int?(specialAmmo.BulletsMaxCap) : null); } int? num = obj; return num.GetValueOrDefault(-1); } } [PresenceFormatProvider("HasLobby")] public static bool HasLobby { get { SNet_Lobby lobby = SNet.Lobby; if (lobby == null) { return false; } SNet_LobbyIdentifier identifier = lobby.Identifier; if (identifier == null) { return false; } _ = identifier.ID; return true; } } [PresenceFormatProvider("LobbyID")] public static string LobbyID { get { SNet_Lobby lobby = SNet.Lobby; object obj; if (lobby == null) { obj = null; } else { SNet_LobbyIdentifier identifier = lobby.Identifier; obj = ((identifier != null) ? identifier.ID.ToString() : null); } if (obj == null) { obj = "0123456789"; } return (string)obj; } } [PresenceFormatProvider("LocalCharacterID")] public static int LocalCharacterID { get { try { PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent(); return (localPlayerAgent != null) ? localPlayerAgent.CharacterID : 0; } catch (Exception) { return 0; } } } [PresenceFormatProvider("OpenSlots")] public static int OpenSlots => MaxPlayerSlots - GetPlayerCount(); [PresenceFormatProvider("MaxPlayerSlots")] public static int MaxPlayerSlots => GetMaxPlayers(); [PresenceFormatProvider("ExpeditionTier")] public static string ExpeditionTier { get { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) ExpeditionInTierData activeExpedition = RundownManager.ActiveExpedition; object obj; if (activeExpedition == null) { obj = null; } else { DescriptiveData descriptive = activeExpedition.Descriptive; obj = ((descriptive != null) ? descriptive.Prefix : null); } if (obj == null) { obj = "?"; } string text = (string)obj; GameBuildInfo buildInfo = Feature.BuildInfo; if (RundownFlagsExtensions.IsIncludedIn(((GameBuildInfo)(ref buildInfo)).Rundown, (RundownFlags)6) && text.Length > 2) { return text.Substring(2); } return text; } } [PresenceFormatProvider("ExpeditionTierIsSpecial")] public static bool ExpeditionTierIsSpecial { get { if (Is.R6OrLater) { return IsActiveExpeditionSpecial(); } return false; } } [PresenceFormatProvider("ExpeditionSkipExpNumberInName")] public static bool ExpeditionSkipExpNumberInName { get { try { if (Is.R6OrLater) { return ShouldSkipExpNumberInName(); } } catch { } return false; } } [PresenceFormatProvider("ExpeditionNumber")] public static int ExpeditionNumber { get; set; } [PresenceFormatProvider("ExpeditionName")] public static string ExpeditionName { get { ExpeditionInTierData activeExpedition = RundownManager.ActiveExpedition; object obj; if (activeExpedition == null) { obj = null; } else { DescriptiveData descriptive = activeExpedition.Descriptive; obj = ((descriptive != null) ? descriptive.PublicName : null); } if (obj == null) { obj = "???"; } return (string)obj; } } [PresenceFormatProvider("ZonePrefix")] public static string ZonePrefix { get { PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent(); object obj; if (localPlayerAgent == null) { obj = null; } else { AIG_CourseNode courseNode = ((Agent)localPlayerAgent).CourseNode; if (courseNode == null) { obj = null; } else { LG_Zone zone = courseNode.m_zone; if (zone == null) { obj = null; } else { LG_NavInfo navInfo = zone.NavInfo; obj = ((navInfo != null) ? navInfo.PrefixShort : null); } } } if (obj == null) { obj = "?"; } return (string)obj; } } [PresenceFormatProvider("ZonePrefixLong")] public static string ZonePrefixLong { get { PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent(); object obj; if (localPlayerAgent == null) { obj = null; } else { AIG_CourseNode courseNode = ((Agent)localPlayerAgent).CourseNode; if (courseNode == null) { obj = null; } else { LG_Zone zone = courseNode.m_zone; if (zone == null) { obj = null; } else { LG_NavInfo navInfo = zone.NavInfo; obj = ((navInfo != null) ? navInfo.PrefixLong : null); } } } if (obj == null) { obj = "?"; } return (string)obj; } } [PresenceFormatProvider("ZoneAlias")] public static string ZoneAlias { get { PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent(); object obj; if (localPlayerAgent == null) { obj = null; } else { AIG_CourseNode courseNode = ((Agent)localPlayerAgent).CourseNode; if (courseNode == null) { obj = null; } else { LG_Zone zone = courseNode.m_zone; if (zone == null) { obj = null; } else { LG_NavInfo navInfo = zone.NavInfo; obj = ((navInfo != null) ? navInfo.Number.ToString() : null); } } } if (obj == null) { obj = "?"; } return (string)obj; } } [PresenceFormatProvider("AreaSuffix")] public static string AreaSuffix { get { PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent(); object obj; if (localPlayerAgent == null) { obj = null; } else { AIG_CourseNode courseNode = ((Agent)localPlayerAgent).CourseNode; if (courseNode == null) { obj = null; } else { LG_Area area = courseNode.m_area; if (area == null) { obj = null; } else { LG_NavInfo navInfo = area.m_navInfo; obj = ((navInfo != null) ? navInfo.Suffix : null); } } } if (obj == null) { obj = "?"; } return (string)obj; } } [PresenceFormatProvider("RundownTitleFromDataBlocks")] public static string RundownTitleFromDataBlocks => SharedUtils.GetDataBlockRundownTitle(); public override void Init() { PresenceFormatter.RegisterAllPresenceFormatProviders(typeof(RichPresenceCore), true); } public void OnGameStateChanged(eGameStateName nextState) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected I4, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Invalid comparison between Unknown and I4 //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Invalid comparison between Unknown and I4 switch (nextState - 4) { case 0: PresenceManager.UpdateGameState((PresenceGameState)1, (int)PresenceManager.CurrentState == 0); break; case 1: case 12: PresenceManager.UpdateGameState((PresenceGameState)2); break; case 2: PresenceManager.UpdateGameState((PresenceGameState)3); break; case 3: PresenceManager.UpdateGameState((PresenceGameState)4, keepTimer: true); break; case 6: PresenceManager.UpdateGameState((PresenceGameState)5, (int)PresenceManager.CurrentState == 6); break; case 11: PresenceManager.UpdateGameState((PresenceGameState)6, keepTimer: true); break; case 10: PresenceManager.UpdateGameState((PresenceGameState)7, keepTimer: true); break; case 4: case 5: case 7: case 8: case 9: break; } } public static string ItemNameForSlot(InventorySlot slot) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) BackpackItem val = null; PlayerBackpack localBackpack = PlayerBackpackManager.LocalBackpack; if (localBackpack != null && localBackpack.TryGetBackpackItem(slot, ref val)) { if (val == null) { return null; } GearIDRange gearIDRange = val.GearIDRange; if (gearIDRange == null) { return null; } return gearIDRange.PublicGearName; } return null; } public static string ItemIDForSlot(InventorySlot slot) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) BackpackItem val = null; PlayerBackpack localBackpack = PlayerBackpackManager.LocalBackpack; if (localBackpack != null && localBackpack.TryGetBackpackItem(slot, ref val)) { if (val == null) { return null; } GearIDRange gearIDRange = val.GearIDRange; if (gearIDRange == null) { return null; } return gearIDRange.PlayfabItemId; } return null; } private static int GetClip(InventorySlot slot) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) BackpackItem val = null; PlayerBackpack localBackpack = PlayerBackpackManager.LocalBackpack; if (localBackpack != null && localBackpack.TryGetBackpackItem(slot, ref val)) { int? obj; if (val == null) { obj = null; } else { Item instance = val.Instance; if (instance == null) { obj = null; } else { ItemEquippable obj2 = ((Il2CppObjectBase)instance).TryCast(); obj = ((obj2 != null) ? new int?(obj2.GetCurrentClip()) : null); } } int? num = obj; return num.GetValueOrDefault(-1); } return -1; } private static int GetPlayerCount() { if (Is.R6OrLater) { return GetPlayerCountR6Plus(); } SNet_Lobby lobby = SNet.Lobby; return ((lobby == null) ? null : lobby.Players?.Count).GetValueOrDefault(1); } private static int GetPlayerCountR6Plus() { SNet_Lobby lobby = SNet.Lobby; int? obj; if (lobby == null) { obj = null; } else { List players = lobby.Players; obj = ((players == null) ? null : SharedUtils.ToSystemList(players)?.Where((SNet_Player ply) => !ply.IsBot)?.Count()); } int? num = obj; return num.GetValueOrDefault(1); } private static int GetMaxPlayers() { if (Is.R6OrLater) { return GetMaxPlayersR6Plus(); } return ((Il2CppArrayBase)(object)SNet.Slots.PlayerSlots).Count; } private static int GetMaxPlayersR6Plus() { int num = 0; int count = ((Il2CppArrayBase)(object)SNet.Slots.PlayerSlots).Count; for (int i = 0; i < count; i++) { if (SNet.Slots.IsBotPermittedInSlot(i) || SNet.Slots.IsHumanPermittedInSlot(i)) { num++; } } if (num != 0) { return num; } return count; } [MethodImpl(MethodImplOptions.NoInlining)] public static bool IsActiveExpeditionSpecial() { ExpeditionInTierData activeExpedition = RundownManager.ActiveExpedition; bool? obj; if (activeExpedition == null) { obj = null; } else { DescriptiveData descriptive = activeExpedition.Descriptive; obj = ((descriptive != null) ? new bool?(descriptive.IsExtraExpedition) : null); } bool? flag = obj; return flag.GetValueOrDefault(); } [MethodImpl(MethodImplOptions.NoInlining)] public static bool ShouldSkipExpNumberInName() { ExpeditionInTierData activeExpedition = RundownManager.ActiveExpedition; bool? obj; if (activeExpedition == null) { obj = null; } else { DescriptiveData descriptive = activeExpedition.Descriptive; obj = ((descriptive != null) ? new bool?(descriptive.SkipExpNumberInName) : null); } bool? flag = obj; return flag.GetValueOrDefault(); } } [EnableFeatureByDefault] public class SteamRichPresenceTweaks : Feature { public class SteamRPCSettings { [FSDisplayName("Disable ALL of Steam RPC")] [FSDescription("Enabling this will completely disable relaying your current in-game status as well as prevent anyone from joining on you via steam.")] public bool DisableSteamRPC { get; set; } [FSDisplayName("Custom Status Format")] public string CustomSteamRPCFormat { get; set; } = "%Rundown%%Expedition% \"%ExpeditionName%\""; } [ArchivePatch(/*Could not decode attribute arguments.*/)] internal static class SNet_Core_STEAM_SetFriendsDataPatch { public static void Prefix(FriendsDataType type, ref string data) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between Unknown and I4 if (Config.DisableSteamRPC) { data = string.Empty; } else if ((int)type == 1) { data = PresenceFormatter.FormatPresenceString(Config.CustomSteamRPCFormat) ?? ""; } } } public override string Name => "Steam Rich Presence Tweaks"; public override GroupBase Group => (GroupBase)(object)GroupManager.Presence; public override string Description => "Set a custom text for Steams' presence system."; [FeatureConfig] public static SteamRPCSettings Config { get; set; } } } namespace TheArchive.Core { public static class DRPIcons { public static class Weapons { private static string WeaponPrefix => "weapon_"; public static string HeavyDutyHammer => WeaponPrefix + "hammer"; public static string Knife => WeaponPrefix + "knife"; public static string Bat => WeaponPrefix + "bat"; public static string Spear => WeaponPrefix + "spear"; public static string Maul => WeaponPrefix + "maul"; public static string Sledge => WeaponPrefix + "sledge"; public static string Gavel => WeaponPrefix + "gavel"; public static string Mallet => WeaponPrefix + "mallet"; } public static class Tools { private static string ToolPrefix => "tool_"; public static string Biotracker => ToolPrefix + "bio"; public static string CFoamLauncher => ToolPrefix + "glue"; public static string MineDeployer => ToolPrefix + "mine"; public static string SentryGun => ToolPrefix + "sentry"; } public static class Resources { private static string ResourcePrefix => "res_"; public static string Ammo => ResourcePrefix + "ammo"; public static string Tool => ResourcePrefix + "tool"; public static string Meds => ResourcePrefix + "meds"; } public static class Expedition { public static string ElevatorDropping => "icon_dropping"; public static string Failed => "icon_failed"; public static string Survived => "icon_survived"; public static string Lobby => "icon_lobby"; public static string Reactor => "icon_reactor"; } public static class Characters { private static string CharacterPrefix => "char_"; public static string Woods => CharacterPrefix + "woods"; public static string Dauda => CharacterPrefix + "dauda"; public static string Hackett => CharacterPrefix + "hackett"; public static string Bishop => CharacterPrefix + "bishop"; } public static string GTFOIcon => "gtfo_icon"; public static string Debug => "please_just_work"; public static string EnemyPing => "icon_enemy"; } } namespace TheArchive.Core.Settings { public class RichPresenceSettings { public class GSTopActivity : GSActivity { public List SubActivities = new List(); [JsonIgnore] public bool HasSubActivities => (SubActivities?.Count ?? 0) > 0; public GSTopActivity FillDefaultDictValues(PresenceGameState state) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) RichPresenceSettings @default = Default; if (!base.HasActivities) { @default.DiscordRPCFormat.TryGetValue(state, out var value); Formats = value.Formats; if (!HasSubActivities && value.HasSubActivities) { foreach (GSSubActivity subActivity in value.SubActivities) { SubActivities.Add(subActivity); } } } return this; } } public class GSSubActivity : GSActivity { public List DisplayConditions = new List(); public bool DisplayConditionsAnyMode; } public class GSActivity { public List Formats = new List(); [JsonIgnore] public bool HasActivities { get { List formats = Formats; if (formats == null) { return false; } return formats.Count > 0; } } [JsonIgnore] public bool IsMultiFormat { get { List formats = Formats; if (formats == null) { return false; } return formats.Count > 1; } } [JsonIgnore] public int Count => Formats?.Count ?? 0; [JsonIgnore] public int MultiIndex { get; private set; } [JsonIgnore] public int CurrentMultiCycleCurrency { get; private set; } = 10; public int MultiFormatCycleTime { get; set; } = 10; public GSActivityFormat GetNext() { if (!IsMultiFormat) { return Formats[0]; } if (MultiIndex >= Count) { MultiIndex = 0; } GSActivityFormat result = Formats[MultiIndex]; CurrentMultiCycleCurrency -= 5; if (CurrentMultiCycleCurrency <= 0) { MultiIndex++; CurrentMultiCycleCurrency = MultiFormatCycleTime; } return result; } } public class GSActivityFormat { public string Details { get; set; } = "DefaultDetailsFormatString"; public string Status { get; set; } = "DefaultStatusFormatString"; public GSActivityAssets Assets { get; set; } public bool DisplayStateTimeElapsed { get; set; } = true; public string CustomTimeProvider { get; set; } = ""; public bool CustomProviderIsEndTime { get; set; } = true; public bool DisplayPartyInfo { get; set; } } public class GSActivityAssets { public string LargeImageKey { get; set; } = "please_just_work"; public string LargeTooltip { get; set; } = "Default Large Tooltip"; public string SmallImageKey { get; set; } public string SmallTooltip { get; set; } } public Dictionary DiscordRPCFormat = new Dictionary { { (PresenceGameState)0, new GSTopActivity { Formats = new List { new GSActivityFormat { Details = "Initializing ...", Status = "Waking prisoners ...", Assets = new GSActivityAssets { LargeImageKey = "gtfo_icon", LargeTooltip = "GTFO" } } } } }, { (PresenceGameState)1, new GSTopActivity { Formats = new List { new GSActivityFormat { Details = "%RundownWithNumberOrModdedPrefix%: \"%RundownTitle%\"", Status = "Deciding what to do", Assets = new GSActivityAssets { LargeImageKey = "gtfo_icon", LargeTooltip = "GTFO" } } } } }, { (PresenceGameState)2, new GSTopActivity { Formats = new List { new GSActivityFormat { Details = "%Rundown% %Expedition% \"%ExpeditionName%\"", Status = "In Lobby", Assets = new GSActivityAssets { LargeImageKey = "icon_lobby", LargeTooltip = "GTFO %Rundown% \"%RundownTitle%\"", SmallImageKey = "%CharacterImageKey%", SmallTooltip = "Playing as %CharacterName%" }, DisplayPartyInfo = true } } } }, { (PresenceGameState)3, new GSTopActivity { MultiFormatCycleTime = 5, Formats = new List { new GSActivityFormat { Details = "%Rundown% %Expedition% \"%ExpeditionName%\"", Status = "Dropping .", Assets = new GSActivityAssets { LargeImageKey = "icon_dropping", LargeTooltip = "Riding the elevator to hell ..." }, DisplayPartyInfo = true }, new GSActivityFormat { Details = "%Rundown% %Expedition% \"%ExpeditionName%\"", Status = "Dropping ..", Assets = new GSActivityAssets { LargeImageKey = "icon_dropping", LargeTooltip = "Riding the elevator to hell ..." }, DisplayPartyInfo = true }, new GSActivityFormat { Details = "%Rundown% %Expedition% \"%ExpeditionName%\"", Status = "Dropping ...", Assets = new GSActivityAssets { LargeImageKey = "icon_dropping", LargeTooltip = "Riding the elevator to hell ..." }, DisplayPartyInfo = true } } } }, { (PresenceGameState)4, new GSTopActivity { Formats = new List { new GSActivityFormat { Details = "%Rundown% %Expedition% \"%ExpeditionName%\"", Status = "Engaging brakes ...", Assets = new GSActivityAssets { LargeImageKey = "icon_dropping", LargeTooltip = "Next stop: Hell" }, DisplayPartyInfo = true } } } }, { (PresenceGameState)5, new GSTopActivity { Formats = new List { new GSActivityFormat { Details = "%Rundown% %Expedition% \"%ExpeditionName%\"", Status = "In Expedition", Assets = new GSActivityAssets { LargeImageKey = "gtfo_icon", LargeTooltip = "Exploring %CurrentZoneShort% Area %AreaSuffix%", SmallImageKey = "%MeleeWeaponKey%", SmallTooltip = "%EquippedMeleeWeaponName%" }, DisplayPartyInfo = true }, new GSActivityFormat { Details = "Health: %HealthPercent%%", Status = "In Expedition", Assets = new GSActivityAssets { LargeImageKey = "gtfo_icon", LargeTooltip = "%Rundown% %Expedition% \"%ExpeditionName%\"", SmallImageKey = "res_meds", SmallTooltip = "Prisoner vitals" }, DisplayPartyInfo = true }, new GSActivityFormat { Details = "Primary: %PrimaryAmmoPercent%% Special: %SpecialAmmoPercent%%", Status = "In Expedition", Assets = new GSActivityAssets { LargeImageKey = "gtfo_icon", LargeTooltip = "%Rundown% %Expedition% \"%ExpeditionName%\"", SmallImageKey = "res_ammo", SmallTooltip = "Ammo levels" }, DisplayPartyInfo = true }, new GSActivityFormat { Details = "Tool: %ToolAmmoPercentOrStatus%", Status = "In Expedition", Assets = new GSActivityAssets { LargeImageKey = "%ToolKey%", LargeTooltip = "%EquippedToolName%", SmallImageKey = "res_tool", SmallTooltip = "Resource level" }, DisplayPartyInfo = true } }, SubActivities = new List { new GSSubActivity { DisplayConditions = new List { "%IsReactorActive%", "%IsReactorInIntro%", "%IsReactorTypeStartup%", "!%IsReactorInVerifyFailState%" }, Formats = new List { new GSActivityFormat { Details = "Reactor %ReactorType% (%ReactorWaveCountCurrent%/%ReactorWaveCountMax%)", Status = "Warming Up!", Assets = new GSActivityAssets { LargeImageKey = DRPIcons.Expedition.Reactor, LargeTooltip = "%Rundown% %Expedition% \"%ExpeditionName%\"" }, DisplayPartyInfo = true, DisplayStateTimeElapsed = false, CustomTimeProvider = "%ReactorWaveEndTime%" } } }, new GSSubActivity { DisplayConditions = new List { "%IsReactorActive%", "%IsReactorInIntro%", "%IsReactorTypeStartup%", "%IsReactorInVerifyFailState%" }, Formats = new List { new GSActivityFormat { Details = "%ReactorType% Sequence Failed! (%ReactorWaveCountCurrent%/%ReactorWaveCountMax%)", Status = "Warming Up!", Assets = new GSActivityAssets { LargeImageKey = DRPIcons.Expedition.Reactor, LargeTooltip = "%Rundown% %Expedition% \"%ExpeditionName%\"" }, DisplayPartyInfo = true, DisplayStateTimeElapsed = false, CustomTimeProvider = "%ReactorWaveEndTime%" } } }, new GSSubActivity { DisplayConditions = new List { "%IsReactorActive%", "%IsReactorInIntro%", "!%IsReactorTypeStartup%" }, Formats = new List { new GSActivityFormat { Details = "Reactor %ReactorType% Sequence", Status = "Warning!", Assets = new GSActivityAssets { LargeImageKey = DRPIcons.Expedition.Reactor, LargeTooltip = "%Rundown% %Expedition% \"%ExpeditionName%\"" }, DisplayPartyInfo = true } } }, new GSSubActivity { DisplayConditions = new List { "%IsReactorActive%", "%IsReactorWaveOrChaosActive%", "%IsReactorTypeStartup%" }, Formats = new List { new GSActivityFormat { Details = "Reactor Wave (%ReactorWaveCountCurrent%/%ReactorWaveCountMax%)", Status = "High Intensive Test", Assets = new GSActivityAssets { LargeImageKey = DRPIcons.Expedition.Reactor, LargeTooltip = "%Rundown% %Expedition% \"%ExpeditionName%\"", SmallImageKey = DRPIcons.EnemyPing, SmallTooltip = "Heavy Reactor Load" }, DisplayPartyInfo = true, DisplayStateTimeElapsed = false, CustomTimeProvider = "%ReactorWaveEndTime%" } } }, new GSSubActivity { DisplayConditions = new List { "%IsReactorActive%", "%IsReactorWaveOrChaosActive%", "!%IsReactorTypeStartup%" }, Formats = new List { new GSActivityFormat { Details = "Reactor Shutdown Failure!", Status = "Alarm triggered!", Assets = new GSActivityAssets { LargeImageKey = DRPIcons.Expedition.Reactor, LargeTooltip = "%Rundown% %Expedition% \"%ExpeditionName%\"", SmallImageKey = DRPIcons.EnemyPing, SmallTooltip = "Security System Malfunctioning" }, DisplayPartyInfo = true } } }, new GSSubActivity { DisplayConditions = new List { "%IsReactorActive%", "%IsReactorAwaitingVerify%", "%IsReactorTypeStartup%" }, Formats = new List { new GSActivityFormat { Details = "%ReactorVerificationString% (%ReactorWaveCountCurrent%/%ReactorWaveCountMax%)", Status = "Verification Required!", Assets = new GSActivityAssets { LargeImageKey = DRPIcons.Expedition.Reactor, LargeTooltip = "%Rundown% %Expedition% \"%ExpeditionName%\"" }, DisplayPartyInfo = true, DisplayStateTimeElapsed = false, CustomTimeProvider = "%ReactorWaveEndTime%" } } }, new GSSubActivity { DisplayConditions = new List { "%IsReactorActive%", "%IsReactorAwaitingVerify%", "!%IsReactorTypeStartup%" }, Formats = new List { new GSActivityFormat { Details = "Initiating Shutdown Sequence ...", Status = "Verification Required!", Assets = new GSActivityAssets { LargeImageKey = DRPIcons.Expedition.Reactor, LargeTooltip = "%Rundown% %Expedition% \"%ExpeditionName%\"" }, DisplayPartyInfo = true } } }, new GSSubActivity { DisplayConditions = new List { "%IsReactorActive%", "%IsReactorCompleted%" }, Formats = new List { new GSActivityFormat { Details = "Reactor %ReactorType% Sequence", Status = "Complete!", Assets = new GSActivityAssets { LargeImageKey = DRPIcons.Expedition.Reactor, LargeTooltip = "%Rundown% %Expedition% \"%ExpeditionName%\"" }, DisplayPartyInfo = true } } } } } }, { (PresenceGameState)6, new GSTopActivity { Formats = new List { new GSActivityFormat { Details = "%Rundown% %Expedition% \"%ExpeditionName%\"", Status = "EXPD FAILED", Assets = new GSActivityAssets { LargeImageKey = "icon_failed", LargeTooltip = "Beep, Beep, Beeeeeeeeeeep", SmallImageKey = "%CharacterImageKey%", SmallTooltip = "\"%CharacterName%\", Status: DECEASED" }, DisplayPartyInfo = true } } } }, { (PresenceGameState)7, new GSTopActivity { Formats = new List { new GSActivityFormat { Details = "%Rundown% %Expedition% \"%ExpeditionName%\"", Status = "EXPD SURVIVED", Assets = new GSActivityAssets { LargeImageKey = "icon_survived", LargeTooltip = "Hydrostasis awaits ...", SmallImageKey = "%CharacterImageKey%", SmallTooltip = "\"%CharacterName%\", Status: ALIVE" }, DisplayPartyInfo = true } } } } }; [FSHide] [FSDisplayName("DEBUG Use Default Settings")] public bool DEBUG_UseDefaultSettings { get; set; } [FSIgnore] public bool DEBUG_RichPresenceLogSpam { get; set; } [JsonIgnore] [FSIgnore] internal static RichPresenceSettings Default => new RichPresenceSettings(); public RichPresenceSettings FillDefaultDictValues() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) foreach (KeyValuePair item in new RichPresenceSettings().DiscordRPCFormat) { if (!DiscordRPCFormat.TryGetValue(item.Key, out var value) || value == null) { DiscordRPCFormat.Add(item.Key, item.Value.FillDefaultDictValues(item.Key)); } else { value.FillDefaultDictValues(item.Key); } } return this; } } } namespace TheArchive.Core.Managers { public class ArchiveDiscordManager { public static class DiscordClient { public const long DEFAULT_CLIENT_ID = 946141176338190346L; private static DiscordRpcClient _discordClient; private static ILogger _clientLogger; private static string _lastLobbyId; private static string _lastPartyHash; private static readonly RichPresence DefaultFallbackActivity = new RichPresence { Details = "???", State = "err:// no c0nnec7ion", Assets = new Assets { LargeImageKey = "gtfo_icon", LargeImageText = "GTFO" } }; public static long UsedClientID { get; private set; } public static void Initialize(long clientId = 946141176338190346L) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown UsedClientID = clientId; _clientLogger = (ILogger)(object)new DiscordLogger(LoaderWrapper.CreateLoggerInstance("DiscordClient", ConsoleColor.Magenta), (LogLevel)3); _discordClient = new DiscordRpcClient(clientId.ToString(), -1, _clientLogger, false, (INamedPipeClient)null); _discordClient.RegisterUriScheme(493520u.ToString(), (string)null); _discordClient.OnReady += new OnReadyEvent(OnReady); _discordClient.OnJoin += new OnJoinEvent(OnJoin); _discordClient.Subscribe((EventType)2); _discordClient.Initialize(); } private static void OnJoin(object sender, JoinMessage args) { Logger.Notice("OnJoin received! (" + args.Secret + ")"); ArchiveDiscordManager.OnActivityJoin?.Invoke(args.Secret); } private static void OnReady(object sender, ReadyMessage args) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) Logger.Notice("Discord is ready!"); float realtimeSinceStartup = Time.realtimeSinceStartup; if (!(realtimeSinceStartup < _lastCheckedTime + 5f)) { _lastCheckedTime = realtimeSinceStartup; RichPresence val = BuildActivity(PresenceManager.CurrentState, PresenceManager.CurrentStateStartTime); if (TryUpdateActivity(val)) { _lastActivity = val; } } } private static Party GetParty(string partyId = null) { //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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown return new Party { ID = partyId, Size = PresenceFormatter.Get("MaxPlayerSlots") - PresenceFormatter.Get("OpenSlots"), Max = PresenceFormatter.Get("MaxPlayerSlots") }; } private static Secrets GetSecrets(string joinSecret = null) { //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_0012: Expected O, but got Unknown if (joinSecret == null) { return null; } return new Secrets { JoinSecret = joinSecret }; } private static Timestamps GetTimestamp(ulong? startTime = null, ulong? endTime = null) { //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_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown return new Timestamps { StartUnixMilliseconds = startTime * 1000, EndUnixMilliseconds = endTime * 1000 }; } internal static RichPresence BuildActivity(PresenceGameState state, DateTimeOffset startTime) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) if (!_settings.DiscordRPCFormat.TryGetValue(state, out var value)) { return DefaultFallbackActivity; } RichPresenceSettings.GSActivity gSActivity = value; if (!value.HasSubActivities) { return ActivityFromFormat(gSActivity.GetNext(), state, startTime); } foreach (RichPresenceSettings.GSSubActivity subActivity in value.SubActivities) { try { if (subActivity.DisplayConditionsAnyMode) { bool flag = false; foreach (string displayCondition in subActivity.DisplayConditions) { string text = PresenceFormatter.Format(displayCondition, Array.Empty<(string, string)>()); if (text == "True" || text == "!False") { flag = true; } } if (!flag) { throw null; } } else { foreach (string displayCondition2 in subActivity.DisplayConditions) { string text2 = PresenceFormatter.Format(displayCondition2, Array.Empty<(string, string)>()); if (text2 != "True" && text2 != "!False") { throw null; } } } gSActivity = subActivity; } catch { continue; } break; } return ActivityFromFormat(gSActivity.GetNext(), state, startTime); } private static RichPresence ActivityFromFormat(RichPresenceSettings.GSActivityFormat format, PresenceGameState state, DateTimeOffset startTime) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown if (format == null) { return DefaultFallbackActivity; } (string, string) tuple = ("state", ((object)(PresenceGameState)(ref state)).ToString()); RichPresence val = new RichPresence(); string details = format.Details; ((BaseRichPresence)val).Details = ((details != null) ? PresenceFormatter.Format(details, new(string, string)[1] { tuple }) : null); string status = format.Status; ((BaseRichPresence)val).State = ((status != null) ? PresenceFormatter.Format(status, new(string, string)[1] { tuple }) : null); RichPresence val2 = val; Assets val3 = new Assets(); string largeImageKey = format.Assets.LargeImageKey; val3.LargeImageKey = ((largeImageKey != null) ? PresenceFormatter.Format(largeImageKey, new(string, string)[1] { tuple }) : null); string largeTooltip = format.Assets.LargeTooltip; val3.LargeImageText = ((largeTooltip != null) ? PresenceFormatter.Format(largeTooltip, new(string, string)[1] { tuple }) : null); string smallImageKey = format.Assets.SmallImageKey; val3.SmallImageKey = ((smallImageKey != null) ? PresenceFormatter.Format(smallImageKey, new(string, string)[1] { tuple }) : null); string smallTooltip = format.Assets.SmallTooltip; val3.SmallImageText = ((smallTooltip != null) ? PresenceFormatter.Format(smallTooltip, new(string, string)[1] { tuple }) : null); ((BaseRichPresence)val2).Assets = val3; ulong result; if (format.DisplayStateTimeElapsed) { ((BaseRichPresence)val2).Timestamps = GetTimestamp((ulong)startTime.ToUnixTimeSeconds()); } else if (!string.IsNullOrWhiteSpace(format.CustomTimeProvider) && ulong.TryParse(PresenceFormatter.Format(format.CustomTimeProvider, Array.Empty<(string, string)>()), out result)) { if (format.CustomProviderIsEndTime) { ulong? endTime = result; ((BaseRichPresence)val2).Timestamps = GetTimestamp(null, endTime); } else { ((BaseRichPresence)val2).Timestamps = GetTimestamp(result); } } if (format.DisplayPartyInfo) { if (PresenceFormatter.Get("HasLobby")) { string text = PresenceFormatter.Get("LobbyID").ToString(); ((BaseRichPresence)val2).Party = GetParty(GetPartyID(text)); ((BaseRichPresence)val2).Secrets = GetSecrets(text); } else { ((BaseRichPresence)val2).Party = GetParty(PartyGuid.ToString()); } } return val2; } private static string GetPartyID(string lobbyId) { bool flag = _lastLobbyId != lobbyId; _lastLobbyId = lobbyId; if (string.IsNullOrWhiteSpace(lobbyId)) { return PartyGuid.ToString(); } if (!flag) { return _lastPartyHash; } string text = Convert.ToBase64String(SHA256.HashData(Encoding.UTF8.GetBytes(lobbyId))); if (text.Length > 128) { text = text.Substring(0, 128); } _lastPartyHash = text; return text; } internal static bool TryUpdateActivity(RichPresence activity) { if (_discordClient == null) { return false; } if (_settings.DEBUG_RichPresenceLogSpam) { Logger.Notice("Activity updated: Details:" + ((BaseRichPresence)activity).Details + " State:" + ((BaseRichPresence)activity).State); } _discordClient.SetPresence(activity); return true; } public static void Dispose() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown if (_discordClient != null) { _discordClient.OnReady += new OnReadyEvent(OnReady); _discordClient.OnJoin += new OnJoinEvent(OnJoin); _discordClient.Dispose(); } _discordClient = null; } public static void RunCallbacks() { _discordClient.Invoke(); } } private static RichPresence _lastActivity; private static float _lastCheckedTime; private static RichPresenceSettings _settings; private static IArchiveLogger _logger; public static bool HasBeenSetup => _settings != null; public static bool IsEnabled { get; private set; } public static Guid PartyGuid { get; private set; } = Guid.NewGuid(); private static IArchiveLogger Logger => _logger ?? (_logger = LoaderWrapper.CreateLoggerInstance("ArchiveDiscordManager", ConsoleColor.Magenta)); public static event Action OnActivityJoin; public static void Enable(RichPresenceSettings rpcSettings) { if (rpcSettings == null) { throw new ArgumentNullException("rpcSettings"); } if (rpcSettings.DEBUG_UseDefaultSettings) { _settings = RichPresenceSettings.Default; } else { _settings = rpcSettings; } try { DiscordClient.Initialize(); DiscordClient.RunCallbacks(); IsEnabled = true; } catch (Exception ex) { Logger.Error($"Exception has been thrown in {"ArchiveDiscordManager"}. {ex}: {ex.Message}"); Logger.Exception(ex); } } public static void Disable() { if (IsEnabled) { DiscordClient.Dispose(); IsEnabled = false; } } public static void Update() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) if (!IsEnabled) { return; } float time = Time.time; if (_lastCheckedTime + 5f <= time) { _lastCheckedTime = time; RichPresence val = DiscordClient.BuildActivity(PresenceManager.CurrentState, PresenceManager.CurrentStateStartTime); if (!((object)val).Equals((object?)_lastActivity) && DiscordClient.TryUpdateActivity(val)) { _lastActivity = val; } } DiscordClient.RunCallbacks(); } public static void RenewPartyGuid() { PartyGuid = Guid.NewGuid(); } } public class DiscordLogger : ILogger { private readonly IArchiveLogger _logger; public LogLevel Level { get; set; } public DiscordLogger(IArchiveLogger archiveLogger, LogLevel logLevel) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) _logger = archiveLogger; Level = logLevel; } public void Trace(string message, params object[] args) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)Level <= 1) { string text = message; if (args.Length != 0) { text = string.Format(message, args); } _logger.Debug(text); } } public void Info(string message, params object[] args) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)Level <= 2) { string text = message; if (args.Length != 0) { text = string.Format(message, args); } _logger.Msg(ConsoleColor.DarkMagenta, text); } } public void Warning(string message, params object[] args) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)Level <= 3) { string text = message; if (args.Length != 0) { text = string.Format(message, args); } _logger.Warning(text); } } public void Error(string message, params object[] args) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)Level <= 4) { string text = message; if (args.Length != 0) { text = string.Format(message, args); } _logger.Error(text); } } } public class PresenceManager { private static IArchiveLogger _logger; public static PresenceGameState LastState { get; private set; } = (PresenceGameState)0; public static PresenceGameState CurrentState { get; private set; } = (PresenceGameState)0; public static DateTimeOffset CurrentStateStartTime { get; private set; } = DateTimeOffset.UtcNow; private static IArchiveLogger Logger => _logger ?? (_logger = LoaderWrapper.CreateLoggerInstance("PresenceManager", ConsoleColor.DarkMagenta)); [FallbackPresenceFormatProvider("EquippedMeleeWeaponName", false)] public static string EquippedMeleeWeaponName => "None"; [FallbackPresenceFormatProvider("EquippedMeleeWeaponID", false)] public static string EquippedMeleeWeaponID => "None"; [PresenceFormatProvider("MeleeWeaponKey")] public static string MeleeWeaponKey { get { string text = PresenceFormatter.Get("EquippedMeleeWeaponID")?.ToLower(); switch (text) { case "heavydutyhammer": text = "hammer"; goto default; case "sledgehammer": text = "sledge"; goto default; default: return "weapon_" + text; case null: return "please_just_work"; } } } [FallbackPresenceFormatProvider("EquippedToolName", false)] public static string EquippedToolName => "None"; [FallbackPresenceFormatProvider("EquippedToolID", false)] public static string EquippedToolID => "None"; [PresenceFormatProvider("ToolKey")] public static string ToolKey { get { string text = PresenceFormatter.Get("EquippedToolID")?.ToLower(); if (text != null) { if (text.Contains("sentry")) { return "tool_sentry"; } if (text.Contains("bio")) { return "tool_bio"; } if (text.Contains("mine")) { return "tool_mine"; } if (text.Contains("glue")) { return "tool_glue"; } } return "please_just_work"; } } [FallbackPresenceFormatProvider("PrimaryAmmo", false)] public static int PrimaryAmmo => -1; [FallbackPresenceFormatProvider("MaxPrimaryAmmo", false)] public static int MaxPrimaryAmmo => -1; [PresenceFormatProvider("PrimaryAmmoPercent")] public static int PrimaryAmmoPercent => GetPercentFromInts("PrimaryAmmo", "MaxPrimaryAmmo"); [FallbackPresenceFormatProvider("SpecialAmmo", false)] public static int SpecialAmmo => -1; [FallbackPresenceFormatProvider("MaxSpecialAmmo", false)] public static int MaxSpecialAmmo => -1; [PresenceFormatProvider("SpecialAmmoPercent")] public static int SpecialAmmoPercent => GetPercentFromInts("SpecialAmmo", "MaxSpecialAmmo"); [FallbackPresenceFormatProvider("ToolAmmo", false)] public static int ToolAmmo => -1; [FallbackPresenceFormatProvider("MaxToolAmmo", false)] public static int MaxToolAmmo => -1; [PresenceFormatProvider("ToolAmmoOrStatus")] public static string ToolAmmoOrStatus { get { string text = PresenceFormatter.Get("ToolKey"); int num = PresenceFormatter.Get("ToolAmmo"); int value = PresenceFormatter.Get("MaxToolAmmo"); if (!(text == "tool_bio")) { if (text == "tool_sentry") { if (num > 0) { return $"{num}/{value}"; } return "Deployed/Empty"; } if (num > 0) { return $"{num}/{value}"; } return "Empty"; } return "Infinite"; } } [PresenceFormatProvider("ToolAmmoPercent")] public static int ToolAmmoPercent => GetPercentFromInts("ToolAmmo", "MaxToolAmmo"); [PresenceFormatProvider("ToolAmmoPercentOrStatus")] public static string ToolAmmoPercentOrStatus { get { string text = PresenceFormatter.Get("ToolKey"); float num = PresenceFormatter.Get("ToolAmmo"); float max = PresenceFormatter.Get("MaxToolAmmo"); if (!(text == "tool_bio")) { if (text == "tool_sentry") { if (num > 0f) { return $"{GetPercent(num, max)}%"; } return "Deployed/Empty"; } if (num > 0f) { return $"{GetPercent(num, max)}%"; } return "Empty"; } return "∞"; } } [FallbackPresenceFormatProvider("LocalCharacterID", false)] public static int LocalCharacterID { get; set; } = 0; [PresenceFormatProvider("CharacterImageKey")] public static string CharacterImageKey => PresenceFormatter.Get("LocalCharacterID") switch { 0 => "char_woods", 1 => "char_dauda", 2 => "char_hackett", 3 => "char_bishop", _ => "please_just_work", }; [PresenceFormatProvider("CharacterName")] public static string CharacterName { get { int num = PresenceFormatter.Get("LocalCharacterID"); return SNet.Core.GetBotNickname(num); } } [FallbackPresenceFormatProvider("HealthRaw", false)] public static float HealthRaw => -1f; [FallbackPresenceFormatProvider("MaxHealthRaw", false)] public static float MaxHealthRaw => 25f; [PresenceFormatProvider("HealthPercent")] public static int HealthPercent => GetPercentFromFloats("HealthRaw", "MaxHealthRaw"); [FallbackPresenceFormatProvider("HasLobby", false)] public static bool HasLobby => false; [FallbackPresenceFormatProvider("LobbyID", false)] public static string LobbyID => "0123456789"; [FallbackPresenceFormatProvider("OpenSlots", false)] public static int OpenSlots { get; set; } = 0; [FallbackPresenceFormatProvider("MaxPlayerSlots", true)] public static int MaxPlayerSlots { get; set; } = 4; [FallbackPresenceFormatProvider("ExpeditionTier", false)] public static string ExpeditionTier { get; set; } = string.Empty; [FallbackPresenceFormatProvider("ExpeditionTierIsSpecial", true)] public static bool ExpeditionTierIsSpecial { get; set; } = false; [FallbackPresenceFormatProvider("ExpeditionSkipExpNumberInName", true)] public static bool ExpeditionSkipExpNumberInName { get; set; } = false; [FallbackPresenceFormatProvider("ExpeditionNumber", false)] public static string ExpeditionNumber { get; set; } = string.Empty; [FallbackPresenceFormatProvider("ExpeditionName", false)] public static string ExpeditionName { get; set; } = string.Empty; [FallbackPresenceFormatProvider("ZonePrefix", false)] public static string ZonePrefix { get; set; } = string.Empty; [FallbackPresenceFormatProvider("ZonePrefixLong", false)] public static string ZonePrefixLong { get; set; } = string.Empty; [FallbackPresenceFormatProvider("ZoneAlias", false)] public static string ZoneAlias { get; set; } = string.Empty; [FallbackPresenceFormatProvider("AreaSuffix", false)] public static string AreaSuffix { get; set; } = string.Empty; [FallbackPresenceFormatProvider("RundownTitleFromDataBlocks", false)] public static string RundownTitleFromDataBlocks { get; set; } = "Unknown"; [PresenceFormatProvider("CurrentZoneShort")] public static string CurrentZoneShort => $"{PresenceFormatter.Get("ZonePrefix")}_{PresenceFormatter.Get("ZoneAlias")}"; [PresenceFormatProvider("CurrentZoneLong")] public static string CurrentZoneLong => $"{PresenceFormatter.Get("ZonePrefixLong")} {PresenceFormatter.Get("ZoneAlias")}"; [PresenceFormatProvider("CurrentArea")] public static string CurrentArea => $"Area {PresenceFormatter.Get("AreaSuffix")}"; [PresenceFormatProvider("ExpeditionWithNumber")] public static string ExpeditionWithNumber => $"{PresenceFormatter.Get("ExpeditionTier")}{PresenceFormatter.Get("ExpeditionNumber")}"; [PresenceFormatProvider("Expedition")] public static string Expedition { get { if (PresenceFormatter.Get("ExpeditionSkipExpNumberInName")) { return $"{PresenceFormatter.Get("ExpeditionTier")}"; } return ExpeditionWithNumber ?? ""; } } [PresenceFormatProvider("Rundown")] public static string Rundown { get { if (ArchiveMod.IsPlayingModded) { return "Mod"; } if (ArchiveMod.IsOnALTBuild) { string text = PresenceFormatter.Get("ExpeditionTier").ToString(); if (text.StartsWith("R7") || text.StartsWith("R8")) { return string.Empty; } return "Alt"; } return $"R{RundownNumber}"; } } [PresenceFormatProvider("RundownNumber")] public static int RundownNumber => (int)ArchiveMod.CurrentRundown; [PresenceFormatProvider("RundownName")] public static string RundownName => RundownTitle; [PresenceFormatProvider("RundownTitle")] public static string RundownTitle { get { //IL_0030: Unknown result type (might be due to invalid IL or missing references) if (ArchiveMod.IsPlayingModded || ArchiveMod.IsOnALTBuild) { return $"{PresenceFormatter.Get("RundownTitleFromDataBlocks")}"; } return Utils.GetRundownTitle(ArchiveMod.CurrentRundown); } } [PresenceFormatProvider("RundownWithNumberOrModdedPrefix")] public static string RundownWithNumberOrModdedPrefix { get { if (ArchiveMod.IsPlayingModded) { return "Modded"; } if (ArchiveMod.IsOnALTBuild) { return "GTFO"; } return $"Rundown {PresenceFormatter.Get("RundownNumber")}"; } } public static void UpdateGameState(PresenceGameState state, bool keepTimer = false) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) Logger.Msg(ConsoleColor.DarkMagenta, $"GameState has been updated: {CurrentState} --> {state}, keepTimer: {keepTimer}"); LastState = CurrentState; CurrentState = state; if (!keepTimer) { CurrentStateStartTime = DateTimeOffset.UtcNow; } } public static int GetPercentFromInts(string val, string max) { float val2 = PresenceFormatter.Get(val); float max2 = PresenceFormatter.Get(max); return GetPercent(val2, max2); } public static int GetPercentFromFloats(string val, string max) { float val2 = PresenceFormatter.Get(val); float max2 = PresenceFormatter.Get(max); return GetPercent(val2, max2); } public static int GetPercent(float val, float max) { return (int)Math.Round(val / max * 100f); } } }