Decompiled source of Zips Killfeed v1.2.1

BepInEx/plugins/ZipsKillfeed/ZipsKillfeed.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using ExitGames.Client.Photon;
using HarmonyLib;
using InControl;
using Photon.Pun;
using Photon.Realtime;
using TMPro;
using UnboundLib;
using UnboundLib.GameModes;
using UnboundLib.Utils.UI;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: InternalsVisibleTo("ZipsKillfeedProbe")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("ZipsKillfeed")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.2.1.0")]
[assembly: AssemblyInformationalVersion("1.2.1")]
[assembly: AssemblyProduct("ZipsKillfeed")]
[assembly: AssemblyTitle("ZipsKillfeed")]
[assembly: AssemblyVersion("1.2.1.0")]
namespace ZipsKillfeed;

internal sealed class StatLine
{
	internal string Label;

	internal string Value;

	internal StatLine(string label, string value)
	{
		Label = label;
		Value = value;
	}
}
internal sealed class BuildProfile
{
	internal BuildClass Kind;

	internal string Name;

	internal Dictionary<BuildClass, int> Scores = new Dictionary<BuildClass, int>();

	internal List<StatLine> Stats = new List<StatLine>();
}
internal static class BuildClassifier
{
	private sealed class CachedProfile
	{
		internal float Checked;

		internal int Signature;

		internal BuildProfile Profile;
	}

	private static readonly Dictionary<int, CachedProfile> Cache = new Dictionary<int, CachedProfile>();

	private static readonly BuildClass[] Classes = new BuildClass[7]
	{
		BuildClass.Damage,
		BuildClass.Health,
		BuildClass.Sniper,
		BuildClass.Sustain,
		BuildClass.Ricochet,
		BuildClass.Magazine,
		BuildClass.Block
	};

	private static readonly Regex Number = new Regex("[-+]?\\d+(?:[.,]\\d+)?", RegexOptions.Compiled);

	internal static string ClassName(BuildClass kind)
	{
		return kind switch
		{
			BuildClass.Damage => "Damage", 
			BuildClass.Health => "Health", 
			BuildClass.Sniper => "Sharpshooter", 
			BuildClass.Sustain => "Vampire", 
			BuildClass.Ricochet => "Ricochet", 
			BuildClass.Magazine => "Gunner", 
			BuildClass.Block => "Guardian", 
			_ => "Unclassified", 
		};
	}

	internal static BuildProfile For(Player player)
	{
		if (!Object.op_Implicit((Object)(object)player) || (Object)(object)player.data == (Object)null)
		{
			return Empty();
		}
		int num = 17;
		List<CardInfo> currentCards = player.data.currentCards;
		if (currentCards != null)
		{
			foreach (CardInfo item in currentCards)
			{
				num = num * 31 + (Object.op_Implicit((Object)(object)item) ? ((Object)item).GetInstanceID() : 0);
			}
		}
		if (!Cache.TryGetValue(((Object)player).GetInstanceID(), out var value))
		{
			value = new CachedProfile();
			Cache[((Object)player).GetInstanceID()] = value;
		}
		if (value.Profile == null || value.Signature != num || Time.unscaledTime - value.Checked > 0.75f)
		{
			value.Profile = Describe(player);
			value.Signature = num;
			value.Checked = Time.unscaledTime;
		}
		return value.Profile;
	}

	private static BuildProfile Empty()
	{
		BuildProfile buildProfile = new BuildProfile
		{
			Kind = BuildClass.Unclassified,
			Name = ClassName(BuildClass.Unclassified)
		};
		BuildClass[] classes = Classes;
		foreach (BuildClass key in classes)
		{
			buildProfile.Scores[key] = 0;
		}
		return buildProfile;
	}

	private static BuildProfile Describe(Player player)
	{
		BuildProfile buildProfile = Empty();
		BuildClass[] classes;
		if (player.data.currentCards != null)
		{
			foreach (CardInfo currentCard in player.data.currentCards)
			{
				if (Object.op_Implicit((Object)(object)currentCard))
				{
					Dictionary<BuildClass, int> dictionary = ScoreCard(currentCard);
					classes = Classes;
					foreach (BuildClass key in classes)
					{
						buildProfile.Scores[key] += dictionary[key];
					}
				}
			}
		}
		int num = 0;
		classes = Classes;
		foreach (BuildClass buildClass in classes)
		{
			int num2 = buildProfile.Scores[buildClass];
			if (num2 > num)
			{
				num = num2;
				buildProfile.Kind = buildClass;
			}
		}
		buildProfile.Name = ClassName(buildProfile.Kind);
		PopulateStats(player, buildProfile.Stats);
		return buildProfile;
	}

	internal static Dictionary<BuildClass, int> ScoreCard(CardInfo card)
	{
		Dictionary<BuildClass, int> dictionary = new Dictionary<BuildClass, int>();
		BuildClass[] classes = Classes;
		foreach (BuildClass key in classes)
		{
			dictionary[key] = 0;
		}
		if (!Object.op_Implicit((Object)(object)card))
		{
			return dictionary;
		}
		Gun component = ((Component)card).GetComponent<Gun>();
		CharacterStatModifiers component2 = ((Component)card).GetComponent<CharacterStatModifiers>();
		Block componentInChildren = ((Component)card).GetComponentInChildren<Block>(true);
		float num = (Object.op_Implicit((Object)(object)component) ? (component.damage - 1f) : 0f);
		float num2 = (Object.op_Implicit((Object)(object)component2) ? (component2.health - 1f) : 0f);
		float num3 = (Object.op_Implicit((Object)(object)component) ? (component.projectileSpeed - 1f) : 0f);
		float num4 = (Object.op_Implicit((Object)(object)component2) ? component2.lifeSteal : 0f);
		float num5 = (Object.op_Implicit((Object)(object)component2) ? (component2.regen / 100f) : 0f);
		float num6 = (Object.op_Implicit((Object)(object)component) ? component.reflects : 0);
		float num7 = (Object.op_Implicit((Object)(object)component) ? component.ammo : 0);
		float num8 = (Object.op_Implicit((Object)(object)component) ? (1f - component.reloadTime) : 0f);
		float num9 = (Object.op_Implicit((Object)(object)component) ? (0f - component.reloadTimeAdd) : 0f);
		bool block = Object.op_Implicit((Object)(object)componentInChildren) && (componentInChildren.additionalBlocks != 0 || componentInChildren.cdAdd != 0f || Mathf.Abs(componentInChildren.cdMultiplier - 1f) > 0.0001f || componentInChildren.healing != 0f || componentInChildren.forceToAdd != 0f || componentInChildren.forceToAddUp != 0f || componentInChildren.autoBlock || (componentInChildren.objectsToSpawn != null && componentInChildren.objectsToSpawn.Count > 0));
		bool improvedBlock = Object.op_Implicit((Object)(object)componentInChildren) && (componentInChildren.additionalBlocks > 0 || componentInChildren.cdAdd < 0f || componentInChildren.cdMultiplier < 0.9999f);
		float num10 = 0f;
		float num11 = 0f;
		float num12 = 0f;
		float num13 = 0f;
		float num14 = 0f;
		float num15 = 0f;
		float num16 = 0f;
		float num17 = 0f;
		float num18 = 0f;
		if (card.cardStats != null && !IsUltimateCard(card))
		{
			CardInfoStat[] cardStats = card.cardStats;
			foreach (CardInfoStat val in cardStats)
			{
				if (val == null)
				{
					continue;
				}
				string text = (val.stat ?? "").ToLowerInvariant().Replace("-", " ");
				string text2 = (val.amount ?? "").Trim().Replace('−', '-');
				if (!TryAmount(text2, out var value))
				{
					if (text.Contains("block"))
					{
						block = true;
					}
					continue;
				}
				bool flag = text2.Contains("%") || text2.IndexOf('x') >= 0 || text2.IndexOf('×') >= 0;
				bool flag2 = text2.ToLowerInvariant().Contains("s");
				bool flag3 = text2.IndexOf('+') >= 0 || text2.IndexOf('-') >= 0;
				if (value > 0f && !flag3 && !val.positive)
				{
					value = 0f - value;
				}
				bool flag4;
				bool flag5;
				if (text.Contains("block"))
				{
					block = true;
					flag4 = text.Contains("cooldown") || text.Contains("cd");
					flag5 = text.Trim() == "blocks" || text.Contains("block count") || text.Contains("block charges") || ((text.Contains("additional") || text.Contains("extra")) && !text.Contains("damage") && !text.Contains("healing") && !text.Contains("force") && !text.Contains("duration"));
					if (flag4)
					{
						bool num19;
						if (!flag3)
						{
							if (!val.positive)
							{
								goto IL_0440;
							}
							num19 = value != 0f;
						}
						else
						{
							num19 = value < 0f;
						}
						if (num19)
						{
							improvedBlock = true;
							goto IL_0456;
						}
					}
					goto IL_0440;
				}
				goto IL_0456;
				IL_0440:
				if (!flag4 && flag5 && value > 0f)
				{
					improvedBlock = true;
				}
				goto IL_0456;
				IL_0456:
				if (text.Contains("lifesteal") || text.Contains("life steal"))
				{
					num13 += (flag ? (value / 100f) : value);
				}
				else if (text.Contains("regen"))
				{
					num14 += value / 100f;
				}
				else if (text.Contains("bullet speed") || text.Contains("projectile speed"))
				{
					num12 += (flag ? (value / 100f) : value);
				}
				else if (text.Contains("damage") && !text.Contains("self") && !text.Contains("taken") && !text.Contains("received") && !text.Contains("incoming") && !text.Contains("block"))
				{
					if (flag)
					{
						num10 += value / 100f;
					}
				}
				else if ((text.Contains("health") || text == "hp") && !text.Contains("heal on"))
				{
					if (flag)
					{
						num11 += value / 100f;
					}
				}
				else if (text.Contains("bounce") || text.Contains("reflect"))
				{
					num15 += value;
				}
				else if (text.Contains("ammo") || text.Contains("magazine"))
				{
					num16 += value;
				}
				else if (text.Contains("reload"))
				{
					bool flag6 = text.Contains("speed") || text.Contains("faster");
					float num20 = ((!flag3) ? (Mathf.Abs(value) * (float)(val.positive ? 1 : (-1))) : (flag6 ? value : (0f - value)));
					if (flag)
					{
						num17 += num20 / 100f;
					}
					else if (flag2 || !flag6)
					{
						num18 += num20;
					}
				}
			}
		}
		if (Mathf.Abs(num) < 0.0001f)
		{
			num = num10;
		}
		if (Mathf.Abs(num2) < 0.0001f)
		{
			num2 = num11;
		}
		if (Mathf.Abs(num3) < 0.0001f)
		{
			num3 = num12;
		}
		if (Mathf.Abs(num4) < 0.0001f)
		{
			num4 = num13;
		}
		if (Mathf.Abs(num5) < 0.0001f)
		{
			num5 = num14;
		}
		if (Mathf.Abs(num6) < 0.0001f)
		{
			num6 = num15;
		}
		if (Mathf.Abs(num7) < 0.0001f)
		{
			num7 = num16;
		}
		if (Mathf.Abs(num8) < 0.0001f)
		{
			num8 = num17;
		}
		if (Mathf.Abs(num9) < 0.0001f)
		{
			num9 = num18;
		}
		return ClassScoring.Score(new CardTraits
		{
			Damage = num,
			Health = num2,
			BulletSpeed = num3,
			Lifesteal = num4,
			RegenPercent = num5,
			Bounces = num6,
			Ammo = num7,
			ReloadPercent = num8,
			ReloadSeconds = num9,
			Block = block,
			ImprovedBlock = improvedBlock
		});
	}

	internal static int ThresholdPoints(float units)
	{
		return ClassScoring.Points(units);
	}

	private static bool TryAmount(string amount, out float value)
	{
		value = 0f;
		Match match = Number.Match(amount.Replace('−', '-'));
		if (!match.Success)
		{
			return false;
		}
		if (!float.TryParse(match.Value.Replace(',', '.'), NumberStyles.Float, CultureInfo.InvariantCulture, out value))
		{
			return false;
		}
		if (amount.IndexOf('x') >= 0 || amount.IndexOf('×') >= 0)
		{
			value = (value - 1f) * 100f;
		}
		return true;
	}

