Decompiled source of Risk of Deadlock v1.0.0

plugins/DeadlockOfRain.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using DeadlockOfRain.Sheets;
using DeadlockOfRain.States;
using EntityStates;
using HarmonyLib;
using KinematicCharacterController;
using Rewired;
using RoR2;
using RoR2.CameraModes;
using RoR2.CharacterAI;
using RoR2.ConVar;
using RoR2.ContentManagement;
using RoR2.ExpansionManagement;
using RoR2.Navigation;
using RoR2.Networking;
using RoR2.Projectile;
using RoR2.Skills;
using RoR2.UI;
using RoR2.UI.MainMenu;
using TMPro;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("DeadlockOfRain")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+f360653062c6271fc0f998add72022b2dfdb78ea")]
[assembly: AssemblyProduct("DeadlockOfRain")]
[assembly: AssemblyTitle("DeadlockOfRain")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace DeadlockOfRain
{
	public static class Buffs
	{
		public static readonly Dictionary<string, BuffDef> Defs = new Dictionary<string, BuffDef>();

		private static readonly Dictionary<string, Dictionary<CharacterBody, CharacterBody>> owners = new Dictionary<string, Dictionary<CharacterBody, CharacterBody>>();

		public static BuffDef Get(string id)
		{
			if (id == null || !Defs.TryGetValue(id, out var value))
			{
				return null;
			}
			return value;
		}

		public static void Create()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			BuffRow[] all = BuffRow.All;
			foreach (BuffRow buffRow in all)
			{
				BuffDef val = ScriptableObject.CreateInstance<BuffDef>();
				((Object)val).name = "bdDeadlock" + buffRow.Id;
				val.buffColor = Sheet.Color(buffRow.Color);
				val.canStack = buffRow.CanStack;
				val.isDebuff = buffRow.IsDebuff;
				val.isHidden = buffRow.IsHidden;
				if (buffRow.Icon == "none" || File.Exists(DeadlockCache.ImageFile(buffRow.Icon)))
				{
					val.iconSprite = DeadlockCache.Sprite(buffRow.Icon);
				}
				Defs[buffRow.Id] = val;
			}
		}

		public static void InitHooks()
		{
			GlobalEventManager.onServerDamageDealt += HealBack.OnDamage;
		}

		public static int Count(CharacterBody b, string id)
		{
			BuffDef val = Get(id);
			if (!Object.op_Implicit((Object)(object)b) || !Object.op_Implicit((Object)(object)val))
			{
				return 0;
			}
			return b.GetBuffCount(val);
		}

		public static CharacterBody OwnerOf(CharacterBody victim, string id)
		{
			if (!Object.op_Implicit((Object)(object)victim) || !owners.TryGetValue(id, out var value) || !value.TryGetValue(victim, out var value2))
			{
				return null;
			}
			return value2;
		}

		public static void AddTimed(CharacterBody b, string id, float duration, int max = 0)
		{
			BuffDef val = Get(id);
			if (!Object.op_Implicit((Object)(object)b) || !Object.op_Implicit((Object)(object)val) || !NetworkServer.active)
			{
				return;
			}
			if (duration <= 0f)
			{
				if (max <= 0 || b.GetBuffCount(val) < max)
				{
					b.AddBuff(val);
				}
			}
			else if (max > 0 && b.GetBuffCount(val) >= max)
			{
				b.ClearTimedBuffs(val);
				for (int i = 0; i < max; i++)
				{
					b.AddTimedBuff(val, duration);
				}
			}
			else
			{
				b.AddTimedBuff(val, duration);
			}
		}

		public static void Apply(CharacterBody owner, CharacterBody victim, string id, float bossMult = 1f)
		{
			BuffRow buffRow = Sheet.Buff(id);
			if (buffRow == null || !Object.op_Implicit((Object)(object)victim) || !NetworkServer.active)
			{
				return;
			}
			float num = buffRow.Duration * (victim.isChampion ? bossMult : 1f);
			if (!(num <= 0f))
			{
				Clear(victim, id);
				AddTimed(victim, id, num);
				SetOwner(owner, victim, id);
				if (buffRow.Disarm && Object.op_Implicit((Object)(object)Buffs.DisableAllSkills))
				{
					victim.ClearTimedBuffs(Buffs.DisableAllSkills);
					victim.AddTimedBuff(Buffs.DisableAllSkills, num);
				}
				if (buffRow.WithBuff != "none" && buffRow.WithBuff != id)
				{
					Apply(owner, victim, buffRow.WithBuff, bossMult);
				}
			}
		}

		public static void AddStacks(CharacterBody owner, CharacterBody victim, string id, int n)
		{
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			BuffRow buffRow = Sheet.Buff(id);
			BuffDef val = Get(id);
			if (buffRow != null && Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)victim) && n > 0 && NetworkServer.active)
			{
				int buffCount = victim.GetBuffCount(val);
				int num = Mathf.Min((!buffRow.CanStack) ? 1 : Mathf.Max(1, (int)buffRow.MaxStacks), buffCount + n);
				victim.ClearTimedBuffs(val);
				while (victim.GetBuffCount(val) > 0)
				{
					victim.RemoveBuff(val);
				}
				for (int i = 0; i < num; i++)
				{
					victim.AddTimedBuff(val, buffRow.Duration);
				}
				if (Object.op_Implicit((Object)(object)owner))
				{
					SetOwner(owner, victim, id);
				}
				if (buffCount == 0 && buffRow.Vfx != "none")
				{
					Relay.Vfx(buffRow.Vfx, "hit", victim.corePosition, 1f, ((Component)victim).gameObject);
				}
			}
		}

		public static bool Stack(CharacterBody owner, CharacterBody victim, string id, bool crit)
		{
			BuffRow buffRow = Sheet.Buff(id);
			if (buffRow == null || !Object.op_Implicit((Object)(object)owner) || !Object.op_Implicit((Object)(object)victim) || !NetworkServer.active)
			{
				return false;
			}
			int num = ((!buffRow.CanStack) ? 1 : ((int)buffRow.MaxStacks));
			int num2 = Count(victim, id);
			int num3 = ((!crit || !(buffRow.CritStacks > 0f)) ? 1 : ((int)buffRow.CritStacks));
			for (int i = 0; i < num3; i++)
			{
				AddTimed(victim, id, buffRow.Duration, num);
			}
			SetOwner(owner, victim, id);
			if (buffRow.WithBuff != "none")
			{
				Apply(owner, victim, buffRow.WithBuff);
			}
			int num4 = (int)buffRow.TriggerStacks;
			if (num4 <= 0)
			{
				return false;
			}
			int num5 = Mathf.Min(num, num2 + num3);
			if (!(buffRow.TriggerClears ? (num5 >= num4) : (num2 / num4 < num5 / num4)))
			{
				return false;
			}
			if (buffRow.TriggerClears)
			{
				Clear(victim, id);
			}
			Trigger(owner, victim, buffRow);
			return true;
		}

		private static void Trigger(CharacterBody owner, CharacterBody victim, BuffRow row)
		{
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: 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_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: 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_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: 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)
			List<HurtBox> list = new List<HurtBox>();
			if (Object.op_Implicit((Object)(object)victim.mainHurtBox))
			{
				list.Add(victim.mainHurtBox);
			}
			if (row.TriggerTargets > 0f)
			{
				foreach (HurtBox item in Fx.Enemies(owner, victim.corePosition, row.TriggerRadius))
				{
					if ((float)list.Count > row.TriggerTargets)
					{
						break;
					}
					if ((Object)(object)item.healthComponent.body != (Object)(object)victim)
					{
						list.Add(item);
					}
				}
			}
			Color c = Sheet.Color(row.Color);
			Relay.Flash(victim.corePosition, c, 6f, 0.25f);
			foreach (HurtBox item2 in list)
			{
				CharacterBody body = item2.healthComponent.body;
				if ((Object)(object)body != (Object)(object)victim)
				{
					Relay.Bolt(victim.corePosition, Object.op_Implicit((Object)(object)body) ? body.corePosition : ((Component)item2).transform.position, c, 0.35f, 0.25f);
				}
				if (row.TriggerDamagePct > 0f)
				{
					Fx.Hit(owner, item2, row.TriggerDamagePct / 100f, 0.5f, ((Component)item2).transform.position, default(DamageTypeCombo), (DamageColorIndex)5);
				}
				if (row.TriggerStun > 0f)
				{
					Fx.Stun(item2.healthComponent, row.TriggerStun);
				}
				if (row.TriggerBuff != "none" && Object.op_Implicit((Object)(object)body))
				{
					Apply(owner, body, row.TriggerBuff);
				}
				if (row.DotDamagePct > 0f && Object.op_Implicit((Object)(object)body))
				{
					Burn(owner, body, row.DotDamagePct);
				}
			}
			MeltyTest.Report("trigger:" + row.Id, ok: true, owner.baseNameToken);
		}

		public static void Burn(CharacterBody owner, CharacterBody victim, float pct)
		{
			//IL_001a: 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_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_0076: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)owner) && Object.op_Implicit((Object)(object)victim) && NetworkServer.active)
			{
				InflictDotInfo val = new InflictDotInfo
				{
					attackerObject = ((Component)owner).gameObject,
					victimObject = ((Component)victim).gameObject,
					dotIndex = (DotIndex)1,
					duration = 3f,
					damageMultiplier = pct / 100f * 2f
				};
				DotController.InflictDot(ref val);
				Relay.Sound("infernus_gun", "hit", victim.corePosition);
			}
		}

		public static void Dot(CharacterBody owner, CharacterBody victim, DotIndex index, float seconds, int stacks)
		{
			//IL_001e: 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_0041: 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_005b: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)owner) && Object.op_Implicit((Object)(object)victim) && NetworkServer.active)
			{
				for (int i = 0; i < stacks; i++)
				{
					InflictDotInfo val = new InflictDotInfo
					{
						attackerObject = ((Component)owner).gameObject,
						victimObject = ((Component)victim).gameObject,
						dotIndex = index,
						duration = seconds,
						damageMultiplier = 1f
					};
					DotController.InflictDot(ref val);
				}
			}
		}

		public static void Clear(CharacterBody b, string id)
		{
			BuffDef val = Get(id);
			if (Object.op_Implicit((Object)(object)b) && Object.op_Implicit((Object)(object)val) && NetworkServer.active)
			{
				b.ClearTimedBuffs(val);
				while (b.HasBuff(val))
				{
					b.RemoveBuff(val);
				}
			}
		}

		private static void SetOwner(CharacterBody owner, CharacterBody victim, string id)
		{
			if (!owners.TryGetValue(id, out var value))
			{
				value = (owners[id] = new Dictionary<CharacterBody, CharacterBody>());
			}
			value[victim] = owner;
		}
	}
	public sealed class HealBack : MonoBehaviour
	{
		private struct Part
		{
			public float Rate;

			public float Until;
		}

		private readonly List<Part> parts = new List<Part>();

		private HealthComponent hc;

		private float next;

		public static void OnDamage(DamageReport r)
		{
			if (r == null || !Object.op_Implicit((Object)(object)r.victimBody) || r.damageDealt <= 0f)
			{
				return;
			}
			HeroRow heroRow = Sheet.Hero(Survivors.HeroOf(r.victimBody));
			if (heroRow != null && !(heroRow.DamageHealBack <= 0f) && !(heroRow.DamageHealBackTime <= 0f))
			{
				HealBack healBack = ((Component)r.victimBody).GetComponent<HealBack>();
				if (!Object.op_Implicit((Object)(object)healBack))
				{
					healBack = ((Component)r.victimBody).gameObject.AddComponent<HealBack>();
				}
				healBack.parts.Add(new Part
				{
					Rate = r.damageDealt * heroRow.DamageHealBack / heroRow.DamageHealBackTime,
					Until = Time.fixedTime + heroRow.DamageHealBackTime
				});
			}
		}

		private void Awake()
		{
			hc = ((Component)this).GetComponent<HealthComponent>();
		}

		private void FixedUpdate()
		{
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active || !Object.op_Implicit((Object)(object)hc) || !hc.alive || parts.Count == 0 || Time.fixedTime < next)
			{
				return;
			}
			next = Time.fixedTime + 0.25f;
			float num = 0f;
			for (int num2 = parts.Count - 1; num2 >= 0; num2--)
			{
				num += parts[num2].Rate * 0.25f;
				if (Time.fixedTime >= parts[num2].Until)
				{
					parts.RemoveAt(num2);
				}
			}
			if (num > 0f)
			{
				hc.Heal(num, default(ProcChainMask), true);
			}
		}
	}
	[HarmonyPatch(typeof(CharacterBody), "RecalculateStats")]
	internal static class StatsPatch
	{
		private static readonly ConditionalWeakTable<CharacterBody, float[]> lastHealthAdd = new ConditionalWeakTable<CharacterBody, float[]>();

		private static readonly Dictionary<string, MethodInfo> setters = new Dictionary<string, MethodInfo>();

		private static void Prefix(CharacterBody __instance, out float[] __state)
		{
			__state = null;
			if (NetworkServer.active && Object.op_Implicit((Object)(object)__instance.healthComponent) && lastHealthAdd.TryGetValue(__instance, out var value) && value[0] != 0f)
			{
				__state = new float[2]
				{
					__instance.healthComponent.health,
					__instance.maxHealth - value[0]
				};
			}
		}

		private static void Postfix(CharacterBody __instance, float[] __state)
		{
			float maxHealth = __instance.maxHealth;
			float num = 0f;
			float num2 = 0f;
			float num3 = 0f;
			float num4 = 0f;
			float num5 = 0f;
			float num6 = 0f;
			float num7 = 0f;
			float num8 = 0f;
			float num9 = 0f;
			float num10 = 0f;
			BuffRow[] all = BuffRow.All;
			foreach (BuffRow buffRow in all)
			{
				if (buffRow.MoveSpeedAdd == 0f && buffRow.AttackSpeedAdd == 0f && buffRow.ArmorAdd == 0f && buffRow.RegenAdd == 0f && buffRow.SlowResist == 0f && buffRow.MaxHealthAdd == 0f && buffRow.AccelerationAdd == 0f && buffRow.JumpPowerAdd == 0f && buffRow.JumpCountAdd == 0f)
				{
					continue;
				}
				BuffDef val = Buffs.Get(buffRow.Id);
				if (!Object.op_Implicit((Object)(object)val))
				{
					continue;
				}
				int buffCount = __instance.GetBuffCount(val);
				if (buffCount > 0)
				{
					int num11 = ((!buffRow.CanStack) ? 1 : buffCount);
					float num12 = (float)num11 * (__instance.isChampion ? (1f - buffRow.BossStatCut) : 1f);
					if (buffRow.LinearSlow)
					{
						num7 += buffRow.MoveSpeedAdd * num12;
					}
					else
					{
						num += buffRow.MoveSpeedAdd * num12;
					}
					num2 += buffRow.AttackSpeedAdd * num12;
					num3 += buffRow.ArmorAdd * (float)num11;
					num4 += buffRow.RegenAdd * (float)num11;
					num6 += buffRow.MaxHealthAdd * (float)num11;
					num8 += buffRow.AccelerationAdd * (float)num11;
					num9 += buffRow.JumpPowerAdd * (float)num11;
					num10 += buffRow.JumpCountAdd * (float)num11;
					num5 = Mathf.Max(num5, buffRow.SlowResist);
				}
			}
			if (num6 != 0f || lastHealthAdd.TryGetValue(__instance, out var _))
			{
				lastHealthAdd.GetValue(__instance, (CharacterBody _) => new float[1])[0] = num6;
			}
			if (num6 != 0f)
			{
				Set(__instance, "maxHealth", __instance.maxHealth + num6);
			}
			if (__state != null && NetworkServer.active && Object.op_Implicit((Object)(object)__instance.healthComponent) && __instance.healthComponent.alive)
			{
				float num13 = __state[0] + Mathf.Max(0f, maxHealth - __state[1]);
				__instance.healthComponent.Networkhealth = Mathf.Clamp(num13, 1f, __instance.maxHealth);
			}
			if (num8 != 0f)
			{
				Set(__instance, "acceleration", __instance.acceleration * Mathf.Max(0.02f, 1f + num8));
			}
			if (num9 != 0f)
			{
				Set(__instance, "jumpPower", __instance.jumpPower * Mathf.Max(0.1f, 1f + num9));
			}
			if (num10 != 0f)
			{
				SetInt(__instance, "maxJumpCount", Mathf.Max(0, __instance.maxJumpCount + (int)num10));
			}
			if (num == 0f && num2 == 0f && num3 == 0f && num4 == 0f && num5 == 0f && num7 == 0f)
			{
				return;
			}
			float num14 = __instance.moveSpeed;
			if (num > 0f)
			{
				num14 *= 1f + num;
			}
			else if (num < 0f)
			{
				num14 /= 1f - num;
			}
			if (num7 < 0f)
			{
				num14 *= Mathf.Max(0.1f, 1f + num7);
			}
			if (num5 > 0f)
			{
				float num15 = (__instance.baseMoveSpeed + __instance.levelMoveSpeed * (__instance.level - 1f)) * (__instance.isSprinting ? __instance.sprintingSpeedMultiplier : 1f);
				if (num14 < num15)
				{
					num14 += (num15 - num14) * num5;
				}
			}
			Set(__instance, "moveSpeed", num14);
			Set(__instance, "attackSpeed", __instance.attackSpeed * Mathf.Max(0.1f, 1f + num2));
			Set(__instance, "armor", __instance.armor + num3);
			Set(__instance, "regen", __instance.regen + num4 * (1f + 0.2f * (__instance.level - 1f)));
		}

		private static void Set(CharacterBody b, string prop, float v)
		{
			if (!setters.TryGetValue(prop, out var value))
			{
				value = (setters[prop] = AccessTools.PropertySetter(typeof(CharacterBody), prop));
			}
			value.Invoke(b, new object[1] { v });
		}

		private static void SetInt(CharacterBody b, string prop, int v)
		{
			if (!setters.TryGetValue(prop, out var value))
			{
				value = (setters[prop] = AccessTools.PropertySetter(typeof(CharacterBody), prop));
			}
			value.Invoke(b, new object[1] { v });
		}
	}
	[HarmonyPatch(typeof(CharacterBody), "AddTimedBuffInternal")]
	internal static class DebuffResistPatch
	{
		private static void Prefix(CharacterBody __instance, BuffDef buffDef, ref float duration)
		{
			if (Object.op_Implicit((Object)(object)buffDef) && buffDef.isDebuff)
			{
				HeroRow heroRow = Sheet.Hero(Survivors.HeroOf(__instance));
				if (heroRow != null && heroRow.DebuffResist > 0f)
				{
					duration *= 1f - heroRow.DebuffResist;
				}
			}
		}
	}
	[HarmonyPatch(typeof(HealthComponent), "TakeDamage")]
	internal static class DamagePatch
	{
		private static readonly Random rng = new Random();

		private static void Prefix(HealthComponent __instance, DamageInfo damageInfo)
		{
			if (damageInfo == null || !Object.op_Implicit((Object)(object)__instance))
			{
				return;
			}
			CharacterBody body = __instance.body;
			if (!Object.op_Implicit((Object)(object)body))
			{
				return;
			}
			CharacterBody val = (Object.op_Implicit((Object)(object)damageInfo.attacker) ? damageInfo.attacker.GetComponent<CharacterBody>() : null);
			BuffRow buffRow = Sheet.Buff("bullet_dance");
			if (buffRow != null && Buffs.Count(body, "bullet_dance") > 0 && Object.op_Implicit((Object)(object)val) && (Object)(object)val != (Object)(object)body && rng.NextDouble() < (double)buffRow.EvasionChance)
			{
				damageInfo.rejected = true;
			}
			else
			{
				if (!Object.op_Implicit((Object)(object)val))
				{
					return;
				}
				BuffRow[] all = BuffRow.All;
				foreach (BuffRow buffRow2 in all)
				{
					if (!(buffRow2.DamageTakenFromOwnerPerStack <= 0f))
					{
						int num = Buffs.Count(body, buffRow2.Id);
						if (num > 0 && !((Object)(object)Buffs.OwnerOf(body, buffRow2.Id) != (Object)(object)val))
						{
							damageInfo.damage *= 1f + (float)((!buffRow2.CanStack) ? 1 : num) * buffRow2.DamageTakenFromOwnerPerStack;
						}
					}
				}
			}
		}
	}
	public static class Equipment
	{
		[HarmonyPatch(typeof(EquipmentSlot), "PerformEquipmentAction")]
		private static class FirePatch
		{
			private static bool Prefix(EquipmentSlot __instance, EquipmentDef equipmentDef, ref bool __result)
			{
				SkillRow skillRow = RowOf(equipmentDef);
				if (skillRow == null)
				{
					return true;
				}
				CharacterBody characterBody = __instance.characterBody;
				__result = Object.op_Implicit((Object)(object)characterBody) && (!characterBody.hasEffectiveAuthority || Fire(characterBody, skillRow));
				if (__result)
				{
					MeltyTest.Report("equipment-fires", ok: true, characterBody.baseNameToken);
				}
				return false;
			}
		}

		[HarmonyPatch(typeof(EquipmentSlot), "RpcOnClientEquipmentActivationRecieved")]
		private static class ClientFirePatch
		{
			private static void Postfix(EquipmentSlot __instance)
			{
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				if (NetworkServer.active)
				{
					return;
				}
				CharacterBody characterBody = __instance.characterBody;
				if (Object.op_Implicit((Object)(object)characterBody) && characterBody.hasEffectiveAuthority)
				{
					SkillRow skillRow = RowOf(EquipmentCatalog.GetEquipmentDef(__instance.equipmentIndex));
					if (skillRow != null)
					{
						Fire(characterBody, skillRow);
					}
				}
			}
		}

		public static readonly Dictionary<string, EquipmentDef> Defs = new Dictionary<string, EquipmentDef>();

		private static readonly Dictionary<EquipmentDef, SkillRow> rowOf = new Dictionary<EquipmentDef, SkillRow>();

		private static readonly HashSet<CharacterMaster> given = new HashSet<CharacterMaster>();

		internal const float FigurePadding = 2.2f;

		public static GameObject FigureFor(string vfx)
		{
			foreach (KeyValuePair<EquipmentDef, SkillRow> item in rowOf)
			{
				if (item.Value.Vfx == vfx && Object.op_Implicit((Object)(object)item.Key.pickupModelPrefab))
				{
					return item.Key.pickupModelPrefab;
				}
			}
			return null;
		}

		public static SkillRow RowOf(EquipmentDef def)
		{
			if (!Object.op_Implicit((Object)(object)def) || !rowOf.TryGetValue(def, out var value))
			{
				return null;
			}
			return value;
		}

		public static EquipmentDef OfHero(string hero)
		{
			if (hero == null)
			{
				return null;
			}
			EquipmentRow[] all = EquipmentRow.All;
			foreach (EquipmentRow equipmentRow in all)
			{
				if (equipmentRow.Hero == hero && Defs.TryGetValue(equipmentRow.Id, out var value))
				{
					return value;
				}
			}
			return null;
		}

		public static void Init()
		{
			CharacterBody.onBodyStartGlobal += GiveStartingEquipment;
			Run.onRunStartGlobal += delegate
			{
				given.Clear();
			};
		}

		public static void Build(Transform holder)
		{
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			EquipmentRow[] all = EquipmentRow.All;
			foreach (EquipmentRow equipmentRow in all)
			{
				SkillRow skillRow = Sheet.Skill(equipmentRow.Skill);
				HeroRow heroRow = Sheet.Hero(equipmentRow.Hero);
				if (skillRow != null && heroRow != null && Survivors.Bodies.ContainsKey(heroRow.Id))
				{
					EquipmentDef val = ScriptableObject.CreateInstance<EquipmentDef>();
					((Object)val).name = "edDeadlock_" + skillRow.Id;
					val.nameToken = Sheet.Token("equip", equipmentRow.Id);
					val.pickupToken = Sheet.Token("equippickup", equipmentRow.Id);
					val.descriptionToken = Sheet.Token("equipdesc", equipmentRow.Id);
					val.loreToken = Sheet.Token("equiplore", equipmentRow.Id);
					val.cooldown = skillRow.Cooldown;
					val.canDrop = equipmentRow.CanDrop;
					val.enigmaCompatible = equipmentRow.EnigmaCompatible;
					val.canBeRandomlyTriggered = equipmentRow.RandomTrigger;
					val.appearsInSinglePlayer = true;
					val.appearsInMultiPlayer = true;
					val.colorIndex = (ColorIndex)5;
					val.pickupIconSprite = DeadlockCache.Sprite(skillRow.Icon);
					val.pickupModelPrefab = PickupModel(heroRow, holder, equipmentRow.Figure);
					Defs[equipmentRow.Id] = val;
					rowOf[val] = skillRow;
					Survivors.Tokens[val.nameToken] = heroRow.DisplayName + "'s " + skillRow.Name;
					Survivors.Tokens[val.pickupToken] = equipmentRow.PickupText;
					Survivors.Tokens[val.descriptionToken] = skillRow.Description;
					Survivors.Tokens[val.loreToken] = equipmentRow.Lore;
					Log.Info($"Built equipment {skillRow.Name} ({skillRow.Cooldown:F0}s)");
				}
			}
		}

		private static GameObject PickupModel(HeroRow hero, Transform holder, string figure)
		{
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Expected O, but got Unknown
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Expected O, but got Unknown
			//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)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Expected O, but got Unknown
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Expected O, but got Unknown
			GameObject val = ModelBuilder.Build(hero, forDisplay: true, (figure == "all") ? null : figure);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return null;
			}
			try
			{
				Animation component = val.GetComponent<Animation>();
				string idle = Sheet.Anims(hero.Id).Idle;
				if (Object.op_Implicit((Object)(object)component) && idle != "none" && (TrackedReference)(object)component[idle] != (TrackedReference)null)
				{
					AnimationState obj = component[idle];
					obj.enabled = true;
					obj.weight = 1f;
					obj.time = 0f;
					component.Sample();
					obj.enabled = false;
				}
				SkinnedMeshRenderer[] componentsInChildren = val.GetComponentsInChildren<SkinnedMeshRenderer>(true);
				List<Mesh> list = new List<Mesh>();
				List<Material> list2 = new List<Material>();
				Bounds val2 = default(Bounds);
				bool flag = true;
				SkinnedMeshRenderer[] array = componentsInChildren;
				foreach (SkinnedMeshRenderer val3 in array)
				{
					if (Object.op_Implicit((Object)(object)val3.sharedMesh))
					{
						Mesh val4 = new Mesh();
						val3.BakeMesh(val4);
						val4.RecalculateBounds();
						Material val5 = new Material(((Renderer)val3).sharedMaterial)
						{
							name = ((Object)((Renderer)val3).sharedMaterial).name + "_Figure"
						};
						if (val5.HasProperty("_Fade"))
						{
							val5.SetFloat("_Fade", 1f);
						}
						val5.DisableKeyword("DITHER");
						list.Add(val4);
						list2.Add(val5);
						if (flag)
						{
							val2 = val4.bounds;
							flag = false;
						}
						else
						{
							((Bounds)(ref val2)).Encapsulate(val4.bounds);
						}
					}
				}
				if (list.Count == 0)
				{
					return null;
				}
				CombineInstance[] array2 = (CombineInstance[])(object)new CombineInstance[list.Count];
				Matrix4x4 transform = Matrix4x4.Translate(-((Bounds)(ref val2)).center);
				for (int j = 0; j < list.Count; j++)
				{
					int num = j;
					CombineInstance val6 = default(CombineInstance);
					((CombineInstance)(ref val6)).mesh = list[j];
					((CombineInstance)(ref val6)).transform = transform;
					array2[num] = val6;
				}
				Mesh val7 = new Mesh
				{
					name = "mshDeadlock" + hero.DisplayName + "Figure",
					indexFormat = (IndexFormat)1
				};
				val7.CombineMeshes(array2, false, true);
				val7.RecalculateBounds();
				Bounds bounds = val7.bounds;
				Vector3 center = ((Bounds)(ref bounds)).center;
				bounds = val7.bounds;
				val7.bounds = new Bounds(center, ((Bounds)(ref bounds)).size * 2.2f);
				foreach (Mesh item in list)
				{
					Object.Destroy((Object)(object)item);
				}
				GameObject val8 = new GameObject("PickupDeadlock" + hero.DisplayName);
				val8.transform.SetParent(holder, false);
				val8.AddComponent<MeshFilter>().sharedMesh = val7;
				((Renderer)val8.AddComponent<MeshRenderer>()).sharedMaterials = list2.ToArray();
				return val8;
			}
			finally
			{
				Object.DestroyImmediate((Object)(object)val);
			}
		}

		private static void GiveStartingEquipment(CharacterBody body)
		{
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Invalid comparison between Unknown and I4
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active || !Object.op_Implicit((Object)(object)body) || !Object.op_Implicit((Object)(object)Run.instance))
			{
				return;
			}
			EquipmentDef val = OfHero(Survivors.HeroOf(body));
			CharacterMaster master = body.master;
			if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)master) && Object.op_Implicit((Object)(object)master.inventory) && Object.op_Implicit((Object)(object)master.playerCharacterMasterController) && !given.Contains(master) && Run.instance.stageClearCount <= 0)
			{
				given.Add(master);
				if ((int)master.inventory.currentEquipmentIndex == -1)
				{
					EquipmentLocation activeEquipmentLocation = master.inventory.activeEquipmentLocation;
					master.inventory.SetEquipmentIndex(val.equipmentIndex, ref activeEquipmentLocation);
					MeltyTest.Report("starting-equipment", ok: true, body.baseNameToken);
				}
			}
		}

		public static bool Fire(CharacterBody body, SkillRow row)
		{
			if (!Object.op_Implicit((Object)(object)body) || row == null)
			{
				return false;
			}
			Type type = Survivors.StateFor(row.Kind);
			if (type == null)
			{
				return false;
			}
			EntityStateMachine val = EntityStateMachine.FindByCustomName(((Component)body).gameObject, Survivors.MachineFor(row.Kind));
			if (!Object.op_Implicit((Object)(object)val))
			{
				val = EntityStateMachine.FindByCustomName(((Component)body).gameObject, "Weapon");
			}
			if (!Object.op_Implicit((Object)(object)val))
			{
				val = ((Component)body).GetComponent<EntityStateMachine>();
			}
			if (!Object.op_Implicit((Object)(object)val))
			{
				return false;
			}
			DlrState dlrState = (DlrState)Activator.CreateInstance(type);
			dlrState.RowOverride = row;
			bool flag;
			if (val.state is Burrow && dlrState is UltDevil ultDevil)
			{
				ultDevil.FromBurrow = true;
				val.SetNextState((EntityState)(object)dlrState);
				flag = true;
			}
			else
			{
				flag = val.SetInterruptState((EntityState)(object)dlrState, (InterruptPriority)2);
			}
			if (flag && body.isPlayerControlled && body.hasEffectiveAuthority)
			{
				Voice.SkillLine(row);
			}
			return flag;
		}
	}
	[HarmonyPatch]
	internal static class LoadoutSkinRowPatch
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static UnityAction <>9__2_0;

			internal void <Postfix>b__2_0()
			{
			}
		}

		private static Type rowType = AccessTools.Inner(typeof(LoadoutPanelController), "Row");

		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(rowType, "FromSkin", (Type[])null, (Type[])null);
		}

		private static void Postfix(object __result, LoadoutPanelController owner, BodyIndex bodyIndex)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: 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: Expected O, but got Unknown
			if (__result == null)
			{
				return;
			}
			IList list = (IList)AccessTools.Field(rowType, "rowData").GetValue(__result);
			if (list == null || list.Count > 0)
			{
				return;
			}
			CharacterBody bodyPrefabBodyComponent = BodyCatalog.GetBodyPrefabBodyComponent(bodyIndex);
			DeadlockHero deadlockHero = (Object.op_Implicit((Object)(object)bodyPrefabBodyComponent) ? ((Component)bodyPrefabBodyComponent).GetComponent<DeadlockHero>() : null);
			if (Object.op_Implicit((Object)(object)deadlockHero))
			{
				HeroRow heroRow = Sheet.Hero(deadlockHero.HeroId);
				Sprite val = DeadlockCache.Sprite(heroRow.ImageSmall);
				Survivors.Tokens["DLR_SKIN_DEFAULT"] = "Default";
				MethodInfo methodInfo = AccessTools.Method(rowType, "AddButton", (Type[])null, (Type[])null);
				object[] obj = new object[10]
				{
					owner,
					val,
					"DLR_SKIN_DEFAULT",
					"",
					Sheet.Color(heroRow.PrimaryColor),
					null,
					null,
					null,
					null,
					null
				};
				object obj2 = <>c.<>9__2_0;
				if (obj2 == null)
				{
					UnityAction val2 = delegate
					{
					};
					<>c.<>9__2_0 = val2;
					obj2 = (object)val2;
				}
				obj[5] = obj2;
				obj[6] = "";
				obj[8] = false;
				obj[9] = 0;
				methodInfo.Invoke(__result, obj);
			}
		}
	}
	public static class MissingHeroes
	{
		[HarmonyPatch(typeof(UserProfile), "HasSurvivorUnlocked")]
		private static class LockPatch
		{
			private static bool Prefix(SurvivorIndex survivorIndex, ref bool __result)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				if (!Is(SurvivorCatalog.GetSurvivorDef(survivorIndex)))
				{
					return true;
				}
				__result = false;
				return false;
			}
		}

		[HarmonyPatch(typeof(SurvivorIconController), "Rebuild")]
		private static class IconPatch
		{
			private static void Postfix(SurvivorIconController __instance)
			{
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
				//IL_0095: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
				//IL_0129: Unknown result type (might be due to invalid IL or missing references)
				SurvivorDef survivorDef = __instance.survivorDef;
				if (Is(survivorDef))
				{
					if (Object.op_Implicit((Object)(object)__instance.survivorIcon))
					{
						((Graphic)__instance.survivorIcon).color = Color.white;
					}
					bool flag = soon.Contains(survivorDef);
					string text = Language.GetString(survivorDef.displayNameToken) + (flag ? ": coming soon" : ": not available");
					string text2 = (Object.op_Implicit((Object)(object)survivorDef.unlockableDef) ? survivorDef.unlockableDef.getHowToUnlockString() : "");
					Color val = (flag ? new Color(0.6f, 0.6f, 0.6f, 1f) : new Color(0.9f, 0.2f, 0.2f, 1f));
					if (Object.op_Implicit((Object)(object)__instance.tooltipProvider))
					{
						((Behaviour)__instance.tooltipProvider).enabled = true;
						__instance.tooltipProvider.overrideTitleText = text;
						__instance.tooltipProvider.titleColor = val;
						__instance.tooltipProvider.overrideBodyText = text2;
					}
					HGButton component = ((Component)__instance).GetComponent<HGButton>();
					if (Object.op_Implicit((Object)(object)component))
					{
						val.a = 0.2f;
						component.hoverToken = Language.GetStringFormatted("LOGBOOK_HOVER_DESCRIPTION_FORMAT", new object[3]
						{
							text,
							text2,
							ColorUtility.ToHtmlStringRGBA(val)
						});
					}
				}
			}
		}

		public static readonly Dictionary<string, GameObject> Bodies = new Dictionary<string, GameObject>();

		public static readonly Dictionary<string, SurvivorDef> Defs = new Dictionary<string, SurvivorDef>();

		public static readonly Dictionary<string, UnlockableDef> Unlockables = new Dictionary<string, UnlockableDef>();

		private static readonly HashSet<SurvivorDef> placeholders = new HashSet<SurvivorDef>();

		private static readonly HashSet<SurvivorDef> soon = new HashSet<SurvivorDef>();

		private static Texture2D icon;

		public static bool Is(SurvivorDef def)
		{
			if (Object.op_Implicit((Object)(object)def))
			{
				return placeholders.Contains(def);
			}
			return false;
		}

		public static void Add(GameObject commando, Transform holder, HeroRow hero, string why)
		{
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Expected O, but got Unknown
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			string text = Survivors.CodeName(hero);
			GameObject val = Object.Instantiate<GameObject>(commando, holder);
			((Object)val).name = "Deadlock" + text + "MissingBody";
			NetworkIdentity component = val.GetComponent<NetworkIdentity>();
			if (Object.op_Implicit((Object)(object)component))
			{
				byte[] array = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes("DeadlockOfRain." + ((Object)val).name));
				AccessTools.Field(typeof(NetworkIdentity), "m_AssetId").SetValue(component, NetworkHash128.Parse(BitConverter.ToString(array).Replace("-", "").ToLowerInvariant()));
			}
			CharacterBody component2 = val.GetComponent<CharacterBody>();
			component2.baseNameToken = "DLR_MISSING_NAME_" + hero.Id.ToUpperInvariant();
			component2.subtitleNameToken = component2.baseNameToken;
			component2.portraitIcon = (Texture)(object)((why == null) ? (Silhouette(DeadlockCache.Image(hero.ImageSmall)) ?? Icon()) : Icon());
			Survivors.Tokens[component2.baseNameToken] = hero.DisplayName;
			string text2 = ((why == null) ? (hero.DisplayName + " is coming in a later update.") : (hero.DisplayName + " couldn't be read from your Deadlock (" + why + "). The other heroes are ready to play.\n\n" + BuiltWith.Versions()));
			UnlockableDef val2 = ScriptableObject.CreateInstance<UnlockableDef>();
			val2.cachedName = "DeadlockOfRain.Missing." + hero.Id;
			val2.nameToken = component2.baseNameToken;
			val2.hidden = true;
			val2.getHowToUnlockString = () => text2;
			val2.getUnlockedString = () => text2;
			GameObject val3 = new GameObject("Deadlock" + text + "MissingDisplay");
			val3.transform.SetParent(holder, false);
			SurvivorDef val4 = ScriptableObject.CreateInstance<SurvivorDef>();
			((Object)val4).name = "Deadlock" + text + "Missing";
			val4.cachedName = "Deadlock" + text + "Missing";
			val4.bodyPrefab = val;
			val4.displayPrefab = val3;
			val4.displayNameToken = component2.baseNameToken;
			val4.descriptionToken = component2.baseNameToken;
			val4.primaryColor = ((why == null) ? Color.black : Color.red);
			val4.desiredSortPosition = hero.SortPosition;
			val4.unlockableDef = val2;
			Bodies[hero.Id] = val;
			Defs[hero.Id] = val4;
			Unlockables[hero.Id] = val2;
			placeholders.Add(val4);
			if (why == null)
			{
				soon.Add(val4);
				Log.Info(hero.DisplayName + ": shown as a blacked-out \"coming soon\" tile in character select");
			}
			else
			{
				Log.Warn(hero.DisplayName + ": shown as a locked red ! tile in character select (" + why + ")");
			}
		}

		private static Texture2D Silhouette(Texture2D src)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			//IL_0057: 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)
			if (!Object.op_Implicit((Object)(object)src))
			{
				return null;
			}
			Texture2D val = new Texture2D(((Texture)src).width, ((Texture)src).height, (TextureFormat)4, false)
			{
				name = ((Object)src).name + "_soon",
				wrapMode = (TextureWrapMode)1
			};
			Color32[] pixels = src.GetPixels32();
			for (int i = 0; i < pixels.Length; i++)
			{
				pixels[i] = new Color32((byte)0, (byte)0, (byte)0, pixels[i].a);
			}
			val.SetPixels32(pixels);
			val.Apply();
			return val;
		}

		private static Texture2D Icon()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)icon))
			{
				return icon;
			}
			icon = new Texture2D(128, 128, (TextureFormat)4, false)
			{
				name = "DeadlockOfRainMissing",
				wrapMode = (TextureWrapMode)1
			};
			Color32[] array = (Color32[])(object)new Color32[16384];
			Color32 val = default(Color32);
			((Color32)(ref val))..ctor((byte)70, (byte)8, (byte)8, byte.MaxValue);
			Color32 val2 = default(Color32);
			((Color32)(ref val2))..ctor((byte)235, (byte)40, (byte)40, byte.MaxValue);
			for (int i = 0; i < 128; i++)
			{
				for (int j = 0; j < 128; j++)
				{
					float num = (float)j - 64f + 0.5f;
					float num2 = (float)i - 64f + 0.5f;
					bool flag = num * num + num2 * num2 <= 3844f;
					bool flag2 = Mathf.Abs(num) <= 9f && i >= 46 && i <= 108;
					bool flag3 = num * num + ((float)i - 28f) * ((float)i - 28f) <= 110f;
					array[i * 128 + j] = (Color32)((!flag) ? new Color32((byte)0, (byte)0, (byte)0, (byte)0) : ((flag2 || flag3) ? val2 : val));
				}
			}
			icon.SetPixels32(array);
			icon.Apply();
			return icon;
		}
	}
	public sealed class DeadlockHero : MonoBehaviour
	{
		public string HeroId;
	}
	[AttributeUsage(AttributeTargets.Class)]
	public sealed class KindAttribute : Attribute
	{
		public readonly string Kind;

		public KindAttribute(string kind)
		{
			Kind = kind;
		}
	}
	public static class Survivors
	{
		public static readonly Dictionary<string, GameObject> Bodies = new Dictionary<string, GameObject>();

		public static readonly Dictionary<string, SurvivorDef> Defs = new Dictionary<string, SurvivorDef>();

		public static readonly Dictionary<string, SkillDef> SkillDefs = new Dictionary<string, SkillDef>();

		public static readonly Dictionary<SkillDef, SkillRow> RowOfSkill = new Dictionary<SkillDef, SkillRow>();

		public static readonly List<SkillFamily> Families = new List<SkillFamily>();

		public static readonly List<Type> StateTypes = new List<Type>();

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

		public static float CommandoHeight;

		private static GameObject holder;

		private static HeroRow[] released;

		private static HeroRow[] comingSoon;

		private static Dictionary<string, Type> kindTypes;

		public static HeroRow[] Released
		{
			get
			{
				if (released != null)
				{
					return released;
				}
				string path = Path.Combine(Plugin.PluginDir ?? "", "heroes.txt");
				if (!File.Exists(path))
				{
					return released = HeroRow.All;
				}
				HashSet<string> ids = new HashSet<string>(from l in File.ReadAllLines(path)
					select l.Trim() into l
					where l.Length > 0
					select l);
				HeroRow[] all = HeroRow.All;
				foreach (HeroRow heroRow in all)
				{
					if (!ids.Contains(heroRow.Id))
					{
						Log.Info(heroRow.DisplayName + ": not in this release (heroes.txt)");
					}
				}
				return released = HeroRow.All.Where((HeroRow h) => ids.Contains(h.Id)).ToArray();
			}
		}

		public static HeroRow[] ComingSoon
		{
			get
			{
				if (comingSoon != null)
				{
					return comingSoon;
				}
				string path = Path.Combine(Plugin.PluginDir ?? "", "coming-soon.txt");
				if (!File.Exists(path))
				{
					return comingSoon = new HeroRow[0];
				}
				HashSet<string> ids = new HashSet<string>(from l in File.ReadAllLines(path)
					select l.Trim() into l
					where l.Length > 0
					select l);
				return comingSoon = HeroRow.All.Where((HeroRow h) => ids.Contains(h.Id) && !Released.Contains(h)).ToArray();
			}
		}

		public static string CodeName(HeroRow hero)
		{
			return Regex.Replace(hero.DisplayName, "[^A-Za-z0-9]", "");
		}

		public static void LimitTo(ICollection<string> ids)
		{
			List<string> list = (from h in Released
				where !ids.Contains(h.Id)
				select h.DisplayName).ToList();
			if (list.Count > 0)
			{
				Log.Info("Not chosen in the hero picker (not read from Deadlock yet): " + string.Join(", ", list));
			}
			released = Released.Where((HeroRow h) => ids.Contains(h.Id)).ToArray();
		}

		public static bool IsHero(CharacterBody b, string id)
		{
			DeadlockHero deadlockHero = (Object.op_Implicit((Object)(object)b) ? ((Component)b).GetComponent<DeadlockHero>() : null);
			if (Object.op_Implicit((Object)(object)deadlockHero))
			{
				return deadlockHero.HeroId == id;
			}
			return false;
		}

		public static string HeroOf(CharacterBody b)
		{
			DeadlockHero deadlockHero = (Object.op_Implicit((Object)(object)b) ? ((Component)b).GetComponent<DeadlockHero>() : null);
			if (!Object.op_Implicit((Object)(object)deadlockHero))
			{
				return null;
			}
			return deadlockHero.HeroId;
		}

		private static Dictionary<string, Type> KindTypes()
		{
			Dictionary<string, Type> dictionary = new Dictionary<string, Type>();
			Type[] types = typeof(Survivors).Assembly.GetTypes();
			foreach (Type type in types)
			{
				KindAttribute kindAttribute = (KindAttribute)Attribute.GetCustomAttribute(type, typeof(KindAttribute));
				if (kindAttribute != null)
				{
					dictionary[kindAttribute.Kind] = type;
				}
				if (typeof(EntityState).IsAssignableFrom(type) && !type.IsAbstract)
				{
					StateTypes.Add(type);
				}
			}
			return dictionary;
		}

		public static string MachineFor(string kind)
		{
			switch (kind)
			{
			default:
				return "Weapon";
			case "dash_charge":
			case "dash_trail":
			case "ult_leap":
			case "phantom_strike":
			case "heavy_melee":
			case "burrow":
			case "ult_devil":
			case "goo_cube":
			case "banner_leap":
			case "storm_flight":
			case "bashdown":
			case "rising_ram":
			case "ult_chains":
				return "Body";
			}
		}

		public static bool NoFallDamage(CharacterBody b)
		{
			return Sheet.Hero(HeroOf(b))?.NoFallDamage ?? false;
		}

		public static Type StateFor(string kind)
		{
			if (kindTypes == null || !kindTypes.TryGetValue(kind, out var value))
			{
				return null;
			}
			return value;
		}

		public static IEnumerator Build()
		{
			holder = new GameObject("DeadlockOfRainPrefabs");
			holder.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)holder);
			GameObject commando = Addressables.LoadAssetAsync<GameObject>((object)"RoR2/Base/Commando/CommandoBody.prefab").WaitForCompletion();
			SkinnedMeshRenderer componentInChildren = ((Component)commando.GetComponent<ModelLocator>().modelTransform).GetComponentInChildren<SkinnedMeshRenderer>(true);
			ModelBuilder.Template = Addressables.LoadAssetAsync<Material>((object)"RoR2/Base/Commando/matCommandoDualies.mat").WaitForCompletion();
			Log.Info("hero material template: " + (Object.op_Implicit((Object)(object)ModelBuilder.Template) ? ((Object)ModelBuilder.Template.shader).name : "none"));
			CapsuleCollider component = commando.GetComponent<CapsuleCollider>();
			float num = 0f;
			if (Object.op_Implicit((Object)(object)componentInChildren) && Object.op_Implicit((Object)(object)componentInChildren.sharedMesh))
			{
				Bounds bounds = componentInChildren.sharedMesh.bounds;
				num = ((Bounds)(ref bounds)).size.y * ((Component)componentInChildren).transform.lossyScale.y;
			}
			CommandoHeight = ((num > 1f && num < 3f) ? num : component.height);
			HeroRow heroRow = Sheet.Hero("haze");
			ModelBuilder.GlobalScale = CommandoHeight / heroRow.SourceHeight;
			Log.Info($"Commando height {CommandoHeight:F3} m (mesh {num:F3}, capsule {component.height:F3}); Deadlock->RoR2 scale {ModelBuilder.GlobalScale:F4}");
			Dictionary<string, Type> kinds = (kindTypes = KindTypes());
			Buffs.Create();
			Fx.Preload();
			yield return null;
			HeroRow[] array = ComingSoon;
			foreach (HeroRow hero in array)
			{
				MissingHeroes.Add(commando, holder.transform, hero, null);
			}
			FirstRun.BuildBegin(Released.Length);
			HeroRow[] array2 = Released;
			foreach (HeroRow hero2 in array2)
			{
				FirstRun.BuildHero(hero2.DisplayName);
				int frame = Time.frameCount;
				while (Time.frameCount == frame)
				{
					yield return null;
				}
				if (DeadlockCache.Failed.ContainsKey(hero2.Id) || DeadlockCache.LoadHero(hero2.Id) == null)
				{
					string value;
					string text = (DeadlockCache.Failed.TryGetValue(hero2.Id, out value) ? value : "no Deadlock content for it");
					Log.Error("hero " + hero2.Id + " skipped: Deadlock could not be read for it (" + text + ")");
					MissingHeroes.Add(commando, holder.transform, hero2, text);
					FirstRun.BuildHeroDone(hero2.DisplayName, text);
					continue;
				}
				GameObject val = BuildBody(commando, hero2, kinds);
				Bodies[hero2.Id] = val;
				GameObject val2 = ModelBuilder.Build(hero2, forDisplay: true);
				val2.transform.SetParent(holder.transform, false);
				((Object)val2).name = "Deadlock" + CodeName(hero2) + "Display";
				SurvivorDef val3 = ScriptableObject.CreateInstance<SurvivorDef>();
				((Object)val3).name = "Deadlock" + CodeName(hero2);
				val3.cachedName = "Deadlock" + CodeName(hero2);
				val3.bodyPrefab = val;
				val3.displayPrefab = val2;
				val3.displayNameToken = Sheet.Token("name", hero2.Id);
				val3.descriptionToken = Sheet.Token("desc", hero2.Id);
				val3.outroFlavorToken = Sheet.Token("outro", hero2.Id);
				val3.mainEndingEscapeFailureFlavorToken = Sheet.Token("fail", hero2.Id);
				val3.primaryColor = Sheet.Color(hero2.PrimaryColor);
				val3.desiredSortPosition = hero2.SortPosition;
				Defs[hero2.Id] = val3;
				AddTokens(hero2);
				Log.Info($"Built survivor {hero2.DisplayName} ({FirstRun.HeroSeconds:F1} s)");
				FirstRun.BuildHeroDone(hero2.DisplayName, null);
			}
			Equipment.Build(holder.transform);
			Net.Build(holder.transform);
		}

		private static GameObject BuildBody(GameObject commando, HeroRow hero, Dictionary<string, Type> kinds)
		{
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0375: Unknown result type (might be due to invalid IL or missing references)
			//IL_0344: 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_034b: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_056f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0574: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ec: Expected O, but got Unknown
			//IL_06ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_07be: Unknown result type (might be due to invalid IL or missing references)
			//IL_07c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_07dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0601: Unknown result type (might be due to invalid IL or missing references)
			//IL_0603: Unknown result type (might be due to invalid IL or missing references)
			//IL_060a: Unknown result type (might be due to invalid IL or missing references)
			//IL_060c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0586: Unknown result type (might be due to invalid IL or missing references)
			//IL_0588: Unknown result type (might be due to invalid IL or missing references)
			//IL_058d: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_085d: Unknown result type (might be due to invalid IL or missing references)
			//IL_085f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0832: Unknown result type (might be due to invalid IL or missing references)
			//IL_0849: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(commando, holder.transform);
			((Object)val).name = "Deadlock" + CodeName(hero) + "Body";
			NetworkIdentity component = val.GetComponent<NetworkIdentity>();
			if (Object.op_Implicit((Object)(object)component))
			{
				string text = BitConverter.ToString(MD5.Create().ComputeHash(Encoding.UTF8.GetBytes("DeadlockOfRain." + ((Object)val).name))).Replace("-", "").ToLowerInvariant();
				AccessTools.Field(typeof(NetworkIdentity), "m_AssetId").SetValue(component, NetworkHash128.Parse(text));
			}
			ModelLocator component2 = val.GetComponent<ModelLocator>();
			Transform modelTransform = component2.modelTransform;
			Transform val2 = (Object.op_Implicit((Object)(object)component2.modelBaseTransform) ? component2.modelBaseTransform : modelTransform.parent);
			GameObject val3 = ModelBuilder.Build(hero, forDisplay: false);
			val3.transform.SetParent(val2, false);
			val3.transform.localPosition = modelTransform.localPosition;
			val3.transform.localRotation = Quaternion.identity;
			Object.DestroyImmediate((Object)(object)((Component)modelTransform).gameObject);
			AccessTools.Field(typeof(ModelLocator), "_modelTransform").SetValue(component2, val3.transform);
			CharacterBody component3 = val.GetComponent<CharacterBody>();
			HealthComponent component4 = val.GetComponent<HealthComponent>();
			val3.GetComponent<CharacterModel>().body = component3;
			HurtBox[] componentsInChildren = val3.GetComponentsInChildren<HurtBox>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].healthComponent = component4;
			}
			CharacterDirection component5 = val.GetComponent<CharacterDirection>();
			if (Object.op_Implicit((Object)(object)component5))
			{
				component5.modelAnimator = null;
			}
			AimAnimator[] componentsInChildren2 = val.GetComponentsInChildren<AimAnimator>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren2[i]);
			}
			StatRow statRow = Sheet.Stats(hero.Id);
			component3.baseNameToken = Sheet.Token("name", hero.Id);
			component3.subtitleNameToken = Sheet.Token("subtitle", hero.Id);
			component3.portraitIcon = (Texture)(object)DeadlockCache.Image(hero.ImageSmall);
			component3.bodyColor = Sheet.Color(hero.PrimaryColor);
			component3.baseMaxHealth = statRow.BaseMaxHealth;
			component3.levelMaxHealth = statRow.LevelMaxHealth;
			component3.baseRegen = statRow.BaseRegen;
			component3.levelRegen = statRow.LevelRegen;
			component3.baseDamage = statRow.BaseDamage;
			component3.levelDamage = statRow.LevelDamage;
			component3.baseArmor = statRow.BaseArmor;
			component3.levelArmor = statRow.LevelArmor;
			component3.baseAttackSpeed = statRow.BaseAttackSpeed;
			component3.levelAttackSpeed = statRow.LevelAttackSpeed;
			component3.baseCrit = statRow.BaseCrit;
			component3.levelCrit = statRow.LevelCrit;
			component3.baseMoveSpeed = statRow.BaseMoveSpeed;
			component3.levelMoveSpeed = 0f;
			component3.baseJumpPower = statRow.BaseJumpPower;
			component3.levelJumpPower = 0f;
			component3.baseJumpCount = (int)statRow.BaseJumpCount;
			component3.baseAcceleration = statRow.BaseAcceleration;
			component3.baseMaxShield = statRow.BaseMaxShield;
			component3.levelMaxShield = 0f;
			component3.sprintingSpeedMultiplier = statRow.SprintingSpeedMultiplier;
			if (hero.NoFallDamage)
			{
				component3.bodyFlags = (BodyFlags)(component3.bodyFlags | 1);
			}
			CapsuleCollider component6 = val.GetComponent<CapsuleCollider>();
			float num = component6.height * hero.HeightScale;
			float num2 = component6.radius * hero.WidthScale;
			float num3 = component6.center.y * hero.HeightScale;
			GameObject val4 = VanillaBody(hero.CapsuleFrom);
			CapsuleCollider val5 = (Object.op_Implicit((Object)(object)val4) ? val4.GetComponent<CapsuleCollider>() : null);
			if (Object.op_Implicit((Object)(object)val5))
			{
				num = val5.height;
				num2 = val5.radius;
				num3 = val5.center.y;
			}
			component6.height = num;
			component6.radius = Mathf.Min(num2, num * 0.5f);
			component6.center = new Vector3(0f, num3, 0f);
			KinematicCharacterMotor component7 = val.GetComponent<KinematicCharacterMotor>();
			if (Object.op_Implicit((Object)(object)component7))
			{
				AccessTools.Field(typeof(KinematicCharacterMotor), "CapsuleHeight").SetValue(component7, num);
				AccessTools.Field(typeof(KinematicCharacterMotor), "CapsuleRadius").SetValue(component7, Mathf.Min(num2, num * 0.5f));
				AccessTools.Field(typeof(KinematicCharacterMotor), "CapsuleYOffset").SetValue(component7, num3);
			}
			if (Object.op_Implicit((Object)(object)component3.aimOriginTransform))
			{
				component3.aimOriginTransform.localPosition = Vector3.Scale(component3.aimOriginTransform.localPosition, new Vector3(1f, hero.HeightScale, 1f));
			}
			CameraTargetParams component8 = val.GetComponent<CameraTargetParams>();
			GameObject val6 = VanillaBody(hero.CameraFrom);
			CameraTargetParams val7 = (Object.op_Implicit((Object)(object)val6) ? val6.GetComponent<CameraTargetParams>() : null);
			if (Object.op_Implicit((Object)(object)component8) && ((Object.op_Implicit((Object)(object)val7) && Object.op_Implicit((Object)(object)val7.cameraParams)) || Object.op_Implicit((Object)(object)component8.cameraParams)))
			{
				CharacterCameraParams val8 = Object.Instantiate<CharacterCameraParams>((Object.op_Implicit((Object)(object)val7) && Object.op_Implicit((Object)(object)val7.cameraParams)) ? val7.cameraParams : component8.cameraParams);
				((Object)val8).name = "ccpDeadlock" + hero.DisplayName;
				CharacterCameraParamsData data = val8.data;
				if (!Object.op_Implicit((Object)(object)val7))
				{
					data.idealLocalCameraPos.value = data.idealLocalCameraPos.value * Mathf.Lerp(1f, hero.HeightScale, 0.8f);
					data.pivotVerticalOffset.value = data.pivotVerticalOffset.value * hero.HeightScale;
				}
				Vector3 value = data.idealLocalCameraPos.value * hero.CameraScale;
				value.x += hero.CameraRight;
				data.idealLocalCameraPos.value = value;
				val8.data = data;
				component8.cameraParams = val8;
			}
			Interactor component9 = val.GetComponent<Interactor>();
			if (Object.op_Implicit((Object)(object)component9))
			{
				component9.maxInteractionDistance *= hero.InteractRange;
			}
			SkillLocator component10 = val.GetComponent<SkillLocator>();
			FieldInfo fieldInfo = AccessTools.Field(typeof(GenericSkill), "_skillFamily");
			foreach (SkillRow item in Sheet.SkillsOf(hero.Id))
			{
				if (!(item.Slot == "equipment"))
				{
					SkillDef val9 = MakeSkillDef(item, kinds);
					SkillFamily val10 = ScriptableObject.CreateInstance<SkillFamily>();
					((Object)val10).name = "sfDeadlock_" + item.Id;
					Variant[] array = new Variant[1];
					Variant val11 = new Variant
					{
						skillDef = val9
					};
					((Variant)(ref val11)).viewableNode = new Node(val9.skillNameToken, false, (Node)null);
					array[0] = val11;
					val10.variants = (Variant[])(object)array;
					Families.Add(val10);
					GenericSkill obj;
					switch (item.Slot)
					{
					case "primary":
						obj = component10.primary;
						break;
					case "secondary":
						obj = component10.secondary;
						break;
					case "utility":
						obj = component10.utility;
						break;
					case "special":
						obj = component10.special;
						break;
					default:
						Log.Error("skill " + item.Id + ": unknown slot " + item.Slot);
						continue;
					}
					fieldInfo.SetValue(obj, val10);
				}
			}
			PassiveSkill passiveSkill = component10.passiveSkill;
			passiveSkill.enabled = hero.PassiveName != "none";
			if (passiveSkill.enabled)
			{
				passiveSkill.skillNameToken = Sheet.Token("passive", hero.Id);
				passiveSkill.skillDescriptionToken = Sheet.Token("passivedesc", hero.Id);
				passiveSkill.icon = DeadlockCache.Sprite(hero.PassiveIcon);
				passiveSkill.keywordToken = null;
				Tokens[passiveSkill.skillNameToken] = hero.PassiveName;
				Tokens[passiveSkill.skillDescriptionToken] = hero.PassiveDescription;
			}
			component10.passiveSkill = passiveSkill;
			val.AddComponent<DeadlockHero>().HeroId = hero.Id;
			val.AddComponent<HeroRuntime>();
			return val;
		}

		private static SkillDef MakeSkillDef(SkillRow row, Dictionary<string, Type> kinds)
		{
			//IL_00a1: 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_00ec: Unknown result type (might be due to invalid IL or missing references)
			SkillDef val = ScriptableObject.CreateInstance<SkillDef>();
			((Object)val).name = "sdDeadlock_" + row.Id;
			val.skillName = "Deadlock_" + row.Id;
			val.skillNameToken = Sheet.Token("skill", row.Id);
			val.skillDescriptionToken = Sheet.Token("skilldesc", row.Id);
			val.icon = DeadlockCache.Sprite(row.Icon);
			if (!kinds.TryGetValue(row.Kind, out var value))
			{
				Log.Error("no state for kind " + row.Kind);
				value = typeof(Idle);
			}
			val.activationState = new SerializableEntityStateType(value);
			val.activationStateMachineName = MachineFor(row.Kind);
			bool flag = row.Slot == "primary";
			bool flag2 = row.Slot == "special";
			val.interruptPriority = (InterruptPriority)((!flag) ? ((!flag2) ? 1 : 2) : 0);
			val.baseRechargeInterval = (flag ? 0f : row.Cooldown);
			val.baseMaxStock = (int)Mathf.Max(1f, row.Stocks);
			val.rechargeStock = 1;
			val.requiredStock = 1;
			val.stockToConsume = ((!flag) ? 1 : 0);
			val.fullRestockOnAssign = true;
			val.isCombatSkill = true;
			val.mustKeyPress = !flag;
			bool flag3 = row.Kind.StartsWith("dash") || row.Kind == "burrow" || (row.Kind == "self_buff" && row.Buff == "smoke");
			val.cancelSprintingOnActivation = !flag3;
			val.canceledFromSprinting = false;
			val.hideCooldown = false;
			val.hideStockCount = flag;
			val.beginSkillCooldownOnSkillEnd = row.CooldownOnEnd;
			SkillDefs[row.Id] = val;
			RowOfSkill[val] = row;
			Tokens[val.skillNameToken] = row.Name;
			Tokens[val.skillDescriptionToken] = row.Description;
			return val;
		}

		private static void AddTokens(HeroRow hero)
		{
			Tokens[Sheet.Token("name", hero.Id)] = hero.DisplayName;
			Tokens[Sheet.Token("subtitle", hero.Id)] = hero.Subtitle;
			Tokens[Sheet.Token("outro", hero.Id)] = "..and so " + hero.DisplayName + " left, the contract fulfilled.";
			Tokens[Sheet.Token("fail", hero.Id)] = "..and so " + hero.DisplayName + " vanished into the storm.";
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(hero.Lore).Append("\n\n");
			foreach (SkillRow item in Sheet.SkillsOf(hero.Id))
			{
				string value = ((item.Slot == "primary") ? "M1" : ((item.Slot == "secondary") ? "M2" : ((item.Slot == "utility") ? "Shift" : ((item.Slot == "special") ? "R" : "Q (Ultimate equipment)"))));
				stringBuilder.Append("< ! > <style=cIsUtility>").Append(value).Append(" - ")
					.Append(item.Name)
					.Append("</style>\n");
			}
			stringBuilder.Append("\n<style=cIsUtility>You start every run holding your Deadlock ultimate as equipment (Q, 120s). Swap it for another and it stays on the ground for anyone to take.</style>");
			Tokens[Sheet.Token("desc", hero.Id)] = stringBuilder.ToString();
			BuffRow[] all = BuffRow.All;
			foreach (BuffRow buffRow in all)
			{
				Tokens[Sheet.Token("buff", buffRow.Id)] = buffRow.Name;
			}
		}

		private static GameObject VanillaBody(string name)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(name) || name == "none")
			{
				return null;
			}
			try
			{
				return Addressables.LoadAssetAsync<GameObject>((object)("RoR2/Base/" + name.Replace("Body", "") + "/" + name + ".prefab")).WaitForCompletion();
			}
			catch (Exception ex)
			{
				Log.Warn("vanilla body " + name + ": " + ex.Message);
				return null;
			}
		}

		public static SkillRow RowFor(GenericSkill gs)
		{
			if (!Object.op_Implicit((Object)(object)gs) || !Object.op_Implicit((Object)(object)gs.skillDef) || !RowOfSkill.TryGetValue(gs.skillDef, out var value))
			{
				return null;
			}
			return value;
		}
	}
	public sealed class HeroRuntime : MonoBehaviour
	{
		public int Ammo = -1;

		public bool Reloading;

		public bool AltMuzzle;

		public float SmokeUntil;

		private float reloadEnd;

		private int clip;

		private CharacterBody body;

		private HeroRow hero;

		private SoundRow steps;

		private SoundRow lands;

		private Transform rider;

		private Vector3 riderScale = Vector3.one;

		private bool riderHidden;

		private GameObject frenzy;

		private float nextStep;

		private float airTime;

		private bool wasGrounded = true;

		private float reloadTime;

		private int dodgesUsed;

		public float ComboUntil;

		public int Combo;

		public float LastSwingEnd = -99f;

		public float GunBlockedUntil;

		public int Octagon;

		private float hangUntil;

		private float hangUsed;

		private bool hanging;

		private bool jumpPressed;

		private float airSince;

		private float nextUntarget;

		private int lastJumps;

		public float ReloadFraction
		{
			get
			{
				if (!Reloading || !(reloadTime > 0f))
				{
					return 1f;
				}
				return Mathf.Clamp01(1f - (reloadEnd - Time.time) / reloadTime);
			}
		}

		public int Extra => DlrPuddle.Supply(body);

		public bool CanFire
		{
			get
			{
				if (Extra <= 0)
				{
					if (!Reloading)
					{
						return Ammo > 0;
					}
					return false;
				}
				return true;
			}
		}

		public int Rounds => Extra + ((!Reloading) ? Mathf.Max(0, Ammo) : 0);

		public int Dodges
		{
			get
			{
				if (hero == null)
				{
					return 0;
				}
				return (int)hero.AirDodges;
			}
		}

		public int DodgesLeft => Dodges - dodgesUsed;

		public float HangLeft => Mathf.Max(0f, hangUntil - Time.fixedTime);

		private void Awake()
		{
			body = ((Component)this).GetComponent<CharacterBody>();
		}

		private void Start()
		{
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			hero = Sheet.Hero(Survivors.HeroOf(body));
			if (hero == null)
			{
				return;
			}
			if (hero.ImmuneToForce && NetworkServer.active && !body.HasBuff(Buffs.ImmuneToPhysicsForces))
			{
				body.AddBuff(Buffs.ImmuneToPhysicsForces);
			}
			SkillRow skillRow = Sheet.SkillsOf(hero.Id).FirstOrDefault((SkillRow s) => s.Slot == "primary");
			steps = ((skillRow != null) ? Sheet.Sound(skillRow.Id + "/step") : null);
			lands = ((skillRow != null) ? (Sheet.Sound(skillRow.Id + "/land") ?? steps) : null);
			Transform val = (Object.op_Implicit((Object)(object)body.modelLocator) ? body.modelLocator.modelTransform : null);
			if (!Object.op_Implicit((Object)(object)val) || !(hero.RiderBone != "none"))
			{
				return;
			}
			Transform[] componentsInChildren = ((Component)val).GetComponentsInChildren<Transform>(true);
			foreach (Transform val2 in componentsInChildren)
			{
				if (((Object)val2).name == hero.RiderBone)
				{
					rider = val2;
					riderScale = val2.localScale;
					break;
				}
			}
		}

		public static bool Melee(CharacterBody b)
		{
			if (!Object.op_Implicit((Object)(object)b))
			{
				return false;
			}
			BuffRow[] all = BuffRow.All;
			foreach (BuffRow buffRow in all)
			{
				if (buffRow.Melee && Buffs.Count(b, buffRow.Id) > 0)
				{
					return true;
				}
			}
			return false;
		}

		public static bool NoGun(CharacterBody b)
		{
			if (!Object.op_Implicit((Object)(object)b))
			{
				return false;
			}
			BuffRow[] all = BuffRow.All;
			foreach (BuffRow buffRow in all)
			{
				if (buffRow.NoGun && Buffs.Count(b, buffRow.Id) > 0)
				{
					return true;
				}
			}
			GenericSkill val = (Object.op_Implicit((Object)(object)b.skillLocator) ? b.skillLocator.primary : null);
			if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.skillDef))
			{
				return (Object)(object)val.skillDef == (Object)(object)CommonAssets.disabledSkill;
			}
			return false;
		}

		private void LateUpdate()
		{
			//IL_00ba: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: 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_01be: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)rider))
			{
				bool flag = Melee(body);
				if (flag != riderHidden)
				{
					riderHidden = flag;
					rider.localScale = (flag ? Vector3.zero : riderScale);
					if (flag)
					{
						frenzy = Vfx.Play("mokrill_punch", "frenzy", body.footPosition, body.radius, ((Component)body).transform);
					}
					else
					{
						Vfx.Stop(frenzy, 0.6f);
						frenzy = null;
					}
				}
				else if (flag)
				{
					rider.localScale = Vector3.zero;
				}
			}
			if (steps == null || !Object.op_Implicit((Object)(object)body) || !Object.op_Implicit((Object)(object)body.characterMotor) || !Object.op_Implicit((Object)(object)body.healthComponent) || !body.healthComponent.alive)
			{
				return;
			}
			CharacterMotor characterMotor = body.characterMotor;
			bool isGrounded = characterMotor.isGrounded;
			if (!isGrounded)
			{
				airTime += Time.deltaTime;
			}
			else
			{
				if (!wasGrounded && airTime > 0.6f)
				{
					Fx.Sound(lands.Skill, "hit", body.footPosition);
					if (hero.LandShake > 0f)
					{
						ShakeEmitter.CreateSimpleShakeEmitter(body.footPosition, new Wave
						{
							amplitude = hero.LandShake,
							frequency = 25f
						}, 0.3f, 12f, true);
					}
				}
				airTime = 0f;
				Vector3 velocity = characterMotor.velocity;
				velocity.y = 0f;
				if (((Vector3)(ref velocity)).magnitude > 1f && Time.time >= nextStep)
				{
					nextStep = Time.time + 2.75f / Mathf.Max(2f, ((Vector3)(ref velocity)).magnitude);
					Fx.Sound(steps.Skill, "cast", body.footPosition);
				}
			}
			wasGrounded = isGrounded;
		}

		public void BeginReload(SkillRow gun, float attackSpeed)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			if (!Reloading)
			{
				Reloading = true;
				clip = (int)gun.ClipSize;
				reloadTime = gun.ReloadTime / Mathf.Max(0.1f, attackSpeed);
				reloadEnd = Time.time + reloadTime;
				Fx.Sound(gun.Id, "reload", ((Component)this).transform.position);
			}
		}

		public void Spend(int n)
		{
			n -= DlrPuddle.Draw(body, n);
			if (n > 0 && !Reloading)
			{
				Ammo = Mathf.Max(0, Ammo - n);
			}
		}

		private void Update()
		{
			if (hero != null && hero.AirDodges > 0f && Object.op_Implicit((Object)(object)body) && Object.op_Implicit((Object)(object)body.inputBank) && ((ButtonState)(ref body.inputBank.jump)).justPressed)
			{
				jumpPressed = true;
			}
			if (Reloading && Time.time >= reloadEnd)
			{
				Reloading = false;
				Ammo = clip;
				MeltyTest.Report("gun-reloads", ok: true, Object.op_Implicit((Object)(object)body) ? body.baseNameToken : "");
			}
		}

		public void UseDodge()
		{
			dodgesUsed++;
		}

		public void RefreshDodges()
		{
			dodgesUsed = 0;
			hangUsed = 0f;
		}

		public void HangFor(float seconds, float budget)
		{
			if (Object.op_Implicit((Object)(object)body) && Object.op_Implicit((Object)(object)body.characterMotor) && !body.characterMotor.isGrounded && !(hangUsed >= budget))
			{
				float fixedTime = Time.fixedTime;
				float num = Mathf.Max(0f, hangUntil - fixedTime);
				float num2 = Mathf.Min(seconds - num, budget - hangUsed);
				if (!(num2 <= 0f))
				{
					hangUsed += num2;
					hangUntil = fixedTime + num + num2;
				}
			}
		}

		public void EndHang()
		{
			hangUntil = 0f;
			hangUsed = float.MaxValue;
		}

		public void Refill(SkillRow gun, float pct)
		{
			if (gun != null && !(pct <= 0f) && !(gun.ClipSize <= 0f))
			{
				int num = Mathf.Max(1, Mathf.RoundToInt(gun.ClipSize * pct / 100f));
				if (Reloading)
				{
					Reloading = false;
					Ammo = 0;
				}
				if (Ammo < 0)
				{
					Ammo = (int)gun.ClipSize;
				}
				Ammo = Mathf.Min((int)gun.ClipSize, Ammo + num);
			}
		}

		private void BillyFixedUpdate()
		{
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			CharacterMotor characterMotor = body.characterMotor;
			if (characterMotor.isGrounded)
			{
				dodgesUsed = 0;
				hangUsed = 0f;
				airSince = Time.fixedTime;
			}
			if (jumpPressed)
			{
				jumpPressed = false;
				if (!characterMotor.isGrounded && Time.fixedTime - airSince > 0.1f && characterMotor.jumpCount >= body.maxJumpCount)
				{
					BillyAir.TryDodge(body);
				}
			}
			bool flag = Time.fixedTime < hangUntil && !characterMotor.isGrounded;
			if (flag != hanging)
			{
				hanging = flag;
				CharacterGravityParameters gravityParameters = characterMotor.gravityParameters;
				gravityParameters.channeledAntiGravityGranterCount += (flag ? 1 : (-1));
				characterMotor.gravityParameters = gravityParameters;
			}
			if (flag && characterMotor.velocity.y < 0f)
			{
				Vector3 velocity = characterMotor.velocity;
				velocity.y = 0f;
				characterMotor.velocity = velocity;
			}
		}

		private void FixedUpdate()
		{
			//IL_0184: 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_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: 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_00fd: Unknown result type (might be due to invalid IL or missing references)
			if (hero != null && hero.AirDodges > 0f && Object.op_Implicit((Object)(object)body) && body.hasEffectiveAuthority && Object.op_Implicit((Object)(object)body.characterMotor))
			{
				BillyFixedUpdate();
			}
			if (hero != null && hero.AirJumpMult != 1f && Object.op_Implicit((Object)(object)body) && body.hasEffectiveAuthority && Object.op_Implicit((Object)(object)body.characterMotor))
			{
				CharacterMotor characterMotor = body.characterMotor;
				if (characterMotor.jumpCount > lastJumps && lastJumps >= 1 && !characterMotor.isGrounded && characterMotor.velocity.y > 0f)
				{
					Vector3 velocity = characterMotor.velocity;
					velocity.y *= hero.AirJumpMult;
					characterMotor.velocity = velocity;
					MeltyTest.Report("air-jump", ok: true, body.baseNameToken);
				}
				lastJumps = characterMotor.jumpCount;
			}
			if (!NetworkServer.active || !Object.op_Implicit((Object)(object)body) || !body.hasCloakBuff || Time.fixedTime < nextUntarget)
			{
				return;
			}
			nextUntarget = Time.fixedTime + 0.2f;
			foreach (CharacterMaster readOnlyInstances in CharacterMaster.readOnlyInstancesList)
			{
				if (!Object.op_Implicit((Object)(object)readOnlyInstances) || readOnlyInstances.teamIndex == body.teamComponent.teamIndex || readOnlyInstances.AiComponents == null)
				{
					continue;
				}
				BaseAI[] aiComponents = readOnlyInstances.AiComponents;
				foreach (BaseAI val in aiComponents)
				{
					if (Object.op_Implicit((Object)(object)val) && val.currentEnemy != null && (Object)(object)val.currentEnemy.gameObject == (Object)(object)((Component)body).gameObject)
					{
						val.currentEnemy.Reset();
					}
				}
			}
		}
	}
	internal sealed class DeadlockContentProvider : IContentPackProvider
	{
		private readonly ContentPack pack = new ContentPack();

		public string identifier => "melty.deadlockofrain";

		public IEnumerator LoadStaticContentAsync(LoadStaticContentAsyncArgs args)
		{
			if (FirstRun.Started)
			{
				while (FirstRun.Choosing || (FirstRun.Running && !FirstRun.StopIfStalled()))
				{
					args.ReportProgress(0.45f * FirstRun.Progress);
					yield return null;
				}
				FirstRun.Finish(DeadlockCache.DefaultDir());
				Plugin.OpenCache();
				if (FirstRun.Wanted != null)
				{
					Survivors.LimitTo(FirstRun.Wanted);
				}
				DeadlockAudio.Init();
			}
			if (DeadlockCache.Ready)
			{
				IEnumerator e = Survivors.Build();
				while (e.MoveNext())
				{
					args.ReportProgress(0.5f);
					yield return e.Current;
				}
			}
			FirstRun.BuildEnd();
			pack.bodyPrefabs.Add(Survivors.Bodies.Values.ToArray());
			pack.survivorDefs.Add(Survivors.Defs.Values.ToArray());
			pack.bodyPrefabs.Add(MissingHeroes.Bodies.Values.ToArray());
			pack.survivorDefs.Add(MissingHeroes.Defs.Values.ToArray());
			pack.unlockableDefs.Add(MissingHeroes.Unlockables.Values.ToArray());
			pack.skillDefs.Add(Survivors.SkillDefs.Values.ToArray());
			pack.skillFamilies.Add(Survivors.Families.ToArray());
			pack.entityStateTypes.Add(Survivors.StateTypes.ToArray());
			pack.buffDefs.Add(Buffs.Defs.Values.ToArray());
			pack.equipmentDefs.Add(Equipment.Defs.Values.ToArray());
			if (Net.RelayDef != null)
			{
				pack.effectDefs.Add((EffectDef[])(object)new EffectDef[1] { Net.RelayDef });
			}
			pack.effectDefs.Add(Fx.TintedDefs.ToArray());
			Net.RegisterModList();
			args.ReportProgress(1f);
		}

		public IEnumerator GenerateContentPackAsync(GetContentPackAsyncArgs args)
		{
			ContentPack.Copy(pack, args.output);
			args.ReportProgress(1f);
			yield break;
		}

		public IEnumerator FinalizeAsync(FinalizeAsyncArgs args)
		{
			args.ReportProgress(1f);
			yield break;
		}
	}
	[HarmonyPatch(typeof(Language), "GetLocalizedStringByToken")]
	internal static class LanguagePatch
	{
		private static bool Prefix(string token, ref string __result)
		{
			if (token != null && token.StartsWith("DLR_", StringComparison.Ordinal) && Survivors.Tokens.TryGetValue(token, out var value))
			{
				__result = value;
				return false;
			}
			return true;
		}
	}
	[BepInPlugin("melty.deadlockofrain", "Deadlock of Rain", "1.0.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static CollectContentPackProvidersDelegate <>9__6_0;

			internal void <Awake>b__6_0(AddContentPackProviderDelegate add)
			{
				add.Invoke((IContentPackProvider)(object)new DeadlockContentProvider());
			}
		}

		public const string Guid = "melty.deadlockofrain";

		public const string Version = "1.0.0";

		public static Plugin Instance;

		public static ConfigEntry<float> Volume;

		public static ConfigEntry<string> DeadlockFolder;

		public static string PluginDir;

		private void Awake()
		{
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Expected O, but got Unknown
			Instance = this;
			Log.Source = ((BaseUnityPlugin)this).Logger;
			PluginDir = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
			Volume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "Deadlock sound volume", 1f, "Volume of the Deadlock sounds (0-1), on top of the game's master and SFX volume.");
			DeadlockFolder = ((BaseUnityPlugin)this).Config.Bind<string>("Deadlock", "Deadlock folder", "", "Only needed if Deadlock is not found by itself: your Deadlock folder, e.g. D:\\SteamLibrary\\steamapps\\common\\Deadlock (Steam: Deadlock > Manage > Browse local files). Its game or game\\citadel folder works too.");
			QuitSafety.Init();
			if (MeltyTest.Off("mod"))
			{
				MeltyTest.Init();
				return;
			}
			BuiltWith.Read();
			FirstRunOverlay.Show();
			if (!FirstRun.Start(DeadlockCache.DefaultDir(), DeadlockFolder.Value))
			{
				OpenCache();
			}
			if (!MeltyTest.Off("harmony"))
			{
				new Harmony("melty.deadlockofrain").PatchAll(typeof(Plugin).Assembly);
			}
			object obj = <>c.<>9__6_0;
			if (obj == null)
			{
				CollectContentPackProvidersDelegate val = delegate(AddContentPackProviderDelegate add)
				{
					add.Invoke((IContentPackProvider)(object)new DeadlockContentProvider());
				};
				<>c.<>9__6_0 = val;
				obj = (object)val;
			}
			ContentManager.collectContentPackProviders += (CollectContentPackProvidersDelegate)obj;
			Equipment.Init();
			Buffs.InitHooks();
			GunHits.Init();
			Net.Init();
			if (!FirstRun.Started && !MeltyTest.Off("audio"))
			{
				DeadlockAudio.Init();
			}
			Voice.Init();
			DlrHopper.InitTrophies();
			FirstRun.Init();
			CommunityButton.Init();
			MeltyTest.Init();
			DpsBench.Init();
		}

		public static void OpenCache()
		{
			DeadlockCache.Open(DeadlockCache.DefaultDir());
			Log.Info("Deadlock of Rain 1.0.0: Deadlock content from build " + DeadlockCache.DeadlockBuild + " at " + DeadlockCache.Dir);
			if (!DeadlockCache.Ready && FirstRun.Problem == null)
			{
				FirstRun.Problem = "The Deadlock heroes are missing. Install Deadlock (free on Steam) and restart Risk of Rain 2.\n\n" + BuiltWith.Versions();
			}
		}

		private void OnDestroy()
		{
			DeadlockAudio.Shutdown();
		}

		private void OnApplicationQuit()
		{
			DeadlockAudio.Shutdown();
		}
	}
	public static class Log
	{
		public static ManualLogSource Source;

		public static void Info(string s)
		{
			ManualLogSource source = Source;
			if (source != null)
			{
				source.LogInfo((object)s);
			}
		}

		public static void Warn(string s)
		{
			ManualLogSource source = Source;
			if (source != null)
			{
				source.LogWarning((object)s);
			}
		}

		public static void Error(string s)
		{
			ManualLogSource source = Source;
			if (source != null)
			{
				source.LogError((object)s);
			}
		}
	}
	[HarmonyPatch(typeof(SkillIcon), "LateUpdate")]
	internal static class AmmoCounter
	{
		private static void Postfix(SkillIcon __instance)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			if ((int)__instance.targetSkillSlot == 0)
			{
				AmmoLabel ammoLabel = ((Component)__instance).GetComponent<AmmoLabel>();
				if (!Object.op_Implicit((Object)(object)ammoLabel))
				{
					ammoLabel = ((Component)__instance).gameObject.AddComponent<AmmoLabel>();
				}
				ammoLabel.Show(__instance);
			}
		}
	}
	internal sealed class AmmoLabel : MonoBehaviour
	{
		private static readonly Color Full = Color.white;

		private static readonly Color Reload = new Color(0.6f, 0.6f, 0.6f);

		public static string Shown;

		public static CharacterBody ShownFor;

		public static float LastShow = -1f;

		private TextMeshProUGUI text;

		private int shownAmmo = int.MinValue;

		private int shownClip = -1;

		private int shownExtra = -1;

		private bool shownReload;

		public void Show(SkillIcon icon)
		{
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			GenericSkill targetSkill = icon.targetSkill;
			CharacterBody val = (Object.op_Implicit((Object)(object)targetSkill) ? targetSkill.characterBody : null);
			SkillRow skillRow = Survivors.RowFor(targetSkill);
			HeroRuntime heroRuntime = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<HeroRuntime>() : null);
			if (skillRow == null || !(skillRow.ClipSize > 0f) || !Object.op_Implicit((Object)(object)heroRuntime) || !val.hasEffectiveAuthority)
			{
				if (Object.op_Implicit((Object)(object)text))
				{
					((Component)text).gameObject.SetActive(false);
				}
				return;
			}
			LastShow = Time.unscaledTime;
			if (!Object.op_Implicit((Object)(object)text))
			{
				Build(icon);
			}
			if (Object.op_Implicit((Object)(object)text))
			{
				int num = (int)skillRow.ClipSize;
				int num2 = ((heroRuntime.Ammo < 0) ? num : heroRuntime.Ammo);
				int extra = heroRuntime.Extra;
				if (!((Component)text).gameObject.activeSelf)
				{
					((Component)text).gameObject.SetActive(true);
				}
				if (num2 != shownAmmo || num != shownClip || extra != shownExtra || heroRuntime.Reloading != shownReload)
				{
					shownAmmo = num2;
					shownClip = num;
					shownExtra = extra;
					shownReload = heroRuntime.Reloading;
					string arg = ((extra > 0) ? $"{extra}+" : "");
					((TMP_Text)text).SetText((extra > 0) ? $"<color=#8CFF5A>{arg}</color>{num2}/{num}" : $"{num2}/{num}", true);
					Shown = $"{arg}{num2}/{num}";
					ShownFor = val;
					((Graphic)text).color = (heroRuntime.Reloading ? Reload : Full);
				}
			}
		}

		private void Build(SkillIcon icon)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: 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_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_0055: 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_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: 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)
			GameObject val = new GameObject("DlrAmmo", new Type[1] { typeof(RectTransform) });
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent(((Component)icon).transform, false);
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0.5f, 1f);
			val2.anchorMax = val3;
			val2.anchorMin = val3;
			val2.pivot = new Vector2(0.5f, 0f);
			val2.anchoredPosition = new Vector2(0f, 4f);
			val2.sizeDelta = new Vector2(160f, 28f);
			text = (TextMeshProUGUI)(object)val.AddComponent<HGTextMeshProUGUI>();
			TextMeshProUGUI val4 = (Object.op_Implicit((Object)(object)icon.stockText) ? icon.stockText : icon.cooldownText);
			if (Object.op_Implicit((Object)(object)val4))
			{
				((TMP_Text)text).font = ((TMP_Text)val4).font;
				((TMP_Text)text).fontSharedMaterial = ((TMP_Text)val4).fontSharedMaterial;
			}
			((TMP_Text)text).fontSize = 22f;
			((TMP_Text)text).alignment = (TextAlignmentOptions)1026;
			((TMP_Text)text).enableWordWrapping = false;
			((Graphic)text).raycastTarget = false;
		}
	}
	public static class BillyAir
	{
		public static HurtBox Nearest(CharacterBody body, float range, bool onScreen = false)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0062: 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_0045: 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_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)body))
			{
				return null;
			}
			foreach (HurtBox item in Fx.Enemies(body, body.corePosition, range))
			{
				CharacterBody body2 = item.healthComponent.body;
				if (!Object.op_Implicit((Object)(object)body2) || (onScreen && !OnScreen(body, body2.corePosition)))
				{
					continue;
				}
				Vector3 corePosition = body.corePosition;
				Vector3 corePosition2 = body2.corePosition;
				LayerIndex world = LayerIndex.world;
				if (Physics.Linecast(corePosition, corePosition2, LayerMask.op_Implicit(((LayerIndex)(ref world)).mask), (QueryTriggerInteraction)1))
				{
					Vector3 corePosition3 = body.corePosition;
					Vector3 val = body2.corePosition + Vector3.up * body2.radius;
					world = LayerIndex.world;
					if (Physics.Linecast(corePosition3, val, LayerMask.op_Implicit(((LayerIndex)(ref world)).mask), (QueryTriggerInteraction)1))
					{
						continue;
					}
				}
				return item;
			}
			return null;
		}

		public static bool OnScreen(CharacterBody body, Vector3 point)
		{
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: 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)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			foreach (CameraRigController readOnlyInstances in CameraRigController.readOnlyInstancesList)
			{
				if (Object.op_Implicit((Object)(object)readOnlyInstances) && !((Object)(object)readOnlyInstances.target != (Object)(object)((Component)body).gameObject) && Object.op_Implicit((Object)(object)readOnlyInstances.sceneCam))
				{
					Vector3 val = readOnlyInstances.sceneCam.WorldToViewportPoint(point);
					return val.z > 0f && val.x >= 0f && val.x <= 1f && val.y >= 0f && val.y <= 1f;
				}
			}
			return Vector3.Dot(Object.op_Implicit((Object)(object)body.inputBank) ? body.inputBank.aimDirection : ((Component)body).transform.forward, point - body.corePosition) > 0f;
		}

		public static void SlamDown(HealthComponent hc, float speed)
		{
			if (Object.op_Implicit((Object)(object)hc) && Object.op_Implicit((Object)(object)hc.body) && NetworkServer.active)
			{
				DlrLift dlrLift = ((Component)hc.body).GetComponent<DlrLift>();
				if (!Object.op_Implicit((Object)(object)dlrLift))
				{
					dlrLift = ((Component)hc.body).gameObject.AddComponent<DlrLift>();
				}
				dlrLift.Slam(speed);
			}
		}

		public static void DragDown(HealthComponent hc, CharacterBody by, float speed)
		{
			if (Object.op_Implicit((Object)(object)hc) && Object.op_Implicit((Object)(object)hc.body) && Object.op_Implicit((Object)(object)by) && NetworkServer.active)
			{
				DlrLift dlrLift = ((Component)hc.body).GetComponent<DlrLift>();
				if (!Object.op_Implicit((Object)(object)dlrLift))
				{
					dlrLift = ((Component)hc.body).gameObject.AddComponent<DlrLift>();
				}
				dlrLift.Drag(by, speed);
			}
		}

		public static void LetGo(CharacterBody by, float speed)
		{
			if (Object.op_Implicit((Object)(object)by) && NetworkServer.active)
			{
				DlrLift[] array = Object.FindObjectsOfType<DlrLift>();
				for (int i = 0; i < array.Length; i++)
				{
					array[i].Release(by, speed);
				}
			}
		}

		public static bool InAir(CharacterBody body)
		{
			CharacterMotor val = (Object.op_Implicit((Object)(object)body) ? body.characterMotor : null);
			if (Object.op_Implicit((Object)(object)val))
			{
				if (val.isGrounded)
				{
					return val.velocity.y > 1f;
				}
				return true;
			}
			return false;
		}

		public static bool InCombo(CharacterBody body)
		{
			HeroRuntime heroRuntime = (Object.op_Implicit((Object)(object)body) ? ((Component)body).GetComponent<HeroRuntime>() : null);
			if (Object.op_Implicit((Object)(object)heroRuntime) && heroRuntime.Dodges > 0)
			{
				if (!Object.op_Implicit((Object)(object)body.characterMotor) || body.characterMotor.isGrounded)
				{
					return Time.time < heroRuntime.ComboUntil;
				}
				return true;
			}
			return false;
		}

		public static bool TryDodge(CharacterBody body)
		{
			//IL_0072: 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_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: 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_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			HeroRuntime heroRuntime = (Object.op_Implicit((Object)(object)body) ? ((Component)body).GetComponent<HeroRuntime>() : null);
			if (!Object.op_Implicit((Object)(object)heroRuntime) || !body.hasEffectiveAuthority || heroRuntime.DodgesLeft <= 0)
			{
				return false;
			}
			EntityStateMachine val = EntityStateMachine.FindByCustomName(((Component)body).gameObject, "Body");
			if (!Object.op_Implicit((Object)(object)val) || !(val.state is GenericCharacterMain))
			{
				return false;
			}
			InputBankTest inputBank = body.inputBank;
			Vector3 val2 = (Object.op_Implicit((Object)(object)inputBank) ? inputBank.aimDirection : ((Component)body).transform.forward);
			if (Object.op_Implicit((Object)(object)inputBank) && ((Vector3)(ref inputBank.moveVector)).sqrMagnitude > 0.1f)
			{
				val2 = inputBank.moveVector;
				val2.y = 0f;
			}
			val.SetNextState((EntityState)(object)new BillyDodge
			{
				Dir = ((Vector3)(ref val2)).normalized
			});
			return true;
		}
	}
	public sealed class DlrLift : MonoBehaviour
	{
		private enum Phase
		{
			Rise,
			Drift,
			Hold,
			Slam,
			Drag
		}

		private Phase phase;

		private CharacterBody body;

		private float riseSpeed;

		private float riseEnd;

		private float until;

		private float cap;

		private float driftSpeed;

		private float slamSpeed;

		private float start;

		private float slamUntil;

		private bool antiGravity;

		private bool flyer;

		private bool hold;

		private bool lifted;

		private CharacterBody dragBy;

		public static DlrLift Float(CharacterBody victim, float height, float riseTime, float floatTime)
		{
			if (!Object.op_Implicit((Object)(object)victim) || !NetworkServer.active)
			{
				return null;
			}
			DlrLift obj = ((Component)victim).GetComponent<DlrLift>() ?? ((Component)victim).gameObject.AddComponent<DlrLift>();
			obj.Begin(height, riseTime, floatTime, holdOnly: false);
			return obj;
		}

		public static DlrLift Haul(CharacterBody victim, float height, float riseTime, float holdTime)
		{
			if (!Object.op_Implicit((Object)(object)victim) || !NetworkServer.active)
			{
				return null;
			}
			DlrLift obj = ((Component)victim).GetComponent<DlrLift>() ?? ((Component)victim).gameObject.AddComponent<DlrLift>();
			obj.Begin(height, riseTime, riseTime + holdTime, holdOnly: true);
			return obj;
		}

		public static bool Floating(CharacterBody b)
		{
			DlrLift dlrLift = (Object.op_Implicit((Object)(object)b) ? ((Component)b).GetComponent<DlrLift>() : null);
			if (Object.op_Implicit((Object)(object)dlrLift) && dlrLift.phase != Phase.Slam)
			{
				return dlrLift.phase != Phase.Drag;
			}
			return false;
		}

		public static bool Dragged(CharacterBody b, CharacterBody by)
		{
			DlrLift dlrLift = (Object.op_Implicit((Object)(object)b) ? ((Component)b).GetComponent<DlrLift>() : null);
			if (Object.op_Implicit((Object)(object)dlrLift) && dlrLift.phase == Phase.Drag