Decompiled source of DeathViz3D v1.3.0

plugins/DeathViz3D.dll

Decompiled 21 hours ago
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