Decompiled source of Kill Feed v1.0.2

KillFeed.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using InControl;
using SFQoL;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("KillFeed")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1+562f2a5697c435654782039a6e570db5445afc1f")]
[assembly: AssemblyProduct("KillFeed")]
[assembly: AssemblyTitle("KillFeed")]
[assembly: AssemblyVersion("1.0.1.0")]
namespace SFQoL
{
	internal static class Compat
	{
		private static bool searched;

		private static FieldInfo roundsActive;

		private static PropertyInfo roundsArmed;

		private static FieldInfo cardPicking;

		private static bool cardSearched;

		public static bool Rounds
		{
			get
			{
				Find();
				try
				{
					if ((object)roundsArmed != null && (bool)roundsArmed.GetValue(null, null))
					{
						return true;
					}
					if ((object)roundsActive != null && (bool)roundsActive.GetValue(null))
					{
						return true;
					}
				}
				catch
				{
				}
				return false;
			}
		}

		public static bool CardScreen
		{
			get
			{
				if (!cardSearched)
				{
					Type type = RoundsType("StickRounds.CardPick");
					cardSearched = (object)type != null || Time.frameCount > 1;
					if ((object)type != null)
					{
						cardPicking = type.GetField("Picking", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
					}
				}
				try
				{
					return (object)cardPicking != null && (bool)cardPicking.GetValue(null);
				}
				catch
				{
					return false;
				}
			}
		}

		public static bool RoundsMatch
		{
			get
			{
				Find();
				try
				{
					return (object)roundsActive != null && (bool)roundsActive.GetValue(null) && !GameManager.stillInMenu;
				}
				catch
				{
					return false;
				}
			}
		}

		private static Type RoundsType(string name)
		{
			if (!Chainloader.PluginInfos.TryGetValue("stickfight.stickrounds", out var value) || (Object)(object)value.Instance == (Object)null)
			{
				return null;
			}
			return ((object)value.Instance).GetType().Assembly.GetType(name, throwOnError: false);
		}

		private static void Find()
		{
			if (!searched)
			{
				Type type = RoundsType("StickRounds.RoundsMode");
				searched = (object)type != null || Time.frameCount > 1;
				if ((object)type != null)
				{
					roundsActive = type.GetField("Active", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
					roundsArmed = type.GetProperty("Armed", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				}
			}
		}

		public static bool IsBotDevice(InputDevice d)
		{
			if (d != null)
			{
				return ((object)d).GetType().Name == "BotDevice";
			}
			return false;
		}
	}
	internal static class QolConfig
	{
		public static ConfigEntry<bool> Enabled(ConfigFile config, string section, string description)
		{
			return config.Bind<bool>(section, "Enabled", true, description);
		}

		private static Dictionary<ConfigDefinition, string> Orphans(ConfigFile config)
		{
			return Traverse.Create((object)config).Property("OrphanedEntries", (object[])null).GetValue<Dictionary<ConfigDefinition, string>>();
		}

		public static string Old(ConfigFile config, string section, string key)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			Dictionary<ConfigDefinition, string> dictionary = Orphans(config);
			if (dictionary == null || !dictionary.TryGetValue(new ConfigDefinition(section, key), out var value))
			{
				return null;
			}
			return value;
		}

		public static void SetOld(ConfigFile config, string section, string key, string value)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			Dictionary<ConfigDefinition, string> dictionary = Orphans(config);
			if (dictionary != null)
			{
				dictionary[new ConfigDefinition(section, key)] = value;
			}
		}

		public static void DropOld(ConfigFile config)
		{
			Dictionary<ConfigDefinition, string> dictionary = Orphans(config);
			if (dictionary != null && dictionary.Count != 0)
			{
				dictionary.Clear();
				config.Save();
			}
		}
	}
	internal static class Ui
	{
		public static readonly Color Panel = new Color(0.176f, 0.176f, 0.176f);

		public static readonly Color Strip = new Color(0.147f, 0.147f, 0.147f);

		public static readonly Color Item = new Color(0.265f, 0.265f, 0.265f);

		public static readonly Color Grey = new Color(0.6f, 0.6f, 0.6f);

		private static TMP_FontAsset font;

		private static Sprite box;

		private static bool boxSearched;

		private static Camera menuCam;