	private static bool IsUltimateCard(CardInfo card)
	{
		MonoBehaviour[] components = ((Component)card).GetComponents<MonoBehaviour>();
		foreach (MonoBehaviour val in components)
		{
			if (!Object.op_Implicit((Object)(object)val))
			{
				continue;
			}
			Type type = ((object)val).GetType();
			while (type != null)
			{
				if (type.FullName == "ZipsUltimates.UltimateCard" || type.FullName == "ZipsUltimates.UltimateUpgradeCard")
				{
					return true;
				}
				type = type.BaseType;
			}
		}
		return false;
	}

	private static void PopulateStats(Player player, List<StatLine> lines)
	{
		//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: Unknown result type (might be due to invalid IL or missing references)
		CharacterData data = player.data;
		Gun val = (((Object)(object)data.weaponHandler != (Object)null) ? data.weaponHandler.gun : null);
		CharacterStatModifiers stats = data.stats;
		GunAmmo val2 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponentInChildren<GunAmmo>(true) : null);
		float num = 0f;
		float num2 = 0f;
		if (Object.op_Implicit((Object)(object)val) && val.projectiles != null && val.projectiles.Length != 0 && val.projectiles[0] != null && Object.op_Implicit((Object)(object)val.projectiles[0].objectToSpawn))
		{
			ProjectileHit component = val.projectiles[0].objectToSpawn.GetComponent<ProjectileHit>();
			if (Object.op_Implicit((Object)(object)component))
			{
				num = component.damage * val.damage * val.bulletDamageMultiplier;
			}
			MoveTransform component2 = val.projectiles[0].objectToSpawn.GetComponent<MoveTransform>();
			if (Object.op_Implicit((Object)(object)component2))
			{
				Vector3 val3 = component2.localForce * val.projectileSpeed + component2.worldForce;
				num2 = ((Vector3)(ref val3)).magnitude * val.projectielSimulatonSpeed * component2.multiplier;
			}
		}
		lines.Add(new StatLine("BULLET DAMAGE", (num > 0f) ? (F(num) + ((val.percentageDamage > 0f) ? (" + " + F(val.percentageDamage * 100f) + "% HP") : "")) : (Object.op_Implicit((Object)(object)val) ? (F(val.damage) + "×") : "—")));
		lines.Add(new StatLine("MAXIMUM HEALTH", F(data.maxHealth)));
		lines.Add(new StatLine("BULLET SPEED", (num2 > 0f) ? (F(num2) + " m/s") : (Object.op_Implicit((Object)(object)val) ? (F(val.projectileSpeed * val.projectielSimulatonSpeed) + "×") : "—")));
		lines.Add(new StatLine("LIFESTEAL", Object.op_Implicit((Object)(object)stats) ? (F(stats.lifeSteal * 100f) + "%") : "0%"));
		float value = (Object.op_Implicit((Object)(object)data.healthHandler) ? data.healthHandler.regeneration : 0f);
		lines.Add(new StatLine("REGENERATION", F(value) + " HP/s"));
		lines.Add(new StatLine("BULLET BOUNCES", Object.op_Implicit((Object)(object)val) ? Math.Max(0, val.reflects).ToString(CultureInfo.InvariantCulture) : "0"));
		lines.Add(new StatLine("MAGAZINE", Object.op_Implicit((Object)(object)val2) ? val2.maxAmmo.ToString(CultureInfo.InvariantCulture) : "—"));
		lines.Add(new StatLine("RELOAD TIME", Object.op_Implicit((Object)(object)val2) ? (F(Mathf.Max(0f, (val2.reloadTime + val2.reloadTimeAdd) * val2.reloadTimeMultiplier)) + "s") : "—"));
		float value2 = (Object.op_Implicit((Object)(object)val) ? ((val.lockGunToDefault ? val.defaultCooldown : val.attackSpeed) / Mathf.Max(0.0001f, val.attackSpeedMultiplier)) : 0f);
		lines.Add(new StatLine("FIRE INTERVAL", Object.op_Implicit((Object)(object)val) ? (F(value2) + "s" + ((val.numberOfProjectiles > 1) ? (" · " + val.numberOfProjectiles + " pellets") : "")) : "—"));
		lines.Add(new StatLine("BLOCK COOLDOWN", Object.op_Implicit((Object)(object)data.block) ? (F(Mathf.Max(0f, data.block.Cooldown())) + "s" + ((data.block.additionalBlocks > 0) ? (" · " + (data.block.additionalBlocks + 1) + " blocks") : "")) : "—"));
	}

	private static string F(float value)
	{
		return value.ToString("0.##", CultureInfo.InvariantCulture);
	}

	internal static void Clear()
	{
		Cache.Clear();
	}
}
internal enum BuildClass
{
	Unclassified,
	Damage,
	Health,
	Sniper,
	Sustain,
	Ricochet,
	Magazine,
	Block
}
internal sealed class CardTraits
{
	internal float Damage;

	internal float Health;

	internal float BulletSpeed;

	internal float Lifesteal;

	internal float RegenPercent;

	internal float Bounces;

	internal float Ammo;

	internal float ReloadPercent;

	internal float ReloadSeconds;

	internal bool Block;

	internal bool ImprovedBlock;
}
internal static class ClassScoring
{
	internal static Dictionary<BuildClass, int> Score(CardTraits traits)
	{
		return new Dictionary<BuildClass, int>
		{
			{
				BuildClass.Damage,
				Points(traits.Damage / 0.3f)
			},
			{
				BuildClass.Health,
				Points(traits.Health / 0.5f)
			},
			{
				BuildClass.Sniper,
				Cap(Points(traits.BulletSpeed) + Points(traits.Damage / 0.4f))
			},
			{
				BuildClass.Sustain,
				Cap(Points(traits.Lifesteal / 0.3f) + Points(traits.RegenPercent / 0.04f))
			},
			{
				BuildClass.Ricochet,
				Points(traits.Bounces / 2f)
			},
			{
				BuildClass.Magazine,
				Cap(Points(traits.Ammo / 3f) + Points(traits.ReloadPercent / 0.5f) + Points(traits.ReloadSeconds / 0.5f))
			},
			{
				BuildClass.Block,
				traits.ImprovedBlock ? 3 : (traits.Block ? 2 : 0)
			}
		};
	}

	internal static int Points(float units)
	{
		if (float.IsNaN(units))
		{
			return 0;
		}
		if (units >= 3f)
		{
			return 3;
		}
		if (units <= -3f)
		{
			return -3;
		}
		if (!(units >= 0f))
		{
			return (int)Math.Ceiling(units - 0.0001f);
		}
		return (int)Math.Floor(units + 0.0001f);
	}

	private static int Cap(int value)
	{
		return Math.Max(-3, Math.Min(3, value));
	}
}
public sealed class CombatStats
{
	public int Kills;

	public int FinalBlows;

	public int SoloKills;

	public int Deaths;

	public double DamageDealt;

	public double Healing;

	public double DamageReceived;
}
public sealed class KillEvent
{
	public int KillerId = -1;

	public int VictimId;

	public bool IsVoid;

	public bool IsUltimate;

	public string UltimateId = "";

	public DeathCause Cause;

	public double Time;
}
public sealed class CombatLedger
{
	private sealed class Contribution
	{
		internal double Fraction;

		internal double EligibleUntil = double.NegativeInfinity;

		internal double LastBullet = double.NegativeInfinity;

		internal long BulletOrder;

		internal double LastDamage = double.NegativeInfinity;
	}

	private sealed class Impact
	{
		internal int Attacker;

		internal bool Void;

		internal bool Ultimate;

		internal bool Lethal;

		internal string UltimateId;

		internal DeathCause Cause;
	}

	private sealed class Life
	{
		internal readonly Dictionary<int, Contribution> Contributors = new Dictionary<int, Contribution>();

		internal Impact Last;

		internal bool Dead;
	}

	private readonly Dictionary<int, CombatStats> totals = new Dictionary<int, CombatStats>();

	private readonly Dictionary<int, int> teams = new Dictionary<int, int>();

	private readonly Dictionary<int, Life> lives = new Dictionary<int, Life>();

	private long hitOrder;

	public event Action<KillEvent> Feed;

	public event Action MatchReset;

	public CombatStats Get(int playerId)
	{
		if (!totals.TryGetValue(playerId, out var value))
		{
			value = (totals[playerId] = new CombatStats());
		}
		return value;
	}

	public void RegisterPlayer(int playerId, int teamId)
	{
		teams[playerId] = teamId;
		Get(playerId);
	}

	public bool IsEnemy(int first, int second)
	{
		if (first < 0 || second < 0 || first == second)
		{
			return false;
		}
		if (teams.TryGetValue(first, out var value) && teams.TryGetValue(second, out var value2))
		{
			return value != value2;
		}
		return true;
	}

	public void ResetMatch()
	{
		totals.Clear();
		lives.Clear();
		teams.Clear();
		hitOrder = 0L;
		if (this.MatchReset != null)
		{
			this.MatchReset();
		}
	}

	public void ClearLife(int playerId)
	{
		lives.Remove(playerId);
	}

	private Life GetLife(int playerId)
	{
		if (!lives.TryGetValue(playerId, out var value))
		{
			value = (lives[playerId] = new Life());
		}
		return value;
	}

	public void RecordHealing(int playerId, double amount)
	{
		if (FinitePositive(amount))
		{
			Get(playerId).Healing += amount;
		}
	}

	public void RecordDamage(int victimId, int attackerId, double amount, double maxHealth, double now, bool bullet = false, bool ultimate = false, string ultimateId = "", bool isVoid = false, bool lethal = false, DeathCause cause = DeathCause.Unknown)
	{
		if (double.IsNaN(now) || double.IsInfinity(now) || double.IsNaN(amount) || double.IsInfinity(amount) || amount < 0.0)
		{
			return;
		}
		Life life = GetLife(victimId);
		if (life.Dead || (amount <= 0.0 && !lethal))
		{
			return;
		}
		Get(victimId).DamageReceived += amount;
		if (cause == DeathCause.Unknown)
		{
			cause = (ultimate ? DeathCause.Ultimate : (isVoid ? DeathCause.Void : ((attackerId >= 0) ? DeathCause.Bullet : DeathCause.Hazard)));
		}
		life.Last = new Impact
		{
			Attacker = attackerId,
			Void = isVoid,
			Ultimate = ultimate,
			UltimateId = (ultimateId ?? ""),
			Lethal = lethal,
			Cause = cause
		};
		if (IsEnemy(attackerId, victimId))
		{
			Get(attackerId).DamageDealt += amount;
			if (!life.Contributors.TryGetValue(attackerId, out var value))
			{
				value = (life.Contributors[attackerId] = new Contribution());
			}
			if (FinitePositive(maxHealth))
			{
				value.Fraction += amount / maxHealth;
			}
			if (amount > 0.0)
			{
				value.LastDamage = now;
			}
			double num = Math.Floor(value.Fraction * 10.0 + 1E-07);
			if (num >= 1.0)
			{
				value.EligibleUntil = now + num;
			}
			if (bullet && amount > 0.0)
			{
				value.LastBullet = now;
				value.BulletOrder = ++hitOrder;
			}
		}
	}

	public KillEvent RecordDeath(int victimId, double now, bool forceVoid = false)
	{
		Life life = GetLife(victimId);
		if (life.Dead)
		{
			return null;
		}
		life.Dead = true;
		Get(victimId).Deaths++;
		Impact last = life.Last;
		int num = ((last != null && last.Lethal && !forceVoid && !last.Void) ? last.Attacker : (-1));
		bool flag = forceVoid || (last != null && (last.Void || last.Cause == DeathCause.Void));
		DeathCause deathCause = (flag ? DeathCause.Void : ((last != null && last.Lethal) ? last.Cause : DeathCause.Hazard));
		bool flag2 = num >= 0 && last != null && last.Ultimate;
		string ultimateId = (flag2 ? last.UltimateId : "");
		if (flag)
		{
			long num2 = long.MinValue;
			foreach (KeyValuePair<int, Contribution> contributor in life.Contributors)
			{
				if (now - contributor.Value.LastBullet >= -1E-07 && now - contributor.Value.LastBullet <= 3.0000001 && contributor.Value.BulletOrder > num2)
				{
					num = contributor.Key;
					num2 = contributor.Value.BulletOrder;
				}
			}
			flag2 = false;
			ultimateId = "";
		}
		else if (deathCause == DeathCause.Hazard && num < 0)
		{
			num = LatestHostileHit(victimId, now, 3.0, bulletsOnly: false);
		}
		if (IsEnemy(num, victimId))
		{
			Get(num).FinalBlows++;
			Get(num).Kills++;
			if (life.Contributors.Count == 1 && life.Contributors.ContainsKey(num))
			{
				Get(num).SoloKills++;
			}
		}
		foreach (KeyValuePair<int, Contribution> contributor2 in life.Contributors)
		{
			if (contributor2.Key != num && IsEnemy(contributor2.Key, victimId) && contributor2.Value.EligibleUntil + 1E-07 >= now)
			{
				Get(contributor2.Key).Kills++;
			}
		}
		KillEvent killEvent = new KillEvent
		{
			KillerId = num,
			VictimId = victimId,
			IsVoid = flag,
			IsUltimate = flag2,
			UltimateId = ultimateId,
			Time = now,
			Cause = deathCause
		};
		if (this.Feed != null)
		{
			this.Feed(killEvent);
		}
		return killEvent;
	}

