using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("DenisUIKillFeed")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+0d77aba4ef99a87d6be4daeb81b0de1f2e0c0dca")] [assembly: AssemblyProduct("DenisUIKillFeed")] [assembly: AssemblyTitle("DenisUIKillFeed")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace DenisUIKillFeed { internal static class EnemyFeedTracker { internal static Enemy GetEnemyFromParent(EnemyParent enemyParent) { try { object? obj = Plugin.EnemyParentEnemyField?.GetValue(enemyParent); return (Enemy)((obj is Enemy) ? obj : null); } catch { return null; } } internal static bool GetParentSpawned(EnemyParent enemyParent) { try { object obj = Plugin.EnemyParentSpawnedField?.GetValue(enemyParent); if (obj is bool) { bool result = (bool)obj; if (true) { return result; } } } catch { } return true; } internal static bool GetEnemyHasHealth(Enemy enemy) { try { if ((Object)(object)enemy == (Object)null) { return false; } object obj = Plugin.EnemyHasHealthField?.GetValue(enemy); if (obj is bool) { bool result = (bool)obj; if (true) { return result; } } } catch { } return false; } internal static EnemyHealth GetEnemyHealth(Enemy enemy) { try { object? obj = Plugin.EnemyHealthRefField?.GetValue(enemy); return (EnemyHealth)((obj is EnemyHealth) ? obj : null); } catch { return null; } } internal static int GetEnemyHealthCurrent(EnemyHealth health) { try { if ((Object)(object)health == (Object)null) { return 0; } object obj = Plugin.EnemyHealthCurrentField?.GetValue(health); if (obj is int) { int result = (int)obj; if (true) { return result; } } } catch { } return 0; } internal static bool GetEnemyHealthDead(EnemyHealth health) { try { if ((Object)(object)health == (Object)null) { return false; } object obj = Plugin.EnemyHealthDeadField?.GetValue(health); if (obj is bool) { bool result = (bool)obj; if (true) { return result; } } } catch { } return false; } internal static float GetMapValueTotal() { return 0f; } internal static bool EnemyShouldRequireOrbConfirmation(string enemyName) { return !Plugin.NoOrbEnemyNames.Contains(enemyName); } internal static void SeedSeenValuables() { ValuableObject[] array = Object.FindObjectsOfType(); if (array == null) { return; } ValuableObject[] array2 = array; foreach (ValuableObject val in array2) { if ((Object)(object)val != (Object)null) { Plugin.SeenValuableIds.Add(((Object)((Component)val).gameObject).GetInstanceID()); } } } internal static bool ObserveNewEnemyOrbFor(string enemyName, float mapValueBeforeDeath) { ValuableObject[] array = Object.FindObjectsOfType(); if (array == null) { return false; } bool flag = EnemyShouldRequireOrbConfirmation(enemyName); float mapValueTotal = GetMapValueTotal(); ValuableObject[] array2 = array; foreach (ValuableObject val in array2) { if ((Object)(object)val == (Object)null) { continue; } int instanceID = ((Object)((Component)val).gameObject).GetInstanceID(); if (!Plugin.SeenValuableIds.Contains(instanceID)) { Plugin.SeenValuableIds.Add(instanceID); string text = ((Object)((Component)val).gameObject).name ?? string.Empty; if (text.IndexOf("Enemy Valuable", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } } return !flag && mapValueTotal > mapValueBeforeDeath; } internal static void ObserveEnemiesFromDirector() { //IL_0667: Unknown result type (might be due to invalid IL or missing references) //IL_0494: Unknown result type (might be due to invalid IL or missing references) HashSet seen = new HashSet(); try { EnemyDirector instance = EnemyDirector.instance; if ((Object)(object)instance == (Object)null || instance.enemiesSpawned == null) { return; } foreach (EnemyParent item in instance.enemiesSpawned) { if ((Object)(object)item == (Object)null) { continue; } int instanceID = ((Object)item).GetInstanceID(); seen.Add(instanceID); string text = (string.IsNullOrWhiteSpace(item.enemyName) ? "Enemy" : item.enemyName); Enemy enemyFromParent = GetEnemyFromParent(item); bool parentSpawned = GetParentSpawned(item); EnemyHealth enemyHealth = GetEnemyHealth(enemyFromParent); bool flag = (Object)(object)enemyHealth != (Object)null && GetEnemyHasHealth(enemyFromParent); int num = (flag ? GetEnemyHealthCurrent(enemyHealth) : 0); bool flag2 = flag && (GetEnemyHealthDead(enemyHealth) || num <= 0); bool flag3 = flag2 || !parentSpawned; if (!Plugin.EnemyStates.TryGetValue(instanceID, out var value)) { Plugin.EnemyStates[instanceID] = new ObservedEnemyState { EnemyParent = item, Name = text, WasDead = flag3, LastHealth = num, FirstSeenAt = Time.time, AliveSince = ((!flag3 && parentSpawned) ? Time.time : (-1f)), PendingDeathSince = (flag3 ? Time.time : (-1f)), DeathAnnounced = false, Spawned = parentSpawned, HasEnteredStableAlivePhase = false, HadAliveHealthSample = (!flag3 && num > 0), HadDamageEvidence = false }; continue; } value.EnemyParent = item; value.Name = text; value.Spawned = parentSpawned; bool flag4 = Time.time - value.FirstSeenAt >= 1f; bool flag5 = Time.time - value.FirstSeenAt < 1f; if (!flag3 && parentSpawned) { if (value.AliveSince < 0f) { value.AliveSince = Time.time; } if (num > 0) { value.HadAliveHealthSample = true; } if (value.LastHealth > 0 && num > 0 && num < value.LastHealth) { value.HadDamageEvidence = true; } if (!value.HasEnteredStableAlivePhase && value.AliveSince >= 0f && Time.time - value.AliveSince >= 0.35f) { value.HasEnteredStableAlivePhase = true; } } bool flag6 = EnemyShouldRequireOrbConfirmation(text); bool flag7 = !flag6 && value.HadAliveHealthSample && (flag2 || value.HadDamageEvidence || (value.LastHealth > 0 && num <= 0)); if (!value.WasDead && flag3) { if (flag4 && !flag5 && value.HasEnteredStableAlivePhase && (flag6 || flag7)) { value.PendingDeathSince = Time.time; value.MapValueBeforeDeath = GetMapValueTotal(); value.OrbConfirmed = false; } else { value.PendingDeathSince = -1f; value.OrbConfirmed = false; } } else if (!flag3) { value.PendingDeathSince = -1f; value.DeathAnnounced = false; value.OrbConfirmed = false; } if (!value.DeathAnnounced && flag4 && flag3 && value.PendingDeathSince >= 0f && Time.time - value.PendingDeathSince >= 0.2f) { if (!value.OrbConfirmed) { value.OrbConfirmed = ObserveNewEnemyOrbFor(text, value.MapValueBeforeDeath); } bool flag8 = !flag6 && flag7; bool flag9 = value.LastAnnouncementAt <= 0f || Time.time - value.LastAnnouncementAt >= 6f; if ((value.OrbConfirmed || flag8) && flag9) { if (Plugin.ShowEnemyKillsConfig.Value && Time.time - Plugin.LevelStartTime >= 1f) { Plugin.AddEntry(text + " killed", new Color(0.96f, 0.82f, 0.28f, 1f)); } value.DeathAnnounced = true; value.LastAnnouncementAt = Time.time; } } value.WasDead = flag3; value.LastHealth = num; } } catch (Exception arg) { Debug.LogError((object)$"[DenisUIKillFeed] ObserveEnemiesFromDirector error: {arg}"); } List list = Plugin.EnemyStates.Keys.Where((int id) => !seen.Contains(id)).ToList(); foreach (int item2 in list) { ObservedEnemyState observedEnemyState = Plugin.EnemyStates[item2]; bool flag10 = Time.time - observedEnemyState.FirstSeenAt >= 1f; if (!observedEnemyState.DeathAnnounced && flag10 && observedEnemyState.PendingDeathSince >= 0f) { if (!observedEnemyState.OrbConfirmed) { observedEnemyState.OrbConfirmed = ObserveNewEnemyOrbFor(observedEnemyState.Name, observedEnemyState.MapValueBeforeDeath); } bool flag11 = !EnemyShouldRequireOrbConfirmation(observedEnemyState.Name) && observedEnemyState.HadAliveHealthSample && observedEnemyState.HadDamageEvidence; bool flag12 = observedEnemyState.LastAnnouncementAt <= 0f || Time.time - observedEnemyState.LastAnnouncementAt >= 6f; if ((observedEnemyState.OrbConfirmed || flag11) && flag12) { if (Plugin.ShowEnemyKillsConfig.Value && Time.time - Plugin.LevelStartTime >= 1f) { Plugin.AddEntry(observedEnemyState.Name + " killed", new Color(0.96f, 0.82f, 0.28f, 1f)); } observedEnemyState.LastAnnouncementAt = Time.time; } } Plugin.EnemyStates.Remove(item2); } } } [HarmonyPatch(typeof(RoundDirector))] internal static class KillFeedHud { [HarmonyPatch("Update")] [HarmonyPostfix] private static void Update_Postfix() { bool flag = SemiFunc.RunIsLevel(); if (flag) { Plugin.LastLevelActiveAt = Time.time; } if (!EnsureHud()) { return; } if (!flag) { if (Time.time - Plugin.LastLevelActiveAt <= 8f) { UpdateKillFeedHud(); return; } SetInactive(); Plugin.ResetObservedState(); } else { PlayerFeedTracker.ObservePlayers(); EnemyFeedTracker.ObserveEnemiesFromDirector(); UpdateKillFeedHud(); } } internal static bool EnsureHud() { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) GameObject val = GameObject.Find("Game Hud"); GameObject val2 = GameObject.Find("Tax Haul"); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { return false; } TMP_Text component = val2.GetComponent(); TMP_FontAsset val3 = ((component != null) ? component.font : null); if ((Object)(object)val3 == (Object)null) { return false; } if ((Object)(object)Plugin.FeedInstance == (Object)null) { Plugin.FeedInstance = new GameObject("Denis UI Killfeed HUD"); Plugin.FeedInstance.SetActive(false); Plugin.FeedInstance.transform.SetParent(val.transform, false); Plugin.FeedText = Plugin.FeedInstance.AddComponent(); ((TMP_Text)Plugin.FeedText).font = val3; ((TMP_Text)Plugin.FeedText).fontSize = 24f; ((TMP_Text)Plugin.FeedText).enableWordWrapping = false; ((TMP_Text)Plugin.FeedText).alignment = (TextAlignmentOptions)260; ((TMP_Text)Plugin.FeedText).horizontalAlignment = (HorizontalAlignmentOptions)4; ((TMP_Text)Plugin.FeedText).verticalAlignment = (VerticalAlignmentOptions)256; ((Graphic)Plugin.FeedText).raycastTarget = false; ((TMP_Text)Plugin.FeedText).margin = Vector4.zero; ((TMP_Text)Plugin.FeedText).characterSpacing = 0f; ((TMP_Text)Plugin.FeedText).wordSpacing = 0f; ((TMP_Text)Plugin.FeedText).fontStyle = (FontStyles)0; ContentSizeFitter val4 = Plugin.FeedInstance.AddComponent(); val4.verticalFit = (FitMode)2; val4.horizontalFit = (FitMode)0; RectTransform component2 = Plugin.FeedInstance.GetComponent(); component2.pivot = new Vector2(1f, 1f); component2.anchorMin = new Vector2(1f, 1f); component2.anchorMax = new Vector2(1f, 1f); component2.sizeDelta = new Vector2(520f, 220f); component2.anchoredPosition = new Vector2(-10f, -250f); } else if ((Object)(object)Plugin.FeedText != (Object)null && (Object)(object)((TMP_Text)Plugin.FeedText).transform.parent != (Object)(object)val.transform) { ((TMP_Text)Plugin.FeedText).transform.SetParent(val.transform, false); } return true; } internal static void UpdateKillFeedHud() { //IL_0101: Unknown result type (might be due to invalid IL or missing references) Plugin.Entries.RemoveAll((KillFeedEntry e) => Time.time > e.ExpiresAt); if (Plugin.Entries.Count == 0) { Plugin.FeedInstance.SetActive(false); Plugin.LastRenderedFeedText = string.Empty; Plugin.LastRenderedFontSize = -1f; Plugin.HudShowStartedAt = -100000f; return; } bool activeSelf = Plugin.FeedInstance.activeSelf; Plugin.FeedInstance.SetActive(true); if (!activeSelf) { Plugin.HudShowStartedAt = Time.time; } RectTransform component = Plugin.FeedInstance.GetComponent(); float num = Mathf.Max(0f, Time.time - Plugin.HudShowStartedAt); float num2 = Mathf.Clamp01(num / 0.18f); float num3 = 1f - Mathf.Pow(1f - num2, 3f); float num4 = Mathf.Lerp(24f, 0f, num3); component.anchoredPosition = new Vector2(-10f + num4, -250f); int num5 = Plugin.Entries.Max((KillFeedEntry e) => e.Text.Length); int num6 = Mathf.Clamp((num5 - 1) / 46, 0, 3); float num7 = Mathf.Clamp(Plugin.TextScaleConfig?.Value ?? 1f, 0.7f, 1f); float num8 = Plugin.MobHudSizes[num6] * num7; if (!Mathf.Approximately(Plugin.LastRenderedFontSize, num8)) { ((TMP_Text)Plugin.FeedText).fontSize = num8; ((TMP_Text)Plugin.FeedText).lineSpacing = (0f - num8) * 1.05f; Plugin.LastRenderedFontSize = num8; } StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < Plugin.Entries.Count; i++) { KillFeedEntry killFeedEntry = Plugin.Entries[i]; if (i > 0) { stringBuilder.Append('\n'); } float num9 = Mathf.Max(0f, Time.time - killFeedEntry.CreatedAt); float num10 = Mathf.Max(0f, killFeedEntry.ExpiresAt - Time.time); float num11 = Mathf.Clamp01(num9 / 0.16f); float num12 = Mathf.Clamp01(num10 / 0.24f); float num13 = Mathf.Min(num11, num12); string value = Mathf.Clamp(Mathf.RoundToInt(num13 * 255f), 0, 255).ToString("X2"); stringBuilder.Append("') .Append(killFeedEntry.Text) .Append(""); } string text = stringBuilder.ToString(); if (text != Plugin.LastRenderedFeedText) { ((TMP_Text)Plugin.FeedText).text = text; Plugin.LastRenderedFeedText = text; } } internal static void SetInactive() { if ((Object)(object)Plugin.FeedInstance != (Object)null) { Plugin.FeedInstance.SetActive(false); } } } internal sealed class KillFeedEntry { public string Text; public string Color; public float ExpiresAt; public float CreatedAt; } internal sealed class ObservedPlayerState { public PlayerAvatar Avatar; public string Name; public bool WasDead; public float LastDeathAt; } internal sealed class PendingDisconnectState { public string Name; public float MissingSince; public bool HadRecentDeath; } internal sealed class ObservedEnemyState { public EnemyParent EnemyParent; public string Name; public bool WasDead; public int LastHealth; public float FirstSeenAt; public float PendingDeathSince; public bool DeathAnnounced; public bool Spawned; public float MapValueBeforeDeath; public bool OrbConfirmed; public float AliveSince; public bool HasEnteredStableAlivePhase; public bool HadAliveHealthSample; public bool HadDamageEvidence; public float LastAnnouncementAt; } internal static class PlayerFeedTracker { [HarmonyPatch(typeof(PlayerAvatar), "PlayerDeathRPC")] internal static class PlayerAvatarDeathPatch { [HarmonyPostfix] private static void Postfix(PlayerAvatar __instance) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) string text = ResolvePlayerName(__instance); string item = SanitizeDisplayName(text); if (!Plugin.PlayersWithDisconnectFeed.Contains(item) && Plugin.ShowPlayerDeathsConfig.Value && Time.time - Plugin.LevelStartTime >= 1f) { Plugin.AddEntry(text + " died", new Color(0.7f, 0.23f, 0.23f, 1f)); } int num = (((Object)(object)__instance != (Object)null) ? ((Object)__instance).GetInstanceID() : 0); if (num != 0 && Plugin.PlayerStates.TryGetValue(num, out var value)) { value.WasDead = true; value.LastDeathAt = Time.time; } } } internal static string ResolvePlayerName(PlayerAvatar avatar) { if ((Object)(object)avatar == (Object)null) { return "Player"; } try { string raw = Plugin.PlayerNameField?.GetValue(avatar) as string; raw = SanitizeDisplayName(raw); if (!string.IsNullOrWhiteSpace(raw)) { return raw; } } catch { } return SanitizeDisplayName((!string.IsNullOrWhiteSpace(((Object)avatar).name)) ? ((Object)avatar).name : "Player"); } internal static string SanitizeDisplayName(string raw) { if (string.IsNullOrEmpty(raw)) { return raw; } StringBuilder stringBuilder = new StringBuilder(raw.Length); foreach (char c in raw) { if (!char.IsControl(c)) { UnicodeCategory unicodeCategory = CharUnicodeInfo.GetUnicodeCategory(c); if (unicodeCategory != UnicodeCategory.Format) { stringBuilder.Append(c); } } } return stringBuilder.ToString().Trim(); } internal static bool IsPlayerDead(PlayerAvatar avatar) { if ((Object)(object)avatar == (Object)null) { return false; } try { object obj = Plugin.PlayerDeadSetField?.GetValue(avatar); if (obj is bool) { bool result = (bool)obj; if (true) { return result; } } } catch { } return false; } internal static void ObservePlayers() { //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_03fe: Unknown result type (might be due to invalid IL or missing references) HashSet seen = new HashSet(); try { List list = SemiFunc.PlayerGetAll(); if (list == null) { return; } foreach (PlayerAvatar item2 in list) { if ((Object)(object)item2 == (Object)null) { continue; } int instanceID = ((Object)item2).GetInstanceID(); seen.Add(instanceID); string text = ResolvePlayerName(item2); bool flag = IsPlayerDead(item2); if (!Plugin.PlayerStates.TryGetValue(instanceID, out var value)) { value = new ObservedPlayerState { Avatar = item2, Name = text, WasDead = flag }; Plugin.PlayerStates[instanceID] = value; } else { value.Avatar = item2; value.Name = text; } Plugin.PlayerStatesByName[text] = value; Plugin.PendingDisconnects.Remove(text); if (!value.WasDead && flag) { string item = SanitizeDisplayName(text); if (!Plugin.PlayersWithDisconnectFeed.Contains(item) && Plugin.ShowPlayerDeathsConfig.Value && Time.time - Plugin.LevelStartTime >= 1f) { Plugin.AddEntry(text + " died", new Color(0.7f, 0.23f, 0.23f, 1f)); } value.LastDeathAt = Time.time; } value.WasDead = flag; } } catch (Exception arg) { Debug.LogError((object)$"[DenisUIKillFeed] ObservePlayers error: {arg}"); } List list2 = Plugin.PlayerStates.Keys.Where((int id) => !seen.Contains(id)).ToList(); foreach (int item3 in list2) { ObservedPlayerState observedPlayerState = Plugin.PlayerStates[item3]; if (observedPlayerState != null && !string.IsNullOrWhiteSpace(observedPlayerState.Name) && !Plugin.SceneResetInProgress) { bool hadRecentDeath = observedPlayerState.LastDeathAt > 0f && Time.time - observedPlayerState.LastDeathAt <= 2.5f; string text2 = SanitizeDisplayName(observedPlayerState.Name); if (!string.IsNullOrWhiteSpace(text2) && !Plugin.PendingDisconnects.ContainsKey(text2)) { Plugin.PendingDisconnects[text2] = new PendingDisconnectState { Name = text2, MissingSince = Time.time, HadRecentDeath = hadRecentDeath }; } } if (observedPlayerState != null && !string.IsNullOrWhiteSpace(observedPlayerState.Name)) { Plugin.PlayerStatesByName.Remove(observedPlayerState.Name); } Plugin.PlayerStates.Remove(item3); } List list3 = Plugin.PendingDisconnects.Keys.ToList(); foreach (string item4 in list3) { if (Plugin.PlayerStatesByName.ContainsKey(item4)) { Plugin.PendingDisconnects.Remove(item4); } else { if (Time.time - Plugin.LevelStartTime < 4f) { continue; } PendingDisconnectState pendingDisconnectState = Plugin.PendingDisconnects[item4]; if (Time.time - pendingDisconnectState.MissingSince < 1.25f) { continue; } if (Plugin.RecentlyDisconnectedPlayers.Add(pendingDisconnectState.Name)) { if (Plugin.ShowDisconnectsConfig.Value) { Plugin.AddEntry(pendingDisconnectState.Name + " disconnected", new Color(0.58f, 0.58f, 0.62f, 1f)); } Plugin.PlayersWithDisconnectFeed.Add(pendingDisconnectState.Name); } Plugin.PendingDisconnects.Remove(item4); } } if (Plugin.SceneResetInProgress && seen.Count > 0) { Plugin.SceneResetInProgress = false; } } } [BepInPlugin("denis.repo.denisuikillfeed", "Denis UI Killfeed", "1.1.0")] public class Plugin : BaseUnityPlugin { internal static GameObject FeedInstance; internal static TextMeshProUGUI FeedText; internal static readonly List Entries = new List(); internal static readonly Dictionary PlayerStates = new Dictionary(); internal static readonly Dictionary PlayerStatesByName = new Dictionary(StringComparer.OrdinalIgnoreCase); internal static readonly HashSet RecentlyDisconnectedPlayers = new HashSet(StringComparer.OrdinalIgnoreCase); internal static readonly HashSet PlayersWithDisconnectFeed = new HashSet(StringComparer.OrdinalIgnoreCase); internal static readonly Dictionary PendingDisconnects = new Dictionary(StringComparer.OrdinalIgnoreCase); internal static readonly Dictionary EnemyStates = new Dictionary(); internal static readonly HashSet SeenValuableIds = new HashSet(); internal static readonly HashSet NoOrbEnemyNames = new HashSet(StringComparer.OrdinalIgnoreCase) { "Gnome", "Banger", "Tick" }; internal static readonly float[] MobHudSizes = new float[4] { 24f, 18f, 14f, 11f }; internal static bool SceneResetInProgress; internal static float LastLevelActiveAt; internal static float LevelStartTime; internal static float HudShowStartedAt = -100000f; internal static string LastRenderedFeedText = string.Empty; internal static float LastRenderedFontSize = -1f; internal static readonly FieldInfo PlayerNameField = typeof(PlayerAvatar).GetField("playerName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); internal static readonly FieldInfo PlayerDeadSetField = typeof(PlayerAvatar).GetField("deadSet", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); internal static readonly FieldInfo EnemyParentEnemyField = typeof(EnemyParent).GetField("Enemy", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? typeof(EnemyParent).GetField("enemy", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); internal static readonly FieldInfo EnemyParentSpawnedField = typeof(EnemyParent).GetField("Spawned", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? typeof(EnemyParent).GetField("spawned", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); internal static readonly FieldInfo EnemyHasHealthField = typeof(Enemy).GetField("HasHealth", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? typeof(Enemy).GetField("hasHealth", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); internal static readonly FieldInfo EnemyHealthRefField = typeof(Enemy).GetField("Health", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? typeof(Enemy).GetField("health", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); internal static readonly FieldInfo EnemyHealthCurrentField = typeof(EnemyHealth).GetField("healthCurrent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); internal static readonly FieldInfo EnemyHealthDeadField = typeof(EnemyHealth).GetField("dead", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); internal static ConfigEntry ShowEnemyKillsConfig; internal static ConfigEntry ShowPlayerDeathsConfig; internal static ConfigEntry ShowDisconnectsConfig; internal static ConfigEntry TextScaleConfig; internal const float HudGraceAfterLevelEnds = 8f; internal const float DisconnectConfirmSeconds = 1.25f; internal const float DisconnectStartupGuardSeconds = 4f; internal const float SpawnGraceSeconds = 1f; internal const float AliveStableSeconds = 0.35f; internal const float EnemyAnnouncementCooldownSeconds = 6f; internal const float HudSlideSeconds = 0.18f; internal const float EntryFadeInSeconds = 0.16f; internal const float EntryFadeOutSeconds = 0.24f; internal static Plugin Instance { get; private set; } internal Harmony Harmony { get; private set; } private void Awake() { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected O, but got Unknown Instance = this; ((Component)this).transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; TextScaleConfig = ((BaseUnityPlugin)this).Config.Bind("Killfeed Activity", "Text Scale", 1f, new ConfigDescription("Scales the killfeed text size.", (AcceptableValueBase)(object)new AcceptableValueRange(0.7f, 1f), Array.Empty())); ShowEnemyKillsConfig = ((BaseUnityPlugin)this).Config.Bind("Killfeed Activity", "Enemy deaths", true, "Show enemy death events in the killfeed."); ShowPlayerDeathsConfig = ((BaseUnityPlugin)this).Config.Bind("Killfeed Activity", "Player deaths", true, "Show player death events in the killfeed."); ShowDisconnectsConfig = ((BaseUnityPlugin)this).Config.Bind("Killfeed Activity", "Player disconnects", true, "Show player disconnect events in the killfeed."); Harmony = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID); Harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Denis UI Killfeed loaded"); } private void OnDestroy() { Harmony harmony = Harmony; if (harmony != null) { harmony.UnpatchSelf(); } } internal static void AddEntry(string text, Color color) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) string text2 = ColorUtility.ToHtmlStringRGB(color); if (Entries.Count > 0) { KillFeedEntry killFeedEntry = Entries[0]; if (killFeedEntry.Text == text && killFeedEntry.Color == text2 && Time.time - killFeedEntry.CreatedAt <= 0.35f) { killFeedEntry.ExpiresAt = Time.time + 7f; return; } } Entries.Insert(0, new KillFeedEntry { Text = text, Color = text2, ExpiresAt = Time.time + 7f, CreatedAt = Time.time }); if (Entries.Count > 5) { Entries.RemoveRange(5, Entries.Count - 5); } } internal static void ResetObservedState() { PlayerStates.Clear(); PlayerStatesByName.Clear(); EnemyStates.Clear(); SeenValuableIds.Clear(); RecentlyDisconnectedPlayers.Clear(); PlayersWithDisconnectFeed.Clear(); PendingDisconnects.Clear(); SceneResetInProgress = true; LevelStartTime = Time.time; HudShowStartedAt = -100000f; LastRenderedFeedText = string.Empty; LastRenderedFontSize = -1f; } } }