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 DeathViz3D v1.3.0
plugins/DeathViz3D.dll
Decompiled 21 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using RoR2; using RoR2.Projectile; using RoR2.UI; using TMPro; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.SceneManagement; 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(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("DeathViz")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+4eca4894d4756b513e0a2e7e3264c7de3da65946")] [assembly: AssemblyProduct("DeathViz")] [assembly: AssemblyTitle("DeathViz")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [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; } } } public static class DeathVizVisualConfig { private static ConfigEntry<string> playerColor; private static ConfigEntry<string> deathColor; private static ConfigEntry<string> killerColor; private static ConfigEntry<string> attackerColor; private static ConfigEntry<string> sawOnlyColor; private static ConfigEntry<string> passiveEnemyColor; private static ConfigEntry<string> projectileColor; private static ConfigEntry<string> hitProjectileColor; private static ConfigEntry<string> killingProjectileColor; private static ConfigEntry<string> environmentColor; private static ConfigEntry<string> deathCandidateColor; private static ConfigEntry<string> playerReplayStartColor; private static ConfigEntry<string> playerReplayEndColor; private static ConfigEntry<string> killerReplayStartColor; private static ConfigEntry<string> killerReplayEndColor; private static ConfigEntry<string> attackerPathStartColor; private static ConfigEntry<string> attackerPathEndColor; private static ConfigEntry<string> sawOnlyPathStartColor; private static ConfigEntry<string> sawOnlyPathEndColor; private static ConfigEntry<string> attackerReplayStartColor; private static ConfigEntry<string> attackerReplayEndColor; private static ConfigEntry<string> sawOnlyReplayStartColor; private static ConfigEntry<string> sawOnlyReplayEndColor; private static ConfigEntry<float> lineWidth3DMultiplier; private static ConfigEntry<float> player3DContextPathWidthMultiplier; private static ConfigEntry<float> player3DReplayPathWidthMultiplier; private static ConfigEntry<float> killer3DContextPathWidthMultiplier; private static ConfigEntry<float> killer3DReplayPathWidthMultiplier; private static ConfigEntry<float> attacker3DContextPathWidthMultiplier; private static ConfigEntry<float> attacker3DReplayPathWidthMultiplier; private static ConfigEntry<float> sawOnly3DContextPathWidthMultiplier; private static ConfigEntry<float> sawOnly3DReplayPathWidthMultiplier; private static ConfigEntry<float> sphere3DScaleMultiplier; private static ConfigEntry<float> cube3DScaleMultiplier; private static ConfigEntry<float> ring3DRadiusMultiplier; private static ConfigEntry<float> ring3DWidthMultiplier; private static ConfigEntry<float> cone3DScaleMultiplier; private static ConfigEntry<float> lineWidth2DMultiplier; private static ConfigEntry<float> player2DContextPathWidthMultiplier; private static ConfigEntry<float> player2DReplayPathWidthMultiplier; private static ConfigEntry<float> killer2DContextPathWidthMultiplier; private static ConfigEntry<float> killer2DReplayPathWidthMultiplier; private static ConfigEntry<float> attacker2DContextPathWidthMultiplier; private static ConfigEntry<float> attacker2DReplayPathWidthMultiplier; private static ConfigEntry<float> sawOnly2DContextPathWidthMultiplier; private static ConfigEntry<float> sawOnly2DReplayPathWidthMultiplier; private static ConfigEntry<float> marker2DScaleMultiplier; private static ConfigEntry<float> ring2DRadiusMultiplier; private static ConfigEntry<float> ring2DWidthMultiplier; private static ConfigEntry<float> triangle2DScaleMultiplier; private static ConfigEntry<string> enemyStatusKillerRingColor; private static ConfigEntry<string> enemyStatusAttackerRingColor; private static ConfigEntry<string> enemyStatusSawOnlyRingColor; private static ConfigEntry<string> enemyStatusUninvolvedRingColor; private static ConfigEntry<string> enemyStatusAliveMarkerColor; private static ConfigEntry<string> enemyStatusDeadMarkerColor; private static ConfigEntry<string> enemyStatusUnknownMarkerColor; private static ConfigEntry<float> enemyStatus3DSphereScaleMultiplier; private static ConfigEntry<float> enemyStatus3DRingRadiusMultiplier; private static ConfigEntry<float> enemyStatus3DRingWidthMultiplier; private static ConfigEntry<float> enemyStatus3DRingYOffset; private static ConfigEntry<float> enemyStatus3DSphereYOffset; private static ConfigEntry<float> enemyStatus2DCircleScaleMultiplier; private static ConfigEntry<float> enemyStatus2DRingRadiusMultiplier; private static ConfigEntry<float> enemyStatus2DRingWidthMultiplier; public static void Bind(ConfigFile config) { playerColor = config.Bind<string>("DeathViz.Colors", "PlayerColor", "", "User input RGBA hex override for player geometry. Example: #00DFFFFF. Empty = use built-in default"); deathColor = config.Bind<string>("DeathViz.Colors", "DeathColor", "", "User input RGBA hex override for death geometry. Example: #FF0000FF. Empty = use built-in default"); killerColor = config.Bind<string>("DeathViz.Colors", "KillerColor", "", "User input RGBA hex override for killer geometry. Example: #FF0000FF. Empty = use built-in default"); attackerColor = config.Bind<string>("DeathViz.Colors", "AttackerColor", "", "User input RGBA hex override for attacker geometry. Example: #FF7300FF. Empty = use built-in default"); sawOnlyColor = config.Bind<string>("DeathViz.Colors", "SawOnlyColor", "", "User input RGBA hex override for saw-only enemy geometry. Example: #73FF40FF. Empty = use built-in default"); passiveEnemyColor = config.Bind<string>("DeathViz.Colors", "PassiveEnemyColor", "", "User input RGBA hex override for passive enemy geometry. Example: #DDDDDDFF. Empty = use built-in default"); projectileColor = config.Bind<string>("DeathViz.Colors", "ProjectileColor", "", "User input RGBA hex override for neutral projectile geometry. Example: #FFE000FF. Empty = use built-in default"); hitProjectileColor = config.Bind<string>("DeathViz.Colors", "HitProjectileColor", "", "User input RGBA hex override for nonlethal/attacker projectile hit geometry. Example: #FF7300FF. Empty = use built-in default"); killingProjectileColor = config.Bind<string>("DeathViz.Colors", "KillingProjectileColor", "", "User input RGBA hex override for killing projectile geometry. Example: #FF0000FF. Empty = use built-in default"); environmentColor = config.Bind<string>("DeathViz.Colors", "EnvironmentColor", "", "User input RGBA hex override for environmental damage. Example: #A0A0A0FF. Empty = use built-in default"); deathCandidateColor = config.Bind<string>("DeathViz.Colors", "DeathCandidateColor", "", "User input RGBA hex override for death candidate markers. Example: #FF33D9FF. Empty = use built-in default"); attackerPathStartColor = config.Bind<string>("DeathViz.Path.Colors", "AttackerPathStartColor", "#FFC266B3", "Start/oldest color for attacker context movement paths. RGBA hex."); attackerPathEndColor = config.Bind<string>("DeathViz.Path.Colors", "AttackerPathEndColor", "#CC4A00F2", "End/newest color for attacker context movement paths. RGBA hex."); sawOnlyPathStartColor = config.Bind<string>("DeathViz.Path.Colors", "SawOnlyPathStartColor", "#B6FF99B3", "Start/oldest color for saw-only context movement paths. RGBA hex."); sawOnlyPathEndColor = config.Bind<string>("DeathViz.Path.Colors", "SawOnlyPathEndColor", "#39FF39F2", "End/newest color for saw-only context movement paths. RGBA hex."); lineWidth3DMultiplier = config.Bind<float>("DeathViz.3D.Widths", "LineWidthMultiplier", 1f, "Global multiplier for 3D path/trail/ring line widths."); player3DContextPathWidthMultiplier = BindPathWidthMultiplier(config, "DeathViz.3D.Widths", "PlayerContextPathWidthMultiplier", "Multiplier for 3D PLAYER context/static path width."); player3DReplayPathWidthMultiplier = BindPathWidthMultiplier(config, "DeathViz.3D.Widths", "PlayerReplayPathWidthMultiplier", "Multiplier for 3D PLAYER replay path width."); killer3DContextPathWidthMultiplier = BindPathWidthMultiplier(config, "DeathViz.3D.Widths", "KillerContextPathWidthMultiplier", "Multiplier for 3D KILLER context/static path width."); killer3DReplayPathWidthMultiplier = BindPathWidthMultiplier(config, "DeathViz.3D.Widths", "KillerReplayPathWidthMultiplier", "Multiplier for 3D KILLER replay path width."); attacker3DContextPathWidthMultiplier = BindPathWidthMultiplier(config, "DeathViz.3D.Widths", "AttackerContextPathWidthMultiplier", "Multiplier for 3D ATTACKERS context/static path width."); attacker3DReplayPathWidthMultiplier = BindPathWidthMultiplier(config, "DeathViz.3D.Widths", "AttackerReplayPathWidthMultiplier", "Multiplier for 3D ATTACKERS replay path width."); sawOnly3DContextPathWidthMultiplier = BindPathWidthMultiplier(config, "DeathViz.3D.Widths", "SawOnlyContextPathWidthMultiplier", "Multiplier for 3D SAW ONLY context/static path width."); sawOnly3DReplayPathWidthMultiplier = BindPathWidthMultiplier(config, "DeathViz.3D.Widths", "SawOnlyReplayPathWidthMultiplier", "Multiplier for 3D SAW ONLY replay path width."); sphere3DScaleMultiplier = config.Bind<float>("DeathViz.3D.Sizes", "SphereScaleMultiplier", 1f, "Global multiplier for 3D sphere marker sizes."); cube3DScaleMultiplier = config.Bind<float>("DeathViz.3D.Sizes", "CubeScaleMultiplier", 1f, "Global multiplier for 3D cube marker sizes."); ring3DRadiusMultiplier = config.Bind<float>("DeathViz.3D.Sizes", "RingRadiusMultiplier", 1f, "Global multiplier for 3D ring radii."); ring3DWidthMultiplier = config.Bind<float>("DeathViz.3D.Widths", "RingWidthMultiplier", 1f, "Global multiplier for 3D ring line widths."); cone3DScaleMultiplier = config.Bind<float>("DeathViz.3D.Sizes", "ConeScaleMultiplier", 1f, "Global multiplier for 3D projectile cone length/radius."); lineWidth2DMultiplier = config.Bind<float>("DeathViz.2D.Widths", "LineWidthMultiplier", 1f, "Global multiplier for 2D path/trail/ring line widths."); player2DContextPathWidthMultiplier = BindPathWidthMultiplier(config, "DeathViz.2D.Widths", "PlayerContextPathWidthMultiplier", "Multiplier for 2D PLAYER context/static path width."); player2DReplayPathWidthMultiplier = BindPathWidthMultiplier(config, "DeathViz.2D.Widths", "PlayerReplayPathWidthMultiplier", "Multiplier for 2D PLAYER replay path width."); killer2DContextPathWidthMultiplier = BindPathWidthMultiplier(config, "DeathViz.2D.Widths", "KillerContextPathWidthMultiplier", "Multiplier for 2D KILLER context/static path width."); killer2DReplayPathWidthMultiplier = BindPathWidthMultiplier(config, "DeathViz.2D.Widths", "KillerReplayPathWidthMultiplier", "Multiplier for 2D KILLER replay path width."); attacker2DContextPathWidthMultiplier = BindPathWidthMultiplier(config, "DeathViz.2D.Widths", "AttackerContextPathWidthMultiplier", "Multiplier for 2D ATTACKERS context/static path width."); attacker2DReplayPathWidthMultiplier = BindPathWidthMultiplier(config, "DeathViz.2D.Widths", "AttackerReplayPathWidthMultiplier", "Multiplier for 2D ATTACKERS replay path width."); sawOnly2DContextPathWidthMultiplier = BindPathWidthMultiplier(config, "DeathViz.2D.Widths", "SawOnlyContextPathWidthMultiplier", "Multiplier for 2D SAW ONLY context/static path width."); sawOnly2DReplayPathWidthMultiplier = BindPathWidthMultiplier(config, "DeathViz.2D.Widths", "SawOnlyReplayPathWidthMultiplier", "Multiplier for 2D SAW ONLY replay path width."); marker2DScaleMultiplier = config.Bind<float>("DeathViz.2D.Sizes", "MarkerScaleMultiplier", 1f, "Global multiplier for 2D marker sizes."); ring2DRadiusMultiplier = config.Bind<float>("DeathViz.2D.Sizes", "RingRadiusMultiplier", 1f, "Global multiplier for 2D ring radii."); ring2DWidthMultiplier = config.Bind<float>("DeathViz.2D.Widths", "RingWidthMultiplier", 1f, "Global multiplier for 2D ring line widths."); triangle2DScaleMultiplier = config.Bind<float>("DeathViz.2D.Sizes", "TriangleScaleMultiplier", 1f, "Global multiplier for 2D projectile direction triangles."); enemyStatusKillerRingColor = config.Bind<string>("DeathViz.EnemyStatus.Colors", "KillerRingColor", "#FF0000FF", "Ring color for killer enemy status overlays."); enemyStatusAttackerRingColor = config.Bind<string>("DeathViz.EnemyStatus.Colors", "AttackerRingColor", "#FF7300FF", "Ring color for attacker enemy status overlays."); enemyStatusSawOnlyRingColor = config.Bind<string>("DeathViz.EnemyStatus.Colors", "SawOnlyRingColor", "#39FF39FF", "Ring color for saw-only enemy status overlays."); enemyStatusUninvolvedRingColor = config.Bind<string>("DeathViz.EnemyStatus.Colors", "UninvolvedRingColor", "#B0B0B0FF", "Ring color for uninvolved/passive enemy status overlays."); enemyStatusAliveMarkerColor = config.Bind<string>("DeathViz.EnemyStatus.Colors", "AliveSphereCircleColor", "#39FF39FF", "Sphere/circle color for alive enemies."); enemyStatusDeadMarkerColor = config.Bind<string>("DeathViz.EnemyStatus.Colors", "DeadSphereCircleColor", "#FFFFFFFF", "Sphere/circle color for dead enemies."); enemyStatusUnknownMarkerColor = config.Bind<string>("DeathViz.EnemyStatus.Colors", "UnknownSphereCircleColor", "#B0B0B0FF", "Sphere/circle color for enemies with unknown life status."); enemyStatus3DSphereScaleMultiplier = config.Bind<float>("DeathViz.EnemyStatus.3D", "SphereScaleMultiplier", 1f, "Multiplier for 3D enemy status sphere size."); enemyStatus3DRingRadiusMultiplier = config.Bind<float>("DeathViz.EnemyStatus.3D", "RingRadiusMultiplier", 1f, "Multiplier for 3D enemy status ring radius."); enemyStatus3DRingWidthMultiplier = config.Bind<float>("DeathViz.EnemyStatus.3D", "RingWidthMultiplier", 1f, "Multiplier for 3D enemy status ring width."); enemyStatus3DRingYOffset = config.Bind<float>("DeathViz.EnemyStatus.3D", "RingYOffset", 0.1f, "Vertical offset for 3D enemy status ring."); enemyStatus3DSphereYOffset = config.Bind<float>("DeathViz.EnemyStatus.3D", "SphereYOffset", 0.65f, "Vertical offset for 3D enemy status sphere."); enemyStatus2DCircleScaleMultiplier = config.Bind<float>("DeathViz.EnemyStatus.2D", "CircleScaleMultiplier", 1f, "Multiplier for 2D enemy status circle size."); enemyStatus2DRingRadiusMultiplier = config.Bind<float>("DeathViz.EnemyStatus.2D", "RingRadiusMultiplier", 1f, "Multiplier for 2D enemy status ring radius."); enemyStatus2DRingWidthMultiplier = config.Bind<float>("DeathViz.EnemyStatus.2D", "RingWidthMultiplier", 1f, "Multiplier for 2D enemy status ring width."); playerReplayStartColor = config.Bind<string>("DeathViz.Replay.Colors", "PlayerReplayStartColor", "#B3FFFFFF", "Start color for the active player replay trail. RGBA hex."); playerReplayEndColor = config.Bind<string>("DeathViz.Replay.Colors", "PlayerReplayEndColor", "#001AFFFF", "End/cursor color for the active player replay trail and marker. RGBA hex."); killerReplayStartColor = config.Bind<string>("DeathViz.Replay.Colors", "KillerReplayStartColor", "#FFCC33FF", "Start color for the active killer replay trail. RGBA hex."); killerReplayEndColor = config.Bind<string>("DeathViz.Replay.Colors", "KillerReplayEndColor", "#FF0000FF", "End/cursor color for the active killer replay trail and marker. RGBA hex."); attackerReplayStartColor = config.Bind<string>("DeathViz.Replay.Colors", "AttackerReplayStartColor", "#FFC266FF", "Start color for active attacker replay trails. RGBA hex."); attackerReplayEndColor = config.Bind<string>("DeathViz.Replay.Colors", "AttackerReplayEndColor", "#CC4A00FF", "End/cursor color for active attacker replay trails. RGBA hex."); sawOnlyReplayStartColor = config.Bind<string>("DeathViz.Replay.Colors", "SawOnlyReplayStartColor", "#B6FF99FF", "Start color for active saw-only replay trails. RGBA hex."); sawOnlyReplayEndColor = config.Bind<string>("DeathViz.Replay.Colors", "SawOnlyReplayEndColor", "#39FF39FF", "End/cursor color for active saw-only replay trails. RGBA hex."); } public static Color PlayerColor(Color fallback) { //IL_0006: 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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) return ReadColor(playerColor, fallback); } public static Color DeathColor(Color fallback) { //IL_0006: 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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) return ReadColor(deathColor, fallback); } public static Color KillerColor(Color fallback) { //IL_0006: 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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) return ReadColor(killerColor, fallback); } public static Color AttackerColor(Color fallback) { //IL_0006: 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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) return ReadColor(attackerColor, fallback); } public static Color SawOnlyColor(Color fallback) { //IL_0006: 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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) return ReadColor(sawOnlyColor, fallback); } public static Color PassiveEnemyColor(Color fallback) { //IL_0006: 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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) return ReadColor(passiveEnemyColor, fallback); } public static Color ProjectileColor(Color fallback) { //IL_0006: 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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) return ReadColor(projectileColor, fallback); } public static Color HitProjectileColor(Color fallback) { //IL_0006: 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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) return ReadColor(hitProjectileColor, fallback); } public static Color KillingProjectileColor(Color fallback) { //IL_0006: 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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) return ReadColor(killingProjectileColor, fallback); } public static Color EnvironmentColor(Color fallback) { //IL_0006: 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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) return ReadColor(environmentColor, fallback); } public static Color DeathCandidateColor(Color fallback) { //IL_0006: 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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) return ReadColor(deathCandidateColor, fallback); } public static Color PlayerReplayStartColor(Color fallback) { //IL_0006: 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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) return ReadColor(playerReplayStartColor, fallback); } public static Color PlayerReplayEndColor(Color fallback) { //IL_0006: 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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) return ReadColor(playerReplayEndColor, fallback); } public static Color KillerReplayStartColor(Color fallback) { //IL_0006: 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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) return ReadColor(killerReplayStartColor, fallback); } public static Color KillerReplayEndColor(Color fallback) { //IL_0006: 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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) return ReadColor(killerReplayEndColor, fallback); } public static Color AttackerPathStartColor(Color fallback) { //IL_0006: 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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) return ReadColor(attackerPathStartColor, fallback); } public static Color AttackerPathEndColor(Color fallback) { //IL_0006: 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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) return ReadColor(attackerPathEndColor, fallback); } public static Color SawOnlyPathStartColor(Color fallback) { //IL_0006: 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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) return ReadColor(sawOnlyPathStartColor, fallback); } public static Color SawOnlyPathEndColor(Color fallback) { //IL_0006: 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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) return ReadColor(sawOnlyPathEndColor, fallback); } public static Color AttackerReplayStartColor(Color fallback) { //IL_0006: 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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) return ReadColor(attackerReplayStartColor, fallback); } public static Color AttackerReplayEndColor(Color fallback) { //IL_0006: 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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) return ReadColor(attackerReplayEndColor, fallback); } public static Color SawOnlyReplayStartColor(Color fallback) { //IL_0006: 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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) return ReadColor(sawOnlyReplayStartColor, fallback); } public static Color SawOnlyReplayEndColor(Color fallback) { //IL_0006: 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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) return ReadColor(sawOnlyReplayEndColor, fallback); } public static Color ApplyConfiguredColorByName(string objectName, Color fallback) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_008f: 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_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011f: 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_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) string text = (objectName ?? "").ToLowerInvariant(); if (text.Contains("killingprojectile")) { return KillingProjectileColor(fallback); } if (text.Contains("deathcandidate")) { return DeathCandidateColor(fallback); } if (text.Contains("tetherdeathendpoint")) { return fallback; } if (text.Contains("deathpoint") || text.Contains("deathmarker") || text.Contains("killinghit")) { return DeathColor(fallback); } if (text.Contains("killer")) { return KillerColor(fallback); } if (text.Contains("attacker")) { return AttackerColor(fallback); } if (text.Contains("saw")) { return SawOnlyColor(fallback); } if (text.Contains("passive")) { return PassiveEnemyColor(fallback); } if (text.Contains("player")) { return PlayerColor(fallback); } if (text.Contains("environment")) { return EnvironmentColor(fallback); } if (text.Contains("projectilespawn")) { return ProjectileColor(fallback); } return fallback; } public static float Player3DContextPathWidth(float fallback) { return ClampPositive(fallback * ReadMultiplier(player3DContextPathWidthMultiplier)); } public static float Player3DReplayPathWidth(float fallback) { return ClampPositive(fallback * ReadMultiplier(player3DReplayPathWidthMultiplier)); } public static float Killer3DContextPathWidth(float fallback) { return ClampPositive(fallback * ReadMultiplier(killer3DContextPathWidthMultiplier)); } public static float Killer3DReplayPathWidth(float fallback) { return ClampPositive(fallback * ReadMultiplier(killer3DReplayPathWidthMultiplier)); } public static float Attacker3DContextPathWidth(float fallback) { return ClampPositive(fallback * ReadMultiplier(attacker3DContextPathWidthMultiplier)); } public static float Attacker3DReplayPathWidth(float fallback) { return ClampPositive(fallback * ReadMultiplier(attacker3DReplayPathWidthMultiplier)); } public static float SawOnly3DContextPathWidth(float fallback) { return ClampPositive(fallback * ReadMultiplier(sawOnly3DContextPathWidthMultiplier)); } public static float SawOnly3DReplayPathWidth(float fallback) { return ClampPositive(fallback * ReadMultiplier(sawOnly3DReplayPathWidthMultiplier)); } public static float Player2DContextPathWidth(float fallback) { return ClampPositive(fallback * ReadMultiplier(player2DContextPathWidthMultiplier)); } public static float Player2DReplayPathWidth(float fallback) { return ClampPositive(fallback * ReadMultiplier(player2DReplayPathWidthMultiplier)); } public static float Killer2DContextPathWidth(float fallback) { return ClampPositive(fallback * ReadMultiplier(killer2DContextPathWidthMultiplier)); } public static float Killer2DReplayPathWidth(float fallback) { return ClampPositive(fallback * ReadMultiplier(killer2DReplayPathWidthMultiplier)); } public static float Attacker2DContextPathWidth(float fallback) { return ClampPositive(fallback * ReadMultiplier(attacker2DContextPathWidthMultiplier)); } public static float Attacker2DReplayPathWidth(float fallback) { return ClampPositive(fallback * ReadMultiplier(attacker2DReplayPathWidthMultiplier)); } public static float SawOnly2DContextPathWidth(float fallback) { return ClampPositive(fallback * ReadMultiplier(sawOnly2DContextPathWidthMultiplier)); } public static float SawOnly2DReplayPathWidth(float fallback) { return ClampPositive(fallback * ReadMultiplier(sawOnly2DReplayPathWidthMultiplier)); } public static float Apply3DLineWidth(string objectName, float width) { return ClampPositive(width * ReadMultiplier(lineWidth3DMultiplier)); } public static float Apply3DSphereScale(string objectName, float scale) { return ClampPositive(scale * ReadMultiplier(sphere3DScaleMultiplier)); } public static float Apply3DCubeScale(string objectName, float scale) { return ClampPositive(scale * ReadMultiplier(cube3DScaleMultiplier)); } public static float Apply3DRingRadius(string objectName, float radius) { return ClampPositive(radius * ReadMultiplier(ring3DRadiusMultiplier)); } public static float Apply3DRingWidth(string objectName, float width) { return ClampPositive(width * ReadMultiplier(lineWidth3DMultiplier) * ReadMultiplier(ring3DWidthMultiplier)); } public static float Apply3DConeLength(string objectName, float length) { return ClampPositive(length * ReadMultiplier(cone3DScaleMultiplier)); } public static float Apply3DConeRadius(string objectName, float radius) { return ClampPositive(radius * ReadMultiplier(cone3DScaleMultiplier)); } public static float Apply2DLineWidth(string objectName, float width) { return ClampPositive(width * ReadMultiplier(lineWidth2DMultiplier)); } public static float Apply2DMarkerScale(string objectName, float scale) { return ClampPositive(scale * ReadMultiplier(marker2DScaleMultiplier)); } public static float Apply2DRingRadius(string objectName, float radius) { return ClampPositive(radius * ReadMultiplier(ring2DRadiusMultiplier)); } public static float Apply2DRingWidth(string objectName, float width) { return ClampPositive(width * ReadMultiplier(lineWidth2DMultiplier) * ReadMultiplier(ring2DWidthMultiplier)); } public static float Apply2DTriangleLength(string objectName, float length) { return ClampPositive(length * ReadMultiplier(triangle2DScaleMultiplier)); } public static float Apply2DTriangleHalfWidth(string objectName, float halfWidth) { return ClampPositive(halfWidth * ReadMultiplier(triangle2DScaleMultiplier)); } private static ConfigEntry<float> BindPathWidthMultiplier(ConfigFile config, string section, string key, string description) { return config.Bind<float>(section, key, 1f, description + " 1.0 = built-in default. This is applied before the global LineWidthMultiplier."); } private static float ReadMultiplier(ConfigEntry<float> entry) { if (entry == null) { return 1f; } return Mathf.Clamp(entry.Value, 0.01f, 100f); } private static float ReadConfigFloat(ConfigEntry<float> entry, float fallback, float min, float max) { if (entry == null) { return fallback; } return Mathf.Clamp(entry.Value, min, max); } private static float ClampPositive(float value) { return Mathf.Max(0.0001f, value); } private static Color ReadColor(ConfigEntry<string> entry, Color fallback) { //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_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_001e: 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_0026: Unknown result type (might be due to invalid IL or missing references) if (entry == null) { return fallback; } if (TryParseHexColor(entry.Value, out var color)) { return color; } return fallback; } private static bool TryParseHexColor(string value, out Color color) { //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_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) color = Color.white; if (string.IsNullOrWhiteSpace(value)) { return false; } string text = value.Trim(); if (text.StartsWith("#")) { text = text.Substring(1); } if (text.Length != 6 && text.Length != 8) { return false; } if (!TryParseByte(text.Substring(0, 2), out var value2)) { return false; } if (!TryParseByte(text.Substring(2, 2), out var value3)) { return false; } if (!TryParseByte(text.Substring(4, 2), out var value4)) { return false; } byte value5 = byte.MaxValue; if (text.Length == 8 && !TryParseByte(text.Substring(6, 2), out value5)) { return false; } color = new Color((float)(int)value2 / 255f, (float)(int)value3 / 255f, (float)(int)value4 / 255f, (float)(int)value5 / 255f); return true; } public static Color EnemyStatusRingColorForLayer(string layerKey) { //IL_002a: 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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: 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_009e: 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) return (Color)(layerKey switch { "Killer" => ReadColor(enemyStatusKillerRingColor, new Color(1f, 0f, 0f, 1f)), "Attackers" => ReadColor(enemyStatusAttackerRingColor, new Color(1f, 0.45f, 0.05f, 1f)), "SawButDidNotAttack" => ReadColor(enemyStatusSawOnlyRingColor, new Color(0.22f, 1f, 0.22f, 1f)), _ => ReadColor(enemyStatusUninvolvedRingColor, new Color(0.7f, 0.7f, 0.7f, 1f)), }); } public static Color EnemyStatusMarkerColor(bool isAlive, bool isDead) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: 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_003d: 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_006b: Unknown result type (might be due to invalid IL or missing references) if (isDead) { return ReadColor(enemyStatusDeadMarkerColor, Color.white); } if (isAlive) { return ReadColor(enemyStatusAliveMarkerColor, new Color(0.22f, 1f, 0.22f, 1f)); } return ReadColor(enemyStatusUnknownMarkerColor, new Color(0.7f, 0.7f, 0.7f, 1f)); } public static float Apply3DEnemyStatusSphereScale(float scale) { return ClampPositive(scale * ReadMultiplier(enemyStatus3DSphereScaleMultiplier)); } public static float Apply3DEnemyStatusRingRadius(float radius) { return ClampPositive(radius * ReadMultiplier(enemyStatus3DRingRadiusMultiplier)); } public static float Apply3DEnemyStatusRingWidth(float width) { return ClampPositive(width * ReadMultiplier(enemyStatus3DRingWidthMultiplier)); } public static float EnemyStatus3DRingYOffset(float fallback) { return ReadConfigFloat(enemyStatus3DRingYOffset, fallback, 0f, 10f); } public static float EnemyStatus3DSphereYOffset(float fallback) { return ReadConfigFloat(enemyStatus3DSphereYOffset, fallback, 0f, 10f); } public static float Apply2DEnemyStatusCircleScale(float scale) { return ClampPositive(scale * ReadMultiplier(enemyStatus2DCircleScaleMultiplier)); } public static float Apply2DEnemyStatusRingRadius(float radius) { return ClampPositive(radius * ReadMultiplier(enemyStatus2DRingRadiusMultiplier)); } public static float Apply2DEnemyStatusRingWidth(float width) { return ClampPositive(width * ReadMultiplier(enemyStatus2DRingWidthMultiplier)); } private static bool TryParseByte(string hex, out byte value) { return byte.TryParse(hex, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out value); } } public static class TelemetryConstants { public const float SampleInterval = 0.25f; public const float SlidingWindowSeconds = 15f; public const float FallbackCandidateWindow = 0.1f; public const float AuthoritativeDamageMatchWindow = 0.5f; public const float DeathCandidateDisplayWindow = 1f; public const float ConservativeMeleeRange = 5.5f; public const float EnemyVisionRadius = 60f; public const float EnemyVisionConeHalfAngleDeg = 60f; public const float DuplicateDamageWindow = 0.02f; public const float DotSourceDamageWindow = 0.5f; public const float DotChainExpiryGrace = 0.5f; public const float DotChainFallbackDuration = 2f; public const float SourceLessSequenceMaxGap = 0.75f; public const float SourceLessCandidateSampleMaxAge = 0.5f; public const float SourceLessCandidateTargetingWindow = 1f; public const float SourceLessCandidateMaxDistance = 60f; public const int SourceLessCandidateConfirmations = 2; public const float ImportantProjectileDistance = 12f; public const int VisualPathSmoothingSamplesPerSegment = 8; public const float VisualPathSmoothingMaxSegmentDistance = 18f; public const float VisualPathSmoothingMaxTurnAngleDeg = 70f; public const float VisualPathSmoothingReverseTurnAngleDeg = 135f; } public class CachedPlayerState { public bool HasValue { get; private set; } = false; public float T { get; private set; } = -1f; public float[] Pos { get; } = new float[3]; public float Hp { get; private set; } = 0f; public float Shield { get; private set; } = 0f; public void Capture(float t, float x, float y, float z, float hp, float shield) { HasValue = true; T = t; Pos[0] = x; Pos[1] = y; Pos[2] = z; Hp = hp; Shield = shield; } public void Reset() { HasValue = false; T = -1f; Pos[0] = 0f; Pos[1] = 0f; Pos[2] = 0f; Hp = 0f; Shield = 0f; } } public class PendingLethalContext { public bool HasValue { get; private set; } = false; public float CapturedAt { get; private set; } = -1f; public TelemetryEvent? DamageEvent { get; private set; } = null; public float[] PlayerPos { get; } = new float[3]; public float PlayerHp { get; private set; } = 0f; public float PlayerShield { get; private set; } = 0f; public void Capture(TelemetryEvent damageEvent, float capturedAt, float playerHp, float playerShield) { HasValue = true; CapturedAt = capturedAt; DamageEvent = CloneTelemetryEvent(damageEvent); PlayerPos[0] = damageEvent.victim_pos[0]; PlayerPos[1] = damageEvent.victim_pos[1]; PlayerPos[2] = damageEvent.victim_pos[2]; PlayerHp = playerHp; PlayerShield = playerShield; } public bool IsRecent(float now, float maxAgeSeconds) { if (!HasValue) { return false; } float num = now - CapturedAt; return num >= 0f && num <= maxAgeSeconds; } public void Reset() { HasValue = false; CapturedAt = -1f; DamageEvent = null; PlayerPos[0] = 0f; PlayerPos[1] = 0f; PlayerPos[2] = 0f; PlayerHp = 0f; PlayerShield = 0f; } private static TelemetryEvent CloneTelemetryEvent(TelemetryEvent src) { TelemetryEvent telemetryEvent = new TelemetryEvent(); telemetryEvent.t = src.t; telemetryEvent.type = src.type; telemetryEvent.value = src.value; telemetryEvent.canonical_event_id = src.canonical_event_id; telemetryEvent.authoritative = src.authoritative; telemetryEvent.synthetic = src.synthetic; telemetryEvent.source = src.source; telemetryEvent.evidence_role = src.evidence_role; telemetryEvent.attribution_method = src.attribution_method; telemetryEvent.attribution_confidence = src.attribution_confidence; telemetryEvent.attribution_inferred = src.attribution_inferred; telemetryEvent.attribution_chain_id = src.attribution_chain_id; telemetryEvent.attacker_id = src.attacker_id; telemetryEvent.attacker_type = src.attacker_type; telemetryEvent.attacker_pos[0] = src.attacker_pos[0]; telemetryEvent.attacker_pos[1] = src.attacker_pos[1]; telemetryEvent.attacker_pos[2] = src.attacker_pos[2]; telemetryEvent.is_killing_blow = src.is_killing_blow; telemetryEvent.hit_kind = src.hit_kind; telemetryEvent.dot_index = src.dot_index; telemetryEvent.dot_type = src.dot_type; telemetryEvent.dot_chain_id = src.dot_chain_id; telemetryEvent.dot_application_t = src.dot_application_t; telemetryEvent.dot_application_duration = src.dot_application_duration; telemetryEvent.dot_source_attack_name = src.dot_source_attack_name; telemetryEvent.dot_source_body_state = src.dot_source_body_state; telemetryEvent.dot_source_weapon_state = src.dot_source_weapon_state; telemetryEvent.dot_source_aim_state = src.dot_source_aim_state; telemetryEvent.dot_source_state_summary = src.dot_source_state_summary; telemetryEvent.has_blast_origin = src.has_blast_origin; telemetryEvent.has_blast_radius = src.has_blast_radius; telemetryEvent.blast_origin[0] = src.blast_origin[0]; telemetryEvent.blast_origin[1] = src.blast_origin[1]; telemetryEvent.blast_origin[2] = src.blast_origin[2]; telemetryEvent.blast_radius = src.blast_radius; telemetryEvent.has_persistent_area_center = src.has_persistent_area_center; telemetryEvent.has_persistent_area_radius = src.has_persistent_area_radius; telemetryEvent.persistent_area_center[0] = src.persistent_area_center[0]; telemetryEvent.persistent_area_center[1] = src.persistent_area_center[1]; telemetryEvent.persistent_area_center[2] = src.persistent_area_center[2]; telemetryEvent.persistent_area_radius = src.persistent_area_radius; telemetryEvent.persistent_area_measurement = src.persistent_area_measurement; telemetryEvent.distance_to_player = src.distance_to_player; telemetryEvent.inflictor_name = src.inflictor_name; telemetryEvent.inflictor_has_projectile_controller = src.inflictor_has_projectile_controller; telemetryEvent.has_projectile_path_evidence = src.has_projectile_path_evidence; telemetryEvent.victim_pos[0] = src.victim_pos[0]; telemetryEvent.victim_pos[1] = src.victim_pos[1]; telemetryEvent.victim_pos[2] = src.victim_pos[2]; telemetryEvent.has_victim_position = src.has_victim_position; telemetryEvent.has_attacker_position = src.has_attacker_position; telemetryEvent.has_inflictor_position = src.has_inflictor_position; telemetryEvent.has_attacker = src.has_attacker; telemetryEvent.has_inflictor = src.has_inflictor; telemetryEvent.inflictor_id = src.inflictor_id; telemetryEvent.inflictor_type = src.inflictor_type; telemetryEvent.attacker_forward[0] = src.attacker_forward[0]; telemetryEvent.attacker_forward[1] = src.attacker_forward[1]; telemetryEvent.attacker_forward[2] = src.attacker_forward[2]; telemetryEvent.attacker_body_state = src.attacker_body_state; telemetryEvent.attacker_weapon_state = src.attacker_weapon_state; telemetryEvent.attacker_aim_state = src.attacker_aim_state; telemetryEvent.attacker_state_summary = src.attacker_state_summary; telemetryEvent.vertical_distance_to_player = src.vertical_distance_to_player; telemetryEvent.damage_flags = src.damage_flags; telemetryEvent.damage_color_index = src.damage_color_index; telemetryEvent.proc_coefficient = src.proc_coefficient; telemetryEvent.is_environmental = src.is_environmental; telemetryEvent.unknown_signature = src.unknown_signature; return telemetryEvent; } } public class HostileContext { public string attacker_id = ""; public string attacker_type = ""; public float[] last_pos = new float[3]; public float last_seen_t = -1f; public float last_saw_player_t = -1f; public float last_los_t = -1f; public float last_damage_t = -1f; public float last_damage_value = 0f; public int damage_count = 0; public float last_distance_to_player = -1f; public string last_hit_kind = "unknown"; public int last_dot_index = -1; public string last_dot_type = ""; public string last_dot_chain_id = ""; public float last_dot_application_t = -1f; public float last_dot_application_duration = 0f; public string last_dot_source_attack_name = ""; public string last_dot_source_body_state = ""; public string last_dot_source_weapon_state = ""; public string last_dot_source_aim_state = ""; public string last_dot_source_state_summary = ""; public string last_inflictor_name = ""; public string last_inflictor_id = ""; public bool last_inflictor_has_projectile_controller = false; public string last_body_state = ""; public string last_weapon_state = ""; public string last_aim_state = ""; public string last_state_summary = ""; public float MostRecentEvidenceTime { get { float num = last_seen_t; if (last_saw_player_t > num) { num = last_saw_player_t; } if (last_los_t > num) { num = last_los_t; } if (last_damage_t > num) { num = last_damage_t; } return num; } } public bool IsRecent(float now, float window) { float mostRecentEvidenceTime = MostRecentEvidenceTime; if (mostRecentEvidenceTime < 0f) { return false; } float num = now - mostRecentEvidenceTime; return num >= 0f && num <= window; } } public class HostileContextCache { private readonly Dictionary<string, HostileContext> byAttackerId = new Dictionary<string, HostileContext>(); public IEnumerable<HostileContext> Values => byAttackerId.Values; public void Reset() { byAttackerId.Clear(); } public void Cleanup(float now, float window) { List<string> list = new List<string>(); foreach (KeyValuePair<string, HostileContext> item in byAttackerId) { if (!item.Value.IsRecent(now, window)) { list.Add(item.Key); } } for (int i = 0; i < list.Count; i++) { byAttackerId.Remove(list[i]); } } public void UpdateFromDamage(TelemetryEvent evt, float now) { if (evt != null && !evt.is_environmental && !IsUnknownAttacker(evt.attacker_id, evt.attacker_type)) { HostileContext orCreate = GetOrCreate(evt.attacker_id, evt.attacker_type); orCreate.attacker_type = evt.attacker_type ?? orCreate.attacker_type; if (evt.has_attacker_position) { orCreate.last_pos[0] = evt.attacker_pos[0]; orCreate.last_pos[1] = evt.attacker_pos[1]; orCreate.last_pos[2] = evt.attacker_pos[2]; orCreate.last_seen_t = now; orCreate.last_distance_to_player = evt.distance_to_player; } orCreate.last_damage_t = evt.t; orCreate.last_damage_value = evt.value; orCreate.damage_count++; orCreate.last_hit_kind = evt.hit_kind ?? "unknown"; orCreate.last_inflictor_name = evt.inflictor_name ?? ""; orCreate.last_inflictor_id = evt.inflictor_id ?? ""; orCreate.last_inflictor_has_projectile_controller = evt.inflictor_has_projectile_controller; orCreate.last_dot_index = evt.dot_index; orCreate.last_dot_type = evt.dot_type ?? ""; orCreate.last_dot_chain_id = evt.dot_chain_id ?? ""; orCreate.last_dot_application_t = evt.dot_application_t; orCreate.last_dot_application_duration = evt.dot_application_duration; orCreate.last_dot_source_attack_name = evt.dot_source_attack_name ?? ""; orCreate.last_dot_source_body_state = evt.dot_source_body_state ?? ""; orCreate.last_dot_source_weapon_state = evt.dot_source_weapon_state ?? ""; orCreate.last_dot_source_aim_state = evt.dot_source_aim_state ?? ""; orCreate.last_dot_source_state_summary = evt.dot_source_state_summary ?? ""; orCreate.last_body_state = evt.attacker_body_state ?? ""; orCreate.last_weapon_state = evt.attacker_weapon_state ?? ""; orCreate.last_aim_state = evt.attacker_aim_state ?? ""; orCreate.last_state_summary = evt.attacker_state_summary ?? ""; } } public void UpdateFromPerception(string attackerId, string attackerType, float x, float y, float z, float distanceToPlayer, bool hasLineOfSight, bool sawPlayer, string bodyState, string weaponState, string aimState, string stateSummary, float now) { if (!string.IsNullOrEmpty(attackerId)) { HostileContext orCreate = GetOrCreate(attackerId, attackerType); orCreate.attacker_type = attackerType ?? orCreate.attacker_type; orCreate.last_pos[0] = x; orCreate.last_pos[1] = y; orCreate.last_pos[2] = z; orCreate.last_seen_t = now; orCreate.last_distance_to_player = distanceToPlayer; if (hasLineOfSight) { orCreate.last_los_t = now; } if (sawPlayer) { orCreate.last_saw_player_t = now; } orCreate.last_body_state = bodyState ?? ""; orCreate.last_weapon_state = weaponState ?? ""; orCreate.last_aim_state = aimState ?? ""; orCreate.last_state_summary = stateSummary ?? ""; } } public bool TryGet(string attackerId, out HostileContext? context) { if (string.IsNullOrWhiteSpace(attackerId)) { context = null; return false; } return byAttackerId.TryGetValue(attackerId, out context); } private HostileContext GetOrCreate(string attackerId, string attackerType) { if (!byAttackerId.TryGetValue(attackerId, out HostileContext value)) { value = new HostileContext(); value.attacker_id = attackerId; value.attacker_type = attackerType ?? "Unknown"; byAttackerId[attackerId] = value; } return value; } private static bool IsUnknownAttacker(string attackerId, string attackerType) { if (string.IsNullOrWhiteSpace(attackerId) || string.Equals(attackerId, "unknown", StringComparison.OrdinalIgnoreCase)) { return true; } return string.Equals(attackerType, "Environment", StringComparison.OrdinalIgnoreCase) || string.Equals(attackerType, "Unknown", StringComparison.OrdinalIgnoreCase) || string.Equals(attackerType, "Unknown_Attacker", StringComparison.OrdinalIgnoreCase); } } public sealed class PreDamageAttributionEvidence { public string evidenceId = ""; public string evidenceKind = ""; public int victimInstanceId = 0; public string sourceId = ""; public string sourceType = ""; public bool hasSourcePosition = false; public float[] sourcePos = new float[3]; public float[] sourceForward = new float[3]; public string sourceBodyState = ""; public string sourceWeaponState = ""; public string sourceAimState = ""; public string sourceStateSummary = ""; public int dotIndex = -1; public string dotType = ""; public string dotChainId = ""; public float applicationT = -1f; public float applicationDuration = 0f; public float expiresT = -1f; public string sourceAttackName = ""; } public sealed class PreDamageAttributionLedger { private readonly Dictionary<string, PreDamageAttributionEvidence> evidenceById = new Dictionary<string, PreDamageAttributionEvidence>(); public void Reset() { evidenceById.Clear(); } public void UpsertDot(PreDamageAttributionEvidence evidence) { if (evidence != null && string.Equals(evidence.evidenceKind, "dot", StringComparison.Ordinal) && !string.IsNullOrEmpty(evidence.evidenceId) && !IsUnknownSourceId(evidence.sourceId)) { evidenceById[evidence.evidenceId] = evidence; } } public bool TryResolveDot(int victimInstanceId, int dotIndex, string reportedSourceId, float now, out PreDamageAttributionEvidence? resolved) { Cleanup(now); resolved = null; bool flag = !IsUnknownSourceId(reportedSourceId); int num = 0; foreach (PreDamageAttributionEvidence value in evidenceById.Values) { if (string.Equals(value.evidenceKind, "dot", StringComparison.Ordinal) && value.victimInstanceId == victimInstanceId && value.dotIndex == dotIndex && !(now > value.expiresT + 0.5f) && (!flag || string.Equals(value.sourceId, reportedSourceId, StringComparison.Ordinal))) { num++; if (resolved == null || value.applicationT > resolved.applicationT) { resolved = value; } } } if (flag) { return resolved != null; } return num == 1 && resolved != null; } private void Cleanup(float now) { List<string> list = new List<string>(); foreach (KeyValuePair<string, PreDamageAttributionEvidence> item in evidenceById) { if (now > item.Value.expiresT + 0.5f) { list.Add(item.Key); } } for (int i = 0; i < list.Count; i++) { evidenceById.Remove(list[i]); } } private static bool IsUnknownSourceId(string sourceId) { return string.IsNullOrWhiteSpace(sourceId) || string.Equals(sourceId, "unknown", StringComparison.OrdinalIgnoreCase); } } public class TelemetrySession { public RunTelemetry Telemetry { get; private set; } = new RunTelemetry(); public float RunTimer { get; set; } = 0f; public float SampleTimer { get; set; } = 0f; public float LastHealth { get; set; } = -1f; public bool HadBody { get; set; } = false; public bool DeathSaved { get; set; } = false; public string LastDamageFingerprint { get; set; } = ""; public float LastDamageLoggedAt { get; set; } = -999f; public int LastDamageEventIndex { get; set; } = -1; public CachedPlayerState LastKnownPlayerState { get; } = new CachedPlayerState(); public PendingLethalContext PendingLethalContext { get; } = new PendingLethalContext(); public HostileContextCache HostileContextCache { get; } = new HostileContextCache(); public PreDamageAttributionLedger PreDamageLedger { get; } = new PreDamageAttributionLedger(); public void Reset() { Telemetry = new RunTelemetry(); Telemetry.run_id = Guid.NewGuid().ToString(); Telemetry.stage = 1; RunTimer = 0f; SampleTimer = 0f; LastHealth = -1f; HadBody = false; DeathSaved = false; LastDamageFingerprint = ""; LastDamageLoggedAt = -999f; LastDamageEventIndex = -1; LastKnownPlayerState.Reset(); PendingLethalContext.Reset(); HostileContextCache.Reset(); PreDamageLedger.Reset(); } } [HarmonyPatch(typeof(BlastAttack), "Fire")] public static class BlastAttackPatches { private static void Prefix(BlastAttack __instance) { BlastEvidenceCache.Record(__instance); } } public static class BlastEvidenceCache { private sealed class BlastEvidence { public float capturedRealtime; public Vector3 origin; public float radius; public TeamIndex teamIndex = (TeamIndex)(-1); public string attackerId = ""; public string inflictorId = ""; public string inflictorName = ""; public string sourceId = ""; public string sourceType = ""; public bool hasSourcePosition = false; public Vector3 sourcePos; public Vector3 sourceForward; public string bodyState = ""; public string weaponState = ""; public string aimState = ""; public string stateSummary = ""; } private const float MaxEvidenceAgeSeconds = 0.35f; private const float MatchDistancePadding = 2f; private const float AmbiguousScoreMargin = 0.25f; private const int MaxEntries = 128; private static readonly List<BlastEvidence> entries = new List<BlastEvidence>(); public static void Clear() { entries.Clear(); } public static void Record(BlastAttack blast) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) if (blast != null && !(blast.radius <= 0f)) { float time = Time.time; Prune(time); BlastEvidence blastEvidence = new BlastEvidence { capturedRealtime = time, origin = blast.position, radius = Mathf.Max(0.05f, blast.radius), teamIndex = blast.teamIndex, attackerId = GetObjectId(blast.attacker), inflictorId = GetObjectId(blast.inflictor), inflictorName = (((Object)(object)blast.inflictor != (Object)null) ? (((Object)blast.inflictor).name ?? "") : "") }; CaptureSourceSnapshot(blastEvidence, ((Object)(object)blast.attacker != (Object)null) ? blast.attacker : blast.inflictor); entries.Add(blastEvidence); while (entries.Count > 128) { entries.RemoveAt(0); } } } public static bool TryApplyToEvent(TelemetryEvent evt, DamageInfo damageInfo, CharacterBody victimBody) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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) //IL_0057: 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) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Invalid comparison between Unknown and I4 //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Invalid comparison between Unknown and I4 //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_04d8: Unknown result type (might be due to invalid IL or missing references) //IL_04dd: Unknown result type (might be due to invalid IL or missing references) //IL_04f5: Unknown result type (might be due to invalid IL or missing references) if (evt == null || damageInfo == null || (Object)(object)victimBody == (Object)null || evt.is_environmental) { return false; } Vector3 corePosition = victimBody.corePosition; string objectId = GetObjectId(((Component)victimBody).gameObject); TeamIndex val = (TeamIndex)((!((Object)(object)victimBody.teamComponent != (Object)null)) ? (-1) : ((int)victimBody.teamComponent.teamIndex)); float time = Time.time; if (DeathVizHitPolicy.NormalizeHitKind(evt.hit_kind) == "dot" || evt.dot_index >= 0 || !string.IsNullOrWhiteSpace(evt.dot_type)) { return false; } Prune(time); string objectId2 = GetObjectId(damageInfo.attacker); string objectId3 = GetObjectId(damageInfo.inflictor); bool flag = !string.IsNullOrEmpty(objectId2) || !string.IsNullOrEmpty(objectId3); int num = -1; float num2 = float.MaxValue; float num3 = float.MaxValue; for (int i = 0; i < entries.Count; i++) { BlastEvidence blastEvidence = entries[i]; float num4 = time - blastEvidence.capturedRealtime; if (num4 < -0.05f || num4 > 0.35f) { continue; } float num5 = Vector3.Distance(corePosition, blastEvidence.origin); if (num5 > blastEvidence.radius + 2f) { continue; } bool flag2 = !string.IsNullOrEmpty(objectId2) && objectId2 == blastEvidence.attackerId; bool flag3 = !string.IsNullOrEmpty(objectId3) && objectId3 == blastEvidence.inflictorId; bool flag4 = (!string.IsNullOrEmpty(blastEvidence.sourceId) && blastEvidence.sourceId == objectId) || (!string.IsNullOrEmpty(blastEvidence.attackerId) && blastEvidence.attackerId == objectId); bool flag5 = (int)blastEvidence.teamIndex != -1 && (int)val != -1 && blastEvidence.teamIndex == val; if (flag || !(flag4 || flag5)) { float num6 = num4 * 2f + num5 * 0.01f; if ((!string.IsNullOrEmpty(blastEvidence.attackerId) || !string.IsNullOrEmpty(blastEvidence.inflictorId)) && !flag2 && !flag3) { num6 += 5f; } if (!string.IsNullOrEmpty(objectId3) && !flag3) { num6 += 0.75f; } if (num6 < num2) { num3 = num2; num2 = num6; num = i; } else if (num6 < num3) { num3 = num6; } } } if (num < 0) { return false; } BlastEvidence blastEvidence2 = entries[num]; bool flag6 = !string.IsNullOrEmpty(objectId2) || !string.IsNullOrEmpty(objectId3); bool flag7 = !string.IsNullOrEmpty(objectId2) && objectId2 == blastEvidence2.attackerId; bool flag8 = !string.IsNullOrEmpty(objectId3) && objectId3 == blastEvidence2.inflictorId; if (flag6 && !flag7 && !flag8) { return false; } if (!flag6 && num3 < float.MaxValue && num3 - num2 < 0.25f) { return false; } evt.has_blast_origin = true; evt.has_blast_radius = true; evt.blast_origin[0] = blastEvidence2.origin.x; evt.blast_origin[1] = blastEvidence2.origin.y; evt.blast_origin[2] = blastEvidence2.origin.z; evt.blast_radius = blastEvidence2.radius; bool flag9 = false; if (!evt.has_attacker && !string.IsNullOrWhiteSpace(blastEvidence2.sourceId)) { evt.attacker_id = blastEvidence2.sourceId; evt.attacker_type = ((!string.IsNullOrWhiteSpace(blastEvidence2.sourceType)) ? blastEvidence2.sourceType : "Unknown"); evt.has_attacker = true; evt.has_attacker_position = blastEvidence2.hasSourcePosition; evt.is_environmental = false; if (blastEvidence2.hasSourcePosition) { evt.attacker_pos[0] = blastEvidence2.sourcePos.x; evt.attacker_pos[1] = blastEvidence2.sourcePos.y; evt.attacker_pos[2] = blastEvidence2.sourcePos.z; evt.attacker_forward[0] = blastEvidence2.sourceForward.x; evt.attacker_forward[1] = blastEvidence2.sourceForward.y; evt.attacker_forward[2] = blastEvidence2.sourceForward.z; evt.distance_to_player = Vector3.Distance(blastEvidence2.sourcePos, corePosition); evt.vertical_distance_to_player = blastEvidence2.sourcePos.y - corePosition.y; } evt.attacker_body_state = blastEvidence2.bodyState; evt.attacker_weapon_state = blastEvidence2.weaponState; evt.attacker_aim_state = blastEvidence2.aimState; evt.attacker_state_summary = blastEvidence2.stateSummary; flag9 = true; } if (string.IsNullOrWhiteSpace(evt.inflictor_name)) { evt.inflictor_name = blastEvidence2.inflictorName; } evt.hit_kind = "aoe_blast"; evt.unknown_signature = ""; if (flag9) { evt.attribution_method = "blast_fire_snapshot"; evt.attribution_confidence = "linked"; evt.attribution_inferred = false; evt.attribution_chain_id = ((!string.IsNullOrEmpty(blastEvidence2.inflictorId)) ? blastEvidence2.inflictorId : blastEvidence2.sourceId); } AppendEventSource(evt, "blast_fire_snapshot"); return true; } private static void CaptureSourceSnapshot(BlastEvidence evidence, GameObject attackerObject) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Invalid comparison between Unknown and I4 //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) if (evidence == null || (Object)(object)attackerObject == (Object)null) { return; } CharacterBody val = ResolveBody(attackerObject); if (!((Object)(object)val == (Object)null)) { GameObject gameObject = ((Component)val).gameObject; evidence.sourceId = ((Object)gameObject).GetInstanceID().ToString(); evidence.sourceType = val.baseNameToken ?? ((Object)val).name ?? "Unknown"; evidence.sourcePos = val.corePosition; evidence.sourceForward = gameObject.transform.forward; evidence.hasSourcePosition = true; if ((int)evidence.teamIndex == -1 && (Object)(object)val.teamComponent != (Object)null) { evidence.teamIndex = val.teamComponent.teamIndex; } evidence.bodyState = GetStateTypeName(gameObject, "Body"); evidence.weaponState = GetStateTypeName(gameObject, "Weapon"); evidence.aimState = GetStateTypeName(gameObject, "Aim"); evidence.stateSummary = BuildStateSummary(evidence.bodyState, evidence.weaponState, evidence.aimState); } } private static CharacterBody ResolveBody(GameObject source) { if ((Object)(object)source == (Object)null) { return null; } CharacterBody component = source.GetComponent<CharacterBody>(); if ((Object)(object)component != (Object)null) { return component; } CharacterMaster component2 = source.GetComponent<CharacterMaster>(); if ((Object)(object)component2 != (Object)null && (Object)(object)component2.GetBody() != (Object)null) { return component2.GetBody(); } ProjectileController component3 = source.GetComponent<ProjectileController>(); if ((Object)(object)component3 != (Object)null && (Object)(object)component3.owner != (Object)null && (Object)(object)component3.owner != (Object)(object)source) { return ResolveBody(component3.owner); } return source.GetComponentInParent<CharacterBody>(); } private static string GetStateTypeName(GameObject stateObject, string machineName) { if ((Object)(object)stateObject == (Object)null) { return ""; } EntityStateMachine[] components = stateObject.GetComponents<EntityStateMachine>(); foreach (EntityStateMachine val in components) { if (!((Object)(object)val == (Object)null) && !(val.customName != machineName) && val.state != null) { Type type = ((object)val.state).GetType(); return type.FullName ?? type.Name ?? ""; } } return ""; } private static string BuildStateSummary(string bodyState, string weaponState, string aimState) { List<string> list = new List<string>(); if (!string.IsNullOrWhiteSpace(bodyState)) { list.Add("Body=" + bodyState); } if (!string.IsNullOrWhiteSpace(weaponState)) { list.Add("Weapon=" + weaponState); } if (!string.IsNullOrWhiteSpace(aimState)) { list.Add("Aim=" + aimState); } return string.Join(" | ", list); } private static void AppendEventSource(TelemetryEvent evt, string sourceMarker) { if (string.IsNullOrWhiteSpace(evt.source)) { evt.source = sourceMarker; } else if (evt.source.IndexOf(sourceMarker, StringComparison.Ordinal) < 0) { evt.source = evt.source + "+" + sourceMarker; } } private static void Prune(float now) { for (int num = entries.Count - 1; num >= 0; num--) { if (now - entries[num].capturedRealtime > 0.35f) { entries.RemoveAt(num); } } } private static string GetObjectId(GameObject obj) { return ((Object)(object)obj != (Object)null) ? ((Object)obj).GetInstanceID().ToString() : ""; } } public class DamageClassifier { public string ClassifyHitKind(CharacterBody? attacker, DamageInfo damageInfo, float distance, bool hasProjectileController) { return ClassifyHitKind(attacker, damageInfo, distance, hasProjectileController, "", "", "", ""); } public string ClassifyHitKind(CharacterBody? attacker, DamageInfo damageInfo, float distance, bool hasProjectileController, string attackerBodyState, string attackerWeaponState, string attackerAimState, string attackerStateSummary) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: 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_0031: Invalid comparison between Unknown and I4 //IL_00ba: Unknown result type (might be due to invalid IL or missing references) bool flag = (Object)(object)attacker != (Object)null; bool flag2 = (Object)(object)damageInfo.inflictor != (Object)null; if ((int)DamageTypeCombo.op_Implicit(damageInfo.damageType & DamageTypeCombo.op_Implicit((DamageType)2097152)) > 0) { return "fall_damage"; } if (!flag && !flag2) { return "unknown"; } string text = (flag ? (attacker.baseNameToken ?? "").ToLowerInvariant() : ""); string text2 = (flag2 ? ((Object)damageInfo.inflictor).name.ToLowerInvariant() : ""); string value = BuildRuntimeStateText(attackerBodyState, attackerWeaponState, attackerAimState, attackerStateSummary); float num = 0f; if (flag) { num = attacker.corePosition.y - damageInfo.position.y; } if (hasProjectileController) { return "projectile"; } if (ContainsAny(text2, "firetrail", "dot", "burn", "bleed", "poison", "blight") || ContainsAny(value, "firetrail", "dot", "burn", "bleed", "poison", "blight")) { return "dot"; } if (ContainsAny(text2, "blast", "explosion", "bomb", "nova") || ContainsAny(value, "meganova", "nova", "explosion", "explode", "detonate", "blast")) { return "aoe_blast"; } if (ContainsAny(text2, "wave", "quake", "slam", "ground", "spike", "pillar", "pool") || ContainsAny(value, "groundslam", "slam", "quake", "shockwave", "ground", "pillar", "spike", "pool")) { return "aoe_ground"; } if (ContainsAny(text2, "beam", "laser", "breath", "flamethrower", "cone") || ContainsAny(value, "beam", "laser", "firelaser", "chargelaser", "breath", "flamethrower", "cone")) { return "beam_or_cone"; } if (text.Contains("golem") && text2.Contains("golembody") && distance > 5f) { return "beam_or_cone"; } if (text.Contains("titan") && text2.Contains("titanbody") && damageInfo.procCoefficient <= 0.15f) { return "beam_or_cone"; } if (text.Contains("wisp") && text2.Contains("wispbody") && distance > 8f && damageInfo.procCoefficient <= 0.34f) { return "beam_or_cone"; } if (text.Contains("beetleguard") && text2.Contains("beetleguardbody") && distance <= 8f) { return "aoe_ground"; } if (text.Contains("beetleguard") && text2.Contains("sunder")) { return "projectile"; } if (flag && flag2 && (Object)(object)damageInfo.inflictor == (Object)(object)((Component)attacker).gameObject && distance <= 5.5f && Mathf.Abs(num) <= 3.5f) { return "melee"; } if (flag && !hasProjectileController && distance <= 5.5f && Mathf.Abs(num) <= 3.5f) { return "melee"; } if (!flag && flag2 && (text2.Contains("trap") || text2.Contains("hazard") || text2.Contains("ward"))) { return "environment"; } if (flag && !hasProjectileController && distance > 5.5f) { return "hitscan"; } return "unknown"; } public string ResolveDotType(DamageInfo damageInfo, string attackerBodyState, string attackerWeaponState, string attackerAimState, string attackerStateSummary) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 if ((int)damageInfo.dotIndex != -1) { return ((object)Unsafe.As<DotIndex, DotIndex>(ref damageInfo.dotIndex)/*cast due to .constrained prefix*/).ToString(); } string text = (((Object)(object)damageInfo.inflictor != (Object)null) ? ((Object)damageInfo.inflictor).name.ToLowerInvariant() : ""); string text2 = BuildRuntimeStateText(attackerBodyState, attackerWeaponState, attackerAimState, attackerStateSummary); string value = text + " " + text2; if (ContainsAny(value, "bleed", "hemorrhage")) { return "Bleed"; } if (ContainsAny(value, "poison", "venom")) { return "Poison"; } if (ContainsAny(value, "blight")) { return "Blight"; } if (ContainsAny(value, "collapse", "fracture")) { return "Collapse"; } if (ContainsAny(value, "firetrail", "fire trail", "burn", "ignite", "flame", "hellfire", "helfire")) { return "Burn"; } return ""; } public string BuildUnknownSignature(TelemetryEvent evt) { return string.Join("|", evt.attacker_type ?? "", evt.inflictor_name ?? "", evt.inflictor_type ?? "", evt.has_attacker ? "has_attacker" : "no_attacker", evt.has_inflictor ? "has_inflictor" : "no_inflictor", evt.inflictor_has_projectile_controller ? "projctrl" : "no_projctrl", GetDistanceBucket(evt.distance_to_player), GetVerticalBucket(evt.vertical_distance_to_player), evt.proc_coefficient.ToString("F3"), evt.damage_flags.ToString(), evt.attacker_body_state ?? "", evt.attacker_weapon_state ?? "", evt.attacker_aim_state ?? "", evt.attacker_state_summary ?? ""); } private static string BuildRuntimeStateText(string bodyState, string weaponState, string aimState, string stateSummary) { return string.Join(" ", bodyState ?? "", weaponState ?? "", aimState ?? "", stateSummary ?? "").ToLowerInvariant(); } private static bool ContainsAny(string value, params string[] tokens) { if (string.IsNullOrWhiteSpace(value) || tokens == null) { return false; } foreach (string value2 in tokens) { if (!string.IsNullOrWhiteSpace(value2) && value.Contains(value2)) { return true; } } return false; } private string GetDistanceBucket(float distance) { if (distance < 0f) { return "unknown_dist"; } if (distance <= 5f) { return "0_5"; } if (distance <= 10f) { return "5_10"; } if (distance <= 20f) { return "10_20"; } if (distance <= 35f) { return "20_35"; } return "35_plus"; } private string GetVerticalBucket(float verticalDistance) { float num = Mathf.Abs(verticalDistance); if (num <= 2f) { return "flat"; } if (num <= 6f) { return "mid"; } return "high"; } } public class DamageEventBuilder { public TelemetryEvent BuildDamageEvent(CharacterBody? attacker, DamageInfo damageInfo, CharacterBody victimBody, float eventTime, DamageClassifier damageClassifier) { //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_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_0471: Unknown result type (might be due to invalid IL or missing references) //IL_0480: Unknown result type (might be due to invalid IL or missing references) //IL_048f: Unknown result type (might be due to invalid IL or missing references) //IL_049e: Unknown result type (might be due to invalid IL or missing references) //IL_04ae: Unknown result type (might be due to invalid IL or missing references) //IL_04be: Unknown result type (might be due to invalid IL or missing references) //IL_04e8: Unknown result type (might be due to invalid IL or missing references) //IL_04f7: Unknown result type (might be due to invalid IL or missing references) //IL_0506: Unknown result type (might be due to invalid IL or missing references) //IL_058e: Unknown result type (might be due to invalid IL or missing references) //IL_0598: Expected I4, but got Unknown //IL_059b: Unknown result type (might be due to invalid IL or missing references) //IL_05a1: Invalid comparison between Unknown and I4 //IL_05d0: Unknown result type (might be due to invalid IL or missing references) //IL_05e3: Unknown result type (might be due to invalid IL or missing references) //IL_05ed: Expected I4, but got Unknown Vector3 val = Vector3.zero; string text = ""; string text2 = ""; string text3 = ""; string text4 = ""; GameObject val2 = (((Object)(object)attacker != (Object)null) ? ((Component)attacker).gameObject : damageInfo.attacker); if ((Object)(object)attacker == (Object)null && (Object)(object)val2 != (Object)null) { attacker = ResolveAttackerBody(val2); if ((Object)(object)attacker != (Object)null) { val2 = ((Component)attacker).gameObject; } } if ((Object)(object)attacker == (Object)null && (Object)(object)val2 == (Object)null && (Object)(object)damageInfo.inflictor != (Object)null) { ProjectileController component = damageInfo.inflictor.GetComponent<ProjectileController>(); if ((Object)(object)component != (Object)null && (Object)(object)component.owner != (Object)null) { attacker = ResolveAttackerBody(component.owner); val2 = (((Object)(object)attacker != (Object)null) ? ((Component)attacker).gameObject : component.owner); } } bool flag = (Object)(object)val2 != (Object)null || (Object)(object)attacker != (Object)null; bool flag2 = (Object)(object)damageInfo.inflictor != (Object)null; string attacker_id; string attacker_type; Vector3 val3; if ((Object)(object)attacker != (Object)null) { attacker_id = ((Object)((Component)attacker).gameObject).GetInstanceID().ToString(); attacker_type = attacker.baseNameToken ?? "Unknown"; val3 = attacker.corePosition; val = ((Component)attacker).transform.forward; text = GetStateTypeName(((Component)attacker).gameObject, "Body"); text2 = GetStateTypeName(((Component)attacker).gameObject, "Weapon"); text3 = GetStateTypeName(((Component)attacker).gameObject, "Aim"); text4 = BuildStateSummary(text, text2, text3); } else if ((Object)(object)val2 != (Object)null) { attacker_id = ((Object)val2).GetInstanceID().ToString(); attacker_type = ((Object)val2).name ?? ((object)val2).GetType().Name; val3 = val2.transform.position; val = val2.transform.forward; } else { attacker_id = "unknown"; attacker_type = (flag2 ? "Unknown_Attacker" : "Unknown"); val3 = (((Object)(object)damageInfo.inflictor != (Object)null) ? damageInfo.inflictor.transform.position : victimBody.corePosition); } Vector3 corePosition = victimBody.corePosition; float num = ((flag || flag2) ? Vector3.Distance(val3, corePosition) : (-1f)); float vertical_distance_to_player = ((flag || flag2) ? (val3.y - corePosition.y) : 0f); bool flag3 = (Object)(object)damageInfo.inflictor != (Object)null && (Object)(object)damageInfo.inflictor.GetComponent<ProjectileController>() != (Object)null; string inflictor_name = (((Object)(object)damageInfo.inflictor != (Object)null) ? ((Object)damageInfo.inflictor).name : ""); string inflictor_id = (((Object)(object)damageInfo.inflictor != (Object)null) ? ((Object)damageInfo.inflictor).GetInstanceID().ToString() : ""); string inflictor_type = (((Object)(object)damageInfo.inflictor != (Object)null) ? ((object)damageInfo.inflictor).GetType().Name : ""); string text5 = damageClassifier.ClassifyHitKind(attacker, damageInfo, num, flag3, text, text2, text3, text4); bool flag4 = string.Equals(text5, "environment", StringComparison.OrdinalIgnoreCase) || string.Equals(text5, "fall_damage", StringComparison.OrdinalIgnoreCase); if (flag4 && !flag) { attacker_type = "Environment"; } TelemetryEvent telemetryEvent = new TelemetryEvent(); telemetryEvent.t = eventTime; telemetryEvent.type = "damage_taken"; telemetryEvent.value = damageInfo.damage; telemetryEvent.canonical_event_id = Guid.NewGuid().ToString("N"); telemetryEvent.authoritative = false; telemetryEvent.synthetic = false; telemetryEvent.source = "take_damage_postfix"; telemetryEvent.evidence_role = "normal_damage"; if (flag) { telemetryEvent.attribution_method = "damage_info_attacker"; telemetryEvent.attribution_confidence = "reported"; } else if (flag2) { telemetryEvent.attribution_method = "damage_info_inflictor_only"; telemetryEvent.attribution_confidence = "partial"; } else if (flag4) { telemetryEvent.attribution_method = "explicit_environment"; telemetryEvent.attribution_confidence = "reported"; } else { telemetryEvent.attribution_method = "unresolved"; telemetryEvent.attribution_confidence = "none"; } telemetryEvent.attacker_id = attacker_id; telemetryEvent.attacker_type = attacker_type; telemetryEvent.attacker_pos[0] = val3.x; telemetryEvent.attacker_pos[1] = val3.y; telemetryEvent.attacker_pos[2] = val3.z; telemetryEvent.victim_pos[0] = corePosition.x; telemetryEvent.victim_pos[1] = corePosition.y; telemetryEvent.victim_pos[2] = corePosition.z; telemetryEvent.has_victim_position = true; telemetryEvent.has_attacker_position = flag; telemetryEvent.has_inflictor_position = flag2; telemetryEvent.attacker_forward[0] = val.x; telemetryEvent.attacker_forward[1] = val.y; telemetryEvent.attacker_forward[2] = val.z; telemetryEvent.attacker_body_state = text; telemetryEvent.attacker_weapon_state = text2; telemetryEvent.attacker_aim_state = text3; telemetryEvent.attacker_state_summary = text4; telemetryEvent.hit_kind = text5; telemetryEvent.distance_to_player = num; telemetryEvent.vertical_distance_to_player = vertical_distance_to_player; telemetryEvent.has_attacker = flag; telemetryEvent.has_inflictor = flag2; telemetryEvent.is_environmental = flag4; telemetryEvent.inflictor_name = inflictor_name; telemetryEvent.inflictor_id = inflictor_id; telemetryEvent.inflictor_type = inflictor_type; telemetryEvent.inflictor_has_projectile_controller = flag3; telemetryEvent.dot_index = (int)damageInfo.dotIndex; telemetryEvent.dot_type = (((int)damageInfo.dotIndex != -1 || text5 == "dot") ? damageClassifier.ResolveDotType(damageInfo, text, text2, text3, text4) : ""); telemetryEvent.damage_flags = (uint)DamageTypeCombo.op_Implicit(damageInfo.damageType); telemetryEvent.damage_color_index = (int)damageInfo.damageColorIndex; telemetryEvent.proc_coefficient = damageInfo.procCoefficient; ApplyKnownEnvironmentalDamageEvidence(telemetryEvent, damageInfo); BlastEvidenceCache.TryApplyToEvent(telemetryEvent, damageInfo, victimBody); ApplyPersistentAreaEvidence(telemetryEvent, damageInfo.inflictor); if (telemetryEvent.hit_kind == "unknown") { telemetryEvent.unknown_signature = damageClassifier.BuildUnknownSignature(telemetryEvent); } else { telemetryEvent.unknown_signature = ""; } return telemetryEvent; } private static bool ApplyKnownEnvironmentalDamageEvidence(TelemetryEvent damageEvent, DamageInfo damageInfo) { if (damageEvent == null || damageInfo == null) { return false; } if (!((Object)(object)damageInfo.attacker == (Object)null) || !((Object)(object)damageInfo.inflictor == (Object)null) || damageEvent.damage_flags != 66 || damageEvent.damage_color_index != 9) { return false; } damageEvent.attacker_id = "environment:void_fog"; damageEvent.attacker_type = "Void Fog"; damageEvent.has_attacker = false; damageEvent.has_inflictor = false; damageEvent.has_attacker_position = false; damageEvent.has_inflictor_position = false; damageEvent.distance_to_player = -1f; damageEvent.vertical_distance_to_player = 0f; damageEvent.hit_kind = "persistent_area"; damageEvent.is_environmental = true; damageEvent.unknown_signature = ""; damageEvent.attribution_method = "void_fog_signature"; damageEvent.attribution_confidence = "reported"; damageEvent.attribution_inferred = false; damageEvent.attribution_chain_id = "environment:void_fog"; damageEvent.source = (string.IsNullOrWhiteSpace(damageEvent.source) ? "void_fog_signature" : (damageEvent.source + "+void_fog_signature")); return true; } public bool ApplyPersistentAreaEvidence(TelemetryEvent damageEvent, GameObject? inflictor) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018c: 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_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_0281: Unknown result type (might be due to invalid IL or missing references) if (damageEvent == null || (Object)(object)inflictor == (Object)null) { return false; } bool flag = string.Equals(damageEvent.hit_kind, "persistent_area", StringComparison.OrdinalIgnoreCase); bool flag2 = false; Transform transform = inflictor.transform; bool flag3 = false; Bounds val = default(Bounds); Component[] componentsInChildren = inflictor.GetComponentsInChildren<Component>(true); foreach (Component val2 in componentsInChildren) { if ((Object)(object)val2 == (Object)null) { continue; } string name = ((object)val2).GetType().Name; if (string.Equals(name, "ProjectileDotZone", StringComparison.Ordinal)) { flag2 = true; transform = val2.transform; } if (!string.Equals(name, "HitBox", StringComparison.Ordinal)) { continue; } Collider component = val2.GetComponent<Collider>(); if ((Object)(object)component == (Object)null || !component.enabled) { continue; } Bounds bounds = component.bounds; Vector3 size = ((Bounds)(ref bounds)).size; if (!(((Vector3)(ref size)).sqrMagnitude <= 0.0001f)) { if (!flag3) { val = bounds; flag3 = true; } else { ((Bounds)(ref val)).Encapsulate(bounds); } } } if (!flag && !flag2) { return false; } if (flag2) { damageEvent.hit_kind = "persistent_area"; damageEvent.unknown_signature = ""; } if (!damageEvent.has_persistent_area_center) { Vector3 position = transform.position; damageEvent.has_persistent_area_center = true; damageEvent.persistent_area_center[0] = position.x; damageEvent.persistent_area_center[1] = position.y; damageEvent.persistent_area_center[2] = position.z; } if (string.IsNullOrWhiteSpace(damageEvent.persistent_area_measurement)) { damageEvent.persistent_area_measurement = (flag2 ? "projectile_dot_zone_transform" : "stationary_projectile_transform"); } if (!flag3) { return true; } float num = Mathf.Max(((Bounds)(ref val)).extents.x, ((Bounds)(ref val)).extents.z); if (num <= 0.01f) { return true; } Vector3 center = ((Bounds)(ref val)).center; center.y = transform.position.y; damageEvent.has_persistent_area_center = true; damageEvent.has_persistent_area_radius = true; damageEvent.persistent_area_center[0] = center.x; damageEvent.persistent_area_center[1] = center.y; damageEvent.persistent_area_center[2] = center.z; damageEvent.persistent_area_radius = num; damageEvent.persistent_area_measurement = (flag2 ? "projectile_dot_zone_hitbox_bounds" : "stationary_projectile_hitbox_bounds"); return true; } public string BuildDamageFingerprint(TelemetryEvent evt) { string text = ((!string.IsNullOrEmpty(evt.inflictor_id)) ? evt.inflictor_id : (evt.inflictor_name ?? "")); return string.Join("|", evt.attacker_id ?? "", evt.attacker_type ?? "", text, evt.hit_kind ?? "", evt.dot_index.ToString(), evt.dot_chain_id ?? "", evt.damage_flags.ToString(), evt.damage_color_index.ToString(), evt.proc_coefficient.ToString("F3"), evt.distance_to_player.ToString("F2"), evt.vertical_distance_to_player.ToString("F2"), evt.victim_pos[0].ToString("F2"), evt.victim_pos[1].ToString("F2"), evt.victim_pos[2].ToString("F2")); } private static string GetStateTypeName(GameObject obj, string machineName) { if ((Object)(object)obj == (Object)null) { return ""; } EntityStateMachine[] components = obj.GetComponents<EntityStateMachine>(); foreach (EntityStateMachine val in components) { if (!((Object)(object)val == (Object)null) && !(val.customName != machineName)) { if (val.state == null) { return ""; } Type type = ((object)val.state).GetType(); return type.FullName ?? type.Name ?? ""; } } return ""; } private static CharacterBody? ResolveAttackerBody(GameObject attackerObject) { if ((Object)(object)attackerObject == (Object)null) { return null; } CharacterBody component = attackerObject.GetComponent<CharacterBody>(); if ((Object)(object)component != (Object)null) { return component; } CharacterMaster component2 = attackerObject.GetComponent<CharacterMaster>(); if ((Object)(object)component2 != (Object)null && (Object)(object)component2.GetBody() != (Object)null) { return component2.GetBody(); } ProjectileController component3 = attackerObject.GetComponent<ProjectileController>(); if ((Object)(object)component3 != (Object)null && (Object)(object)component3.owner != (Object)null && (Object)(object)component3.owner != (Object)(object)attackerObject) { return ResolveAttackerBody(component3.owner); } return attackerObject.GetComponentInParent<CharacterBody>(); } private static string BuildStateSummary(string bodyState, string weaponState, string aimState) { List<string> list = new List<string>(); if (!string.IsNullOrEmpty(bodyState)) { list.Add("Body=" + bodyState); } if (!string.IsNullOrEmpty(weaponState)) { list.Add("Weapon=" + weaponState); } if (!string.IsNullOrEmpty(aimState)) { list.Add("Aim=" + aimState); } return string.Join(" | ", list); } } [HarmonyPatch(typeof(HealthComponent), "TakeDamage")] public static class DamagePatches { private struct PlayerSurvivabilitySnapshot { public bool isLocalPlayer; public float total; } private static void Prefix(HealthComponent __instance, out PlayerSurvivabilitySnapshot __state) { __state = default(PlayerSurvivabilitySnapshot); if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance.body == (Object)null)) { LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser(); CharacterBody val = ((firstLocalUser != null) ? firstLocalUser.cachedBody : null); if (!((Object)(object)val == (Object)null) && !((Object)(object)__instance.body != (Object)(object)val)) { __state.isLocalPlayer = true; __state.total = GetCurrentSurvivability(__instance); } } } private static void Postfix(HealthComponent __instance, DamageInfo damageInfo, PlayerSurvivabilitySnapshot __state) { if ((Object)(object)Plugin.Instance == (Object)null || (Object)(object)__instance == (Object)null || !__state.isLocalPlayer || damageInfo == null || damageInfo.damage <= 0f) { return; } float currentSurvivability = GetCurrentSurvivability(__instance); float num = __state.total - currentSurvivability; if (!(num <= 0.001f)) { CharacterBody attacker = null; if ((Object)(object)damageInfo.attacker != (Object)null) { attacker = damageInfo.attacker.GetComponent<CharacterBody>(); } Plugin.Instance.RegisterDamage(attacker, damageInfo); } } private static float GetCurrentSurvivability(HealthComponent healthComponent) { if ((Object)(object)healthComponent == (Object)null) { return 0f; } return Mathf.Max(0f, healthComponent.health) + Mathf.Max(0f, healthComponent.shield) + Mathf.Max(0f, healthComponent.barrier); } } public sealed class DotAttributionTracker { private sealed class DotChain { public int victimInstanceId; public string attackerId = ""; public int dotIndex = -1; public string dotType = ""; public string chainId = ""; public float applicationT = -1f; public float applicationDuration = 0f; public float expiresT = -1f; public bool capturedFromApplication = false; public string sourceAttackName = ""; public string sourceBodyState = ""; public string sourceWeaponState = ""; public string sourceAimState = ""; public string sourceStateSummary = ""; public string sourceType = ""; public bool hasSourcePosition = false; public float[] sourcePos = new float[3]; public float[] sourceForward = new float[3]; } private sealed class RecentDirectDamage { public TelemetryEvent damageEvent = new TelemetryEvent(); public float observedT = -1f; } private readonly Dictionary<string, DotChain> activeChains = new Dictionary<string, DotChain>(); private readonly Dictionary<string, RecentDirectDamage> recentDirectDamage = new Dictionary<string, RecentDirectDamage>(); public void Reset() { activeChains.Clear(); recentDirectDamage.Clear(); } public unsafe void RegisterApplication(InflictDotInfo dotInfo, CharacterBody localVictim, float now, RegistryService registryService, PreDamageAttributionLedger preDamageLedger) { //IL_000a: 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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected I4, but got Unknown //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be