	private static bool FinitePositive(double value)
	{
		if (value > 0.0 && !double.IsNaN(value))
		{
			return !double.IsInfinity(value);
		}
		return false;
	}

	public int LatestHostileHit(int victimId, double now, double window, bool bulletsOnly)
	{
		if (!lives.TryGetValue(victimId, out var value))
		{
			return -1;
		}
		int result = -1;
		double num = double.NegativeInfinity;
		foreach (KeyValuePair<int, Contribution> contributor in value.Contributors)
		{
			double num2 = (bulletsOnly ? contributor.Value.LastBullet : contributor.Value.LastDamage);
			if (num2 >= now - window && num2 <= now && num2 > num && IsEnemy(contributor.Key, victimId))
			{
				num = num2;
				result = contributor.Key;
			}
		}
		return result;
	}
}
internal static class CombatTracker
{
	internal sealed class DamageFrame
	{
		internal Player Victim;

		internal Player Attacker;

		internal float Before;

		internal float ReserveBefore;

		internal float Max;

		internal double ChildLoss;

		internal bool Committed;

		internal bool IsBullet;

		internal bool Ultimate;

		internal bool IsVoid;

		internal string UltimateId;

		internal DeathCause Cause;
	}

	private sealed class BulletContactHint
	{
		internal int Attacker;

		internal double Until;
	}

	internal static readonly CombatLedger Ledger = new CombatLedger();

	private static readonly Dictionary<HealthHandler, List<DamageFrame>> Pending = new Dictionary<HealthHandler, List<DamageFrame>>();

	private static readonly Dictionary<int, BulletContactHint> BulletContacts = new Dictionary<int, BulletContactHint>();

	private static readonly Dictionary<int, double> VoidPulses = new Dictionary<int, double>();

	private static readonly Dictionary<int, int> RegisteredObjects = new Dictionary<int, int>();

	private static readonly List<int> Expired = new List<int>();

	internal static double Now => Time.time;

	internal static void ResetMatch()
	{
		EnvironmentalTracker.Clear();
		Pending.Clear();
		BulletContacts.Clear();
		VoidPulses.Clear();
		RegisteredObjects.Clear();
		Ledger.ResetMatch();
		RegisterPlayers();
	}

	internal static void RegisterPlayers()
	{
		if ((Object)(object)PlayerManager.instance == (Object)null)
		{
			return;
		}
		foreach (Player player in PlayerManager.instance.players)
		{
			if (!((Object)(object)player == (Object)null))
			{
				if (RegisteredObjects.TryGetValue(player.playerID, out var value) && value != ((Object)player).GetInstanceID())
				{
					ClearLife(player.playerID);
				}
				RegisteredObjects[player.playerID] = ((Object)player).GetInstanceID();
				Ledger.RegisterPlayer(player.playerID, player.teamID);
			}
		}
	}

	internal static void Tick()
	{
		RegisterPlayers();
		Expired.Clear();
		foreach (KeyValuePair<int, BulletContactHint> bulletContact in BulletContacts)
		{
			if (bulletContact.Value.Until < Now)
			{
				Expired.Add(bulletContact.Key);
			}
		}
		foreach (int item in Expired)
		{
			BulletContacts.Remove(item);
		}
		Expired.Clear();
		foreach (KeyValuePair<int, double> voidPulse in VoidPulses)
		{
			if (voidPulse.Value < Now)
			{
				Expired.Add(voidPulse.Key);
			}
		}
		foreach (int item2 in Expired)
		{
			VoidPulses.Remove(item2);
		}
	}

	internal static void ClearLife(int playerId)
	{
		Ledger.ClearLife(playerId);
		BulletContacts.Remove(playerId);
		VoidPulses.Remove(playerId);
	}

	internal static void BulletContact(ProjectileHit projectile, int viewId, bool blocked)
	{
		if ((Object)(object)projectile != (Object)null && !blocked)
		{
			PresentationAssets.ObserveImpact(projectile);
		}
		if (!blocked && !((Object)(object)projectile == (Object)null) && !((Object)(object)projectile.ownPlayer == (Object)null) && viewId >= 0)
		{
			PhotonView photonView = PhotonNetwork.GetPhotonView(viewId);
			Player val = (((Object)(object)photonView != (Object)null) ? ((Component)photonView).GetComponent<Player>() : null);
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val.data == (Object)null) && !val.data.dead && !UltimateBridge.IsUltimateDamage(projectile.ownWeapon))
			{
				BulletContacts[val.playerID] = new BulletContactHint
				{
					Attacker = projectile.ownPlayer.playerID,
					Until = Now + 1.0
				};
			}
		}
	}

	internal static void MarkVoid(OutOfBoundsHandler handler)
	{
		object? value = AccessTools.Field(typeof(OutOfBoundsHandler), "data").GetValue(handler);
		CharacterData val = (CharacterData)((value is CharacterData) ? value : null);
		if ((Object)(object)val != (Object)null && (Object)(object)val.player != (Object)null)
		{
			VoidPulses[val.player.playerID] = Now + 0.5;
		}
	}

	internal static DamageFrame BeginDamage(HealthHandler health, Player attacker, GameObject weapon, Vector2 damage, Vector2 position)
	{
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: 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)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_017c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0181: Unknown result type (might be due to invalid IL or missing references)
		//IL_018f: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
		Player val = (((Object)(object)health != (Object)null) ? ((Component)health).GetComponent<Player>() : null);
		if ((Object)(object)val == (Object)null || (Object)(object)val.data == (Object)null || !val.data.isPlaying || val.data.dead || health.isRespawning || damage == Vector2.zero)
		{
			return null;
		}
		RegisterPlayers();
		EnvironmentalTracker.DamageHint damageHint = EnvironmentalTracker.Consume(val, attacker, damage, position);
		EnvironmentalTracker.Context current = EnvironmentalTracker.Current;
		if (damageHint == null && current != null && current.Kind != DeathCause.Unknown)
		{
			damageHint = new EnvironmentalTracker.DamageHint
			{
				Actor = (Object.op_Implicit((Object)(object)current.Actor) ? current.Actor.playerID : (Object.op_Implicit((Object)(object)attacker) ? attacker.playerID : (-1))),
				Kind = current.Kind
			};
		}
		if (damageHint != null && damageHint.Actor >= 0)
		{
			attacker = KillfeedHud.Find(damageHint.Actor);
		}
		bool flag = UltimateBridge.IsUltimateDamage(weapon);
		BulletContactHint value;
		bool flag2 = !flag && (damageHint == null || damageHint.Kind == DeathCause.Bullet) && (Object)(object)attacker != (Object)null && BulletContacts.TryGetValue(val.playerID, out value) && value.Attacker == attacker.playerID && value.Until >= Now;
		if (flag2)
		{
			BulletContacts.Remove(val.playerID);
		}
		double value2;
		bool flag3 = (Object)(object)attacker == (Object)null && VoidPulses.TryGetValue(val.playerID, out value2) && value2 >= Now;
		Vector3 position2 = ((Component)val).transform.position;
		if (damageHint == null && (Object)(object)attacker == (Object)null && (Mathf.Abs(position2.x) >= 35.5f || Mathf.Abs(position2.y) >= 19.95f))
		{
			flag3 = true;
		}
		DamageFrame damageFrame = new DamageFrame
		{
			Victim = val,
			Attacker = attacker,
			Before = val.data.health,
			ReserveBefore = UltimateBridge.GetReserve(val),
			Max = val.data.maxHealth,
			IsBullet = flag2,
			Ultimate = flag,
			IsVoid = flag3,
			UltimateId = (flag ? UltimateBridge.GetDamageUltimateId(weapon, attacker) : ""),
			Cause = (flag ? DeathCause.Ultimate : (flag3 ? DeathCause.Void : ((DeathCause)(((int?)damageHint?.Kind) ?? (Object.op_Implicit((Object)(object)attacker) ? 1 : 4)))))
		};
		if (!Pending.TryGetValue(health, out var value3))
		{
			value3 = (Pending[health] = new List<DamageFrame>());
		}
		value3.Add(damageFrame);
		return damageFrame;
	}

	internal static void Commit(DamageFrame frame)
	{
		if (frame == null || frame.Committed || (Object)(object)frame.Victim == (Object)null || (Object)(object)frame.Victim.data == (Object)null)
		{
			return;
		}
		frame.Committed = true;
		CharacterData data = frame.Victim.data;
		double val = Math.Max(0f, frame.Before) + Math.Max(0f, frame.ReserveBefore);
		double val2 = Math.Max(0f, frame.Before - data.health) + Math.Max(0f, frame.ReserveBefore - UltimateBridge.GetReserve(frame.Victim));
		val2 = Math.Max(0.0, Math.Min(val, val2) - frame.ChildLoss);
		bool lethal = data.health < 0f && !data.healthHandler.isRespawning;
		Ledger.RecordDamage(frame.Victim.playerID, ((Object)(object)frame.Attacker != (Object)null) ? frame.Attacker.playerID : (-1), val2, frame.Max, Now, frame.IsBullet, frame.Ultimate, frame.UltimateId, frame.IsVoid, lethal, frame.Cause);
		if (!Pending.TryGetValue(data.healthHandler, out var value))
		{
			return;
		}
		foreach (DamageFrame item in value)
		{
			if (item != frame && !item.Committed)
			{
				item.ChildLoss += val2;
			}
		}
	}

	internal static void EndDamage(HealthHandler health, DamageFrame frame)
	{
		Commit(frame);
		if (Pending.TryGetValue(health, out var value))
		{
			value.Remove(frame);
			if (value.Count == 0)
			{
				Pending.Remove(health);
			}
		}
	}

	internal static void FlushDamage(HealthHandler health)
	{
		if (Pending.TryGetValue(health, out var value))
		{
			for (int num = value.Count - 1; num >= 0; num--)
			{
				Commit(value[num]);
			}
		}
	}

	internal static void OnDeath(HealthHandler health)
	{
		Player val = (((Object)(object)health != (Object)null) ? ((Component)health).GetComponent<Player>() : null);
		if (!((Object)(object)val == (Object)null) && !((Object)(object)val.data == (Object)null))
		{
			FlushDamage(health);
			Ledger.RecordDeath(val.playerID, Now);
			BulletContacts.Remove(val.playerID);
			VoidPulses.Remove(val.playerID);
		}
	}
}
[HarmonyPatch(typeof(HealthHandler), "DoDamage")]
internal static class ObserveDamage
{
	[HarmonyPriority(800)]
	private static void Prefix(HealthHandler __instance, Vector2 damage, Vector2 position, Player damagingPlayer, GameObject damagingWeapon, out CombatTracker.DamageFrame __state)
	{
		//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)
		__state = CombatTracker.BeginDamage(__instance, damagingPlayer, damagingWeapon, damage, position);
	}

	[HarmonyPriority(800)]
	private static void Postfix(HealthHandler __instance, CombatTracker.DamageFrame __state)
	{
		CombatTracker.EndDamage(__instance, __state);
	}

	private static Exception Finalizer(HealthHandler __instance, CombatTracker.DamageFrame __state, Exception __exception)
	{
		CombatTracker.EndDamage(__instance, __state);
		return __exception;
	}
}
[HarmonyPatch(typeof(HealthHandler), "RPCA_Die")]
internal static class ObserveFinalDeath
{
	[HarmonyPriority(800)]
	private static void Prefix(HealthHandler __instance, out bool __state)
	{
		CharacterData component = ((Component)__instance).GetComponent<CharacterData>();
		__state = (Object)(object)component != (Object)null && component.isPlaying && !component.dead && !__instance.isRespawning;
		if (__state)
		{
			CombatTracker.FlushDamage(__instance);
		}
	}

	[HarmonyPriority(800)]
	private static void Postfix(HealthHandler __instance, bool __state)
	{
		if (__state)
		{
			CharacterData component = ((Component)__instance).GetComponent<CharacterData>();
			if ((Object)(object)component != (Object)null && component.dead)
			{
				CombatTracker.OnDeath(__instance);
			}
		}
	}
}
[HarmonyPatch(typeof(HealthHandler), "RPCA_Die_Phoenix")]
internal static class ObservePhoenix
{
	private static void Postfix(HealthHandler __instance)
	{
		if (__instance.isRespawning)
		{
			CombatTracker.FlushDamage(__instance);
			Player component = ((Component)__instance).GetComponent<Player>();
			if ((Object)(object)component != (Object)null)
			{
				CombatTracker.ClearLife(component.playerID);
			}
		}
	}
}
[HarmonyPatch(typeof(HealthHandler), "Revive")]
internal static class ObserveRevive
{
	private static void Postfix(HealthHandler __instance)
	{
		Player component = ((Component)__instance).GetComponent<Player>();
		if ((Object)(object)component != (Object)null)
		{
			CombatTracker.ClearLife(component.playerID);
		}
	}
}
[HarmonyPatch(typeof(HealthHandler), "Heal")]
internal static class ObserveHealing
{
	private static void Prefix(HealthHandler __instance, out float __state)
	{
		CharacterData component = ((Component)__instance).GetComponent<CharacterData>();
		__state = (((Object)(object)component != (Object)null && component.isPlaying && !component.dead && !__instance.isRespawning) ? component.health : float.NaN);
	}

	private static void Postfix(HealthHandler __instance, float __state)
	{
		if (!float.IsNaN(__state))
		{
			CharacterData component = ((Component)__instance).GetComponent<CharacterData>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.player != (Object)null)
			{
				CombatTracker.Ledger.RecordHealing(component.player.playerID, Math.Max(0f, component.health - __state));
			}
		}
	}
}
[HarmonyPatch(typeof(ProjectileHit), "RPCA_DoHit")]
internal static class ObserveBulletContact
{
	private static void Prefix(ProjectileHit __instance, int viewID, int colliderID, bool wasBlocked, out EnvironmentalTracker.Context __state)
	{
		__state = EnvironmentalTracker.Enter((Component)(object)__instance, __instance.ownPlayer);
		CombatTracker.BulletContact(__instance, viewID, wasBlocked);
		if (wasBlocked || !Object.op_Implicit((Object)(object)__instance.ownPlayer))
		{
			return;
		}
		Collider2D val = null;
		if (viewID >= 0)
		{
			PhotonView photonView = PhotonNetwork.GetPhotonView(viewID);
			if (Object.op_Implicit((Object)(object)photonView))
			{
				val = ((Component)photonView).GetComponentInChildren<Collider2D>();
			}
		}
		else if (colliderID >= 0 && (Object)(object)MapManager.instance != (Object)null && MapManager.instance.currentMap != null && Object.op_Implicit((Object)(object)MapManager.instance.currentMap.Map))
		{
			Collider2D[] componentsInChildren = ((Component)MapManager.instance.currentMap.Map).GetComponentsInChildren<Collider2D>();
			if (colliderID < componentsInChildren.Length)
			{
				val = componentsInChildren[colliderID];
			}
		}
		if (Object.op_Implicit((Object)(object)val) && !Object.op_Implicit((Object)(object)((Component)val).GetComponentInParent<Player>()))
		{
			Damagable componentInParent = ((Component)val).GetComponentInParent<Damagable>();
			EnvironmentalTracker.ObjectHit((Component)(Object.op_Implicit((Object)(object)componentInParent) ? ((object)componentInParent) : ((object)val)), __instance.ownPlayer);
		}
	}

	private static Exception Finalizer(EnvironmentalTracker.Context __state, Exception __exception)
	{
		__state?.Dispose();
		return __exception;
	}
}
[HarmonyPatch(typeof(OutOfBoundsHandler), "RPCA_DisplayOutOfBounds")]
internal static class ObserveVoidPulse
{
	private static void Prefix(OutOfBoundsHandler __instance)
	{
		CombatTracker.MarkVoid(__instance);
	}
}
[HarmonyPatch(typeof(GM_ArmsRace), "StartGame")]
internal static class ObserveNewMatch
{
	private static void Prefix()
	{
		if ((Object)(object)GameManager.instance == (Object)null || !GameManager.instance.isPlaying)
		{
			CombatTracker.ResetMatch();
		}
	}
}
[HarmonyPatch(typeof(GM_ArmsRace), "ResetMatch")]
internal static class ObserveRematch
{
	private static void Postfix()
	{
		CombatTracker.ResetMatch();
	}
}
[HarmonyPatch(typeof(GM_Test), "Start")]
internal static class ObserveSandbox
{
	private static void Prefix(GM_Test __instance)
	{
		if (((Component)__instance).gameObject.activeSelf)
		{
			CombatTracker.ResetMatch();
		}
	}
}
[HarmonyPatch(typeof(PlayerManager), "RemovePlayers")]
internal static class ObservePlayersRemoved
{
	private static void Postfix()
	{
		CombatTracker.ResetMatch();
	}
}
internal static class DeathIcons
{
	private static readonly Dictionary<DeathCause, Texture2D> Cache = new Dictionary<DeathCause, Texture2D>();

	internal static bool IsSpecial(DeathCause cause)
	{
		return cause >= DeathCause.Hazard;
	}

	private static void Ring(GlyphCanvas r, float x, float y, float radius, float width)
	{
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		for (int i = 0; i < 64; i++)
		{
			float num = (float)i * (float)Math.PI / 32f;
			float num2 = (float)(i + 1) * (float)Math.PI / 32f;
			r.Line(x + Mathf.Cos(num) * radius, y + Mathf.Sin(num) * radius, x + Mathf.Cos(num2) * radius, y + Mathf.Sin(num2) * radius, width, Color.white);
		}
	}

	private static void Burst(GlyphCanvas r, float x, float y, float radius)
	{
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: 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)
		for (int i = 0; i < 16; i++)
		{
			float num = (float)i * (float)Math.PI / 8f;
			float num2 = (float)(i + 1) * (float)Math.PI / 8f;
			float num3 = ((i % 2 == 0) ? radius : (radius * 0.42f));
			float num4 = ((i % 2 == 0) ? (radius * 0.42f) : radius);
			r.Triangle(new Vector2(x, y), new Vector2(x + Mathf.Cos(num) * num3, y + Mathf.Sin(num) * num3), new Vector2(x + Mathf.Cos(num2) * num4, y + Mathf.Sin(num2) * num4), Color.white, Color.white, Color.white);
		}
	}

	private static void Bomb(GlyphCanvas r, float x, float y, float radius)
	{
		//IL_0004: 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)
		r.Disc(x, y, radius, Color.white);
		r.Line(x + 0.02f, y + radius * 0.9f, x + 0.08f, y + radius + 0.1f, 0.045f, Color.white);
	}

	private static void Drop(GlyphCanvas r, float x, float y, float radius)
	{
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: 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_0046: Unknown result type (might be due to invalid IL or missing references)
		r.Disc(x, y, radius, Color.white);
		r.Triangle(new Vector2(x - radius * 0.95f, y), new Vector2(x, y + radius * 2.3f), new Vector2(x + radius * 0.95f, y), Color.white, Color.white, Color.white);
	}

	internal static Texture For(DeathCause cause)
	{
		//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_0148: 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_0174: Unknown result type (might be due to invalid IL or missing references)
		//IL_0194: Unknown result type (might be due to invalid IL or missing references)
		//IL_020a: Unknown result type (might be due to invalid IL or missing references)
		//IL_022a: Unknown result type (might be due to invalid IL or missing references)
		//IL_024a: Unknown result type (might be due to invalid IL or missing references)
		//IL_026a: Unknown result type (might be due to invalid IL or missing references)
		//IL_028a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: 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)
		//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_032a: Unknown result type (might be due to invalid IL or missing references)
		//IL_034a: Unknown result type (might be due to invalid IL or missing references)
		//IL_046c: Unknown result type (might be due to invalid IL or missing references)
		//IL_048c: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0572: Unknown result type (might be due to invalid IL or missing references)
		//IL_0581: Unknown result type (might be due to invalid IL or missing references)
		//IL_0590: Unknown result type (might be due to invalid IL or missing references)
		//IL_0595: Unknown result type (might be due to invalid IL or missing references)
		//IL_0596: Unknown result type (might be due to invalid IL or missing references)
		//IL_0597: Unknown result type (might be due to invalid IL or missing references)
		//IL_05a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_05b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_05c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_05cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_05cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_05cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_041f: Unknown result type (might be due to invalid IL or missing references)
		//IL_043f: Unknown result type (might be due to invalid IL or missing references)
		//IL_05f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_04fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_052f: Unknown result type (might be due to invalid IL or missing references)
		//IL_06b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_06d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_06f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0710: Unknown result type (might be due to invalid IL or missing references)
		//IL_0389: Unknown result type (might be due to invalid IL or missing references)
		//IL_0395: Unknown result type (might be due to invalid IL or missing references)
		//IL_072e: Unknown result type (might be due to invalid IL or missing references)
		//IL_073d: Unknown result type (might be due to invalid IL or missing references)
		//IL_074c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0751: Unknown result type (might be due to invalid IL or missing references)
		//IL_0752: Unknown result type (might be due to invalid IL or missing references)
		//IL_0753: Unknown result type (might be due to invalid IL or missing references)
		//IL_0764: Unknown result type (might be due to invalid IL or missing references)
		//IL_0773: Unknown result type (might be due to invalid IL or missing references)
		//IL_0782: Unknown result type (might be due to invalid IL or missing references)
		//IL_0787: Unknown result type (might be due to invalid IL or missing references)
		//IL_0788: Unknown result type (might be due to invalid IL or missing references)
		//IL_0789: Unknown result type (might be due to invalid IL or missing references)
		//IL_065e: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_03da: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_07e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0805: Unknown result type (might be due to invalid IL or missing references)
		//IL_0825: Unknown result type (might be due to invalid IL or missing references)
		//IL_0845: Unknown result type (might be due to invalid IL or missing references)
		//IL_0865: Unknown result type (might be due to invalid IL or missing references)
		//IL_0885: Unknown result type (might be due to invalid IL or missing references)
		//IL_08a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_08b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_08c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_08d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_08dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_08dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_08de: Unknown result type (might be due to invalid IL or missing references)
		//IL_08ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_08fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_090d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0912: Unknown result type (might be due to invalid IL or missing references)
		//IL_0913: Unknown result type (might be due to invalid IL or missing references)
		//IL_0914: Unknown result type (might be due to invalid IL or missing references)
		//IL_0934: Unknown result type (might be due to invalid IL or missing references)
		//IL_0961: Unknown result type (might be due to invalid IL or missing references)
		//IL_0981: Unknown result type (might be due to invalid IL or missing references)
		//IL_09a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_09c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_09d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_09e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_09f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_09f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_09f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_09f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c4a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c6a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c8a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0caa: Unknown result type (might be due to invalid IL or missing references)
		//IL_0cca: Unknown result type (might be due to invalid IL or missing references)
		//IL_0cea: Unknown result type (might be due to invalid IL or missing references)
		//IL_0d0a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a8c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0e58: Unknown result type (might be due to invalid IL or missing references)
		//IL_0e6e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0d36: Unknown result type (might be due to invalid IL or missing references)
		//IL_0d56: Unknown result type (might be due to invalid IL or missing references)
		//IL_0d76: Unknown result type (might be due to invalid IL or missing references)
		//IL_0d96: Unknown result type (might be due to invalid IL or missing references)
		//IL_0db6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0dd6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0df6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0e16: Unknown result type (might be due to invalid IL or missing references)
		//IL_0e36: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c1e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b1d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b42: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b67: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b6c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b6d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b6e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0baf: Unknown result type (might be due to invalid IL or missing references)
		//IL_0bb4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0bbe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0be1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0be6: Unknown result type (might be due to invalid IL or missing references)
		if (cause == DeathCause.Void)
		{
			return PresentationAssets.VoidIcon;
		}
		if (Cache.TryGetValue(cause, out var value))
		{
			return (Texture)(object)value;
		}
		GlyphCanvas glyphCanvas = new GlyphCanvas();
		Color white = Color.white;
		switch (cause)
		{
		case DeathCause.Saw:
		{
			Ring(glyphCanvas, 0.5f, 0.5f, 0.27f, 0.055f);
			Ring(glyphCanvas, 0.5f, 0.5f, 0.08f, 0.04f);
			for (int num8 = 0; num8 < 10; num8++)
			{
				float num9 = (float)num8 * (float)Math.PI / 5f;
				glyphCanvas.Triangle(new Vector2(0.5f + Mathf.Cos(num9) * 0.26f, 0.5f + Mathf.Sin(num9) * 0.26f), new Vector2(0.5f + Mathf.Cos(num9 + 0.3f) * 0.43f, 0.5f + Mathf.Sin(num9 + 0.3f) * 0.43f), new Vector2(0.5f + Mathf.Cos(num9 + 0.5f) * 0.26f, 0.5f + Mathf.Sin(num9 + 0.5f) * 0.26f), white, white, white);
			}
			break;
		}
		case DeathCause.ToxicCloud:
		{
			glyphCanvas.Disc(0.28f, 0.47f, 0.15f, white);
			glyphCanvas.Disc(0.49f, 0.58f, 0.23f, white);
			glyphCanvas.Disc(0.73f, 0.46f, 0.16f, white);
			glyphCanvas.Line(0.28f, 0.36f, 0.75f, 0.36f, 0.12f, white);
			for (int num5 = 0; num5 < 3; num5++)
			{
				Drop(glyphCanvas, 0.32f + (float)num5 * 0.19f, 0.17f, 0.034f);
			}
			break;
		}
		case DeathCause.TimedDetonation:
			Ring(glyphCanvas, 0.5f, 0.45f, 0.29f, 0.065f);
			glyphCanvas.Line(0.5f, 0.45f, 0.5f, 0.64f, 0.045f, white);
			glyphCanvas.Line(0.5f, 0.45f, 0.64f, 0.38f, 0.045f, white);
			glyphCanvas.Line(0.4f, 0.83f, 0.6f, 0.83f, 0.07f, white);
			glyphCanvas.Line(0.5f, 0.74f, 0.5f, 0.83f, 0.05f, white);
			glyphCanvas.Line(0.75f, 0.71f, 0.81f, 0.77f, 0.05f, white);
			break;
		case DeathCause.ExplosiveBullet:
			Burst(glyphCanvas, 0.52f, 0.48f, 0.42f);
			break;
		case DeathCause.BombsAway:
			Bomb(glyphCanvas, 0.49f, 0.35f, 0.19f);
			Bomb(glyphCanvas, 0.19f, 0.65f, 0.105f);
			Bomb(glyphCanvas, 0.8f, 0.65f, 0.105f);
			Burst(glyphCanvas, 0.6f, 0.73f, 0.085f);
			break;
		case DeathCause.Poison:
		{
			glyphCanvas.Disc(0.5f, 0.57f, 0.26f, white);
			glyphCanvas.Line(0.37f, 0.35f, 0.63f, 0.35f, 0.12f, white);
			Vector2 val = default(Vector2);
			for (int m = 0; m < glyphCanvas.Size; m++)
			{
				for (int n = 0; n < glyphCanvas.Size; n++)
				{
					((Vector2)(ref val))..ctor(((float)n + 0.5f) / (float)glyphCanvas.Size, ((float)m + 0.5f) / (float)glyphCanvas.Size);
					if (Vector2.Distance(val, new Vector2(0.4f, 0.59f)) < 0.055f || Vector2.Distance(val, new Vector2(0.6f, 0.59f)) < 0.055f)
					{
						glyphCanvas.Pixels[m * glyphCanvas.Size + n] = Color.clear;
					}
				}
			}
			glyphCanvas.Line(0.25f, 0.15f, 0.75f, 0.28f, 0.05f, white);
			glyphCanvas.Line(0.25f, 0.28f, 0.75f, 0.15f, 0.05f, white);
			break;
		}
		case DeathCause.Parasite:
		{
			glyphCanvas.Line(0.34f, 0.23f, 0.59f, 0.39f, 0.16f, white);
			glyphCanvas.Line(0.59f, 0.39f, 0.4f, 0.6f, 0.16f, white);
			glyphCanvas.Line(0.4f, 0.6f, 0.65f, 0.77f, 0.16f, white);
			glyphCanvas.Disc(0.65f, 0.77f, 0.12f, white);
			for (int l = 0; l < 3; l++)
			{
				glyphCanvas.Line(0.31f, 0.3f + (float)l * 0.19f, 0.18f, 0.33f + (float)l * 0.19f, 0.035f, white);
				glyphCanvas.Line(0.63f, 0.3f + (float)l * 0.19f, 0.79f, 0.33f + (float)l * 0.19f, 0.035f, white);
			}
			break;
		}
		case DeathCause.StaticField:
			Ring(glyphCanvas, 0.5f, 0.5f, 0.4f, 0.025f);
			glyphCanvas.Triangle(new Vector2(0.56f, 0.84f), new Vector2(0.28f, 0.45f), new Vector2(0.55f, 0.45f), white, white, white);
			glyphCanvas.Triangle(new Vector2(0.45f, 0.16f), new Vector2(0.72f, 0.55f), new Vector2(0.45f, 0.55f), white, white, white);
			break;
		case DeathCause.Radiance:
		{
			glyphCanvas.Disc(0.5f, 0.5f, 0.18f, white);
			for (int num10 = 0; num10 < 8; num10++)
			{
				float num11 = (float)num10 * (float)Math.PI / 4f;
				glyphCanvas.Line(0.5f + Mathf.Cos(num11) * 0.28f, 0.5f + Mathf.Sin(num11) * 0.28f, 0.5f + Mathf.Cos(num11) * 0.43f, 0.5f + Mathf.Sin(num11) * 0.43f, 0.05f, white);
			}
			break;
		}
		case DeathCause.Overpower:
			Ring(glyphCanvas, 0.5f, 0.45f, 0.36f, 0.045f);
			glyphCanvas.Line(0.5f, 0.31f, 0.5f, 0.62f, 0.085f, white);
			glyphCanvas.Line(0.35f, 0.46f, 0.65f, 0.46f, 0.085f, white);
			glyphCanvas.Line(0.27f, 0.77f, 0.18f, 0.89f, 0.04f, white);
			glyphCanvas.Line(0.73f, 0.77f, 0.82f, 0.89f, 0.04f, white);
			break;
		case DeathCause.LifeDrain:
			glyphCanvas.Triangle(new Vector2(0.18f, 0.75f), new Vector2(0.44f, 0.7f), new Vector2(0.3f, 0.25f), white, white, white);
			glyphCanvas.Triangle(new Vector2(0.56f, 0.7f), new Vector2(0.82f, 0.75f), new Vector2(0.7f, 0.25f), white, white, white);
			Drop(glyphCanvas, 0.5f, 0.19f, 0.055f);
			break;
		case DeathCause.DarkPower:
			Ring(glyphCanvas, 0.5f, 0.5f, 0.38f, 0.03f);
			glyphCanvas.Line(0.5f, 0.19f, 0.5f, 0.8f, 0.055f, white);
			glyphCanvas.Line(0.27f, 0.68f, 0.27f, 0.48f, 0.05f, white);
			glyphCanvas.Line(0.73f, 0.68f, 0.73f, 0.48f, 0.05f, white);
			glyphCanvas.Line(0.27f, 0.48f, 0.73f, 0.48f, 0.055f, white);
			glyphCanvas.Line(0.5f, 0.8f, 0.38f, 0.65f, 0.05f, white);
			glyphCanvas.Line(0.5f, 0.8f, 0.62f, 0.65f, 0.05f, white);
			break;
		case DeathCause.DemonicPact:
			glyphCanvas.Disc(0.5f, 0.45f, 0.24f, white);
			glyphCanvas.Triangle(new Vector2(0.26f, 0.52f), new Vector2(0.2f, 0.88f), new Vector2(0.45f, 0.65f), white, white, white);
			glyphCanvas.Triangle(new Vector2(0.74f, 0.52f), new Vector2(0.8f, 0.88f), new Vector2(0.55f, 0.65f), white, white, white);
			glyphCanvas.Line(0.36f, 0.2f, 0.64f, 0.2f, 0.045f, white);
			break;
		case DeathCause.DelayedDamage:
			glyphCanvas.Line(0.25f, 0.82f, 0.75f, 0.82f, 0.06f, white);
			glyphCanvas.Line(0.25f, 0.18f, 0.75f, 0.18f, 0.06f, white);
			glyphCanvas.Line(0.3f, 0.77f, 0.7f, 0.23f, 0.04f, white);
			glyphCanvas.Line(0.7f, 0.77f, 0.3f, 0.23f, 0.04f, white);
			glyphCanvas.Triangle(new Vector2(0.33f, 0.27f), new Vector2(0.67f, 0.27f), new Vector2(0.5f, 0.48f), white, white, white);
			break;
		case DeathCause.Supernova:
		{
			Ring(glyphCanvas, 0.5f, 0.5f, 0.17f, 0.045f);
			for (int num6 = 0; num6 < 8; num6++)
			{
				float num7 = (float)num6 * (float)Math.PI / 4f;
				glyphCanvas.Line(0.5f + Mathf.Cos(num7) * 0.42f, 0.5f + Mathf.Sin(num7) * 0.42f, 0.5f + Mathf.Cos(num7) * 0.25f, 0.5f + Mathf.Sin(num7) * 0.25f, 0.035f, white);
			}
			Burst(glyphCanvas, 0.5f, 0.5f, 0.09f);
			break;
		}
		case DeathCause.Hazard:
		{
			for (int i = 0; i < 48; i++)
			{
				float num = (float)i * (float)Math.PI / 24f;
				float num2 = (float)(i + 1) * (float)Math.PI / 24f;
				float num3 = ((i % 2 == 0) ? 0.43f : 0.34f);
				float num4 = ((i % 2 == 0) ? 0.34f : 0.43f);
				glyphCanvas.Triangle(new Vector2(0.5f, 0.5f), new Vector2(0.5f + Mathf.Cos(num) * num3, 0.5f + Mathf.Sin(num) * num3), new Vector2(0.5f + Mathf.Cos(num2) * num4, 0.5f + Mathf.Sin(num2) * num4), white, white, white);
			}
			for (int j = 0; j < glyphCanvas.Size; j++)
			{
				for (int k = 0; k < glyphCanvas.Size; k++)
				{
					if (Vector2.Distance(new Vector2(((float)k + 0.5f) / (float)glyphCanvas.Size, ((float)j + 0.5f) / (float)glyphCanvas.Size), Vector2.one * 0.5f) < 0.2f)
					{
						glyphCanvas.Pixels[j * glyphCanvas.Size + k] = Color.clear;
					}
				}
			}
			glyphCanvas.Disc(0.5f, 0.5f, 0.07f, white);
			break;
		}
		case DeathCause.ChainReaction:
			glyphCanvas.Line(0.12f, 0.22f, 0.25f, 0.76f, 0.1f, white);
			glyphCanvas.Line(0.41f, 0.23f, 0.55f, 0.68f, 0.1f, white);
			glyphCanvas.Line(0.7f, 0.22f, 0.87f, 0.53f, 0.1f, white);
			glyphCanvas.Line(0.08f, 0.13f, 0.91f, 0.13f, 0.035f, white);
			glyphCanvas.Line(0.36f, 0.84f, 0.74f, 0.84f, 0.035f, white);
			glyphCanvas.Line(0.74f, 0.84f, 0.65f, 0.94f, 0.035f, white);
			glyphCanvas.Line(0.74f, 0.84f, 0.65f, 0.74f, 0.035f, white);
			break;
		case DeathCause.PhysicsObject:
			glyphCanvas.Line(0.18f, 0.3f, 0.18f, 0.75f, 0.045f, white);
			glyphCanvas.Line(0.18f, 0.75f, 0.68f, 0.75f, 0.045f, white);
			glyphCanvas.Line(0.68f, 0.75f, 0.68f, 0.3f, 0.045f, white);
			glyphCanvas.Line(0.68f, 0.3f, 0.18f, 0.3f, 0.045f, white);
			glyphCanvas.Line(0.23f, 0.36f, 0.63f, 0.69f, 0.036f, white);
			glyphCanvas.Line(0.23f, 0.69f, 0.63f, 0.36f, 0.036f, white);
			glyphCanvas.Line(0.74f, 0.24f, 0.9f, 0.12f, 0.04f, white);
			glyphCanvas.Line(0.79f, 0.42f, 0.96f, 0.38f, 0.04f, white);
			glyphCanvas.Line(0.6f, 0.22f, 0.63f, 0.06f, 0.04f, white);
			break;
		default:
			glyphCanvas.Line(0.2f, 0.5f, 0.7f, 0.5f, 0.12f, white);
			glyphCanvas.Disc(0.71f, 0.5f, 0.06f, white);
			break;
		}
		value = glyphCanvas.Texture("Zip death cause " + cause);
		Cache[cause] = value;
		return (Texture)(object)value;
	}

	internal static void Dispose()
	{
		foreach (Texture2D value in Cache.Values)
		{
			if (Object.op_Implicit((Object)(object)value))
			{
				Object.Destroy((Object)(object)value);
			}
		}
		Cache.Clear();
	}
}
public enum DeathCause
{
	Unknown,
	Bullet,
	Ultimate,
	Void,
	Hazard,
	PhysicsObject,
	ChainReaction,
	Saw,
	ToxicCloud,
	TimedDetonation,
	ExplosiveBullet,
	BombsAway,
	Poison,
	Parasite,
	StaticField,
	Radiance,
	Overpower,
	LifeDrain,
	DarkPower,
	DemonicPact,
	DelayedDamage,
	Supernova
}
public sealed class CauseCredit
{
	public int PlayerId;

