Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of LethalCompanyHighlights v0.1.8
LethalCompanyHighlights.dll
Decompiled 5 days agousing System; using System.Collections; 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.Permissions; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using Coroner; using GameNetcodeStuff; using HarmonyLib; using LethalCompanyHighlights.Configuration; using LethalCompanyHighlights.Utils; using LethalConfig; using LethalConfig.ConfigItems; using LethalConfig.ConfigItems.Options; using Microsoft.CodeAnalysis; using Steamworks; using Steamworks.Data; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: AssemblyCompany("LethalCompanyHighlights")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("Record, clip, and annotate your Lethal Company deaths with Steam. Your incompetence, now professionally documented. ")] [assembly: AssemblyFileVersion("0.1.8.0")] [assembly: AssemblyInformationalVersion("0.1.8+bc6ad479ae338aa1fcb82ec8f4b91d9fe9b3c29c")] [assembly: AssemblyProduct("LethalCompanyHighlights")] [assembly: AssemblyTitle("LethalCompanyHighlights")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.8.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace LethalCompanyHighlights { internal static class Features { private static readonly bool IsCoronerLoaded = Chainloader.PluginInfos.ContainsKey("com.elitemastereric.coroner"); internal static bool IsEnabled() { return PluginConfig.IsEnabledConfigEntry.Value; } internal static bool IsClippingEnabledForOthers() { return !PluginConfig.OnlyClipMyDeathsConfigEntry.Value; } internal static bool IsProximityEnabled() { return IsClippingEnabledForOthers() && PluginConfig.ProximityCheckConfigEntry.Value; } internal static bool IsVisibilityEnabled() { return IsClippingEnabledForOthers() && PluginConfig.VisibilityCheckConfigEntry.Value; } internal static string GetCauseOfDeath(PlayerControllerB player) { return IsCoronerLoaded ? GetCoronerCauseOfDeath(player) : GetVanillaCauseOfDeath(player); } [MethodImpl(MethodImplOptions.NoInlining)] private static string GetCoronerCauseOfDeath(PlayerControllerB player) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) AdvancedCauseOfDeath? causeOfDeath = API.GetCauseOfDeath(player); return causeOfDeath.HasValue ? API.StringifyCauseOfDeath(causeOfDeath.Value, (Random)null) : GetVanillaCauseOfDeath(player); } private static string GetVanillaCauseOfDeath(PlayerControllerB player) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected I4, but got Unknown CauseOfDeath causeOfDeath = player.causeOfDeath; CauseOfDeath val = causeOfDeath; switch ((int)val) { case 1: return "bludgeoned to death"; case 2: return "fell"; case 3: return "blew up"; case 4: case 5: return "died of asphyxiation"; case 6: return "mauled to death"; case 7: return "caught in a firefight"; case 8: return "crushed"; case 9: return "drowned"; case 10: return "left behind"; case 11: return "electrocuted"; case 12: return "kicked to death"; case 13: return "burned alive"; case 14: return "stabbed"; case 17: return "chopped in two"; default: return "died of unknown causes"; } } } internal static class SimpleDeathTracker { private static readonly ISet<ulong> PlayersKilled = new HashSet<ulong>(); internal static bool PlayerKilled(PlayerControllerB player) { return PlayersKilled.Add(player.playerClientId); } internal static void Reset() { PlayersKilled.Clear(); } } internal class RoundPatches { private static readonly Regex RemoveLeadingNumber = new Regex("^\\d+\\s+", RegexOptions.Compiled); private static string _currentPhaseId; [HarmonyPostfix] [HarmonyPatch(typeof(MenuManager), "SetLoadingScreen")] private static void SetLoadingScreenPostfix(bool isLoading) { if (Features.IsEnabled() && isLoading) { SteamHighlightsPlugin.Logger.LogDebug((object)"MenuManager::SetLoadingScreen, 'LoadingScreen' phase"); SteamTimeline.SetTimelineGameMode((TimelineGameMode)4); } } [HarmonyPostfix] [HarmonyPatch(typeof(StartOfRound), "SetMapScreenInfoToCurrentLevel")] private static void SetMapScreenInfoToCurrentLevelPostfix() { if (Features.IsEnabled()) { SteamHighlightsPlugin.Logger.LogDebug((object)"StartOfRound::SetMapScreenInfoToCurrentLevel, 'Orbiting' phase"); string text = RemoveLeadingNumber.Replace(StartOfRound.Instance.currentLevel.PlanetName, ""); SteamTimeline.SetTimelineGameMode((TimelineGameMode)2); SteamTimeline.SetTimelineTooltip("Orbiting " + text, -3f); } } [HarmonyPostfix] [HarmonyPatch(typeof(StartOfRound), "openingDoorsSequence")] private static void OpeningDoorsSequencePostfix() { if (!Features.IsEnabled()) { return; } SteamHighlightsPlugin.Logger.LogDebug((object)"StartOfRound::openingDoorsSequence, 'Exploring' phase"); string text = RemoveLeadingNumber.Replace(StartOfRound.Instance.currentLevel.PlanetName, ""); _currentPhaseId = $"{text}-{Guid.NewGuid()}"; SteamTimeline.SetTimelineGameMode((TimelineGameMode)1); SteamTimeline.ClearTimelineTooltip(-2f); SteamTimeline.StartGamePhase(); SteamTimeline.SetGamePhaseId(_currentPhaseId); SteamTimeline.AddGamePhaseTag(text, "steam_marker", "Planet", 100u); PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if (((Behaviour)val).isActiveAndEnabled) { SteamTimeline.AddGamePhaseTag(val.playerUsername, "steam_group", "Players", 75u); } } VisibilityTracker visibilityTracker = default(VisibilityTracker); if (!((Component)StartOfRound.Instance.localPlayerController).gameObject.TryGetComponent<VisibilityTracker>(ref visibilityTracker)) { visibilityTracker = ((Component)StartOfRound.Instance.localPlayerController).gameObject.AddComponent<VisibilityTracker>(); } visibilityTracker.Initialize(); } [HarmonyPostfix] [HarmonyPatch(typeof(MenuManager), "Start")] private static void StartPostfix() { if (Features.IsEnabled()) { SteamTimeline.EndGamePhase(); SteamTimeline.SetTimelineGameMode((TimelineGameMode)3); SimpleDeathTracker.Reset(); _currentPhaseId = null; } } [HarmonyPostfix] [HarmonyPatch(typeof(StartOfRound), "ShipLeave")] private static void ShipLeavePostfix() { if (Features.IsEnabled()) { if (Object.op_Implicit((Object)(object)VisibilityTracker.Instance)) { VisibilityTracker.Instance.StopVisibilityCoroutine(); } SteamTimeline.EndGamePhase(); _currentPhaseId = null; } } } internal class PlayerPatches { [CompilerGenerated] private sealed class <SaveDeathClip>d__4 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public PlayerControllerB player; private PlayerControllerB <localPlayer>5__1; private bool <shouldClip>5__2; private string <cause>5__3; private uint <priority>5__4; private string <clipName>5__5; private TimelineEventHandle <handle>5__6; private bool <>s__7; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <SaveDeathClip>d__4(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <localPlayer>5__1 = null; <cause>5__3 = null; <clipName>5__5 = null; <>1__state = -2; } private bool MoveNext() { //IL_0394: Unknown result type (might be due to invalid IL or missing references) //IL_0320: Unknown result type (might be due to invalid IL or missing references) //IL_0325: Unknown result type (might be due to invalid IL or missing references) //IL_02d7: Unknown result type (might be due to invalid IL or missing references) //IL_02dc: Unknown result type (might be due to invalid IL or missing references) //IL_0379: Unknown result type (might be due to invalid IL or missing references) //IL_0383: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (!Features.IsEnabled()) { return false; } if (!SimpleDeathTracker.PlayerKilled(player)) { SteamHighlightsPlugin.Logger.LogDebug((object)("Player '" + player.playerUsername + "' has already been recorded as dead.")); return false; } SteamHighlightsPlugin.Logger.LogDebug((object)("Player '" + player.playerUsername + "' died")); if (!GameNetworkManager.Instance.disableSteam) { SteamTimeline.AddGamePhaseTag(player.playerUsername, "steam_death", "Died", 50u); } <localPlayer>5__1 = StartOfRound.Instance.localPlayerController; <shouldClip>5__2 = false; if ((Object)(object)<localPlayer>5__1 == (Object)(object)player) { SteamHighlightsPlugin.Logger.LogDebug((object)"It was us who died!"); <shouldClip>5__2 = true; } else { bool isPlayerDead = <localPlayer>5__1.isPlayerDead; <>s__7 = isPlayerDead; if (<>s__7) { if (!Features.IsClippingEnabledForOthers() || !((Object)(object)<localPlayer>5__1.spectatedPlayerScript == (Object)(object)player)) { goto IL_020d; } SteamHighlightsPlugin.Logger.LogDebug((object)("Observed " + player.playerUsername + " die in spectator mode")); <shouldClip>5__2 = true; } else if (Features.IsProximityEnabled() && IsPlayerNearby(player, 10f)) { SteamHighlightsPlugin.Logger.LogDebug((object)(player.playerUsername + " died near us")); <shouldClip>5__2 = true; } else { if (!Features.IsVisibilityEnabled() || !VisibilityTracker.Instance.HasSeenRecently(player)) { goto IL_020d; } SteamHighlightsPlugin.Logger.LogDebug((object)(player.playerUsername + " was seen within the last 20 seconds")); <shouldClip>5__2 = true; } } goto IL_021f; case 1: { <>1__state = -1; SteamTimeline.OpenOverlayToTimelineEvent(<handle>5__6); return false; } IL_020d: SteamHighlightsPlugin.Logger.LogDebug((object)"All conditions for marking the death as a clip failed, skipping clipping."); goto IL_021f; IL_021f: if (!<shouldClip>5__2) { return false; } SteamHighlightsPlugin.Logger.LogDebug((object)("Recording death clip for player: '" + player.playerUsername + "'")); <cause>5__3 = Features.GetCauseOfDeath(player); <priority>5__4 = (((Object)(object)StartOfRound.Instance.localPlayerController == (Object)(object)player) ? 100u : 90u); <clipName>5__5 = player.playerUsername + " died"; if (PluginConfig.RecordingKindConfigEntry.Value == RecordingKind.Marker) { <handle>5__6 = SteamTimeline.AddInstantaneousTimelineEvent(<clipName>5__5, <cause>5__3, "steam_death", <priority>5__4, 0f, (TimelineEventClipPriority)3); } else { <handle>5__6 = SteamTimeline.AddRangeTimelineEvent(<clipName>5__5, <cause>5__3, "steam_death", <priority>5__4, (float)(-PluginConfig.PreDeathDurationConfigEntry.Value), (float)(PluginConfig.PreDeathDurationConfigEntry.Value + PluginConfig.PostDeathDurationConfigEntry.Value), (TimelineEventClipPriority)3); } if (!PluginConfig.OpenOverlayConfigEntry.Value) { return false; } if (PluginConfig.OnlyMyDeathsConfigEntry.Value && (Object)(object)player != (Object)(object)StartOfRound.Instance.localPlayerController) { return false; } <>2__current = (object)new WaitForSecondsRealtime((float)PluginConfig.OverlayDelayConfigEntry.Value); <>1__state = 1; return true; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [HarmonyPostfix] [HarmonyPatch(typeof(StartOfRound), "ReviveDeadPlayers")] private static void ReviveDeadPlayersPostfix() { if (Features.IsEnabled()) { SteamHighlightsPlugin.Logger.LogDebug((object)"ReviveDeadPlayers called, clearing killed players list."); SimpleDeathTracker.Reset(); } } [HarmonyPostfix] [HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")] private static void KillPlayerPostfix(PlayerControllerB __instance) { ((MonoBehaviour)SteamHighlightsPlugin.Instance).StartCoroutine(SaveDeathClip(__instance)); } [HarmonyPostfix] [HarmonyPatch(typeof(PlayerControllerB), "KillPlayerClientRpc")] private static void KillPlayerClientRpcPostfix(int playerId) { PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[playerId]; if (Object.op_Implicit((Object)(object)val) && ((Behaviour)val).isActiveAndEnabled) { ((MonoBehaviour)SteamHighlightsPlugin.Instance).StartCoroutine(SaveDeathClip(val)); } } private static bool IsPlayerNearby(PlayerControllerB targetPlayer, float radius) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)StartOfRound.Instance.localPlayerController).transform.position; Vector3 val = position - ((Component)targetPlayer).transform.position; return ((Vector3)(ref val)).sqrMagnitude <= radius * radius; } [IteratorStateMachine(typeof(<SaveDeathClip>d__4))] private static IEnumerator SaveDeathClip(PlayerControllerB player) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <SaveDeathClip>d__4(0) { player = player }; } } [BepInPlugin("com.smrkn.lethal-company-highlights", "LethalCompanyHighlights", "0.1.8")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class SteamHighlightsPlugin : BaseUnityPlugin { internal static ManualLogSource Logger; private Harmony _harmony; internal static SteamHighlightsPlugin Instance { get; private set; } private void Awake() { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); ((Component)this).gameObject.transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; Instance = this; Logger = ((BaseUnityPlugin)this).Logger; Logger.LogInfo((object)"Plugin LethalCompanyHighlights is loaded!"); LobbyCompatibility.Check(); PluginConfig.Init(((BaseUnityPlugin)this).Config); PluginConfigUI.Init(); if (Object.op_Implicit((Object)(object)GameNetworkManager.Instance) && GameNetworkManager.Instance.disableSteam) { Logger.LogWarning((object)"Steam integration is disabled, if you're playing in LAN mode I'm afraid this mod won't work."); return; } _harmony = new Harmony("com.smrkn.lethal-company-highlights"); _harmony.PatchAll(typeof(RoundPatches)); _harmony.PatchAll(typeof(PlayerPatches)); } private void OnDestroy() { if (Object.op_Implicit((Object)(object)GameNetworkManager.Instance) && !GameNetworkManager.Instance.disableSteam && Features.IsEnabled()) { SteamTimeline.EndGamePhase(); } Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } VisibilityTracker[] array = Object.FindObjectsOfType<VisibilityTracker>(); foreach (VisibilityTracker visibilityTracker in array) { Object.Destroy((Object)(object)visibilityTracker); } } } public static class PluginInfo { public const string PLUGIN_GUID = "com.smrkn.lethal-company-highlights"; public const string PLUGIN_NAME = "LethalCompanyHighlights"; public const string PLUGIN_VERSION = "0.1.8"; } } namespace LethalCompanyHighlights.Utils { internal static class LobbyCompatibility { internal static void Check() { if (Chainloader.PluginInfos.TryGetValue("BMX.LobbyCompatibility", out var value)) { SteamHighlightsPlugin.Logger.LogInfo((object)"LobbyCompatibility detected, attempting to register compatibility info."); try { Assembly assembly = ((object)value.Instance).GetType().Assembly; Type type = assembly.GetType("LobbyCompatibility.Enums.CompatibilityLevel"); Type type2 = assembly.GetType("LobbyCompatibility.Enums.VersionStrictness"); Type type3 = assembly.GetType("LobbyCompatibility.Features.PluginHelper"); MethodInfo methodInfo = type3?.GetMethod("RegisterPlugin", new Type[4] { typeof(string), typeof(Version), type, type2 }); if (type3 != null && methodInfo != null) { object obj = Enum.Parse(type, "ClientOnly"); object obj2 = Enum.Parse(type2, "None"); methodInfo.Invoke(null, new object[4] { "com.smrkn.lethal-company-highlights", Version.Parse("0.1.8"), obj, obj2 }); SteamHighlightsPlugin.Logger.LogInfo((object)"Registered with LobbyCompatibility"); } else { SteamHighlightsPlugin.Logger.LogWarning((object)"LobbyCompatibility.RegisterPlugin method not found."); } return; } catch (Exception arg) { SteamHighlightsPlugin.Logger.LogError((object)$"Failed to register with LobbyCompatibility: {arg}"); return; } } SteamHighlightsPlugin.Logger.LogInfo((object)"LobbyCompatibility not detected, skipping compatibility registration"); } } public class VisibilityTracker : MonoBehaviour { [CompilerGenerated] private sealed class <>c__DisplayClass14_0 { public PlayerControllerB localPlayer; public Func<PlayerControllerB, bool> <>9__0; internal bool <UpdateVisibility>b__0(PlayerControllerB player) { return IsHumanPlayerAlive(player) && (Object)(object)player != (Object)(object)localPlayer && IsPlayerVisible(localPlayer, player, 20f); } } [CompilerGenerated] private sealed class <UpdateVisibility>d__14 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public VisibilityTracker <>4__this; private <>c__DisplayClass14_0 <>8__1; private float <now>5__2; private IEnumerator<KeyValuePair<ulong, float>> <>s__3; private ulong <playerId>5__4; private float <seenAt>5__5; private IEnumerator<ulong> <>s__6; private ulong <playerId>5__7; private IEnumerator<PlayerControllerB> <>s__8; private PlayerControllerB <player>5__9; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <UpdateVisibility>d__14(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>8__1 = null; <>s__3 = null; <>s__6 = null; <>s__8 = null; <player>5__9 = null; <>1__state = -2; } private bool MoveNext() { //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass14_0(); <>8__1.localPlayer = ((Component)<>4__this).GetComponentInParent<PlayerControllerB>(); break; case 1: <>1__state = -1; break; } if (Features.IsVisibilityEnabled() && <>4__this._isRunning && IsHumanPlayerAlive(<>8__1.localPlayer)) { <now>5__2 = Time.unscaledTime; <>s__3 = <>4__this._lastSeen.GetEnumerator(); try { while (<>s__3.MoveNext()) { (<playerId>5__4, <seenAt>5__5) = (KeyValuePair<ulong, float>)(ref <>s__3.Current); if (<now>5__2 - <seenAt>5__5 > 20f) { <>4__this._stalePlayerIds.Add(<playerId>5__4); } } } finally { if (<>s__3 != null) { <>s__3.Dispose(); } } <>s__3 = null; <>s__6 = <>4__this._stalePlayerIds.GetEnumerator(); try { while (<>s__6.MoveNext()) { <playerId>5__7 = <>s__6.Current; <>4__this._lastSeen.Remove(<playerId>5__7); } } finally { if (<>s__6 != null) { <>s__6.Dispose(); } } <>s__6 = null; <>4__this._stalePlayerIds.Clear(); <>s__8 = StartOfRound.Instance.allPlayerScripts.Where((PlayerControllerB player) => IsHumanPlayerAlive(player) && (Object)(object)player != (Object)(object)<>8__1.localPlayer && IsPlayerVisible(<>8__1.localPlayer, player, 20f)).GetEnumerator(); try { while (<>s__8.MoveNext()) { <player>5__9 = <>s__8.Current; <>4__this._lastSeen[<player>5__9.playerClientId] = <now>5__2; <player>5__9 = null; } } finally { if (<>s__8 != null) { <>s__8.Dispose(); } } <>s__8 = null; <>2__current = (object)new WaitForSecondsRealtime(0.5f); <>1__state = 1; return true; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private const float DefaultFieldOfView = 66f; private const float DistanceToCheck = 20f; internal const float SecondsToCheck = 20f; private readonly IDictionary<ulong, float> _lastSeen = new Dictionary<ulong, float>(); private readonly IList<ulong> _stalePlayerIds = new List<ulong>(); private Coroutine _visibilityCoroutine; private bool _isRunning = true; internal static VisibilityTracker Instance { get; private set; } public void Awake() { if (Object.op_Implicit((Object)(object)Instance)) { SteamHighlightsPlugin.Logger.LogWarning((object)"A new instance of VisibilityTracker has been created, destroying the old one."); Object.Destroy((Object)(object)Instance); } Instance = this; } public void Initialize() { _isRunning = true; _visibilityCoroutine = ((MonoBehaviour)this).StartCoroutine(UpdateVisibility()); } private static bool IsPlayerVisible(PlayerControllerB from, PlayerControllerB to, float maxDistance) { //IL_003a: 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) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: 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_011c: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) Vector3 val = (Object.op_Implicit((Object)(object)from.gameplayCamera) ? ((Component)from.gameplayCamera).transform.position : (((Component)from).transform.position + Vector3.up * 0.6f)); Vector3 val2 = (Object.op_Implicit((Object)(object)from.gameplayCamera) ? ((Component)from.gameplayCamera).transform.forward : ((Component)from).transform.forward); Vector3 val3 = ((Component)to).transform.position + Vector3.up * 0.6f; Vector3 val4 = val3 - val; float sqrMagnitude = ((Vector3)(ref val4)).sqrMagnitude; if (sqrMagnitude > maxDistance * maxDistance) { return false; } Vector3 normalized = ((Vector3)(ref val4)).normalized; float num = Vector3.Dot(val2, normalized); float num2 = Mathf.Clamp(Object.op_Implicit((Object)(object)from.gameplayCamera) ? from.gameplayCamera.fieldOfView : 66f, 66f, 150f); float num3 = Mathf.Cos(num2 * 0.5f * (MathF.PI / 180f)); if (num < num3) { return false; } RaycastHit val5 = default(RaycastHit); if (Physics.Linecast(val, val3, ref val5, StartOfRound.Instance.collidersAndRoomMask)) { SteamHighlightsPlugin.Logger.LogDebug((object)("Player '" + to.playerUsername + "' is occluded by something")); return false; } SteamHighlightsPlugin.Logger.LogDebug((object)("Player '" + to.playerUsername + "' is visible")); return true; } [IteratorStateMachine(typeof(<UpdateVisibility>d__14))] private IEnumerator UpdateVisibility() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <UpdateVisibility>d__14(0) { <>4__this = this }; } private static bool IsHumanPlayerAlive(PlayerControllerB player) { return Object.op_Implicit((Object)(object)player) && player.isPlayerControlled && !player.isPlayerDead; } public void StopVisibilityCoroutine() { _isRunning = false; _lastSeen.Clear(); _stalePlayerIds.Clear(); if (_visibilityCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(_visibilityCoroutine); } } public bool HasSeenRecently(PlayerControllerB other, float window = 20f) { float value; return _lastSeen.TryGetValue(other.playerClientId, out value) && Time.unscaledTime - value <= window; } public void OnDestroy() { StopVisibilityCoroutine(); } } } namespace LethalCompanyHighlights.Configuration { internal enum RecordingKind { Marker, Clip } internal static class PluginConfig { internal static ConfigEntry<bool> IsEnabledConfigEntry; internal static ConfigEntry<bool> OpenOverlayConfigEntry; internal static ConfigEntry<bool> OnlyMyDeathsConfigEntry; internal static ConfigEntry<int> OverlayDelayConfigEntry; internal static ConfigEntry<int> PreDeathDurationConfigEntry; internal static ConfigEntry<int> PostDeathDurationConfigEntry; internal static ConfigEntry<RecordingKind> RecordingKindConfigEntry; internal static ConfigEntry<bool> OnlyClipMyDeathsConfigEntry; internal static ConfigEntry<bool> ProximityCheckConfigEntry; internal static ConfigEntry<bool> VisibilityCheckConfigEntry; internal static void Init(ConfigFile config) { IsEnabledConfigEntry = config.Bind<bool>("General", "Enable", true, "Enable Steam to capture highlights."); OpenOverlayConfigEntry = config.Bind<bool>("General", "Open Overlay on Death", true, "Would you like to open the Steam Overlay upon death?"); OnlyMyDeathsConfigEntry = config.Bind<bool>("General", "My Deaths Only", true, "Would you like to open the overlay for all deaths, or just yours?"); OverlayDelayConfigEntry = config.Bind<int>("General", "Overlay Delay", 5, "Delay in seconds before the Steam Overlay will open if enabled.\nMust be between 2 and 60 seconds."); PreDeathDurationConfigEntry = config.Bind<int>("Recording", "Context Duration", 10, "Duration to record prior to death.\nMust be between 5 and 60 seconds."); PostDeathDurationConfigEntry = config.Bind<int>("Recording", "Post-Death Duration", 10, "Duration to record after death.\nMust be between 5 and 60 seconds."); RecordingKindConfigEntry = config.Bind<RecordingKind>("General", "Recording Style", RecordingKind.Clip, "Choose the kind of recording to use.\nMarker: Records a marker for the death event, has pretty icons you can click to jump to.\nDuration not supported. \nClip: Marks a clip of the death event with duration support, easier for one-click sharing. No pretty icons :("); OnlyClipMyDeathsConfigEntry = config.Bind<bool>("Death Capture", "Only Clip My Deaths", false, "Would you like to capture the deaths of other players, or just your own?"); ProximityCheckConfigEntry = config.Bind<bool>("Death Capture", "Proximity Check", true, "Would you like to capture a clip when somebody dies near you?"); VisibilityCheckConfigEntry = config.Bind<bool>("Death Capture", "Visibility Check", true, "Would you like to capture a clip when somebody you've seen within the last 10 seconds dies?"); } } internal static class PluginConfigUI { [CompilerGenerated] private static class <>O { public static CanModifyDelegate <0>__CanModifySettings; public static CanModifyDelegate <1>__CanModifyOverlaySettings; public static CanModifyDelegate <2>__CanModifyDeathCheckSettings; public static CanModifyDelegate <3>__CanModifyDurationSettings; } internal static void Init() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_004f: 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) //IL_005a: Expected O, but got Unknown //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Expected O, but got Unknown //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected O, but got Unknown //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Expected O, but got Unknown //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Expected O, but got Unknown //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Expected O, but got Unknown //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Expected O, but got Unknown //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Expected O, but got Unknown //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Expected O, but got Unknown //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Expected O, but got Unknown //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Expected O, but got Unknown //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Expected O, but got Unknown //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Expected O, but got Unknown //IL_0279: Unknown result type (might be due to invalid IL or missing references) //IL_0280: Expected O, but got Unknown //IL_0285: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Expected O, but got Unknown //IL_0266: 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) //IL_0271: Expected O, but got Unknown //IL_02f0: Unknown result type (might be due to invalid IL or missing references) //IL_02f7: Expected O, but got Unknown //IL_02fc: Unknown result type (might be due to invalid IL or missing references) //IL_0303: Expected O, but got Unknown //IL_02dd: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Expected O, but got Unknown //IL_0364: Unknown result type (might be due to invalid IL or missing references) //IL_036b: Expected O, but got Unknown //IL_0345: Unknown result type (might be due to invalid IL or missing references) //IL_034a: Unknown result type (might be due to invalid IL or missing references) //IL_0350: Expected O, but got Unknown //IL_03d3: Unknown result type (might be due to invalid IL or missing references) //IL_03da: Expected O, but got Unknown //IL_03df: Unknown result type (might be due to invalid IL or missing references) //IL_03e6: Expected O, but got Unknown //IL_03c0: Unknown result type (might be due to invalid IL or missing references) //IL_03c5: Unknown result type (might be due to invalid IL or missing references) //IL_03cb: Expected O, but got Unknown //IL_044e: Unknown result type (might be due to invalid IL or missing references) //IL_0455: Expected O, but got Unknown //IL_043b: Unknown result type (might be due to invalid IL or missing references) //IL_0440: Unknown result type (might be due to invalid IL or missing references) //IL_0446: Expected O, but got Unknown ConfigEntry<bool> isEnabledConfigEntry = PluginConfig.IsEnabledConfigEntry; BoolCheckBoxOptions val = new BoolCheckBoxOptions(); ((BaseOptions)val).Name = "Enable Death Capture"; ((BaseOptions)val).Description = "Enable Steam to capture highlights, you must have Steam running and have Game Recording enabled in the Steam settings."; ((BaseOptions)val).Section = "General"; ((BaseOptions)val).RequiresRestart = false; BoolCheckBoxOptions obj = val; object obj2 = <>O.<0>__CanModifySettings; if (obj2 == null) { CanModifyDelegate val2 = CanModifySettings; <>O.<0>__CanModifySettings = val2; obj2 = (object)val2; } ((BaseOptions)obj).CanModifyCallback = (CanModifyDelegate)obj2; BoolCheckBoxConfigItem val3 = new BoolCheckBoxConfigItem(isEnabledConfigEntry, val); ConfigEntry<bool> openOverlayConfigEntry = PluginConfig.OpenOverlayConfigEntry; val = new BoolCheckBoxOptions(); ((BaseOptions)val).Name = "Open Overlay on Death"; ((BaseOptions)val).Description = "Would you like to open the Steam Overlay upon death?"; ((BaseOptions)val).Section = "Overlay Settings"; ((BaseOptions)val).RequiresRestart = false; BoolCheckBoxOptions obj3 = val; object obj4 = <>O.<0>__CanModifySettings; if (obj4 == null) { CanModifyDelegate val4 = CanModifySettings; <>O.<0>__CanModifySettings = val4; obj4 = (object)val4; } ((BaseOptions)obj3).CanModifyCallback = (CanModifyDelegate)obj4; BoolCheckBoxConfigItem val5 = new BoolCheckBoxConfigItem(openOverlayConfigEntry, val); ConfigEntry<bool> onlyMyDeathsConfigEntry = PluginConfig.OnlyMyDeathsConfigEntry; val = new BoolCheckBoxOptions(); ((BaseOptions)val).Name = "My Deaths Only"; ((BaseOptions)val).Description = "Would you like to open the overlay for all deaths, or just yours?"; ((BaseOptions)val).Section = "Overlay Settings"; ((BaseOptions)val).RequiresRestart = false; BoolCheckBoxOptions obj5 = val; object obj6 = <>O.<1>__CanModifyOverlaySettings; if (obj6 == null) { CanModifyDelegate val6 = CanModifyOverlaySettings; <>O.<1>__CanModifyOverlaySettings = val6; obj6 = (object)val6; } ((BaseOptions)obj5).CanModifyCallback = (CanModifyDelegate)obj6; BoolCheckBoxConfigItem val7 = new BoolCheckBoxConfigItem(onlyMyDeathsConfigEntry, val); ConfigEntry<int> overlayDelayConfigEntry = PluginConfig.OverlayDelayConfigEntry; IntSliderOptions val8 = new IntSliderOptions(); ((BaseOptions)val8).Name = "Overlay Delay"; ((BaseOptions)val8).Description = "Delay in seconds before the Steam Overlay will open if enabled.\nMust be between 2 and 60 seconds."; ((BaseOptions)val8).Section = "Overlay Settings"; ((BaseRangeOptions<int>)(object)val8).Min = 2; ((BaseRangeOptions<int>)(object)val8).Max = 60; ((BaseOptions)val8).RequiresRestart = false; IntSliderOptions obj7 = val8; object obj8 = <>O.<1>__CanModifyOverlaySettings; if (obj8 == null) { CanModifyDelegate val9 = CanModifyOverlaySettings; <>O.<1>__CanModifyOverlaySettings = val9; obj8 = (object)val9; } ((BaseOptions)obj7).CanModifyCallback = (CanModifyDelegate)obj8; IntSliderConfigItem val10 = new IntSliderConfigItem(overlayDelayConfigEntry, val8); ConfigEntry<bool> onlyClipMyDeathsConfigEntry = PluginConfig.OnlyClipMyDeathsConfigEntry; val = new BoolCheckBoxOptions(); ((BaseOptions)val).Name = "Only Clip My Deaths"; ((BaseOptions)val).Description = "Would you like to capture the deaths of other players, or just your own?"; ((BaseOptions)val).Section = "Death Capture"; ((BaseOptions)val).RequiresRestart = false; BoolCheckBoxOptions obj9 = val; object obj10 = <>O.<0>__CanModifySettings; if (obj10 == null) { CanModifyDelegate val11 = CanModifySettings; <>O.<0>__CanModifySettings = val11; obj10 = (object)val11; } ((BaseOptions)obj9).CanModifyCallback = (CanModifyDelegate)obj10; BoolCheckBoxConfigItem val12 = new BoolCheckBoxConfigItem(onlyClipMyDeathsConfigEntry, val); ConfigEntry<bool> proximityCheckConfigEntry = PluginConfig.ProximityCheckConfigEntry; val = new BoolCheckBoxOptions(); ((BaseOptions)val).Name = "Proximity Check"; ((BaseOptions)val).Description = "Would you like to capture a clip when somebody dies near you?"; ((BaseOptions)val).Section = "Death Capture"; ((BaseOptions)val).RequiresRestart = false; BoolCheckBoxOptions obj11 = val; object obj12 = <>O.<2>__CanModifyDeathCheckSettings; if (obj12 == null) { CanModifyDelegate val13 = CanModifyDeathCheckSettings; <>O.<2>__CanModifyDeathCheckSettings = val13; obj12 = (object)val13; } ((BaseOptions)obj11).CanModifyCallback = (CanModifyDelegate)obj12; BoolCheckBoxConfigItem val14 = new BoolCheckBoxConfigItem(proximityCheckConfigEntry, val); ConfigEntry<bool> visibilityCheckConfigEntry = PluginConfig.VisibilityCheckConfigEntry; val = new BoolCheckBoxOptions(); ((BaseOptions)val).Name = "Visibility Check"; ((BaseOptions)val).Description = $"Would you like to capture a clip when somebody you've seen within the last {20f} seconds dies?"; ((BaseOptions)val).Section = "Death Capture"; ((BaseOptions)val).RequiresRestart = false; BoolCheckBoxOptions obj13 = val; object obj14 = <>O.<2>__CanModifyDeathCheckSettings; if (obj14 == null) { CanModifyDelegate val15 = CanModifyDeathCheckSettings; <>O.<2>__CanModifyDeathCheckSettings = val15; obj14 = (object)val15; } ((BaseOptions)obj13).CanModifyCallback = (CanModifyDelegate)obj14; BoolCheckBoxConfigItem val16 = new BoolCheckBoxConfigItem(visibilityCheckConfigEntry, val); ConfigEntry<RecordingKind> recordingKindConfigEntry = PluginConfig.RecordingKindConfigEntry; EnumDropDownOptions val17 = new EnumDropDownOptions(); ((BaseOptions)val17).Name = "Recording Style"; ((BaseOptions)val17).Description = "Choose the kind of recording to use.\n\nMarker: Records a marker for the death event, has pretty icons you can click to jump to.\nDuration not supported. \n\nClip: Marks a clip of the death event with duration support, easier for one-click sharing.\nNo pretty icons :("; ((BaseOptions)val17).Section = "General"; ((BaseOptions)val17).RequiresRestart = false; object obj15 = <>O.<0>__CanModifySettings; if (obj15 == null) { CanModifyDelegate val18 = CanModifySettings; <>O.<0>__CanModifySettings = val18; obj15 = (object)val18; } ((BaseOptions)val17).CanModifyCallback = (CanModifyDelegate)obj15; EnumDropDownConfigItem<RecordingKind> val19 = new EnumDropDownConfigItem<RecordingKind>(recordingKindConfigEntry, val17); ConfigEntry<int> preDeathDurationConfigEntry = PluginConfig.PreDeathDurationConfigEntry; val8 = new IntSliderOptions(); ((BaseOptions)val8).Name = "Context Duration"; ((BaseOptions)val8).Description = "Duration to record prior to death.\nMust be between 5 and 60 seconds."; ((BaseOptions)val8).Section = "Recording"; ((BaseRangeOptions<int>)(object)val8).Min = 5; ((BaseRangeOptions<int>)(object)val8).Max = 60; ((BaseOptions)val8).RequiresRestart = false; IntSliderOptions obj16 = val8; object obj17 = <>O.<3>__CanModifyDurationSettings; if (obj17 == null) { CanModifyDelegate val20 = CanModifyDurationSettings; <>O.<3>__CanModifyDurationSettings = val20; obj17 = (object)val20; } ((BaseOptions)obj16).CanModifyCallback = (CanModifyDelegate)obj17; IntSliderConfigItem val21 = new IntSliderConfigItem(preDeathDurationConfigEntry, val8); ConfigEntry<int> postDeathDurationConfigEntry = PluginConfig.PostDeathDurationConfigEntry; val8 = new IntSliderOptions(); ((BaseOptions)val8).Name = "Post-Death Duration"; ((BaseOptions)val8).Description = "Duration to record after death.\nMust be between 5 and 60 seconds."; ((BaseOptions)val8).Section = "Recording"; ((BaseRangeOptions<int>)(object)val8).Min = 5; ((BaseRangeOptions<int>)(object)val8).Max = 60; ((BaseOptions)val8).RequiresRestart = false; IntSliderOptions obj18 = val8; object obj19 = <>O.<3>__CanModifyDurationSettings; if (obj19 == null) { CanModifyDelegate val22 = CanModifyDurationSettings; <>O.<3>__CanModifyDurationSettings = val22; obj19 = (object)val22; } ((BaseOptions)obj18).CanModifyCallback = (CanModifyDelegate)obj19; IntSliderConfigItem val23 = new IntSliderConfigItem(postDeathDurationConfigEntry, val8); LethalConfigManager.SkipAutoGen(); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val3); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val5); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val7); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val10); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val12); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val14); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val16); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val19); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val21); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val23); } private static CanModifyResult CanModifyOverlaySettings() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) if (SteamUtils.IsOverlayEnabled && PluginConfig.OpenOverlayConfigEntry.Value) { return CanModifyResult.True(); } return CanModifyResult.False("Steam Overlay is disabled or you have not enabled the option to open the overlay on death."); } private static CanModifyResult CanModifyDurationSettings() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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) RecordingKind value = PluginConfig.RecordingKindConfigEntry.Value; if (1 == 0) { } CanModifyResult result = (CanModifyResult)(value switch { RecordingKind.Marker => CanModifyResult.False("Duration settings are not applicable for Marker recordings."), RecordingKind.Clip => CanModifyResult.True(), _ => CanModifyResult.False("Unknown recording kind selected."), }); if (1 == 0) { } return result; } private static CanModifyResult CanModifyDeathCheckSettings() { //IL_001e: 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_0015: 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_0026: Unknown result type (might be due to invalid IL or missing references) if (PluginConfig.OnlyClipMyDeathsConfigEntry.Value) { return CanModifyResult.False("You must disable 'Only Clip My Deaths' to use this feature."); } return CanModifyResult.True(); } private static CanModifyResult CanModifySettings() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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_002b: Unknown result type (might be due to invalid IL or missing references) if (SteamClient.IsValid && SteamUtils.IsOverlayEnabled) { return CanModifyResult.True(); } return CanModifyResult.False("Steam is not running or the Steam Overlay is disabled."); } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }