Decompiled source of Risk of Deadlock v0.7.0

plugins/DeadlockOfRain.dll

Decompiled 2 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 RoR2;
using RoR2.CameraModes;
using RoR2.CharacterAI;
using RoR2.ConVar;
using RoR2.ContentManagement;
using RoR2.ExpansionManagement;
using RoR2.Networking;
using RoR2.Orbs;
using RoR2.Projectile;
using RoR2.Skills;
using RoR2.UI;
using RoR2.UI.MainMenu;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;

[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+8172bf46bd16b0df3963567e3cdccf9c5b2801da")]
[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_0031: 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)
			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;
				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 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 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 Dictionary<string, MethodInfo> setters = new Dictionary<string, MethodInfo>();

		private static void Postfix(CharacterBody __instance)
		{
			float num = 0f;
			float num2 = 0f;
			float num3 = 0f;
			float num4 = 0f;
			float num5 = 0f;
			float num6 = 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)
				{
					continue;
				}
				BuffDef val = Buffs.Get(buffRow.Id);
				if (Object.op_Implicit((Object)(object)val))
				{
					int buffCount = __instance.GetBuffCount(val);
					if (buffCount > 0)
					{
						int num7 = ((!buffRow.CanStack) ? 1 : buffCount);
						num += buffRow.MoveSpeedAdd * (float)num7;
						num2 += buffRow.AttackSpeedAdd * (float)num7;
						num3 += buffRow.ArmorAdd * (float)num7;
						num4 += buffRow.RegenAdd * (float)num7;
						num6 += buffRow.MaxHealthAdd * (float)num7;
						num5 = Mathf.Max(num5, buffRow.SlowResist);
					}
				}
			}
			if (num == 0f && num2 == 0f && num3 == 0f && num4 == 0f && num5 == 0f && num6 == 0f)
			{
				return;
			}
			if (num6 != 0f)
			{
				Set(__instance, "maxHealth", __instance.maxHealth + num6);
			}
			float num8 = __instance.moveSpeed;
			if (num > 0f)
			{
				num8 *= 1f + num;
			}
			else if (num < 0f)
			{
				num8 /= 1f - num;
			}
			if (num5 > 0f)
			{
				float num9 = (__instance.baseMoveSpeed + __instance.levelMoveSpeed * (__instance.level - 1f)) * (__instance.isSprinting ? __instance.sprintingSpeedMultiplier : 1f);
				if (num8 < num9)
				{
					num8 += (num9 - num8) * num5;
				}
			}
			Set(__instance, "moveSpeed", num8);
			Set(__instance, "attackSpeed", __instance.attackSpeed * (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 });
		}
	}
	[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 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 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 string CodeName(HeroRow hero)
		{
			return Regex.Replace(hero.DisplayName, "[^A-Za-z0-9]", "");
		}

		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":
				return "Body";
			}
		}

		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 = Released;
			foreach (HeroRow hero in array)
			{
				if (DeadlockCache.LoadHero(hero.Id) == null)
				{
					Log.Error("hero " + hero.Id + " skipped: no Deadlock content");
					continue;
				}
				yield return null;
				GameObject val = BuildBody(commando, hero, kinds);
				Bodies[hero.Id] = val;
				GameObject val2 = ModelBuilder.Build(hero, forDisplay: true);
				val2.transform.SetParent(holder.transform, false);
				((Object)val2).name = "Deadlock" + CodeName(hero) + "Display";
				SurvivorDef val3 = ScriptableObject.CreateInstance<SurvivorDef>();
				((Object)val3).name = "Deadlock" + CodeName(hero);
				val3.cachedName = "Deadlock" + CodeName(hero);
				val3.bodyPrefab = val;
				val3.displayPrefab = val2;
				val3.displayNameToken = Sheet.Token("name", hero.Id);
				val3.descriptionToken = Sheet.Token("desc", hero.Id);
				val3.outroFlavorToken = Sheet.Token("outro", hero.Id);
				val3.mainEndingEscapeFailureFlavorToken = Sheet.Token("fail", hero.Id);
				val3.primaryColor = Sheet.Color(hero.PrimaryColor);
				val3.desiredSortPosition = hero.SortPosition;
				Defs[hero.Id] = val3;
				AddTokens(hero);
				Log.Info("Built survivor " + hero.DisplayName);
			}
			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_035e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_048f: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0558: Unknown result type (might be due to invalid IL or missing references)
			//IL_055d: Unknown result type (might be due to invalid IL or missing references)
			//IL_06b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_06cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_06d5: Expected O, but got Unknown
			//IL_06d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_06d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_07a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_07ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_07c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_05bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_05cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f5: 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_0571: Unknown result type (might be due to invalid IL or missing references)
			//IL_0576: Unknown result type (might be due to invalid IL or missing references)
			//IL_0590: Unknown result type (might be due to invalid IL or missing references)
			//IL_0595: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0846: Unknown result type (might be due to invalid IL or missing references)
			//IL_0848: Unknown result type (might be due to invalid IL or missing references)
			//IL_081b: 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)
			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;
			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;

		public float NextSurge;

		private float reloadEnd;

		private int clip;

		private CharacterBody body;

		private HeroRow hero;

		private SoundRow steps;

		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 nextUntarget;

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

		private void Start()
		{
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			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);
			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;
				}
			}
			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_01c2: 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_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: 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_0229: 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(steps.Skill, "hit", body.footPosition);
					ShakeEmitter.CreateSimpleShakeEmitter(body.footPosition, new Wave
					{
						amplitude = 2f,
						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_004c: Unknown result type (might be due to invalid IL or missing references)
			if (!Reloading)
			{
				Reloading = true;
				clip = (int)gun.ClipSize;
				reloadEnd = Time.time + gun.ReloadTime / Mathf.Max(0.1f, attackSpeed);
				Fx.Sound(gun.Id, "reload", ((Component)this).transform.position);
			}
		}

		private void Update()
		{
			if (Reloading && Time.time >= reloadEnd)
			{
				Reloading = false;
				Ammo = clip;
				MeltyTest.Report("gun-reloads", ok: true, Object.op_Implicit((Object)(object)body) ? body.baseNameToken : "");
			}
		}

		private void FixedUpdate()
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			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.Running)
				{
					args.ReportProgress(0.45f * FirstRun.Progress);
					yield return null;
				}
				FirstRun.Finish(DeadlockCache.DefaultDir());
				Plugin.OpenCache();
				DeadlockAudio.Init();
			}
			if (DeadlockCache.Ready)
			{
				IEnumerator e = Survivors.Build();
				while (e.MoveNext())
				{
					args.ReportProgress(0.5f);
					yield return e.Current;
				}
			}
			pack.bodyPrefabs.Add(Survivors.Bodies.Values.ToArray());
			pack.survivorDefs.Add(Survivors.Defs.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 });
			}
			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", "0.7.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 = "0.7.0";

		public static Plugin Instance;

		public static ConfigEntry<float> Volume;

		public static ConfigEntry<string> DeadlockFolder;

		public static string PluginDir;

		private void Awake()
		{
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: 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: the folder that holds game/citadel/pak01_dir.vpk.");
			if (!FirstRun.Start(DeadlockCache.DefaultDir(), DeadlockFolder.Value))
			{
				OpenCache();
			}
			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)
			{
				DeadlockAudio.Init();
			}
			Voice.Init();
			FirstRun.Init();
			MeltyTest.Init();
			DpsBench.Init();
		}

		public static void OpenCache()
		{
			DeadlockCache.Open(DeadlockCache.DefaultDir());
			Log.Info("Deadlock of Rain 0.7.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.";
			}
		}

		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);
			}
		}
	}
	public sealed class DeadlockAnimator : MonoBehaviour
	{
		public string HeroId;

		private Animation anim;

		private AnimRow rows;

		private Transform upperBody;

		private Transform[] spine;

		private string rig = "";

		private CharacterBody body;

		private CharacterMotor motor;

		private InputBankTest inputs;

		private string loco;

		private string overrideClip;

		private float overrideUntil;

		private bool wasGrounded = true;

		private float landUntil;

		private bool dead;

		private static readonly Dictionary<string, Dictionary<string, AnimationClip>> clipCache = new Dictionary<string, Dictionary<string, AnimationClip>>();

		private Dictionary<string, AnimationClip> clips;

		private readonly Dictionary<string, string> logical = new Dictionary<string, string>();

		private Transform[] rigBones;

		private Transform[] gunParts;

		private Vector3[] rigPos;

		private Vector3[] gunPartPos;

		private Quaternion[] rigRot;

		private Quaternion[] gunPartRot;

		private Transform gunHand;

		private Transform gunBone;

		private Transform mainHand;

		private Vector3 gunOffPos;

		private Vector3 gunFwdLocal;

		private Quaternion gunOffRot;

		private float armWeight = 1f;

		private float armFreeUntil;

		private float recoil;

		private float recoilTime;

		private Transform gunRoot;

		private Vector3 gunRootInHand;

		public float AimError { get; private set; } = -1f;

		public float GunDrift { get; private set; }

		public void ResetDrift()
		{
			GunDrift = 0f;
		}

		public void Setup(string heroId, HeroAsset asset, Transform[] bones, Transform armature)
		{
			HeroId = heroId;
			Animation val = ((Component)this).gameObject.AddComponent<Animation>();
			val.playAutomatically = false;
			val.cullingType = (AnimationCullingType)0;
			foreach (KeyValuePair<string, AnimationClip> item in BuildClips(heroId, asset, bones, ((Component)this).transform))
			{
				val.AddClip(item.Value, item.Key);
			}
			Init();
		}

		private void Init()
		{
			if ((Object)(object)anim != (Object)null)
			{
				return;
			}
			anim = ((Component)this).GetComponent<Animation>();
			if (!Object.op_Implicit((Object)(object)anim) || string.IsNullOrEmpty(HeroId) || !clipCache.TryGetValue(HeroId, out clips))
			{
				anim = null;
				return;
			}
			rows = Sheet.Anims(HeroId);
			logical["idle"] = rows.Idle;
			logical["run_n"] = rows.RunN;
			logical["run_s"] = rows.RunS;
			logical["run_e"] = rows.RunE;
			logical["run_w"] = rows.RunW;
			logical["sprint"] = rows.Sprint;
			logical["jump_start"] = rows.JumpStart;
			logical["jump_air"] = rows.JumpAir;
			logical["land"] = rows.Land;
			logical["fire"] = rows.Fire;
			logical["fire_alt"] = rows.FireAlt;
			logical["reload"] = rows.Reload;
			logical["secondary"] = rows.Secondary;
			logical["utility"] = rows.Utility;
			logical["utility_loop"] = rows.UtilityLoop;
			logical["special_start"] = rows.SpecialStart;
			logical["special"] = rows.Special;
			logical["ult_start"] = rows.UltStart;
			logical["ult_loop"] = rows.UltLoop;
			logical["ult_end"] = rows.UltEnd;
			logical["death"] = rows.Death;
			logical["special_loop"] = rows.SpecialLoop;
			logical["melee"] = rows.Melee;
			logical["melee_alt"] = rows.MeleeAlt;
			rig = ((rows.RigPrefix == "none") ? "" : rows.RigPrefix);
			Transform[] all = ((Component)this).GetComponentsInChildren<Transform>(true);
			upperBody = Bone(rows.UpperBodyBone);
			spine = (Transform[])(object)new Transform[3]
			{
				Bone(rig + "spine_1"),
				Bone(rig + "spine_2"),
				Bone(rig + "spine_3")
			};
			foreach (KeyValuePair<string, AnimationClip> clip in clips)
			{
				AnimationState val = anim[clip.Key];
				if (!((TrackedReference)(object)val == (TrackedReference)null))
				{
					bool flag = IsLocomotion(clip.Key);
					val.layer = ((!flag) ? 1 : 0);
					val.wrapMode = (WrapMode)((!flag && !(clip.Key == rows.UltLoop) && !(clip.Key == rows.UtilityLoop) && !(clip.Key == rows.SpecialLoop) && (!(clip.Key == rows.Secondary) || !rows.LoopSecondary)) ? 1 : 2);
				}
			}
			CaptureRig(all);
			loco = null;
			Play(rows.Idle, 0f);
			loco = rows.Idle;
			Transform Bone(string n)
			{
				Transform[] array = all;
				foreach (Transform val2 in array)
				{
					if (((Object)val2).name == n)
					{
						return val2;
					}
				}
				return null;
			}
		}

		private void CaptureRig(Transform[] all)
		{
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: 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_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0356: Unknown result type (might be due to invalid IL or missing references)
			//IL_031d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0322: Unknown result type (might be due to invalid IL or missing references)
			//IL_0327: Unknown result type (might be due to invalid IL or missing references)
			//IL_0374: Unknown result type (might be due to invalid IL or missing references)
			//IL_035f: Unknown result type (might be due to invalid IL or missing references)
			//IL_036a: Unknown result type (might be due to invalid IL or missing references)
			//IL_036f: Unknown result type (might be due to invalid IL or missing references)
			//IL_038a: Unknown result type (might be due to invalid IL or missing references)
			//IL_038f: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_039f: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
			if (rows.AimPose == "none" || !clips.TryGetValue(rows.AimPose, out var value))
			{
				return;
			}
			value.SampleAnimation(((Component)this).gameObject, 0f);
			gunHand = Bone(rows.GunHand);
			mainHand = (Object.op_Implicit((Object)(object)gunHand) ? gunHand : Bone(rig + "hand_R"));
			gunBone = ((rows.GunBone != "none") ? Bone(rows.GunBone) : null);
			List<Transform> list = new List<Transform>();
			Transform[] array = (Transform[])(object)new Transform[2]
			{
				Bone(rig + "weapon_hand_R"),
				Bone(rig + "weapon_hand_L")
			};
			foreach (Transform val in array)
			{
				if (Object.op_Implicit((Object)(object)val))
				{
					list.AddRange(((Component)val).GetComponentsInChildren<Transform>(true));
				}
			}
			if (Object.op_Implicit((Object)(object)gunBone) && Object.op_Implicit((Object)(object)gunHand))
			{
				array = ((Component)gunBone).GetComponentsInChildren<Transform>(true);
				foreach (Transform val2 in array)
				{
					if ((Object)(object)val2 != (Object)(object)gunBone)
					{
						list.Add(val2);
					}
				}
				gunOffPos = gunHand.InverseTransformPoint(gunBone.position);
				gunOffRot = Quaternion.Inverse(gunHand.rotation) * gunBone.rotation;
			}
			List<Transform> list2 = new List<Transform>();
			string[] array2 = ((!(rows.GunArms == "LR")) ? new string[1] { "R" } : new string[2] { "R", "L" });
			foreach (string text in array2)
			{
				Transform val3 = Bone(rig + "clavicle_" + text);
				if (!Object.op_Implicit((Object)(object)val3))
				{
					continue;
				}
				array = ((Component)val3).GetComponentsInChildren<Transform>(true);
				foreach (Transform item in array)
				{
					if (!list.Contains(item))
					{
						list2.Add(item);
					}
				}
			}
			Snapshot(list2, out rigBones, out rigPos, out rigRot);
			Snapshot(list, out gunParts, out gunPartPos, out gunPartRot);
			gunRoot = (Object.op_Implicit((Object)(object)gunBone) ? gunBone : Bone(rig + "weapon_hand_R"));
			if (Object.op_Implicit((Object)(object)gunRoot) && Object.op_Implicit((Object)(object)mainHand))
			{
				gunRootInHand = mainHand.InverseTransformPoint(gunRoot.position);
			}
			Transform val4 = Bone("muzzle_fx");
			Vector3 val5 = ((Object.op_Implicit((Object)(object)val4) && Object.op_Implicit((Object)(object)mainHand)) ? (val4.position - mainHand.position) : ((Component)this).transform.forward);
			if (((Vector3)(ref val5)).sqrMagnitude < 1E-06f)
			{
				val5 = ((Component)this).transform.forward;
			}
			gunFwdLocal = (Object.op_Implicit((Object)(object)mainHand) ? (Quaternion.Inverse(mainHand.rotation) * ((Vector3)(ref val5)).normalized) : Vector3.forward);
			Transform Bone(string n)
			{
				Transform[] array3 = all;
				foreach (Transform val6 in array3)
				{
					if (((Object)val6).name == n)
					{
						return val6;
					}
				}
				return null;
			}
		}

		private static void Snapshot(List<Transform> bones, out Transform[] t, out Vector3[] pos, out Quaternion[] rot)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			t = bones.ToArray();
			pos = (Vector3[])(object)new Vector3[t.Length];
			rot = (Quaternion[])(object)new Quaternion[t.Length];
			for (int i = 0; i < t.Length; i++)
			{
				pos[i] = t[i].localPosition;
				rot[i] = t[i].localRotation;
			}
		}

		private void Awake()
		{
			Init();
		}

		private bool IsLocomotion(string clip)
		{
			if (!(clip == rows.Idle) && !(clip == rows.RunN) && !(clip == rows.RunS) && !(clip == rows.RunE) && !(clip == rows.RunW) && !(clip == rows.Sprint))
			{
				return clip == rows.JumpAir;
			}
			return true;
		}

		private static Dictionary<string, AnimationClip> BuildClips(string hero, HeroAsset asset, Transform[] bones, Transform root)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: 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_0082: Expected O, but got Unknown
			//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0330: Unknown result type (might be due to invalid IL or missing references)
			//IL_0332: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0313: Unknown result type (might be due to invalid IL or missing references)
			//IL_031b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0323: Unknown result type (might be due to invalid IL or missing references)
			//IL_035f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0366: Unknown result type (might be due to invalid IL or missing references)
			//IL_036b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0376: Unknown result type (might be due to invalid IL or missing references)
			//IL_037d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0382: Unknown result type (might be due to invalid IL or missing references)
			//IL_038d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0394: Unknown result type (might be due to invalid IL or missing references)
			//IL_0399: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			if (clipCache.TryGetValue(hero, out var value))
			{
				return value;
			}
			Dictionary<string, AnimationClip> dictionary = new Dictionary<string, AnimationClip>();
			string[] array = new string[bones.Length];
			for (int i = 0; i < bones.Length; i++)
			{
				array[i] = PathTo(bones[i], root);
			}
			foreach (ClipDef value2 in asset.Clips.Values)
			{
				AnimationClip val = new AnimationClip
				{
					legacy = true,
					name = value2.Name,
					frameRate = value2.Fps
				};
				foreach (TrackDef track in value2.Tracks)
				{
					if (track.Bone < 0 || track.Bone >= bones.Length || (asset.Bones[track.Bone].Parent < 0 && Object.op_Implicit((Object)(object)bones[track.Bone].parent) && ((Object)bones[track.Bone].parent).name != "Armature"))
					{
						continue;
					}
					string text = array[track.Bone];
					bool flag = asset.Bones[track.Bone].Parent < 0 || asset.Bones[track.Bone].Name == "root_motion";
					if (track.Pos.Length != 0 && !flag)
					{
						Keyframe[] array2 = (Keyframe[])(object)new Keyframe[track.Pos.Length];
						Keyframe[] array3 = (Keyframe[])(object)new Keyframe[track.Pos.Length];
						Keyframe[] array4 = (Keyframe[])(object)new Keyframe[track.Pos.Length];
						for (int j = 0; j < track.Pos.Length; j++)
						{
							float num = ((track.Pos.Length == 1) ? 0f : Mathf.Min((float)j / value2.Fps, value2.Length));
							array2[j] = new Keyframe(num, track.Pos[j].x);
							array3[j] = new Keyframe(num, track.Pos[j].y);
							array4[j] = new Keyframe(num, track.Pos[j].z);
						}
						val.SetCurve(text, typeof(Transform), "localPosition.x", Linear(array2));
						val.SetCurve(text, typeof(Transform), "localPosition.y", Linear(array3));
						val.SetCurve(text, typeof(Transform), "localPosition.z", Linear(array4));
					}
					int num2 = track.Rot.Length;
					Keyframe[] array5 = (Keyframe[])(object)new Keyframe[num2];
					Keyframe[] array6 = (Keyframe[])(object)new Keyframe[num2];
					Keyframe[] array7 = (Keyframe[])(object)new Keyframe[num2];
					Keyframe[] array8 = (Keyframe[])(object)new Keyframe[num2];
					Quaternion val2 = track.Rot[0];
					for (int k = 0; k < num2; k++)
					{
						Quaternion val3 = track.Rot[k];
						if (k > 0 && Quaternion.Dot(val2, val3) < 0f)
						{
							((Quaternion)(ref val3))..ctor(0f - val3.x, 0f - val3.y, 0f - val3.z, 0f - val3.w);
						}
						val2 = val3;
						float num3 = ((num2 == 1) ? 0f : Mathf.Min((float)k / value2.Fps, value2.Length));
						array5[k] = new Keyframe(num3, val3.x);
						array6[k] = new Keyframe(num3, val3.y);
						array7[k] = new Keyframe(num3, val3.z);
						array8[k] = new Keyframe(num3, val3.w);
					}
					val.SetCurve(text, typeof(Transform), "localRotation.x", Linear(array5));
					val.SetCurve(text, typeof(Transform), "localRotation.y", Linear(array6));
					val.SetCurve(text, typeof(Transform), "localRotation.z", Linear(array7));
					val.SetCurve(text, typeof(Transform), "localRotation.w", Linear(array8));
				}
				val.EnsureQuaternionContinuity();
				dictionary[value2.Name] = val;
			}
			clipCache[hero] = dictionary;
			return dictionary;
		}

		private static AnimationCurve Linear(Keyframe[] k)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			AnimationCurve val = new AnimationCurve(k);
			for (int i = 0; i < k.Length; i++)
			{
				AnimationUtilityLite.SetLinear(val, i);
			}
			return val;
		}

		private static string PathTo(Transform t, Transform root)
		{
			List<string> list = new List<string>();
			Transform val = t;
			while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)root)
			{
				list.Insert(0, ((Object)val).name);
				val = val.parent;
			}
			return string.Join("/", list);
		}

		private void OnEnable()
		{
			Init();
			if (Object.op_Implicit((Object)(object)anim) && rows != null && !anim.isPlaying)
			{
				Play(rows.Idle, 0f);
			}
		}

		private void Start()
		{
			CharacterModel componentInParent = ((Component)this).GetComponentInParent<CharacterModel>();
			body = (Object.op_Implicit((Object)(object)componentInParent) ? componentInParent.body : null);
			if (!Object.op_Implicit((Object)(object)body))
			{
				body = ((Component)this).GetComponentInParent<CharacterBody>();
			}
			if (Object.op_Implicit((Object)(object)body))
			{
				motor = body.characterMotor;
				inputs = body.inputBank;
			}
		}

		public static DeadlockAnimator Of(CharacterBody b)
		{
			if (!Object.op_Implicit((Object)(object)b) || !Object.op_Implicit((Object)(object)b.modelLocator) || !Object.op_Implicit((Object)(object)b.modelLocator.modelTransform))
			{
				return null;
			}
			return ((Component)b.modelLocator.modelTransform).GetComponent<DeadlockAnimator>();
		}

		private string Clip(string logicalName)
		{
			if (logicalName == null)
			{
				return null;
			}
			if (logical.TryGetValue(logicalName.ToLowerInvariant(), out var value) && value != "none" && clips.ContainsKey(value))
			{
				return value;
			}
			return null;
		}

		private void Play(string clip, float fade)
		{
			if (clip != null && !(clip == "none") && clips.ContainsKey(clip))
			{
				if (fade <= 0f)
				{
					anim.Play(clip);
				}
				else
				{
					anim.CrossFade(clip, fade);
				}
			}
		}

		public void Gesture(string logicalName, float speed = 1f)
		{
			string text = Clip(logicalName);
			if (text != null)
			{
				AnimationState val = anim[text];
				if (Object.op_Implicit((Object)(object)upperBody))
				{
					val.RemoveMixingTransform(upperBody);
					val.AddMixingTransform(upperBody, true);
				}
				val.layer = 1;
				val.speed = speed;
				val.time = 0f;
				anim.CrossFade(text, 0.05f, (PlayMode)0);
				if (logicalName != "land" && logicalName != "jump_start")
				{
					armFreeUntil = Mathf.Max(armFreeUntil, Time.time + val.length / Mathf.Max(0.1f, speed));
				}
			}
		}

		public void Recoil(float degrees = 4f)
		{
			recoil = degrees;
			recoilTime = Time.time;
		}

		public void Override(string logicalName, float duration, bool loop = false)
		{
			string text = Clip(logicalName);
			if (text != null)
			{
				AnimationState val = anim[text];
				if (Object.op_Implicit((Object)(object)upperBody))
				{
					val.RemoveMixingTransform(upperBody);
				}
				val.layer = 2;
				val.wrapMode = (WrapMode)(loop ? 2 : 8);
				val.time = 0f;
				val.speed = ((!loop && duration > 0f) ? Mathf.Max(0.2f, val.length / duration) : 1f);
				anim.CrossFade(text, 0.1f, (PlayMode)0);
				overrideClip = text;
				overrideUntil = ((duration > 0f) ? (Time.time + duration) : float.MaxValue);
			}
		}

		public void StopOverride()
		{
			if (overrideClip != null)
			{
				anim.Blend(overrideClip, 0f, 0.15f);
			}
			overrideClip = null;
		}

		public bool HasClip(string logicalName)
		{
			return Clip(logicalName) != null;
		}

		private void Update()
		{
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)anim == (Object)null)
			{
				return;
			}
			if (overrideClip != null && Time.time > overrideUntil)
			{
				StopOverride();
			}
			if (Object.op_Implicit((Object)(object)body) && Object.op_Implicit((Object)(object)body.healthComponent) && !body.healthComponent.alive)
			{
				if (!dead)
				{
					dead = true;
					string text = Clip("death");
					if (text != null)
					{
						anim.Stop();
						anim[text].layer = 3;
						anim[text].wrapMode = (WrapMode)8;
						anim.Play(text);
					}
				}
				return;
			}
			string text2 = rows.Idle;
			float speed = 1f;
			if (Object.op_Implicit((Object)(object)motor))
			{
				Vector3 velocity = motor.velocity;
				velocity.y = 0f;
				bool isGrounded = motor.isGrounded;
				if (!isGrounded)
				{
					text2 = Clip("jump_air") ?? rows.Idle;
				}
				else if (((Vector3)(ref velocity)).sqrMagnitude > 0.5f)
				{
					Vector3 forward = ((Component)this).transform.forward;
					forward.y = 0f;
					((Vector3)(ref forward)).Normalize();
					Vector3 val = default(Vector3);
					((Vector3)(ref val))..ctor(forward.z, 0f, 0f - forward.x);
					float num = Vector3.Dot(velocity, forward);
					float num2 = Vector3.Dot(velocity, val);
					text2 = ((Object.op_Implicit((Object)(object)body) && body.isSprinting && num > 0f) ? (Clip("sprint") ?? rows.RunN) : ((!(Mathf.Abs(num) >= Mathf.Abs(num2))) ? ((num2 >= 0f) ? rows.RunE : rows.RunW) : ((num >= 0f) ? rows.RunN : rows.RunS)));
					float num3 = (Object.op_Implicit((Object)(object)body) ? Mathf.Max(1f, body.moveSpeed) : 7f);
					speed = Mathf.Clamp(((Vector3)(ref velocity)).magnitude / num3, 0.6f, 1.8f);
				}
				if (isGrounded && !wasGrounded && Clip("land") != null)
				{
					Gesture("land");
					landUntil = Time.time + 0.2f;
				}
				if (!isGrounded && wasGrounded && Object.op_Implicit((Object)(object)inputs) && inputs.jump.down)
				{
					Gesture("jump_start");
				}
				wasGrounded = isGrounded;
			}
			if (text2 != loco && clips.ContainsKey(text2))
			{
				anim.CrossFade(text2, 0.15f, (PlayMode)0);
				loco = text2;
			}
			if (loco != null && (TrackedReference)(object)anim[loco] != (TrackedReference)null)
			{
				anim[loco].speed = speed;
			}
		}

		private void OnDisable()
		{
			if (!Object.op_Implicit((Object)(object)body) || !Object.op_Implicit((Object)(object)body.healthComponent) || body.healthComponent.alive)
			{
				return;
			}
			if (Object.op_Implicit((Object)(object)anim))
			{
				anim.Stop();
				((Behaviour)anim).enabled = false;
			}
			if (Object.op_Implicit((Object)(object)gunBone) && Object.op_Implicit((Object)(object)gunHand))
			{
				gunBone.SetParent(gunHand, true);
			}
			HurtBox[] componentsInChildren = ((Component)this).GetComponentsInChildren<HurtBox>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Collider component = ((Component)componentsInChildren[i]).GetComponent<Collider>();
				if (Object.op_Implicit((Object)(object)component))
				{
					component.enabled = false;
				}
			}
		}

		private void LateUpdate()
		{
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0408: Unknown result type (might be due to invalid IL or missing references)
			//IL_040e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0413: Unknown result type (might be due to invalid IL or missing references)
			//IL_0301: Unknown result type (might be due to invalid IL or missing references)
			//IL_0307: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0317: Unknown result type (might be due to invalid IL or missing references)
			//IL_043d: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: 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_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0461: Unknown result type (might be due to invalid IL or missing references)
			//IL_0466: Unknown result type (might be due to invalid IL or missing references)
			//IL_046c: Unknown result type (might be due to invalid IL or missing references)
			//IL_047c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0294: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_029e: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)anim == (Object)null || rigBones == null)
			{
				return;
			}
			bool flag = dead || overrideClip != null || Time.time < armFreeUntil;
			armWeight = Mathf.MoveTowards(armWeight, flag ? 0f : 1f, Time.deltaTime / 0.15f);
			if (armWeight > 0f)
			{
				for (int i = 0; i < rigBones.Length; i++)
				{
					Transform val = rigBones[i];
					if (Object.op_Implicit((Object)(object)val))
					{
						val.localPosition = Vector3.Lerp(val.localPosition, rigPos[i], armWeight);
						val.localRotation = Quaternion.Slerp(val.localRotation, rigRot[i], armWeight);
					}
				}
			}
			for (int j = 0; j < gunParts.Length; j++)
			{
				if (Object.op_Implicit((Object)(object)gunParts[j]))
				{
					gunParts[j].localPosition = gunPartPos[j];
					gunParts[j].localRotation = gunPartRot[j];
				}
			}
			if (Object.op_Implicit((Object)(object)inputs) && Object.op_Implicit((Object)(object)mainHand) && armWeight > 0f)
			{
				Vector3 val2 = ClampAim(inputs.aimDirection);
				float num = Mathf.Atan2(val2.x, val2.z) * 57.29578f;
				float num2 = Mathf.Asin(Mathf.Clamp(val2.y, -1f, 1f)) * 57.29578f;
				float[] array = new float[3]
				{
					1f / 3f,
					0.5f,
					1f
				};
				Vector3 val5 = default(Vector3);
				for (int k = 0; k < spine.Length; k++)
				{
					if (Object.op_Implicit((Object)(object)spine[k]))
					{
						Vector3 val3 = mainHand.rotation * gunFwdLocal;
						Quaternion val4 = Quaternion.AngleAxis(Mathf.DeltaAngle(Mathf.Atan2(val3.x, val3.z) * 57.29578f, num) * array[k] * armWeight, Vector3.up);
						val3 = val4 * val3;
						float num3 = num2 - Mathf.Asin(Mathf.Clamp(val3.y, -1f, 1f)) * 57.29578f;
						((Vector3)(ref val5))..ctor(val3.x, 0f, val3.z);
						Vector3 val6 = ((((Vector3)(ref val5)).sqrMagnitude > 1E-06f) ? Vector3.Cross(((Vector3)(ref val5)).normalized, Vector3.up) : ((Component)this).transform.right);
						Quaternion val7 = Quaternion.AngleAxis(num3 * array[k] * armWeight, val6);
						spine[k].rotation = val7 * val4 * spine[k].rotation;
					}
				}
				AimError = Vector3.Angle(mainHand.rotation * gunFwdLocal, inputs.aimDirection);
			}
			else
			{
				AimError = -1f;
			}
			if (recoil > 0f && spine.Length > 2 && Object.op_Implicit((Object)(object)spine[2]))
			{
				float num4 = recoil * Mathf.Exp((0f - (Time.time - recoilTime)) / 0.05f);
				if (num4 < 0.05f)
				{
					recoil = 0f;
				}
				else
				{
					spine[2].rotation = Quaternion.AngleAxis(0f - num4, ((Component)this).transform.right) * spine[2].rotation;
				}
			}
			if (Object.op_Implicit((Object)(object)gunBone) && Object.op_Implicit((Object)(object)gunHand))
			{
				gunBone.position = gunHand.TransformPoint(gunOffPos);
				gunBone.rotation = gunHand.rotation * gunOffRot;
			}
			if (Object.op_Implicit((Object)(object)gunRoot) && Object.op_Implicit((Object)(object)mainHand) && mainHand.lossyScale.x > 0.001f)
			{
				GunDrift = Mathf.Max(GunDrift, Vector3.Distance(mainHand.InverseTransformPoint(gunRoot.position), gunRootInHand) * ((Component)this).transform.lossyScale.x);
			}
		}

		private Vector3 ClampAim(Vector3 aim)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ((Component)this).transform.InverseTransformDirection(((Vector3)(ref aim)).normalized);
			float num = Mathf.Atan2(val.x, val.z) * 57.29578f;
			float num2 = Mathf.Asin(Mathf.Clamp(val.y, -1f, 1f)) * 57.29578f;
			num = Mathf.Clamp(num, -70f, 70f);
			num2 = Mathf.Clamp(num2, -80f, 80f);
			return ((Component)this).transform.TransformDirection(Quaternion.Euler(0f - num2, num, 0f) * Vector3.forward);
		}
	}
	internal static class AnimationUtilityLite
	{
		public static void SetLinear(AnimationCurve curve, int i)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: 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_0065: Unknown result type (might be due to invalid IL or missing references)
			Keyframe[] keys = curve.keys;
			Keyframe val = keys[i];
			if (i > 0)
			{
				Keyframe val2 = keys[i - 1];
				float num = ((Keyframe)(ref val)).time - ((Keyframe)(ref val2)).time;
				((Keyframe)(ref val)).inTangent = ((num > 0f) ? ((((Keyframe)(ref val)).value - ((Keyframe)(ref val2)).value) / num) : 0f);
			}
			if (i < keys.Length - 1)
			{
				Keyframe val3 = keys[i + 1];
				float num2 = ((Keyframe)(ref val3)).time - ((Keyframe)(ref val)).time;
				((Keyframe)(ref val)).outTangent = ((num2 > 0f) ? ((((Keyframe)(ref val3)).value - ((Keyframe)(ref val)).value) / num2) : 0f);
			}
			curve.MoveKey(i, val);
		}
	}
	public static class DeadlockAudio
	{
		private sealed class Clip
		{
			public float[] L;

			public float[] R;
		}

		private sealed class Voice
		{
			public Clip clip;

			public int pos;

			public float vol;

			public float pan;

			public bool loop;

			public int id;
		}

		private sealed class Event
		{
			public float volume;

			public List<Clip> clips = new List<Clip>();
		}

		private struct WaveFormatEx
		{
			public short wFormatTag;

			public short nChannels;

			public int nSamplesPerSec;

			public int nAvgBytesPerSec;

			public short nBlockAlign;

			public short wBitsPerSample;

			public short cbSize;
		}

		private struct WaveHdr
		{
			public IntPtr lpData;

			public int dwBufferLength;

			public int dwBytesRecorded;

			public IntPtr dwUser;

			public int dwFlags;

			public int dwLoops;

			public IntPtr lpNext;

			public IntPtr reserved;
		}

		private const int Rate = 44100;

		private const int BufferFrames = 882;

		private const int Buffers = 4;

		private static readonly Dictionary<string, Event> events = new Dictionary<string, Event>(StringComparer.OrdinalIgnoreCase);

		private static readonly List<Voice> voices = new List<Voice>();

		private static readonly object gate = new object();

		private static readonly Random rng = new Random();

		private static Thread thread;

		private static volatile bool running;

		private static volatile float masterVolume = 1f;

		private static IntPtr device;

		private static int nextId = 1;

		public static int Played;

		private static float nextVolumeCheck;

		public static void Init()
		{
			try
			{
				LoadIndex();
				if (events.Count != 0)
				{
					running = true;
					thread = new Thread(Run)
					{
						IsBackground = true,
						Name = "DeadlockAudio"
					};
					thread.Start();
					RoR2Application.onUpdate += UpdateVolume;
				}
			}
			catch (Exception ex)
			{
				Log.Warn("Deadlock audio disabled: " + ex.Message);
			}
		}

		public static void Shutdown()
		{
			running = false;
		}

		private static void UpdateVolume()
		{
			if (Time.unscaledTime < nextVolumeCheck)
			{
				return;
			}
			nextVolumeCheck = Time.unscale