	public int Hops;

	public DeathCause Kind;

	public double Started;

	public double Expires;

	public string Origin;
}
public sealed class EnvironmentalCausality
{
	private readonly Dictionary<string, CauseCredit> causes = new Dictionary<string, CauseCredit>();

	public const double Window = 12.0;

	public void Clear()
	{
		causes.Clear();
	}

	public void Forget(string key)
	{
		if (key != null)
		{
			causes.Remove(key);
		}
	}

	public CauseCredit Remember(string key, int player, DeathCause kind, double now, double lifetime = 12.0)
	{
		if (string.IsNullOrEmpty(key) || player < 0 || double.IsNaN(now) || double.IsInfinity(now))
		{
			return null;
		}
		CauseCredit causeCredit = new CauseCredit();
		causeCredit.PlayerId = player;
		causeCredit.Kind = kind;
		causeCredit.Started = now;
		causeCredit.Expires = now + Math.Max(0.0, Math.Min(12.0, lifetime));
		causeCredit.Origin = key + ":" + player + ":" + now.ToString("R", CultureInfo.InvariantCulture);
		CauseCredit causeCredit2 = causeCredit;
		causes[key] = causeCredit2;
		return causeCredit2;
	}

	public CauseCredit Get(string key, double now)
	{
		if (key == null || !causes.TryGetValue(key, out var value))
		{
			return null;
		}
		if (now > value.Expires || value.Hops > 12)
		{
			causes.Remove(key);
			return null;
		}
		return value;
	}

	public bool Transfer(string source, string target, double now, bool chain = true)
	{
		CauseCredit causeCredit = Get(source, now);
		if (causeCredit == null || source == target || causeCredit.Hops >= 12 || string.IsNullOrEmpty(target))
		{
			return false;
		}
		CauseCredit causeCredit2 = Get(target, now);
		if (causeCredit2 != null && (causeCredit2.Origin == causeCredit.Origin || causeCredit2.Started > causeCredit.Started))
		{
			return false;
		}
		causes[target] = new CauseCredit
		{
			PlayerId = causeCredit.PlayerId,
			Hops = causeCredit.Hops + 1,
			Kind = (chain ? DeathCause.ChainReaction : causeCredit.Kind),
			Started = causeCredit.Started,
			Expires = causeCredit.Expires,
			Origin = causeCredit.Origin
		};
		return true;
	}
}
internal static class EnvironmentalTracker
{
	internal sealed class Context : IDisposable
	{
		internal Context Previous;

		internal Player Actor;

		internal Component Source;

		internal DeathCause Kind;

		public void Dispose()
		{
			if (Current == this)
			{
				Current = Previous;
			}
		}
	}

	internal sealed class DamageHint
	{
		internal int Actor = -1;

		internal DeathCause Kind;

		internal double Until;

		internal Vector2 Position;

		internal float Magnitude;

		internal string Subject;
	}

	private sealed class Displacement
	{
		internal int Actor;

		internal double Until;
	}

	private sealed class Receiver : IOnEventCallback
	{
		public void OnEvent(EventData e)
		{
			Receive(e);
		}
	}

	internal static readonly EnvironmentalCausality Graph = new EnvironmentalCausality();

	private static readonly Dictionary<int, List<DamageHint>> Hints = new Dictionary<int, List<DamageHint>>();

	private static readonly Dictionary<int, Displacement> Displaced = new Dictionary<int, Displacement>();

	private static readonly Dictionary<string, double> Sent = new Dictionary<string, double>();

	private static readonly Receiver Listener = new Receiver();

	private static bool listening;

	private static float nextScan;

	private static int mapId;

	internal static Context Current;

	private const byte EventCode = 179;

	private const string Protocol = "zip.killfeed.causes.v1";

	internal static Player Actor
	{
		get
		{
			if (Current == null)
			{
				return null;
			}
			return Current.Actor;
		}
	}

	private static bool CanSend
	{
		get
		{
			if (PhotonNetwork.InRoom)
			{
				return !PhotonNetwork.OfflineMode;
			}
			return false;
		}
	}

	internal static void Start()
	{
		if (!listening)
		{
			PhotonNetwork.AddCallbackTarget((object)Listener);
			listening = true;
		}
	}

	internal static void Stop()
	{
		if (listening)
		{
			PhotonNetwork.RemoveCallbackTarget((object)Listener);
		}
		listening = false;
		Clear();
	}

	internal static void Clear()
	{
		Graph.Clear();
		Hints.Clear();
		Displaced.Clear();
		Sent.Clear();
		Current = null;
	}

	internal static Context Enter(Component source, Player actor, DeathCause kind = DeathCause.Unknown)
	{
		Context obj = new Context
		{
			Previous = Current,
			Source = source,
			Actor = actor,
			Kind = kind
		};
		Current = obj;
		return obj;
	}

	internal static void Tick()
	{
		if (Time.unscaledTime < nextScan)
		{
			return;
		}
		nextScan = Time.unscaledTime + 0.5f;
		Map val = (((Object)(object)MapManager.instance != (Object)null && MapManager.instance.currentMap != null) ? MapManager.instance.currentMap.Map : null);
		int num = (Object.op_Implicit((Object)(object)val) ? ((Object)val).GetInstanceID() : 0);
		if (num != mapId)
		{
			mapId = num;
			Clear();
		}
		Rigidbody2D[] array = Object.FindObjectsOfType<Rigidbody2D>();
		for (int i = 0; i < array.Length; i++)
		{
			Track(array[i]);
		}
		int[] array2 = Hints.Keys.ToArray();
		foreach (int key in array2)
		{
			Hints[key].RemoveAll((DamageHint h) => h.Until < CombatTracker.Now);
			if (Hints[key].Count == 0)
			{
				Hints.Remove(key);
			}
		}
		array2 = Displaced.Keys.ToArray();
		foreach (int key2 in array2)
		{
			if (Displaced[key2].Until < CombatTracker.Now)
			{
				Displaced.Remove(key2);
			}
		}
	}

	internal static PhysicsCauseProbe Track(Rigidbody2D rb)
	{
		if (!Object.op_Implicit((Object)(object)rb) || Object.op_Implicit((Object)(object)((Component)rb).GetComponentInParent<Player>()) || Object.op_Implicit((Object)(object)((Component)rb).GetComponentInParent<ProjectileHit>()) || Object.op_Implicit((Object)(object)((Component)rb).GetComponentInParent<Holdable>()))
		{
			return null;
		}
		PhysicsCauseProbe physicsCauseProbe = ((Component)rb).GetComponent<PhysicsCauseProbe>();
		if (!Object.op_Implicit((Object)(object)physicsCauseProbe))
		{
			physicsCauseProbe = ((Component)rb).gameObject.AddComponent<PhysicsCauseProbe>();
		}
		if (string.IsNullOrEmpty(physicsCauseProbe.StableKey))
		{
			physicsCauseProbe.StableKey = RawKey((Component)(object)rb);
		}
		return physicsCauseProbe;
	}

	internal static string RawKey(Component source)
	{
		if (!Object.op_Implicit((Object)(object)source))
		{
			return null;
		}
		PhotonView component = source.GetComponent<PhotonView>();
		if (Object.op_Implicit((Object)(object)component) && component.ViewID > 0)
		{
			return "view:" + component.ViewID;
		}
		List<string> list = new List<string>();
		Transform val = source.transform;
		while (Object.op_Implicit((Object)(object)val))
		{
			list.Add(((Object)val).name + "#" + val.GetSiblingIndex());
			if (Object.op_Implicit((Object)(object)((Component)val).GetComponent<Map>()))
			{
				break;
			}
			val = val.parent;
		}
		list.Reverse();
		return string.Join("/", list.ToArray());
	}

	internal static string Key(Component source)
	{
		if (!Object.op_Implicit((Object)(object)source))
		{
			return null;
		}
		Rigidbody2D componentInParent = source.GetComponentInParent<Rigidbody2D>();
		PhysicsCauseProbe physicsCauseProbe = (Object.op_Implicit((Object)(object)componentInParent) ? Track(componentInParent) : null);
		if (!((Object)(object)physicsCauseProbe != (Object)null))
		{
			return RawKey(source);
		}
		return physicsCauseProbe.StableKey;
	}

	internal static void Touch(Component source, Player player, DeathCause kind = DeathCause.PhysicsObject, bool broadcast = true)
	{
		if (Object.op_Implicit((Object)(object)source) && Object.op_Implicit((Object)(object)player))
		{
			string key = Key(source);
			Graph.Remember(key, player.playerID, kind, CombatTracker.Now);
			if (broadcast)
			{
				BroadcastObject(key, player, kind);
			}
		}
	}

	private static void BroadcastObject(string key, Player player, DeathCause kind)
	{
		if (CanSend && !((Object)(object)player.data == (Object)null) && !((Object)(object)player.data.view == (Object)null) && player.data.view.IsMine && (!Sent.TryGetValue(key, out var value) || !(CombatTracker.Now - value < 0.18)))
		{
			Sent[key] = CombatTracker.Now;
			Send(new object[6]
			{
				"zip.killfeed.causes.v1",
				0,
				key,
				player.playerID,
				(int)kind,
				PhotonNetwork.Time
			});
		}
	}

	internal static void Transfer(Rigidbody2D from, Rigidbody2D to)
	{
		if (Object.op_Implicit((Object)(object)from) && Object.op_Implicit((Object)(object)to) && !((Object)(object)from == (Object)(object)to) && !Object.op_Implicit((Object)(object)((Component)to).GetComponentInParent<Player>()))
		{
			PhysicsCauseProbe physicsCauseProbe = Track(from);
			PhysicsCauseProbe physicsCauseProbe2 = Track(to);
			if (!((Object)(object)physicsCauseProbe == (Object)null) && !((Object)(object)physicsCauseProbe2 == (Object)null))
			{
				Graph.Transfer(physicsCauseProbe.StableKey, physicsCauseProbe2.StableKey, CombatTracker.Now);
			}
		}
	}

	internal static void ObjectHit(Component source, Player player)
	{
		if (Object.op_Implicit((Object)(object)source) && Object.op_Implicit((Object)(object)player))
		{
			Touch(source, player);
		}
	}