		private static float menuCamSearchAt;

		public static TMP_FontAsset Font
		{
			get
			{
				if ((Object)(object)font == (Object)null)
				{
					GameManager instance = GameManager.Instance;
					if ((Object)(object)instance != (Object)null && (Object)(object)instance.winText != (Object)null)
					{
						font = ((TMP_Text)instance.winText).font;
					}
					if ((Object)(object)font == (Object)null)
					{
						TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>();
						foreach (TMP_FontAsset val in array)
						{
							if (((Object)val).name.StartsWith("Anton"))
							{
								font = val;
								break;
							}
						}
					}
				}
				return font;
			}
		}

		public static Sprite BoxSprite
		{
			get
			{
				if ((Object)(object)box == (Object)null && !boxSearched)
				{
					boxSearched = true;
					Sprite[] array = Resources.FindObjectsOfTypeAll<Sprite>();
					foreach (Sprite val in array)
					{
						if (((Object)val).name == "box")
						{
							box = val;
							break;
						}
					}
				}
				return box;
			}
		}

		public static int MenuLayer
		{
			get
			{
				int num = LayerMask.NameToLayer("MENU");
				if (num < 0)
				{
					return 31;
				}
				return num;
			}
		}

		public static void Attach(Canvas c)
		{
			//IL_00dd: 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_00aa: Invalid comparison between Unknown and I4
			if ((Object)(object)c == (Object)null)
			{
				return;
			}
			if (((Object)(object)menuCam == (Object)null || !((Behaviour)menuCam).isActiveAndEnabled) && Time.unscaledTime >= menuCamSearchAt)
			{
				menuCamSearchAt = Time.unscaledTime + 1f;
				menuCam = null;
				Camera[] allCameras = Camera.allCameras;
				foreach (Camera val in allCameras)
				{
					if (((Object)val).name == "Camera_Pause" && (val.cullingMask & (1 << MenuLayer)) != 0)
					{
						menuCam = val;
						break;
					}
				}
			}
			if ((Object)(object)menuCam != (Object)null && ((Behaviour)menuCam).isActiveAndEnabled)
			{
				if ((int)c.renderMode != 1 || (Object)(object)c.worldCamera != (Object)(object)menuCam)
				{
					c.renderMode = (RenderMode)1;
					c.worldCamera = menuCam;
					c.planeDistance = 1f;
				}
			}
			else if ((int)c.renderMode != 0)
			{
				c.renderMode = (RenderMode)0;
			}
		}

		public static Canvas MakeCanvas(string name, int order)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_0017: 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)
			GameObject val = new GameObject(name)
			{
				layer = MenuLayer
			};
			Object.DontDestroyOnLoad((Object)val);
			Canvas val2 = val.AddComponent<Canvas>();
			val2.renderMode = (RenderMode)0;
			val2.sortingOrder = order;
			Attach(val2);
			CanvasScaler obj = val.AddComponent<CanvasScaler>();
			obj.uiScaleMode = (ScaleMode)1;
			obj.referenceResolution = new Vector2(1920f, 1080f);
			obj.matchWidthOrHeight = 0.5f;
			return val2;
		}

		public static RectTransform Rect(Transform parent, string name)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected O, but got Unknown
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) })
			{
				layer = ((Component)parent).gameObject.layer
			};
			val.transform.SetParent(parent, false);
			RectTransform val2 = (RectTransform)val.transform;
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0.5f, 0.5f);
			val2.anchorMax = val3;
			val2.anchorMin = val3;
			val2.pivot = new Vector2(0.5f, 0.5f);
			return val2;
		}

		public static Image Box(Transform parent, string name, Color color, Vector2 pos, Vector2 size, bool rounded = false)
		{
			//IL_0008: 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_0022: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			RectTransform obj = Rect(parent, name);
			obj.anchoredPosition = pos;
			obj.sizeDelta = size;
			Image val = ((Component)obj).gameObject.AddComponent<Image>();
			((Graphic)val).color = color;
			((Graphic)val).raycastTarget = false;
			if (rounded && (Object)(object)BoxSprite != (Object)null)
			{
				val.sprite = BoxSprite;
				Vector4 border = BoxSprite.border;
				if (((Vector4)(ref border)).sqrMagnitude > 0f)
				{
					val.type = (Type)1;
				}
			}
			return val;
		}

		public static void Fill(RectTransform rt, float inset)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			rt.anchorMin = Vector2.zero;
			rt.anchorMax = Vector2.one;
			rt.offsetMin = new Vector2(inset, inset);
			rt.offsetMax = new Vector2(0f - inset, 0f - inset);
		}

		public static TextMeshProUGUI Text(Transform parent, string name, string text, float size, Color color, TextAlignmentOptions align)
		{
			//IL_0032: 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)
			TextMeshProUGUI val = ((Component)Rect(parent, name)).gameObject.AddComponent<TextMeshProUGUI>();
			if ((Object)(object)Font != (Object)null)
			{
				((TMP_Text)val).font = Font;
			}
			((TMP_Text)val).fontSize = size;
			((Graphic)val).color = color;
			((TMP_Text)val).alignment = align;
			((TMP_Text)val).enableWordWrapping = false;
			((TMP_Text)val).richText = true;
			((Graphic)val).raycastTarget = false;
			((TMP_Text)val).text = text;
			return val;
		}

		public static Color PlayerColor(Controller c)
		{
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: 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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)c != (Object)null)
			{
				SpriteRenderer componentInChildren = ((Component)c).GetComponentInChildren<SpriteRenderer>();
				SetColorWhenDamaged val = (((Object)(object)componentInChildren != (Object)null) ? ((Component)componentInChildren).GetComponent<SetColorWhenDamaged>() : null);
				if ((Object)(object)val == (Object)null)
				{
					val = ((Component)c).GetComponentInChildren<SetColorWhenDamaged>(true);
				}
				if ((Object)(object)val != (Object)null && val.startColor.a > 0f)
				{
					Color startColor = val.startColor;
					startColor.a = 1f;
					return startColor;
				}
				ControllerHandler instance = ControllerHandler.Instance;
				if ((Object)(object)instance != (Object)null && instance.colors != null && c.playerID >= 0 && c.playerID < instance.colors.Length && (Object)(object)instance.colors[c.playerID] != (Object)null)
				{
					return instance.colors[c.playerID].color;
				}
			}
			return Color.white;
		}

		public static Color SlotColor(int id)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//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)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			ControllerHandler instance = ControllerHandler.Instance;
			if ((Object)(object)instance != (Object)null && instance.colors != null && id >= 0 && id < instance.colors.Length && (Object)(object)instance.colors[id] != (Object)null)
			{
				Color color = instance.colors[id].color;
				color.a = 1f;
				return color;
			}
			return Color.white;
		}

		public static string Hex(Color c)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			return "#" + ((int)(Mathf.Clamp01(c.r) * 255f)).ToString("X2") + ((int)(Mathf.Clamp01(c.g) * 255f)).ToString("X2") + ((int)(Mathf.Clamp01(c.b) * 255f)).ToString("X2");
		}

		public static string Colored(string text, Color c)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			return "<color=" + Hex(c) + ">" + text + "</color>";
		}

		public static Color WithAlpha(Color c, float a)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			c.a = a;
			return c;
		}
	}
}
namespace KillFeed
{
	[BepInPlugin("stickfight.killfeed", "Kill Feed", "1.0.2")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "stickfight.killfeed";

		public const string Name = "Kill Feed";

		public const string Version = "1.0.2";

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> Enabled;

		private void Awake()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Expected O, but got Unknown
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			Enabled = QolConfig.Enabled(((BaseUnityPlugin)this).Config, "Feed", "Short lines in the top-right corner saying who killed whom and how.");
			QolConfig.DropOld(((BaseUnityPlugin)this).Config);
			new Harmony("stickfight.killfeed").PatchAll(typeof(Plugin).Assembly);
			SceneManager.sceneLoaded += delegate(Scene scene, LoadSceneMode mode)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				if ((int)mode == 0)
				{
					Tracker.Reset();
					RocketCredit.Reset();
				}
			};
			GameObject val = new GameObject("KillFeed");
			Object.DontDestroyOnLoad((Object)val);
			((Object)val).hideFlags = (HideFlags)61;
			val.AddComponent<Feed>();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Kill Feed 1.0.2 loaded.");
		}
	}
	internal sealed class Hit
	{
		public Controller By;

		public bool Environment;

		public bool Head;

		public string Weapon;

		public bool Punch;

		public bool Rocket;
	}
	internal sealed class Pending
	{
		public Controller Victim;

		public Controller Killer;

		public Hit Last;

		public bool Fell;
	}
	internal static class Tracker
	{
		public static bool HittingHead;

		public static bool Throwing;

		public static int ThrownId = -1;

		public static readonly Dictionary<Controller, Hit> LastHit = new Dictionary<Controller, Hit>();

		public static readonly List<Pending> Pending = new List<Pending>();

		public static readonly Dictionary<Controller, string> LastFired = new Dictionary<Controller, string>();

		private static readonly Regex number = new Regex("^\\d+\\s*");

		private static Weapons weaponList;

		public static string Clean(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return null;
			}
			string text = number.Replace(name.Replace("(Clone)", ""), "").Trim();
			if (text.Length <= 0)
			{
				return null;
			}
			return text.ToUpperInvariant();
		}

		public static string WeaponById(int id)
		{
			if (id < 0)
			{
				return null;
			}
			if ((Object)(object)weaponList == (Object)null)
			{
				weaponList = Object.FindObjectOfType<Weapons>();
			}
			if ((Object)(object)weaponList == (Object)null || id >= ((Component)weaponList).transform.childCount)
			{
				return null;
			}
			return Clean(((Object)((Component)weaponList).transform.GetChild(id)).name);
		}

		public static string Held(Controller c)
		{
			Fighting val = (((Object)(object)c != (Object)null) ? ((Component)c).GetComponent<Fighting>() : null);
			if (!((Object)(object)val != (Object)null) || !((Object)(object)val.weapon != (Object)null))
			{
				return null;
			}
			return Clean(((Object)val.weapon).name);
		}

		public static void Reset()
		{
			LastHit.Clear();
			LastFired.Clear();
			Pending.Clear();
			weaponList = null;
			Throwing = false;
			HittingHead = false;
		}

		public static string Cause(Controller damager, DamageType type)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if (Throwing)
			{
				string text = WeaponById(ThrownId);
				if (text == null)
				{
					return "THROWN";
				}
				return "THROWN " + text;
			}
			if ((Object)(object)damager == (Object)null)
			{
				return null;
			}
			if ((int)type == 0)
			{
				return Held(damager) ?? "PUNCH";
			}
			if (LastFired.TryGetValue(damager, out var value))
			{
				return value;
			}
			return Held(damager);
		}
	}
	[HarmonyPatch(typeof(Fighting), "Attack")]
	internal static class AttackPatch
	{
		private static void Prefix(Fighting __instance)
		{
			Weapon weapon = __instance.weapon;
			if (!((Object)(object)weapon == (Object)null) && weapon.isGun && !(__instance.counter <= weapon.cd))
			{
				Controller component = ((Component)__instance).GetComponent<Controller>();
				if ((Object)(object)component != (Object)null)
				{
					Tracker.LastFired[component] = Tracker.Clean(((Object)weapon).name);
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class ThrowPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(ThrownWeapon), "LateUpdate", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(WeaponPickUp), "OnCollisionEnter", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(IsBeingThrown), "OnCollisionEnter", (Type[])null, (Type[])null);
		}

		private static void Prefix(Component __instance)
		{
			int thrownId = -1;
			WeaponPickUp val = (WeaponPickUp)(object)((__instance is WeaponPickUp) ? __instance : null);
			if ((Object)(object)val != (Object)null)
			{
				thrownId = val.id;
			}
			else
			{
				ThrownWeapon val2 = (ThrownWeapon)(object)((__instance is ThrownWeapon) ? __instance : null);
				if ((Object)(object)val2 != (Object)null)
				{
					thrownId = val2.weaponID;
				}
			}
			Tracker.ThrownId = thrownId;
			Tracker.Throwing = true;
		}

		private static Exception Finalizer(Exception __exception)
		{
			Tracker.Throwing = false;
			return __exception;
		}
	}
	[HarmonyPatch]
	internal static class BodyPartPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			MethodInfo[] methods = typeof(BodyPart).GetMethods();
			foreach (MethodInfo methodInfo in methods)
			{
				if (methodInfo.Name == "TakeDamageWithParticle")
				{
					yield return methodInfo;
				}
			}
		}

		private static void Prefix(BodyPart __instance)
		{
			Tracker.HittingHead = (Object)(object)((Component)__instance).GetComponent<Head>() != (Object)null;
		}

		private static Exception Finalizer(Exception __exception)
		{
			Tracker.HittingHead = false;
			return __exception;
		}
	}
	[HarmonyPatch(typeof(HealthHandler), "TakeDamage", new Type[]
	{
		typeof(float),
		typeof(Controller),
		typeof(DamageType),
		typeof(bool),
		typeof(Vector3),
		typeof(Vector3)
	})]
	internal static class TakeDamagePatch
	{
		private static void Prefix(HealthHandler __instance, Controller damager, DamageType dmgType)
		{
			//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_0095: Invalid comparison between Unknown and I4
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Invalid comparison between Unknown and I4
			Controller component = ((Component)__instance).GetComponent<Controller>();
			CharacterInformation component2 = ((Component)__instance).GetComponent<CharacterInformation>();
			if (!((Object)(object)component == (Object)null) && !((Object)(object)component2 == (Object)null) && !component2.isDead)
			{
				bool flag = (Object)(object)damager == (Object)null && (Object)(object)RocketCredit.Current != (Object)null;
				if (flag)
				{
					damager = RocketCredit.Current;
				}
				Tracker.LastHit[component] = new Hit
				{
					By = damager,
					Environment = ((Object)(object)damager == (Object)null),
					Head = (Tracker.HittingHead && !Tracker.Throwing && (int)dmgType > 0),
					Weapon = Tracker.Cause(damager, dmgType),
					Punch = ((int)dmgType == 0),
					Rocket = flag
				};
			}
		}
	}
	[HarmonyPatch(typeof(GameManager), "KillPlayer")]
	internal static class KillPlayerPatch
	{
		private static void Prefix(Controller playerToKill)
		{
			if (!((Object)(object)playerToKill == (Object)null))
			{
				Tracker.LastHit.TryGetValue(playerToKill, out var value);
				Controller killer = ((value != null && value.Rocket) ? value.By : playerToKill.damager);
				Tracker.Pending.Add(new Pending
				{
					Victim = playerToKill,
					Killer = killer,
					Last = value
				});
				Tracker.LastHit.Remove(playerToKill);
			}
		}
	}
	[HarmonyPatch(typeof(Controller), "OnFallOut")]
	internal static class FallOutPatch
	{
		private static void Prefix(Controller __instance)
		{
			foreach (Pending item in Tracker.Pending)
			{
				if ((Object)(object)item.Victim == (Object)(object)__instance)
				{
					item.Fell = true;
				}
			}
		}
	}
	internal class Feed : MonoBehaviour
	{
		private sealed class Line
		{
			public RectTransform Rt;

			public CanvasGroup Group;

			public float Born;

			public float Y;
		}

		private const int MaxLines = 5;

		private const float Life = 5f;

		private const float Fade = 0.6f;

		private const float LineHeight = 46f;

		private Canvas canvas;

		private RectTransform root;

		private readonly List<Line> lines = new List<Line>();

		private static readonly FieldInfo winTexts = AccessTools.Field(typeof(WinCounterUI), "mPlayerWinTexts");

		private WinCounterUI counter;

		private TextMeshProUGUI[] counterTexts;

		private float counterSearchAt;

		private static bool overlay;

		private static Controller only;

		private static Func<Controller, Material, Material> paintText;

		private static bool paintLooked;

		private static MethodInfo conceded;

		private static bool concededLooked;

		private void LateUpdate()
		{
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)canvas == (Object)null)
			{
				Build();
			}
			Ui.Attach(canvas);
			if (!Plugin.Enabled.Value)
			{
				Tracker.Pending.Clear();
				foreach (Line line3 in lines)
				{
					Object.Destroy((Object)(object)((Component)line3.Rt).gameObject);
				}
				lines.Clear();
				return;
			}
			if (Tracker.Pending.Count > 0)
			{
				List<Pending> list = new List<Pending>(Tracker.Pending);
				Tracker.Pending.Clear();
				foreach (Pending item in list)
				{
					try
					{
						string text = Describe(item);
						Add(text, item);
						Plugin.Log.LogDebug((object)("Feed: " + Regex.Replace(text, "<[^>]*>", "")));
					}
					catch (Exception ex)
					{
						Plugin.Log.LogWarning((object)("Couldn't describe a kill: " + ex.Message));
					}
				}
			}
			float num = (CornerCounterShowing() ? (-190f) : (-34f));
			root.anchoredPosition = new Vector2(-34f, Mathf.Lerp(root.anchoredPosition.y, num, 1f - Mathf.Exp((0f - Time.unscaledDeltaTime) * 10f)));
			float unscaledTime = Time.unscaledTime;
			for (int num2 = lines.Count - 1; num2 >= 0; num2--)
			{
				Line line = lines[num2];
				if (unscaledTime - line.Born > 5f || num2 >= 5)
				{
					Object.Destroy((Object)(object)((Component)line.Rt).gameObject);
					lines.RemoveAt(num2);
				}
			}
			bool isPaused = PauseManager.isPaused;
			for (int i = 0; i < lines.Count; i++)
			{
				Line line2 = lines[i];
				float num3 = unscaledTime - line2.Born;
				float num4 = (float)(-i) * 46f;
				line2.Y = Mathf.Lerp(line2.Y, num4, 1f - Mathf.Exp((0f - Time.unscaledDeltaTime) * 14f));
				float num5 = Mathf.Clamp01(num3 / 0.18f);
				line2.Rt.anchoredPosition = new Vector2((1f - num5) * (1f - num5) * 120f, line2.Y);
				line2.Group.alpha = (isPaused ? 0f : Mathf.Min(num5, Mathf.Clamp01((5f - num3) / 0.6f)));
			}
		}

		private bool CornerCounterShowing()
		{
			if ((Object)(object)counter == (Object)null && Time.unscaledTime >= counterSearchAt)
			{
				counterSearchAt = Time.unscaledTime + 1f;
				counter = Object.FindObjectOfType<WinCounterUI>();
				counterTexts = (((Object)(object)counter != (Object)null && (object)winTexts != null) ? (winTexts.GetValue(counter) as TextMeshProUGUI[]) : null);
			}
			if ((Object)(object)counter == (Object)null)
			{
				return false;
			}
			TextMeshProUGUI[] array = counterTexts;
			if (array != null && array.Length > 1 && (Object)(object)array[1] != (Object)null)
			{
				return ((Component)array[1]).gameObject.activeInHierarchy;
			}
			return false;
		}

		private static string Name(Controller c)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)c == (Object)null)
			{
				return "?";
			}
			string text = "P" + (c.playerID + 1);
			if (overlay)
			{
				if (!((Object)(object)c == (Object)(object)only))
				{
					return text;
				}
				return "<alpha=#FF>" + text + "<alpha=#00>";
			}
			return Ui.Colored(text, Ui.PlayerColor(c));
		}

		private static string Red(string s)
		{
			if (!overlay)
			{
				return "<color=#FF6B5E>" + s + "</color>";
			}
			return s;
		}

		private static Material PatternedText(Controller player, Material font)
		{
			if (!paintLooked)
			{
				paintLooked = true;
				if (Chainloader.PluginInfos.TryGetValue("stickfight.paintcan", out var value) && (Object)(object)value.Instance != (Object)null)
				{
					MethodInfo methodInfo = ((object)value.Instance).GetType().Assembly.GetType("PaintCan.PaintCanApi")?.GetMethod("PatternedText", BindingFlags.Static | BindingFlags.Public);
					if ((object)methodInfo != null)
					{
						paintText = (Func<Controller, Material, Material>)Delegate.CreateDelegate(typeof(Func<Controller, Material, Material>), methodInfo);
					}
				}
			}
			if (paintText == null || !((Object)(object)player != (Object)null) || !((Object)(object)font != (Object)null))
			{
				return null;
			}
			return paintText(player, font);
		}

		private static void Patterns(Pending p, TextMeshProUGUI t)
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: 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)
			Controller[] array = (Controller[])(object)new Controller[2] { p.Killer, p.Victim };
			for (int i = 0; i < array.Length; i++)
			{
				Controller val = array[i];
				if ((Object)(object)val == (Object)null || (i == 1 && (Object)(object)val == (Object)(object)p.Killer))
				{
					continue;
				}
				Material val2 = PatternedText(val, ((TMP_Text)t).fontSharedMaterial);
				if (!((Object)(object)val2 == (Object)null))
				{
					overlay = true;
					only = val;
					string text;
					try
					{
						text = Describe(p);
					}
					finally
					{
						overlay = false;
						only = null;
					}
					TextMeshProUGUI obj = Ui.Text((Transform)(object)((TMP_Text)t).rectTransform, "Pattern", text, ((TMP_Text)t).fontSize, Color.white, ((TMP_Text)t).alignment);
					Ui.Fill(((TMP_Text)obj).rectTransform, 0f);
					((TMP_Text)obj).margin = ((TMP_Text)t).margin;
					((TMP_Text)obj).alignment = ((TMP_Text)t).alignment;
					((TMP_Text)obj).fontSharedMaterial = val2;
					((Graphic)obj).color = Color.white;
					((TMP_Text)obj).ForceMeshUpdate();
				}
			}
		}

		private static bool BotStalemate(Controller victim)
		{
			if ((Object)(object)victim == (Object)null)
			{
				return false;
			}
			if (!concededLooked)
			{
				concededLooked = true;
				if (Chainloader.PluginInfos.TryGetValue("stickfight.enhancedbots", out var value) && (Object)(object)value.Instance != (Object)null)
				{
					Type type = ((object)value.Instance).GetType().Assembly.GetType("EnhancedBots.Stalemate");
					if ((object)type != null)
					{
						conceded = type.GetMethod("Conceded", new Type[1] { typeof(Controller) });
					}
				}
			}
			if ((object)conceded == null)
			{
				return false;
			}
			try
			{
				return (bool)conceded.Invoke(null, new object[1] { victim });
			}
			catch
			{
				return false;
			}
		}

		private static string Tag(string s)
		{
			if (!overlay)
			{
				return "<color=#B0B0B0><size=80%>" + s + "</size></color>";
			}
			return "<size=80%>" + s + "</size>";
		}

		private static string Describe(Pending p)
		{
			Controller victim = p.Victim;
			Controller killer = p.Killer;
			Hit last = p.Last;
			if (BotStalemate(victim))
			{
				return Name(victim) + "  " + Tag("BOT STALEMATE");
			}
			if ((Object)(object)killer == (Object)null || (Object)(object)killer == (Object)(object)victim)
			{
				if ((Object)(object)killer == (Object)(object)victim && last != null && !last.Environment)
				{
					return Name(victim) + "  " + Tag(((last.Weapon != null) ? (last.Weapon + "  ") : "") + "OWN GOAL");
				}
				return Name(victim) + "  " + Tag(p.Fell ? "FELL" : "DIED");
			}
			string text;
			if (last == null || last.Environment || (Object)(object)last.By != (Object)(object)killer)
			{
				text = (p.Fell ? "RING OUT" : "HAZARD");
			}
			else
			{
				text = last.Weapon ?? (last.Punch ? "PUNCH" : "KILLED");
				if (last.Head)
				{
					text = ((text == "KILLED") ? Red("HEADSHOT") : (text + "  " + Red("HEADSHOT")));
				}
			}
			return Name(killer) + "  " + Tag(text) + "  " + Name(victim);
		}

		private void Add(string text, Pending p)
		{
			//IL_0024: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = Ui.Rect((Transform)(object)root, "Line");
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(1f, 1f);
			val.anchorMax = val2;
			val.anchorMin = val2;
			val.pivot = new Vector2(1f, 1f);
			CanvasGroup val3 = ((Component)val).gameObject.AddComponent<CanvasGroup>();
			val3.alpha = 0f;
			val3.blocksRaycasts = false;
			val3.interactable = false;
			TextMeshProUGUI val4 = Ui.Text((Transform)(object)val, "Text", text, 30f, Color.white, (TextAlignmentOptions)516);
			((TMP_Text)val4).ForceMeshUpdate();
			float num = Mathf.Max(60f, ((TMP_Text)val4).preferredWidth) + 28f;
			val.sizeDelta = new Vector2(num, 40f);
			Ui.Fill(((TMP_Text)val4).rectTransform, 0f);
			((TMP_Text)val4).margin = new Vector4(14f, 0f, 14f, 0f);
			((TMP_Text)val4).alignment = (TextAlignmentOptions)4098;
			Patterns(p, val4);
			Line item = new Line
			{
				Rt = val,
				Group = val3,
				Born = Time.unscaledTime,
				Y = 46f
			};
			lines.Insert(0, item);
		}

		private void Build()
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: 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)
			canvas = Ui.MakeCanvas("KillFeedCanvas", 6);
			root = Ui.Rect(((Component)canvas).transform, "Root");
			RectTransform obj = root;
			RectTransform obj2 = root;
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(1f, 1f);
			obj2.anchorMax = val;
			obj.anchorMin = val;
			root.pivot = new Vector2(1f, 1f);
			root.anchoredPosition = new Vector2(-34f, -34f);
			root.sizeDelta = new Vector2(10f, 10f);
		}
	}
	internal static class RocketCredit
	{
		private struct Blast
		{
			public Vector3 Pos;

			public Controller Owner;

			public float At;
		}

		private static readonly List<Blast> blasts = new List<Blast>();

		public static Controller Current;

		public static void Reset()
		{
			blasts.Clear();
			Current = null;
		}

		public static Controller OwnerOf(Component c)
		{
			DamagerHolder componentInParent = c.GetComponentInParent<DamagerHolder>();
			if ((Object)(object)componentInParent != (Object)null && (Object)(object)componentInParent.damager != (Object)null)
			{
				return componentInParent.damager;
			}
			TeamHolder componentInParent2 = c.GetComponentInParent<TeamHolder>();
			ControllerHandler instance = ControllerHandler.Instance;
			if ((Object)(object)componentInParent2 == (Object)null || (Object)(object)instance == (Object)null || instance.players == null)
			{
				return null;
			}
			for (int i = 0; i < instance.players.Count; i++)
			{
				Controller val = instance.players[i];
				if ((Object)(object)val != (Object)null && !val.isAI && val.playerID == componentInParent2.team)
				{
					return val;
				}
			}
			return null;
		}

		public static void GoesOff(SpawnObject s)
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			Controller val = OwnerOf((Component)(object)s);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			float time = Time.time;
			for (int num = blasts.Count - 1; num >= 0; num--)
			{
				if (time - blasts[num].At > 2f)
				{
					blasts.RemoveAt(num);
				}
			}
			blasts.Add(new Blast
			{
				Pos = ((Component)s).transform.position,
				Owner = val,
				At = time
			});
		}

		public static Controller Find(Vector3 p)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			float time = Time.time;
			for (int num = blasts.Count - 1; num >= 0; num--)
			{
				if (time - blasts[num].At < 1.5f)
				{
					Vector3 val = blasts[num].Pos - p;
					if (((Vector3)(ref val)).sqrMagnitude < 2.25f)
					{
						return blasts[num].Owner;
					}
				}
			}
			return null;
		}
	}
	[HarmonyPatch(typeof(SpawnObject), "GO")]
	internal static class RocketGoesOffPatch
	{
		private static void Prefix(SpawnObject __instance)
		{
			try
			{
				RocketCredit.GoesOff(__instance);
			}
			catch
			{
			}
		}
	}
	[HarmonyPatch(typeof(Explosion), "Explode")]
	internal static class RocketBlastPatch
	{
		private static void Prefix(Explosion __instance)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			RocketCredit.Current = null;
			try
			{
				if ((Object)(object)__instance.damager == (Object)null)
				{
					RocketCredit.Current = RocketCredit.Find(((Component)__instance).transform.position);
				}
			}
			catch
			{
			}
		}

		private static Exception Finalizer(Exception __exception)
		{
			RocketCredit.Current = null;
			return __exception;
		}
	}
	[HarmonyPatch(typeof(CollisionDamage), "OnCollisionEnter")]
	internal static class RocketImpactPatch
	{
		private static void Prefix(CollisionDamage __instance)
		{
			RocketCredit.Current = null;
			try
			{
				RocketCredit.Current = RocketCredit.OwnerOf((Component)(object)__instance);
			}
			catch
			{
			}
		}

		private static Exception Finalizer(Exception __exception)
		{
			RocketCredit.Current = null;
			return __exception;
		}
	}
}