Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Risk of Deadlock v0.7.0
plugins/DeadlockOfRain.dll
Decompiled 2 days ago
The result has been truncated due to the large size, download it to view full contents!
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