	internal static void ExplosionPush(Explosion source, Player player)
	{
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: 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_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)source) || !Object.op_Implicit((Object)(object)player) || Mathf.Abs(source.force) < 0.001f)
		{
			return;
		}
		float num = source.range * (source.scaleRadius ? Mathf.Abs(((Component)source).transform.localScale.x) : 1f);
		if (num <= 0f)
		{
			return;
		}
		HashSet<int> hashSet = new HashSet<int>();
		Collider2D[] array = Physics2D.OverlapCircleAll(Vector2.op_Implicit(((Component)source).transform.position), num);
		foreach (Collider2D val in array)
		{
			if (((Component)val).gameObject.layer == 19 || Object.op_Implicit((Object)(object)((Component)val).GetComponentInParent<Player>()))
			{
				continue;
			}
			Rigidbody2D attachedRigidbody = val.attachedRigidbody;
			if (Object.op_Implicit((Object)(object)attachedRigidbody) && hashSet.Add(((Object)attachedRigidbody).GetInstanceID()))
			{
				Vector2 val2 = attachedRigidbody.position - Vector2.op_Implicit(((Component)source).transform.position);
				if (((Vector2)(ref val2)).sqrMagnitude > 0.0001f)
				{
					Touch((Component)(object)attachedRigidbody, player);
				}
			}
		}
	}

	internal static List<Rigidbody2D> ReleasedBodies(Component source)
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: 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_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: 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_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		List<Rigidbody2D> list = new List<Rigidbody2D>();
		if (!Object.op_Implicit((Object)(object)source))
		{
			return list;
		}
		list.AddRange(source.GetComponentsInChildren<Rigidbody2D>(true));
		Collider2D component = source.GetComponent<Collider2D>();
		if (Object.op_Implicit((Object)(object)component))
		{
			Bounds bounds = component.bounds;
			Collider2D[] array = Physics2D.OverlapBoxAll(Vector2.op_Implicit(((Bounds)(ref bounds)).center), Vector2.op_Implicit(((Bounds)(ref bounds)).size) + new Vector2(0.35f, 0.5f), 0f);
			foreach (Collider2D val in array)
			{
				Rigidbody2D attachedRigidbody = val.attachedRigidbody;
				if (!Object.op_Implicit((Object)(object)attachedRigidbody) || Object.op_Implicit((Object)(object)((Component)attachedRigidbody).GetComponentInParent<Player>()))
				{
					continue;
				}
				if (!((Object)(object)val == (Object)(object)component))
				{
					Bounds bounds2 = val.bounds;
					if (!(((Bounds)(ref bounds2)).min.y >= ((Bounds)(ref bounds)).max.y - 0.25f) && !val.IsTouching(component))
					{
						continue;
					}
				}
				list.Add(attachedRigidbody);
			}
		}
		Rigidbody2D component2 = source.GetComponent<Rigidbody2D>();
		if (Object.op_Implicit((Object)(object)component2))
		{
			Joint2D[] array2 = Object.FindObjectsOfType<Joint2D>();
			foreach (Joint2D val2 in array2)
			{
				if ((Object)(object)val2.connectedBody == (Object)(object)component2 && Object.op_Implicit((Object)(object)val2.attachedRigidbody))
				{
					list.Add(val2.attachedRigidbody);
				}
			}
		}
		foreach (Rigidbody2D item in list)
		{
			Track(item);
		}
		return list.Distinct().ToList();
	}

	internal static void Release(Component source, List<Rigidbody2D> bodies)
	{
		string text = Key(source);
		CauseCredit causeCredit = Graph.Get(text, CombatTracker.Now);
		if (causeCredit == null)
		{
			return;
		}
		foreach (Rigidbody2D body in bodies)
		{
			PhysicsCauseProbe physicsCauseProbe = Track(body);
			if (!((Object)(object)physicsCauseProbe == (Object)null))
			{
				if (physicsCauseProbe.StableKey == text)
				{
					Graph.Remember(text, causeCredit.PlayerId, DeathCause.ChainReaction, causeCredit.Started, causeCredit.Expires - causeCredit.Started);
				}
				else
				{
					Graph.Transfer(text, physicsCauseProbe.StableKey, CombatTracker.Now);
				}
			}
		}
	}

	internal static void Displace(Player victim, Player player, Vector2 force)
	{
		if (Object.op_Implicit((Object)(object)victim) && Object.op_Implicit((Object)(object)player) && !(((Vector2)(ref force)).sqrMagnitude < 1f) && CombatTracker.Ledger.IsEnemy(player.playerID, victim.playerID))
		{
			Displaced[victim.playerID] = new Displacement
			{
				Actor = player.playerID,
				Until = CombatTracker.Now + 3.0
			};
		}
	}

	private static int RecentDisplacer(Player victim)
	{
		if (Displaced.TryGetValue(victim.playerID, out var value) && value.Until >= CombatTracker.Now)
		{
			return value.Actor;
		}
		return CombatTracker.Ledger.LatestHostileHit(victim.playerID, CombatTracker.Now, 3.0, bulletsOnly: false);
	}

	internal static void QueueDamage(HealthHandler health, Vector2 damage, Vector2 position)
	{
		//IL_00c7: 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_016d: Unknown result type (might be due to invalid IL or missing references)
		//IL_017b: Unknown result type (might be due to invalid IL or missing references)
		if (Current == null || Current.Kind == DeathCause.Unknown || !Object.op_Implicit((Object)(object)health))
		{
			return;
		}
		Player component = ((Component)health).GetComponent<Player>();
		if (!Object.op_Implicit((Object)(object)component))
		{
			return;
		}
		DeathCause deathCause = Current.Kind;
		int num = (Object.op_Implicit((Object)(object)Current.Actor) ? Current.Actor.playerID : (-1));
		CauseCredit causeCredit = Graph.Get(Key(Current.Source), CombatTracker.Now);
		if (causeCredit != null)
		{
			num = causeCredit.PlayerId;
			if (causeCredit.Kind == DeathCause.ChainReaction)
			{
				deathCause = DeathCause.ChainReaction;
			}
		}
		if (num < 0 && deathCause == DeathCause.Hazard)
		{
			num = RecentDisplacer(component);
		}
		DamageHint damageHint = new DamageHint
		{
			Actor = num,
			Kind = deathCause,
			Until = CombatTracker.Now + 1.0,
			Position = position,
			Magnitude = ((Vector2)(ref damage)).magnitude,
			Subject = Key(Current.Source)
		};
		PutHint(component.playerID, damageHint);
		if (CanSend && (Object)(object)component.data.view != (Object)null && component.data.view.IsMine)
		{
			Send(new object[10]
			{
				"zip.killfeed.causes.v1",
				1,
				component.playerID,
				num,
				(int)deathCause,
				position.x,
				position.y,
				((Vector2)(ref damage)).magnitude,
				damageHint.Subject ?? "",
				PhotonNetwork.Time
			});
		}
	}

	private static void PutHint(int victim, DamageHint hint)
	{
		if (!Hints.TryGetValue(victim, out var value))
		{
			value = (Hints[victim] = new List<DamageHint>());
		}
		value.Add(hint);
		if (value.Count > 12)
		{
			value.RemoveAt(0);
		}
	}

	internal static DamageHint Consume(Player victim, Player nativeAttacker, Vector2 damage, Vector2 position)
	{
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)victim) || !Hints.TryGetValue(victim.playerID, out var value))
		{
			return null;
		}
		for (int i = 0; i < value.Count; i++)
		{
			DamageHint damageHint = value[i];
			if (damageHint.Until < CombatTracker.Now || Vector2.Distance(damageHint.Position, position) > 0.4f || Mathf.Abs(damageHint.Magnitude - ((Vector2)(ref damage)).magnitude) > Mathf.Max(0.2f, damageHint.Magnitude * 0.025f) || (Object.op_Implicit((Object)(object)nativeAttacker) && damageHint.Actor >= 0 && nativeAttacker.playerID != damageHint.Actor))
			{
				continue;
			}
			if (damageHint.Actor < 0)
			{
				CauseCredit causeCredit = Graph.Get(damageHint.Subject, CombatTracker.Now);
				if (causeCredit != null)
				{
					damageHint.Actor = causeCredit.PlayerId;
					if (causeCredit.Kind == DeathCause.ChainReaction)
					{
						damageHint.Kind = DeathCause.ChainReaction;
					}
				}
			}
			value.RemoveAt(i);
			return damageHint;
		}
		return null;
	}

	private static void Send(object[] data)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Expected O, but got Unknown
		PhotonNetwork.RaiseEvent((byte)179, (object)data, new RaiseEventOptions
		{
			Receivers = (ReceiverGroup)0
		}, SendOptions.SendReliable);
	}

	private static void Receive(EventData e)
	{
		//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)
		if (e.Code != 179 || !(e.CustomData is object[] array) || array.Length < 6 || !(array[0] is string) || (string)array[0] != "zip.killfeed.causes.v1")
		{
			return;
		}
		try
		{
			int num = Convert.ToInt32(array[1]);
			if (num == 0 && array.Length == 6)
			{
				string text = array[2] as string;
				int num2 = Convert.ToInt32(array[3]);
				Player val = KillfeedHud.Find(num2);
				if (text != null && text.Length <= 1024 && Object.op_Implicit((Object)(object)val) && val.data.view.OwnerActorNr == e.Sender && !(Math.Abs(PhotonNetwork.Time - Convert.ToDouble(array[5])) > 2.0))
				{
					int num3 = Convert.ToInt32(array[4]);
					if (num3 == 5 || num3 == 6)
					{
						Graph.Remember(text, num2, (DeathCause)num3, CombatTracker.Now);
					}
				}
			}
			else
			{
				if (num != 1 || array.Length != 10)
				{
					return;
				}
				int num4 = Convert.ToInt32(array[2]);
				Player val2 = KillfeedHud.Find(num4);
				if (!Object.op_Implicit((Object)(object)val2) || val2.data.view.OwnerActorNr != e.Sender || Math.Abs(PhotonNetwork.Time - Convert.ToDouble(array[9])) > 2.0)
				{
					return;
				}
				int num5 = Convert.ToInt32(array[4]);
				if (num5 >= 4 && Enum.IsDefined(typeof(DeathCause), num5))
				{
					float num6 = Convert.ToSingle(array[5]);
					float num7 = Convert.ToSingle(array[6]);
					float num8 = Convert.ToSingle(array[7]);
					if (!float.IsNaN(num6) && !float.IsInfinity(num6) && !float.IsNaN(num7) && !float.IsInfinity(num7) && !float.IsNaN(num8) && !float.IsInfinity(num8) && !(num8 < 0f) && array[8] is string { Length: <=1024 } text2)
					{
						PutHint(num4, new DamageHint
						{
							Actor = Convert.ToInt32(array[3]),
							Kind = (DeathCause)num5,
							Position = new Vector2(num6, num7),
							Magnitude = num8,
							Until = CombatTracker.Now + 1.0,
							Subject = text2
						});
					}
				}
			}
		}
		catch (InvalidCastException)
		{
		}
		catch (FormatException)
		{
		}
		catch (OverflowException)
		{
		}
	}
}
internal sealed class PhysicsCauseProbe : MonoBehaviour
{
	internal string StableKey;

	internal Vector2 BeforeVelocity;

	private Rigidbody2D body;

	private float rest;

	private CauseCredit seen;

	private void Awake()
	{
		body = ((Component)this).GetComponent<Rigidbody2D>();
		if (string.IsNullOrEmpty(StableKey))
		{
			StableKey = EnvironmentalTracker.RawKey((Component)(object)this);
		}
	}

