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 DamageLog v1.2.10
plugins/DamageLog/DamageLog.dll
Decompiled 4 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using RoR2; using RoR2.UI; using TMPro; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.Networking; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("DamageLog")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.2.10.0")] [assembly: AssemblyInformationalVersion("1.2.10+1e09b59c54a44fba7212c74822039aaa249fb6c4")] [assembly: AssemblyProduct("DamageLog")] [assembly: AssemblyTitle("DamageLog")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.2.10.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 DamageLog { internal sealed class BossDamageLog : DamageLog { public readonly uint targetNetId; public override string displayName => $"<style=cStack>{targetNetId:x8}</style> <style=cIsHealth>{base.displayName}</style>"; public override string loggingName => $"{base.loggingName} <{targetNetId:x8}>"; public BossDamageLog(CharacterBody body) { //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) NetworkInstanceId netId = ((NetworkBehaviour)body).netId; targetNetId = ((NetworkInstanceId)(ref netId)).Value; base..ctor(body, Util.GetBestBodyName(((Component)body).gameObject)); } public override bool IsExpired(float elapsedTime) { return false; } public static bool IsIgnoredBossSubtitle(string subtitleNameToken) { if (string.IsNullOrEmpty(subtitleNameToken)) { return true; } switch (subtitleNameToken) { default: return false; case "NULL_SUBTITLE": case "LUNARWISP_BODY_SUBTITLE": case "LUNARGOLEM_BODY_SUBTITLE": case "LUNAREXPLODER_BODY_SUBTITLE": return true; } } } internal static class Compatibility { internal static string ApplicationVersion => "RoR2v" + Application.version + " (" + Application.buildGUID + ")"; internal static string PluginVersion => Assembly.GetExecutingAssembly().GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion; internal static bool DamageInfoChanged() { try { DamageInfoChanged_Test(); return false; } catch (MissingFieldException) { Plugin.Logger.LogError((object)("DamageLogv" + PluginVersion + " is not compatible with " + ApplicationVersion + "\nPlease refer to the README on the mod page for guidance.")); return true; } } [MethodImpl(MethodImplOptions.NoInlining)] private static void DamageInfoChanged_Test() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) ((object)(DamageTypeCombo)(ref new DamageInfo().damageType)).ToString(); } } internal static class ConfigUtility { public static ConfigEntry<string> BindInputKey(this ConfigFile config, string section, string key, string defaultInputKey, string description) { ConfigEntry<string> val = config.Bind<string>(section, key, defaultInputKey, description + "\nKey names follow the naming conventions outlined at: https://docs.unity3d.com/2019.4/Documentation/Manual/class-InputManager.html#:~:text=Key%20family"); try { Input.GetKeyDown(val.Value); } catch (ArgumentException) { Plugin.Logger.LogWarning((object)("Config> " + section + "." + key + " | '" + val.Value + "' is not a valid input key string, using '" + defaultInputKey + "' instead.")); val.Value = defaultInputKey; } return val; } } internal sealed class Config { private readonly ConfigFile file; private readonly ConfigEntry<bool> trackBosses; private readonly ConfigEntry<float> entryMaxRetainTime; private readonly ConfigEntry<bool> onlyShowWithScoreboard; private readonly ConfigEntry<bool> useSimpleTextMode; private readonly ConfigEntry<bool> hideDamageTimer; private readonly ConfigEntry<int> maximumPortraitCount; private readonly ConfigEntry<bool> showDamageIdentifier; private readonly ConfigEntry<bool> compactLines; private readonly ConfigEntry<bool> showRawDamageInsteadOfPercentage; private readonly ConfigEntry<string> cycleUserKey; private readonly ConfigEntry<string> cycleBossKey; private readonly ConfigEntry<float> canvasOffsetRight; private readonly ConfigEntry<float> canvasOffsetTop; private readonly ConfigEntry<float> canvasWidth; private readonly ConfigEntry<float> textSize; private readonly ConfigEntry<float> portraitSpacing; private readonly ConfigEntry<float> portraitSize; private readonly ConfigEntry<float> eliteIconSize; private readonly ConfigEntry<float> portraitTextSize; private readonly ConfigEntry<float> damageTextSize; public bool TrackBosses => trackBosses.Value; public float EntryMaxRetainTime { get { if (!(entryMaxRetainTime.Value < 1f)) { return entryMaxRetainTime.Value; } return 1f; } } public bool OnlyShowWithScoreboard => onlyShowWithScoreboard.Value; public bool SimpleTextMode => useSimpleTextMode.Value; public bool HideDamageTimer => hideDamageTimer.Value; public int MaximumPortraitCount { get { if (maximumPortraitCount.Value <= 0) { return 1; } return maximumPortraitCount.Value; } } public bool ShowIdentifier => showDamageIdentifier.Value; public bool CompactLines => compactLines.Value; public bool ShowRawDamageInsteadOfPercentage => showRawDamageInsteadOfPercentage.Value; public string CycleUserKey => cycleUserKey.Value; public string CycleBossKey => cycleBossKey.Value; public Vector2 CanvasOffsetTopRight => new Vector2(canvasOffsetRight.Value, canvasOffsetTop.Value); public float CanvasWidth => canvasWidth.Value; public float TextSize => textSize.Value; public float PortraitSpacing => portraitSpacing.Value; public float PortraitSize => portraitSize.Value; public float EliteIconSize => eliteIconSize.Value; public float PortraitTextSize => portraitTextSize.Value; public float DamageTextSize => damageTextSize.Value; internal void Reload() { Plugin.Logger.LogDebug((object)("Reloading " + file.ConfigFilePath.Substring(file.ConfigFilePath.LastIndexOf(Path.DirectorySeparatorChar) + 1))); file.Reload(); } internal Config(ConfigFile config) { file = config; trackBosses = config.Bind<bool>("Bosses", "trackBosses", false, "Generate Damage Logs for bosses. Use cycleBossKey to display these in the UI."); entryMaxRetainTime = config.Bind<float>("Constraints", "entryMaxRetainTime", 10f, "The maximum length of time (seconds) a Damage Log entry will be retained for.\nMinimum is 1."); onlyShowWithScoreboard = config.Bind<bool>("Display", "onlyShowWithScoreboard", false, "Only show the Damage Log when the scoreboard is open."); useSimpleTextMode = config.Bind<bool>("Display", "useSimpleTextMode", false, "Display Damage Log entries as text instead of portraits with tooltips."); hideDamageTimer = config.Bind<bool>("Display", "hideDamageTimer", false, "Hide the timer portion of each Damage Log entry showing how long it has been since the damage was inflicted."); maximumPortraitCount = config.Bind<int>("Display: Portraits Mode", "maximumPortraitCount", 12, "The maximum number of Damage Log entry portraits to show at a time.\nMinimum is 1."); showDamageIdentifier = config.Bind<bool>("Display: Portraits Mode", "showDamageIdentifier", false, "Show the damage identifier in the portrait tooltip. Can show additional information about damage attributed to The Planet."); compactLines = config.Bind<bool>("Display: Simple Text Mode", "compactLines", false, "Remove empty lines used as separators between Damage Log entries."); showRawDamageInsteadOfPercentage = config.Bind<bool>("Display: Simple Text Mode", "showRawDamageInsteadOfPercentage", false, "Show the raw damage value instead of the percentage of full combined health."); cycleUserKey = config.BindInputKey("Controls", "cycleUserKey", "left alt", "The key to use to cycle which user's Damage Log should be shown."); cycleBossKey = config.BindInputKey("Controls", "cycleBossKey", "`", "The key to use to cycle which boss's Damage Log should be shown."); canvasOffsetRight = config.Bind<float>("m_Debug", "canvasOffsetRight", 8f, (ConfigDescription)null); canvasOffsetTop = config.Bind<float>("m_Debug", "canvasOffsetTop", 12f, (ConfigDescription)null); canvasWidth = config.Bind<float>("m_Debug", "canvasWidth", 88f, (ConfigDescription)null); textSize = config.Bind<float>("m_Debug", "textSize", 14f, (ConfigDescription)null); portraitSpacing = config.Bind<float>("m_Debug", "portraitSpacing", 8f, (ConfigDescription)null); portraitSize = config.Bind<float>("m_Debug", "portraitSize", 78f, (ConfigDescription)null); eliteIconSize = config.Bind<float>("m_Debug", "eliteIconSize", 24f, (ConfigDescription)null); portraitTextSize = config.Bind<float>("m_Debug", "portraitTextSize", 18f, (ConfigDescription)null); damageTextSize = config.Bind<float>("m_Debug", "damageTextSize", 20f, (ConfigDescription)null); } } public static class DamageDealtMessageExtension { public static bool IsFallDamage(this DamageDealtMessage e) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) return DamageTypeCombo.op_Implicit(e.damageType & DamageTypeCombo.op_Implicit((DamageType)2097152)) != 0; } public static bool IsVoidFogDamage(this DamageDealtMessage e) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Invalid comparison between Unknown and I4 if ((int)DamageTypeCombo.op_Implicit(e.damageType) == 66 && (int)e.damageColorIndex == 9) { return (Object)(object)e.attacker == (Object)null; } return false; } public static bool IsMeridianLightningDamage(this DamageDealtMessage e) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_0038: 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_0047: Unknown result type (might be due to invalid IL or missing references) return DamageTypeCombo.op_Implicit(e.damageType) == DamageTypeCombo.op_Implicit(DamageTypeCombo.Generic | DamageTypeCombo.op_Implicit((DamageType)131072) | DamageTypeCombo.op_Implicit((DamageType)1073741824) | DamageTypeCombo.op_Implicit((DamageTypeExtended)268435456) | DamageTypeCombo.op_Implicit((DamageTypeExtended)536870912)); } public static bool IsWarpedEchoDamage(this DamageDealtMessage e) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 return (int)e.damageColorIndex == 15; } public static string GetAttackerName(this DamageDealtMessage e) { string result = Language.GetString("UNIDENTIFIED_KILLER_NAME"); if ((Object)(object)e.attacker != (Object)null) { string bestBodyName = Util.GetBestBodyName(e.attacker); if (!string.IsNullOrEmpty(bestBodyName)) { result = bestBodyName; } } else if (e.IsFallDamage()) { result = "The Ground"; } else if (e.IsVoidFogDamage()) { result = "Void Fog"; } else if (e.IsMeridianLightningDamage()) { result = "Meridian Lightning"; } else if (e.IsWarpedEchoDamage()) { result = Language.GetString(Items.DelayedDamage.nameToken); } return result; } public static string GenerateIdentifier(this DamageDealtMessage e) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) string result = $"?? | {e.damageType} | {e.damageColorIndex} | {e.damage}"; if (e.IsFallDamage()) { result = "fall_damage"; } if (e.IsVoidFogDamage()) { result = "void_fog_damage"; } if ((Object)(object)e.attacker != (Object)null) { result = $"{((Object)e.attacker).GetInstanceID()} | {e.GetAttackerName()}"; } else if (e.IsMeridianLightningDamage()) { result = "meridian_lightning"; } return result; } } public class DamageLog { private readonly CharacterBody targetBody; private readonly string targetName; private readonly Dictionary<string, DamageSource> entries = new Dictionary<string, DamageSource>(); private float timeOfDeath = -1f; public float Time { get { if (!(timeOfDeath > 0f)) { return Time.time; } return timeOfDeath; } } public virtual string displayName => targetName; public virtual string loggingName => targetName; public DamageLog(NetworkUser user, CharacterBody body) : this(body, user.userName) { } protected DamageLog(CharacterBody targetBody, string targetName) { this.targetBody = targetBody; this.targetName = targetName; Track(targetBody); } private DamageLog Track(CharacterBody body) { GlobalEventManager.onClientDamageNotified += Record; body.master.onBodyDestroyed += Cease; Plugin.Logger.LogDebug((object)("Tracking " + loggingName + ".")); return this; } internal void Untrack() { if (timeOfDeath <= 0f) { timeOfDeath = Time.time; } GlobalEventManager.onClientDamageNotified -= Record; CharacterBody obj = targetBody; if ((Object)(object)((obj != null) ? obj.master : null) != (Object)null) { targetBody.master.onBodyDestroyed -= Cease; } else { Plugin.Logger.LogWarning((object)("Could not unsubscribe RoR2.CharacterMaster::onBodyDestroyed for " + loggingName + ".")); } } private void Cease(CharacterBody _) { Untrack(); Plugin.Logger.LogDebug((object)("Untracking " + loggingName + " (body destroyed).")); } private void Record(DamageDealtMessage e) { if (!((Object)(object)targetBody == (Object)null) && !((Object)(object)e.victim != (Object)(object)((Component)targetBody).gameObject)) { string key = e.GenerateIdentifier(); if (entries.TryGetValue(key, out var value) && !IsExpired(Time - value.time)) { value.Add(e); } else { entries.Remove(key); value = new DamageSource(e); entries.Add(key, value); } if (value.remainingHpPercent <= 0f) { timeOfDeath = Time.time; } Decay(); } } private void Decay() { float time = Time; foreach (DamageSource entry in GetEntries()) { if (IsExpired(time - entry.time)) { entries.Remove(entry.identifier); } } } public virtual bool IsExpired(float elapsedTime) { return elapsedTime > Plugin.Config.EntryMaxRetainTime; } public List<DamageSource> GetEntries() { List<DamageSource> list = entries.Values.ToList(); if (list.Count > 1) { list.Sort((DamageSource a, DamageSource b) => Math.Sign(b.time - a.time)); } return list; } } internal sealed class DamageLogUI : MonoBehaviour { private static HUD hud; private int bossIndex; private bool showingBoss; private Canvas canvas; private HGTextMeshProUGUI text; private readonly List<DamageSourceUI> uiEntries = new List<DamageSourceUI>(); public NetworkUser user { get; private set; } public static void Instantiate(HUD hud, ref bool _) { if (!((Object)(object)DamageLogUI.hud != (Object)null)) { Plugin.Logger.LogDebug((object)"Adding to HUD."); ((Component)hud).gameObject.AddComponent<DamageLogUI>(); DamageLogUI.hud = hud; } } internal static void MoveToGameEndReportPanel(GameEndReportPanelController panel) { if ((Object)(object)hud == (Object)null) { Plugin.Logger.LogWarning((object)"Failed to move canvas (no HUD). This can safely be ignored if triggered by viewing Game End Report from Run History."); return; } DamageLogUI component = ((Component)hud).gameObject.GetComponent<DamageLogUI>(); if ((Object)(object)component == (Object)null) { Plugin.Logger.LogWarning((object)"Failed to move canvas (missing)."); return; } Transform val = ((Component)panel).transform; while ((Object)(object)val != (Object)null) { if (((Object)val).name.Contains("Logbook") || ((Object)val).name.Contains("Pause")) { Plugin.Logger.LogWarning((object)"Blocked attempt to move canvas. This can safely be ignored if triggered by viewing Game End Report from Run History mid-run."); return; } val = val.parent; } ((Behaviour)component).enabled = false; if ((Object)(object)component.canvas == (Object)null) { Plugin.Logger.LogWarning((object)"Attempting to move canvas but it has not been created. Attempting to create."); component.CreateUI(hud.mainContainer); } ((Component)component.canvas).transform.SetParent(((Component)panel).transform); ((Behaviour)component.canvas).enabled = true; Plugin.Logger.LogDebug((object)"Moved canvas."); } internal static void DisplayPlayerDamageLog(NetworkUser user) { if ((Object)(object)hud == (Object)null) { Plugin.Logger.LogWarning((object)"Failed to update canvas (no HUD). This can safely be ignored if triggered by viewing Game End Report from Run History."); return; } DamageLogUI component = ((Component)hud).gameObject.GetComponent<DamageLogUI>(); if ((Object)(object)component == (Object)null) { Plugin.Logger.LogWarning((object)"Failed to update canvas (missing)."); return; } if ((Object)(object)user == (Object)null) { Plugin.Logger.LogWarning((object)"Failed to display player damage log (null)."); return; } if (!Plugin.Data.TryGetUserLog(user, out var log)) { Plugin.Logger.LogWarning((object)("Failed to find damage log for " + user.userName + ".")); return; } component.UpdateText(log); component.UpdatePortraits(log); } private void Start() { CreateUI(hud.mainContainer); } private void CreateUI(GameObject parent) { Plugin.Config.Reload(); HUD obj = hud; object obj2; if (obj == null) { obj2 = null; } else { LocalUser localUserViewer = obj.localUserViewer; obj2 = ((localUserViewer != null) ? localUserViewer.currentNetworkUser : null); } user = (NetworkUser)obj2; if ((Object)(object)user == (Object)null) { Plugin.Logger.LogWarning((object)"Failed to get HUD user (null)."); } CreateCanvas(parent); CreateText(); if (!Plugin.Config.SimpleTextMode) { CreatePortraits(); } Plugin.Logger.LogDebug((object)"Created canvas."); } private void CreateCanvas(GameObject parent) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_007b: 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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) canvas = new GameObject("DamageLogUI", new Type[2] { typeof(Canvas), typeof(GraphicRaycaster) }).GetComponent<Canvas>(); RectTransform component = ((Component)canvas).GetComponent<RectTransform>(); ((Transform)component).SetParent(parent.transform); ResetRectTransform(component); AnchorStretchRight(component); component.pivot = Vector2.one; ((Transform)component).localPosition = ((Transform)component).localPosition - Vector2.op_Implicit(Plugin.Config.CanvasOffsetTopRight); component.sizeDelta = Vector2.right * Plugin.Config.CanvasWidth - Vector2.up * Plugin.Config.CanvasOffsetTopRight; } private void CreatePortraits() { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown VerticalLayoutGroup obj = ((Component)canvas).gameObject.AddComponent<VerticalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = false; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = false; ((HorizontalOrVerticalLayoutGroup)obj).spacing = Plugin.Config.PortraitSpacing; for (int i = 0; i < Plugin.Config.MaximumPortraitCount; i++) { uiEntries.Add(DamageSourceUI.Instantiate((RectTransform)((Component)canvas).transform).Hide()); } } private void CreateText() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_0065: 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_0079: Unknown result type (might be due to invalid IL or missing references) RectTransform component = new GameObject("DamageLogText", new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>(); ((Transform)component).SetParent(((Component)canvas).transform); ResetRectTransform(component); AnchorTopStretch(component); component.pivot = Vector2.one; component.sizeDelta = (Vector2)(Plugin.Config.SimpleTextMode ? Vector2.zero : new Vector2(((RectTransform)((Component)canvas).transform).sizeDelta.x, 0f)); text = ((Component)component).gameObject.AddComponent<HGTextMeshProUGUI>(); ((TMP_Text)text).fontSize = Plugin.Config.TextSize; ((TMP_Text)text).SetText("<style=cDeath>Damage Log <null></style>", true); } private void ListenForRebuild() { if (Input.GetKey((KeyCode)278) && Input.GetKeyDown((KeyCode)279)) { Plugin.Logger.LogWarning((object)"Rebuild input triggered, destroying DamageLogUI."); Object.Destroy((Object)(object)((Component)canvas).gameObject); Object.Destroy((Object)(object)this); hud = null; } } private void Update() { bool flag = !Plugin.Config.OnlyShowWithScoreboard || hud.scoreboardPanel.activeSelf; ((Behaviour)canvas).enabled = flag; if (!flag) { return; } ListenForRebuild(); bool reverse = Input.GetKey("left shift") || Input.GetKey("right shift"); bool keyDown = Input.GetKeyDown(Plugin.Config.CycleUserKey); bool flag2 = Plugin.Config.TrackBosses && Input.GetKeyDown(Plugin.Config.CycleBossKey); if (keyDown) { if (!showingBoss) { user = Plugin.Data.CycleUser(user, reverse); } showingBoss = false; } else if (flag2 && Plugin.Data.HasBossLogs) { if (showingBoss) { bossIndex = Plugin.Data.CycleBossIndex(bossIndex, reverse); } showingBoss = true; } if ((!showingBoss && (Object)(object)user != (Object)null && Plugin.Data.TryGetUserLog(user, out var log)) || (showingBoss && Plugin.Data.TryGetBossLog(bossIndex, out log))) { UpdateText(log); UpdatePortraits(log); } } private void UpdateText(DamageLog log) { //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_0023: 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_0052: Unknown result type (might be due to invalid IL or missing references) ((TMP_Text)text).SetText(GenerateTextLog(log), true); Vector2 sizeDelta = ((TMP_Text)text).rectTransform.sizeDelta; if (sizeDelta.y != ((TMP_Text)text).preferredHeight) { ((TMP_Text)text).rectTransform.sizeDelta = new Vector2(sizeDelta.x, ((TMP_Text)text).preferredHeight); } } private void UpdatePortraits(DamageLog log) { if (Plugin.Config.SimpleTextMode) { return; } float time = log.Time; List<DamageSource> entries = log.GetEntries(); for (int i = 0; i < uiEntries.Count; i++) { if (i >= entries.Count) { uiEntries[i].Hide(); continue; } float elapsedTime = time - entries[i].time; if (log.IsExpired(elapsedTime)) { uiEntries[i].Hide(); } else { uiEntries[i].Display(entries[i], elapsedTime); } } } private static string GenerateTextLog(DamageLog log) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("<style=cWorldEvent>Damage Log"); stringBuilder.AppendLine("<" + log.displayName + "></style>"); if (!Plugin.Config.SimpleTextMode) { return stringBuilder.ToString(); } float time = log.Time; foreach (DamageSource entry in log.GetEntries()) { float num = time - entry.time; if (!log.IsExpired(num)) { if (!Plugin.Config.CompactLines) { stringBuilder.AppendLine(); } string text = (entry.isPlayerDamage ? "cDeath" : (entry.isFallDamage ? "cHumanObjective" : (entry.isVoidFogDamage ? "cIsVoid" : ""))); if (string.IsNullOrEmpty(text)) { stringBuilder.Append(entry.attackerName); } else { stringBuilder.Append("<style=" + text + ">" + entry.attackerName + "</style>"); } bool num2 = entry.hits == 1; if (!num2) { stringBuilder.Append($"<style=cStack><nobr>×{entry.hits}</nobr></style>"); } if (Plugin.Config.ShowRawDamageInsteadOfPercentage) { stringBuilder.Append($" · <style=cIsHealth><nobr>{-1f * entry.totalDamage:0.0}</nobr></style>"); } else { stringBuilder.Append($" · <style=cIsDamage><nobr>{-1f * entry.totalDamagePercent:0.0%}</nobr></style>"); } if (num2) { stringBuilder.Append($" <style=cEvent><nobr>({entry.remainingHpPercent:0.0%})</nobr></style>"); } if (!Plugin.Config.HideDamageTimer) { stringBuilder.AppendLine($" · <style=cSub>{num:0.00s}</style>"); } else { stringBuilder.AppendLine(); } } } return stringBuilder.ToString(); } public static RectTransform ResetRectTransform(RectTransform rect) { //IL_0001: 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_0017: Unknown result type (might be due to invalid IL or missing references) ((Transform)rect).localPosition = Vector3.zero; ((Transform)rect).localScale = Vector3.one; ((Transform)rect).localRotation = Quaternion.identity; ((Component)rect).gameObject.layer = LayerMask.NameToLayer("UI"); return rect; } private static RectTransform AnchorStretchRight(RectTransform rect) { //IL_0001: 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_0017: Unknown result type (might be due to invalid IL or missing references) rect.anchoredPosition = Vector2.zero; rect.anchorMin = Vector2.right; rect.anchorMax = Vector2.one; return rect; } private static RectTransform AnchorTopStretch(RectTransform rect) { //IL_0001: 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_0017: Unknown result type (might be due to invalid IL or missing references) rect.anchoredPosition = Vector2.zero; rect.anchorMin = Vector2.up; rect.anchorMax = Vector2.one; return rect; } } public sealed class DamageSource { private static Texture _PlanetPortrait; private static Texture _SotVPortrait; public readonly string identifier; public readonly string attackerName; public readonly Texture attackerPortrait; public readonly Color attackerPortraitColor; public readonly Sprite eliteIcon; public readonly Color eliteIconColor; public readonly bool isPlayerDamage; public readonly bool isFallDamage; public readonly bool isVoidFogDamage; public readonly float timeStart; private static Texture PlanetPortrait => _PlanetPortrait ?? (_PlanetPortrait = LegacyResourcesAPI.Load<Texture>("Textures/BodyIcons/texUnidentifiedKillerIcon")); private static Texture SotVPortrait => _SotVPortrait ?? (_SotVPortrait = Addressables.LoadAssetAsync<Texture>((object)"RoR2/DLC1/UI/texVoidExpansionIcon.png").WaitForCompletion()); public float time { get; private set; } public int hits { get; private set; } public float totalDamage { get; private set; } public float totalDamagePercent { get; private set; } public float remainingHpPercent { get; private set; } public DamageSource(DamageDealtMessage e) { GameObject attacker = e.attacker; CharacterBody val = ((attacker != null) ? attacker.GetComponent<CharacterBody>() : null); isPlayerDamage = val != null && val.isPlayerControlled; isFallDamage = e.IsFallDamage(); isVoidFogDamage = e.IsVoidFogDamage(); identifier = e.GenerateIdentifier(); attackerName = e.GetAttackerName(); GetAttackerPortrait(e, out attackerPortrait, out attackerPortraitColor); GetEliteIcon(val, out eliteIcon, out eliteIconColor); timeStart = Time.time; time = timeStart; hits = 1; totalDamage = e.damage; UpdateHpDamagePercent(e.victim, e.damage); } public DamageSource Add(DamageDealtMessage e) { time = Time.time; hits++; totalDamage += e.damage; UpdateHpDamagePercent(e.victim, e.damage); return this; } private void UpdateHpDamagePercent(GameObject victim, float latestHitDamage) { HealthComponent val = ((victim != null) ? victim.GetComponent<HealthComponent>() : null); if ((Object)(object)val != (Object)null) { remainingHpPercent = (NetworkServer.active ? val.combinedHealthFraction : ((val.combinedHealth - latestHitDamage) / val.fullCombinedHealth)); totalDamagePercent = totalDamage / val.fullCombinedHealth; } else { Plugin.Logger.LogWarning((object)"Could not UpdateHpDamagePercent"); } } private static void GetAttackerPortrait(DamageDealtMessage e, out Texture portrait, out Color color) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) portrait = PlanetPortrait; color = Color.white; if ((Object)(object)e.attacker != (Object)null) { Texture val = e.attacker.GetComponent<CharacterBody>()?.portraitIcon; if ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)PlanetPortrait) { val = GetAlternativeAttackerPortrait(e.attacker, e.GetAttackerName(), ref color); } if ((Object)(object)val != (Object)null) { portrait = val; } } else if (e.IsFallDamage()) { portrait = (Texture)(object)Artifacts.weakAssKneesArtifactDef.smallIconSelectedSprite.texture; } else if (e.IsVoidFogDamage()) { portrait = (Texture)(object)Buffs.VoidFogMild.iconSprite.texture; color = DamageColor.FindColor((DamageColorIndex)9); } else if (e.IsMeridianLightningDamage()) { portrait = (Texture)(object)Buffs.lunarruin.iconSprite.texture; } else if (e.IsWarpedEchoDamage()) { portrait = (Texture)(object)Buffs.DelayedDamageDebuff.iconSprite.texture; } } private static Texture GetAlternativeAttackerPortrait(GameObject attacker, string attackerName, ref Color color) { //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_001f: Unknown result type (might be due to invalid IL or missing references) if (attackerName == Language.GetString("SHRINE_BLOOD_NAME")) { color = Color32.op_Implicit(ColorCatalog.GetColor((ColorIndex)9)); if (attacker == null) { return null; } ShrineBloodBehavior component = attacker.GetComponent<ShrineBloodBehavior>(); if (component == null) { return null; } Transform symbolTransform = component.symbolTransform; if (symbolTransform == null) { return null; } MeshRenderer component2 = ((Component)symbolTransform).GetComponent<MeshRenderer>(); if (component2 == null) { return null; } Material material = ((Renderer)component2).material; if (material == null) { return null; } return material.mainTexture; } if (attackerName == Language.GetString("VOID_CHEST_NAME") || attackerName == Language.GetString("VOID_TRIPLE_NAME")) { return SotVPortrait; } if (attackerName == Language.GetString("ARTIFACTSHELL_BODY_NAME")) { return (Texture)(object)Items.ArtifactKey.pickupIconSprite.texture; } return null; } private static void GetEliteIcon(CharacterBody body, out Sprite icon, out Color color) { //IL_0021: 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_0026: Unknown result type (might be due to invalid IL or missing references) BuffDef eliteBuffDef = GetEliteBuffDef(body); icon = eliteBuffDef?.iconSprite; color = eliteBuffDef?.buffColor ?? Color.white; } private static BuffDef GetEliteBuffDef(CharacterBody body) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) BuffDef result = null; if ((Object)(object)body == (Object)null || !body.isElite) { return result; } BuffIndex[] eliteBuffIndices = BuffCatalog.eliteBuffIndices; foreach (BuffIndex val in eliteBuffIndices) { if (body.HasBuff(val)) { result = BuffCatalog.GetBuffDef(val); } } return result; } } internal sealed class DamageSourceUI : MonoBehaviour { private RawImage portrait; private Image elite; private HGTextMeshProUGUI damage; private HGTextMeshProUGUI hits; private HGTextMeshProUGUI time; private TooltipProvider tooltip; public static DamageSourceUI Instantiate(RectTransform parent) { //IL_0025: 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) //IL_0035: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) RectTransform val = (RectTransform)new GameObject("DamageEntry", new Type[2] { typeof(DamageSourceUI), typeof(RawImage) }).transform; ((Transform)val).SetParent((Transform)(object)parent, false); val.sizeDelta = Vector2.one * ((Plugin.Config.PortraitSize > 0f) ? Plugin.Config.PortraitSize : parent.sizeDelta.x); return ((Component)val).GetComponent<DamageSourceUI>().Build(val); } private DamageSourceUI Build(RectTransform root) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) float x = root.sizeDelta.x; tooltip = ((Component)root).gameObject.AddComponent<TooltipProvider>(); portrait = ((Component)root).GetComponent<RawImage>(); elite = AddChild<Image>(root, "elite"); AnchorTopLeft(((Graphic)elite).rectTransform); ((Graphic)elite).rectTransform.sizeDelta = Vector2.one * Plugin.Config.EliteIconSize; damage = AddChild<HGTextMeshProUGUI>(root, "damage"); AnchorTopRight(((TMP_Text)damage).rectTransform); ((TMP_Text)damage).enableWordWrapping = false; ((TMP_Text)damage).alignment = (TextAlignmentOptions)260; ((TMP_Text)damage).rectTransform.sizeDelta = Vector2.one * (x - Plugin.Config.EliteIconSize); ((TMP_Text)damage).fontSize = Plugin.Config.DamageTextSize; hits = AddChild<HGTextMeshProUGUI>(root, "hits"); AnchorBottomLeft(((TMP_Text)hits).rectTransform); ((TMP_Text)hits).enableWordWrapping = false; ((TMP_Text)hits).alignment = (TextAlignmentOptions)1025; ((TMP_Text)hits).rectTransform.sizeDelta = Vector2.one * (x / 2f); ((TMP_Text)hits).fontSize = Plugin.Config.PortraitTextSize; time = AddChild<HGTextMeshProUGUI>(root, "time"); AnchorBottomRight(((TMP_Text)time).rectTransform); ((TMP_Text)time).enableWordWrapping = false; ((TMP_Text)time).alignment = (TextAlignmentOptions)1028; ((TMP_Text)time).rectTransform.sizeDelta = Vector2.one * (x / 2f); ((TMP_Text)time).fontSize = Plugin.Config.PortraitTextSize; if (Plugin.Config.HideDamageTimer) { ((Component)time).gameObject.SetActive(false); } return this; } private static T AddChild<T>(RectTransform parent, string name) where T : Graphic { //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_0025: 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) //IL_0035: Expected O, but got Unknown GameObject val = new GameObject(name, new Type[1] { typeof(T) }); val.transform.SetParent((Transform)(object)parent); DamageLogUI.ResetRectTransform((RectTransform)val.transform); T component = val.GetComponent<T>(); ((Graphic)component).raycastTarget = false; return component; } public void Display(DamageSource src, float elapsedTime) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) if (src == null) { Hide(); return; } ((Component)portrait).gameObject.SetActive(true); portrait.texture = src.attackerPortrait; ((Graphic)portrait).color = src.attackerPortraitColor; if ((Object)(object)src.eliteIcon != (Object)null) { elite.sprite = src.eliteIcon; ((Graphic)elite).color = src.eliteIconColor; ((Behaviour)elite).enabled = true; } else { ((Behaviour)elite).enabled = false; } ((TMP_Text)damage).SetText($"<style=cIsDamage>{-1f * src.totalDamagePercent:0.0%}</style>", true); if (src.hits == 1) { ((TMP_Text)hits).SetText("", true); } else { ((TMP_Text)hits).SetText($"<style=cStack>×{src.hits}</style>", true); } ((TMP_Text)time).SetText($"<style=cSub>{elapsedTime:0.00s}</style>", true); tooltip.titleColor = Color32.op_Implicit(src.isPlayerDamage ? ColorCatalog.GetColor((ColorIndex)17) : (src.isFallDamage ? ColorCatalog.GetColor((ColorIndex)16) : (src.isVoidFogDamage ? ColorCatalog.GetColor((ColorIndex)25) : ColorCatalog.GetColor((ColorIndex)20)))); tooltip.titleToken = src.attackerName; tooltip.bodyToken = GenerateTooltipString(src); } public DamageSourceUI Hide() { ((Component)portrait).gameObject.SetActive(false); return this; } private static string GenerateTooltipString(DamageSource src) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append($"Dealt <style=cIsHealth>{src.totalDamage:0.0}</style> damage"); if (src.hits == 1) { stringBuilder.Append($" <style=cEvent>({src.remainingHpPercent:0.0%} health remaining)</style>"); } else { stringBuilder.Append($" in <style=cStack>{src.hits} hits</style> over <style=cSub>{src.time - src.timeStart:0.00s}</style>"); } stringBuilder.AppendLine("."); if (Plugin.Config.ShowIdentifier) { stringBuilder.AppendLine(); stringBuilder.AppendLine("<style=cIsDamage>" + src.identifier + "</style>"); } return stringBuilder.ToString(); } private static void AnchorTopLeft(RectTransform rect) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) Anchor(rect, Vector2.up); } private static void AnchorTopRight(RectTransform rect) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) Anchor(rect, Vector2.one); } private static void AnchorBottomLeft(RectTransform rect) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) Anchor(rect, Vector2.zero); } private static void AnchorBottomRight(RectTransform rect) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) Anchor(rect, Vector2.right); } private static void Anchor(RectTransform rect, Vector2 anchor) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0004: 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_000b: 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_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) Vector2 val2 = (rect.anchorMax = anchor); Vector2 pivot = (rect.anchorMin = val2); rect.pivot = pivot; } } internal sealed class Data { private readonly Dictionary<NetworkUser, DamageLog> userLogs = new Dictionary<NetworkUser, DamageLog>(); private readonly Dictionary<uint, DamageLog> bossLogs = new Dictionary<uint, DamageLog>(); public bool HasBossLogs => bossLogs.Count > 0; internal void AddUserLog(NetworkUser user, DamageLog log) { Add(userLogs, user, log); } internal void AddBossLog(BossDamageLog log) { Add(bossLogs, log.targetNetId, log); } internal bool TryGetUserLog(NetworkUser user, out DamageLog log) { return userLogs.TryGetValue(user, out log); } internal bool TryGetBossLog(int index, out DamageLog log) { return TryGetDamageLog(index, bossLogs, out log); } internal void ClearUserLogs() { Plugin.Logger.LogDebug((object)$"Clearing user damage logs ({userLogs.Count})."); Clear(userLogs); } internal void ClearBossLogs() { if (bossLogs.Count > 0) { Plugin.Logger.LogDebug((object)$"Clearing boss damage logs ({bossLogs.Count})."); Clear(bossLogs); } } internal void ClearAll() { ClearUserLogs(); ClearBossLogs(); } internal NetworkUser CycleUser(NetworkUser current, bool reverse) { if (userLogs.Count <= 0) { return null; } int index = ((!((Object)(object)current == (Object)null)) ? NetworkUser.readOnlyInstancesList.IndexOf(current) : 0); index = CycleCollectionIndex(index, NetworkUser.readOnlyInstancesList, reverse); NetworkUser val = NetworkUser.readOnlyInstancesList[index]; if (userLogs.ContainsKey(val)) { return val; } return CycleUser(val, reverse); } internal int CycleBossIndex(int current, bool reverse) { return CycleCollectionIndex(current, bossLogs, reverse); } internal static int CycleCollectionIndex(int index, ICollection collection, bool reverse) { index = ((!reverse) ? (index + 1) : (index - 1)); if (index < 0) { index = collection.Count - 1; } else if (index >= collection.Count) { index = 0; } return index; } public static void Add<TKey>(Dictionary<TKey, DamageLog> logs, TKey key, DamageLog newLog) { if (logs.TryGetValue(key, out var value)) { value.Untrack(); Plugin.Logger.LogDebug((object)("Untracking " + value.loggingName + " (replacing).")); } logs[key] = newLog; } public static void Clear<TKey>(Dictionary<TKey, DamageLog> logs) { foreach (DamageLog value in logs.Values) { value.Untrack(); Plugin.Logger.LogDebug((object)("Untracking " + value.loggingName + " (clearing).")); } logs.Clear(); } public static bool TryGetDamageLog<TKey>(int index, Dictionary<TKey, DamageLog> dictionary, out DamageLog log) { log = null; if (index < 0) { return false; } if (index >= dictionary.Count) { return false; } log = dictionary.ElementAt(index).Value; return true; } } [HarmonyPatch] internal static class HarmonyPatches { [HarmonyPostfix] [HarmonyPatch(typeof(GameEndReportPanelController), "Awake")] private static void GameEndReportPanelController_Awake(GameEndReportPanelController __instance) { try { DamageLogUI.MoveToGameEndReportPanel(__instance); } catch (Exception ex) { Plugin.Logger.LogError((object)ex); } } [HarmonyPostfix] [HarmonyPatch(typeof(GameEndReportPanelController), "SetPlayerInfo")] private static void GameEndReportPanelController_SetPlayerInfo(PlayerInfo playerInfo) { try { DamageLogUI.DisplayPlayerDamageLog(playerInfo?.networkUser); } catch (Exception ex) { Plugin.Logger.LogError((object)ex); } } [HarmonyPostfix] [HarmonyPatch(typeof(BossGroup), "OnMemberDiscovered")] private static void BossGroup_OnMemberDiscovered(BossGroup __instance, CharacterMaster memberMaster) { try { Plugin.TrackBoss(__instance, memberMaster); } catch (Exception ex) { Plugin.Logger.LogError((object)ex); } } } [BepInPlugin("itsschwer.DamageLog", "DamageLog", "1.2.10")] public sealed class Plugin : BaseUnityPlugin { [CompilerGenerated] private static class <>O { public static ShouldHudDisplayDelegate <0>__Instantiate; public static Action<CharacterBody> <1>__TrackUser; public static Action<Run> <2>__OnRunStartOrDestroy; public static Action<Stage> <3>__OnStageStart; public static Action<CharacterBody> <4>__TrackBoss; } public const string GUID = "itsschwer.DamageLog"; public const string Author = "itsschwer"; public const string Name = "DamageLog"; public const string Version = "1.2.10"; internal static ManualLogSource Logger { get; private set; } internal static Config Config { get; private set; } internal static Data Data { get; private set; } private void Awake() { //IL_0058: Unknown result type (might be due to invalid IL or missing references) Logger.Sources.Remove((ILogSource)(object)((BaseUnityPlugin)this).Logger); Logger = Logger.CreateLogSource("itsschwer.DamageLog"); Config = new Config(((BaseUnityPlugin)this).Config); Data = new Data(); if (Compatibility.DamageInfoChanged()) { Object.DestroyImmediate((Object)(object)this); return; } new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID).PatchAll(); Logger.LogMessage((object)"~awake."); } private void OnEnable() { //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_001b: Expected O, but got Unknown object obj = <>O.<0>__Instantiate; if (obj == null) { ShouldHudDisplayDelegate val = DamageLogUI.Instantiate; <>O.<0>__Instantiate = val; obj = (object)val; } HUD.shouldHudDisplay += (ShouldHudDisplayDelegate)obj; CharacterBody.onBodyStartGlobal += TrackUser; Run.onRunStartGlobal += OnRunStartOrDestroy; Run.onRunDestroyGlobal += OnRunStartOrDestroy; Stage.onStageStartGlobal += OnStageStart; Logger.LogMessage((object)"~enabled."); } private void OnDisable() { //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_001b: Expected O, but got Unknown object obj = <>O.<0>__Instantiate; if (obj == null) { ShouldHudDisplayDelegate val = DamageLogUI.Instantiate; <>O.<0>__Instantiate = val; obj = (object)val; } HUD.shouldHudDisplay -= (ShouldHudDisplayDelegate)obj; CharacterBody.onBodyStartGlobal -= TrackUser; Run.onRunStartGlobal -= OnRunStartOrDestroy; Run.onRunDestroyGlobal -= OnRunStartOrDestroy; Stage.onStageStartGlobal -= OnStageStart; Logger.LogMessage((object)"~disabled."); } private static void OnRunStartOrDestroy(Run _) { Data.ClearAll(); } private static void OnStageStart(Stage _) { Data.ClearBossLogs(); } private static void TrackUser(CharacterBody body) { if (body.isPlayerControlled) { NetworkUser val = Util.LookUpBodyNetworkUser(body); if (!((Object)(object)val == (Object)null)) { DamageLog log = new DamageLog(val, body); Data.AddUserLog(val, log); } } } internal static void TrackBoss(BossGroup boss, CharacterMaster member) { //IL_0031: 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) if (Config.TrackBosses) { ManualLogSource logger = Logger; object[] obj = new object[4] { "TrackBoss", ((Object)member).name, null, null }; NetworkInstanceId netId = ((NetworkBehaviour)member).netId; obj[2] = ((NetworkInstanceId)(ref netId)).Value; obj[3] = ((Object)boss).name; logger.LogDebug((object)string.Format("{0}> Discovered {1} <{2:x8}> | {3}", obj)); member.onBodyStart += TrackBoss; } } private static void TrackBoss(CharacterBody body) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) body.master.onBodyStart -= TrackBoss; if (!BossDamageLog.IsIgnoredBossSubtitle(body.subtitleNameToken)) { ManualLogSource logger = Logger; object[] obj = new object[5] { "TrackBoss", ((Object)body.master).name, null, null, null }; NetworkInstanceId netId = ((NetworkBehaviour)body.master).netId; obj[2] = ((NetworkInstanceId)(ref netId)).Value; obj[3] = ((Object)body).name; netId = ((NetworkBehaviour)body).netId; obj[4] = ((NetworkInstanceId)(ref netId)).Value; logger.LogDebug((object)string.Format("{0}> Found {1} <{2:x8}> | {3} <{4:x8}>", obj)); Data.AddBossLog(new BossDamageLog(body)); } } } }