	private void FixedUpdate()
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		if (Object.op_Implicit((Object)(object)body))
		{
			BeforeVelocity = body.velocity;
			CauseCredit causeCredit = EnvironmentalTracker.Graph.Get(StableKey, CombatTracker.Now);
			if (causeCredit != seen)
			{
				rest = 0f;
				seen = causeCredit;
			}
			Vector2 velocity = body.velocity;
			if (((Vector2)(ref velocity)).sqrMagnitude < 0.04f && Mathf.Abs(body.angularVelocity) < 2f)
			{
				rest += Time.fixedDeltaTime;
			}
			else
			{
				rest = 0f;
			}
			if (rest > 1.5f)
			{
				EnvironmentalTracker.Graph.Forget(StableKey);
			}
		}
	}

	private void OnCollisionEnter2D(Collision2D collision)
	{
		Contact(collision);
	}

	private void OnCollisionStay2D(Collision2D collision)
	{
		//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)
		Vector2 relativeVelocity = collision.relativeVelocity;
		if (((Vector2)(ref relativeVelocity)).sqrMagnitude > 0.5f)
		{
			Contact(collision);
		}
	}

	private void Contact(Collision2D collision)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)body))
		{
			return;
		}
		Vector2 relativeVelocity = collision.relativeVelocity;
		if (((Vector2)(ref relativeVelocity)).sqrMagnitude < 0.25f)
		{
			return;
		}
		Rigidbody2D val = collision.rigidbody;
		if ((Object)(object)val == (Object)(object)body)
		{
			val = collision.otherRigidbody;
		}
		if (!Object.op_Implicit((Object)(object)val) || (Object)(object)val == (Object)(object)body)
		{
			return;
		}
		PhysicsCauseProbe physicsCauseProbe = EnvironmentalTracker.Track(val);
		if (!((Object)(object)physicsCauseProbe == (Object)null))
		{
			float num = ((Vector2)(ref BeforeVelocity)).sqrMagnitude * body.mass;
			float num2 = ((Vector2)(ref physicsCauseProbe.BeforeVelocity)).sqrMagnitude * val.mass;
			if (num > num2 * 1.05f && num > 0.1f)
			{
				EnvironmentalTracker.Transfer(body, val);
			}
			else if (num2 > num * 1.05f && num2 > 0.1f)
			{
				EnvironmentalTracker.Transfer(val, body);
			}
		}
	}
}
[HarmonyPatch(typeof(NetworkPhysicsObject), "BulletPush")]
internal static class TrackBulletPush
{
	private static void Prefix(NetworkPhysicsObject __instance, Vector2 force, CharacterData asker)
	{
		Player val = (Object.op_Implicit((Object)(object)asker) ? asker.player : EnvironmentalTracker.Actor);
		if (((Vector2)(ref force)).sqrMagnitude > 0.01f && Object.op_Implicit((Object)(object)val))
		{
			EnvironmentalTracker.Touch((Component)(object)__instance, val);
		}
	}
}
[HarmonyPatch(typeof(NetworkPhysicsObject), "Push")]
internal static class TrackWalkingPush
{
	private static void Prefix(NetworkPhysicsObject __instance, CharacterData data)
	{
		if (Object.op_Implicit((Object)(object)data) && data.view.IsMine && ((Vector3)(ref data.input.direction)).sqrMagnitude > 0.05f)
		{
			EnvironmentalTracker.Touch((Component)(object)__instance, data.player);
		}
	}
}
[HarmonyPatch(typeof(NetworkPhysicsObject), "OnPlayerCollision")]
internal static class TrackCrateDamage
{
	private static void Prefix(NetworkPhysicsObject __instance, out EnvironmentalTracker.Context __state)
	{
		__state = EnvironmentalTracker.Enter((Component)(object)__instance, null, DeathCause.PhysicsObject);
	}

	private static Exception Finalizer(EnvironmentalTracker.Context __state, Exception __exception)
	{
		__state?.Dispose();
		return __exception;
	}
}
[HarmonyPatch(typeof(DamageBox), "Collide")]
internal static class TrackHazardDamage
{
	private static void Prefix(DamageBox __instance, out EnvironmentalTracker.Context __state)
	{
		Player val = NativeEffectSources.Owner((Component)(object)__instance);
		DeathCause deathCause = NativeEffectSources.Kind((Component)(object)__instance);
		__state = EnvironmentalTracker.Enter((Component)(object)__instance, val, (deathCause != DeathCause.Unknown) ? deathCause : ((!Object.op_Implicit((Object)(object)val)) ? DeathCause.Hazard : DeathCause.Unknown));
	}

	private static Exception Finalizer(EnvironmentalTracker.Context __state, Exception __exception)
	{
		__state?.Dispose();
		return __exception;
	}
}
[HarmonyPatch(typeof(Explosion), "Explode")]
internal static class TrackExplosionPush
{
	private static void Prefix(Explosion __instance, out EnvironmentalTracker.Context __state)
	{
		__state = NativeEffectSources.Enter((Component)(object)__instance);
		EnvironmentalTracker.ExplosionPush(__instance, __state.Actor);
	}

	private static Exception Finalizer(EnvironmentalTracker.Context __state, Exception __exception)
	{
		__state?.Dispose();
		return __exception;
	}
}
[HarmonyPatch(typeof(HealthHandler), "CallTakeDamage")]
internal static class TrackWorldDamagePacket
{
	private static void Prefix(HealthHandler __instance, Vector2 damage, Vector2 position)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		EnvironmentalTracker.QueueDamage(__instance, damage, position);
	}
}
[HarmonyPatch(typeof(HealthHandler), "CallTakeForce")]
internal static class TrackWorldKnockback
{
	private static void Prefix(HealthHandler __instance, Vector2 force, bool ignoreBlock)
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		CharacterData component = ((Component)__instance).GetComponent<CharacterData>();
		if ((Object)(object)component != (Object)null && (ignoreBlock || !component.block.IsBlocking()))
		{
			EnvironmentalTracker.Displace(component.player, EnvironmentalTracker.Actor, force);
		}
	}
}
[HarmonyPatch(typeof(LineRangeEffect), "Update")]
internal static class TrackShockwavePush
{
	private static void Prefix(LineRangeEffect __instance, out EnvironmentalTracker.Context __state)
	{
		__state = NativeEffectSources.Enter((Component)(object)__instance);
	}

	private static Exception Finalizer(EnvironmentalTracker.Context __state, Exception __exception)
	{
		__state?.Dispose();
		return __exception;
	}
}
[HarmonyPatch(typeof(DamagableEvent), "DoDamage")]
internal static class TrackBreakableSource
{
	private static void Prefix(DamagableEvent __instance, Player damagingPlayer)
	{
		if (!__instance.dead && !__instance.disabled && Object.op_Implicit((Object)(object)damagingPlayer))
		{
			EnvironmentalTracker.ObjectHit((Component)(object)__instance, damagingPlayer);
		}
	}
}
[HarmonyPatch(typeof(DamagableEvent), "Die")]
internal static class TrackReleasedSupport
{
	private static void Prefix(DamagableEvent __instance, out List<Rigidbody2D> __state)
	{
		__state = ((!__instance.dead && !__instance.disabled) ? EnvironmentalTracker.ReleasedBodies((Component)(object)__instance) : null);
	}

	private static void Postfix(DamagableEvent __instance, List<Rigidbody2D> __state)
	{
		if (__state != null && __instance.dead)
		{
			EnvironmentalTracker.Release((Component)(object)__instance, __state);
		}
	}
}
[HarmonyPatch(typeof(Destructible), "TakeDamage", new Type[]
{
	typeof(Vector2),
	typeof(Vector2),
	typeof(GameObject),
	typeof(Player),
	typeof(bool),
	typeof(bool)
})]
internal static class TrackNativeDestructible
{
	private static void Prefix(Destructible __instance, Vector2 damage, Player damagingPlayer, out List<Rigidbody2D> __state)
	{
		__state = null;
		if (!(((Vector2)(ref damage)).magnitude < __instance.threshold))
		{
			if (Object.op_Implicit((Object)(object)damagingPlayer))
			{
				EnvironmentalTracker.ObjectHit((Component)(object)__instance, damagingPlayer);
			}
			__state = EnvironmentalTracker.ReleasedBodies((Component)(object)__instance);
		}
	}

	private static void Postfix(Destructible __instance, List<Rigidbody2D> __state)
	{
		if (__state != null && !((Component)__instance).gameObject.activeSelf)
		{
			EnvironmentalTracker.Release((Component)(object)__instance, __state);
		}
	}
}
internal sealed class GlyphCanvas
{
	internal readonly int Size;

	internal readonly Color[] Pixels;

	internal GlyphCanvas(int size = 160)
	{
		Size = size;
		Pixels = (Color[])(object)new Color[size * size];
	}

	internal void Pixel(int x, int y, Color c)
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: 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_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: 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_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: 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_00a4: 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_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: 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_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: 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_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		if (x >= 0 && y >= 0 && x < Size && y < Size && !(c.a <= 0f))
		{
			int num = y * Size + x;
			Color val = Pixels[num];
			float num2 = c.a + val.a * (1f - c.a);
			Pixels[num] = (Color)((num2 > 0f) ? new Color((c.r * c.a + val.r * val.a * (1f - c.a)) / num2, (c.g * c.a + val.g * val.a * (1f - c.a)) / num2, (c.b * c.a + val.b * val.a * (1f - c.a)) / num2, num2) : Color.clear);
		}
	}

	internal void Disc(float x, float y, float radius, Color color)
	{
		//IL_0092: 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_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		int num = Mathf.Max(0, Mathf.FloorToInt((x - radius) * (float)Size));
		int num2 = Mathf.Min(Size - 1, Mathf.CeilToInt((x + radius) * (float)Size));
		int num3 = Mathf.Max(0, Mathf.FloorToInt((y - radius) * (float)Size));
		int num4 = Mathf.Min(Size - 1, Mathf.CeilToInt((y + radius) * (float)Size));
		for (int i = num3; i <= num4; i++)
		{
			for (int j = num; j <= num2; j++)
			{
				float num5 = Vector2.Distance(new Vector2(((float)j + 0.5f) / (float)Size, ((float)i + 0.5f) / (float)Size), new Vector2(x, y));
				Color c = color;
				c.a *= Mathf.Clamp01((radius - num5) * (float)Size + 0.5f);
				Pixel(j, i, c);
			}
		}
	}

	internal void Line(float ax, float ay, float bx, float by, float width, Color color)
	{
		//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_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_010a: Unknown result type (might be due to invalid IL or missing references)
		//IL_010d: 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_011e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_0150: Unknown result type (might be due to invalid IL or missing references)
		Vector2 val = default(Vector2);
		((Vector2)(ref val))..ctor(ax, ay);
		Vector2 val2 = new Vector2(bx, by) - val;
		float sqrMagnitude = ((Vector2)(ref val2)).sqrMagnitude;
		int num = Mathf.Max(0, Mathf.FloorToInt((Mathf.Min(ax, bx) - width) * (float)Size));
		int num2 = Mathf.Min(Size - 1, Mathf.CeilToInt((Mathf.Max(ax, bx) + width) * (float)Size));
		int num3 = Mathf.Max(0, Mathf.FloorToInt((Mathf.Min(ay, by) - width) * (float)Size));
		int num4 = Mathf.Min(Size - 1, Mathf.CeilToInt((Mathf.Max(ay, by) + width) * (float)Size));
		Vector2 val3 = default(Vector2);
		for (int i = num3; i <= num4; i++)
		{
			for (int j = num; j <= num2; j++)
			{
				((Vector2)(ref val3))..ctor(((float)j + 0.5f) / (float)Size, ((float)i + 0.5f) / (float)Size);
				float num5 = ((sqrMagnitude > 0f) ? Mathf.Clamp01(Vector2.Dot(val3 - val, val2) / sqrMagnitude) : 0f);
				float num6 = Vector2.Distance(val3, val + val2 * num5);
				Color c = color;
				c.a *= Mathf.Clamp01((width * 0.5f - num6) * (float)Size + 0.5f);
				Pixel(j, i, c);
			}
		}
	}

	internal void Triangle(Vector2 a, Vector2 b, Vector2 c, Color ca, Color cb, Color cc)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: 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)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: 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_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_002d: 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_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_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: Unknown result type (might be due to invalid IL or missing references)
		//IL_0125: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_012c: 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_012f: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_013e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0140: Unknown result type (might be due to invalid IL or missing references)
		//IL_0145: Unknown result type (might be due to invalid IL or missing references)
		//IL_0146: Unknown result type (might be due to invalid IL or missing references)
		//IL_0148: Unknown result type (might be due to invalid IL or missing references)
		//IL_0183: 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_0190: Unknown result type (might be due to invalid IL or missing references)
		//IL_0195: Unknown result type (might be due to invalid IL or missing references)
		//IL_019a: Unknown result type (might be due to invalid IL or missing references)
		//IL_019e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
		a *= (float)Size;
		b *= (float)Size;
		c *= (float)Size;
		float num = Cross(b - a, c - a);
		if (Mathf.Abs(num) < 0.0001f)
		{
			return;
		}
		int num2 = Mathf.Max(0, Mathf.FloorToInt(Mathf.Min(a.x, Mathf.Min(b.x, c.x))));
		int num3 = Mathf.Min(Size - 1, Mathf.CeilToInt(Mathf.Max(a.x, Mathf.Max(b.x, c.x))));
		int num4 = Mathf.Max(0, Mathf.FloorToInt(Mathf.Min(a.y, Mathf.Min(b.y, c.y))));
		int num5 = Mathf.Min(Size - 1, Mathf.CeilToInt(Mathf.Max(a.y, Mathf.Max(b.y, c.y))));
		Vector2 val = default(Vector2);
		for (int i = num4; i <= num5; i++)
		{
			for (int j = num2; j <= num3; j++)
			{
				((Vector2)(ref val))..ctor((float)j + 0.5f, (float)i + 0.5f);
				float num6 = Cross(b - val, c - val) / num;
				float num7 = Cross(c - val, a - val) / num;
				float num8 = 1f - num6 - num7;
				i