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 T4ylorSurvivors v1.0.0
plugins/TaylorsBalancePatch.dll
Decompiled 7 hours 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.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using EntityStates; using EntityStates.Bandit2.Weapon; using EntityStates.Chef; using EntityStates.Commando; using EntityStates.Commando.CommandoWeapon; using EntityStates.Croco; using EntityStates.Drifter; using EntityStates.Drone.DroneWeapon; using EntityStates.DroneTech.Weapon; using EntityStates.Engi.EngiWeapon; using EntityStates.Engi.Mine; using EntityStates.FalseSon; using EntityStates.Huntress; using EntityStates.Loader; using EntityStates.Mage.Weapon; using EntityStates.Merc; using EntityStates.Merc.Weapon; using EntityStates.Railgunner.Weapon; using EntityStates.Treebot; using EntityStates.Treebot.Weapon; using EntityStates.VoidSurvivor.Weapon; using IL.EntityStates.Chef; using IL.EntityStates.Commando.CommandoWeapon; using IL.EntityStates.Drifter; using IL.EntityStates.FalseSon; using IL.EntityStates.Mage; using IL.EntityStates.Mage.Weapon; using IL.EntityStates.Merc; using IL.EntityStates.Treebot.Weapon; using IL.EntityStates.VoidSurvivor.Weapon; using IL.RoR2; using IL.RoR2.Projectile; using IL.RoR2.UI; using KinematicCharacterController; using Microsoft.CodeAnalysis; using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Collections.Generic; using MonoMod.Cil; using MonoMod.RuntimeDetour; using On; using On.EntityStates; using On.EntityStates.Bandit2.Weapon; using On.EntityStates.Chef; using On.EntityStates.Commando; using On.EntityStates.Commando.CommandoWeapon; using On.EntityStates.Croco; using On.EntityStates.Drone.DroneWeapon; using On.EntityStates.DroneTech.Weapon; using On.EntityStates.Engi.Mine; using On.EntityStates.FalseSon; using On.EntityStates.Loader; using On.EntityStates.Mage.Weapon; using On.EntityStates.Merc; using On.EntityStates.Merc.Weapon; using On.EntityStates.Railgunner.Weapon; using On.EntityStates.Treebot; using On.EntityStates.Treebot.Weapon; using On.EntityStates.VoidSurvivor.Weapon; using On.RoR2; using On.RoR2.Projectile; using On.RoR2.Skills; using On.RoR2.UI; using RoR2; using RoR2.AsyncManagement; using RoR2.ContentManagement; using RoR2.Networking; using RoR2.Projectile; using RoR2.Skills; using RoR2.UI; using UnityEngine; using UnityEngine.Networking; using UnityEngine.Rendering; [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("TaylorsBalancePatch")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("T4ylorSurvivors balance changes for Risk of Rain 2.")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+44d523b5fbe8978c8f396df84e4f4ce33addf3e5")] [assembly: AssemblyProduct("TaylorsBalancePatch")] [assembly: AssemblyTitle("TaylorsBalancePatch")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace TaylorsBalancePatch { internal static class AcolyteBalance { } internal sealed class AcolyteChanges : IDisposable { internal AcolyteChanges(ManualLogSource log) { } internal void Enable() { } public void Dispose() { } } internal static class AcridBalance { internal const string ConfigSection = "Acrid"; internal const string ConfigKey = "EnableAcridChanges"; internal const string ConfigDescription = "Enable all Acrid passive and skill changes and descriptions. Restart the game after changing this setting."; internal const float BlightBaseDuration = 8f; internal const float BlightProcPerStack = 0.1f; internal const int BreathBlightTickInterval = 4; internal const float NeurotoxinCooldown = 2.5f; internal const int FrenziedLeapStock = 1; internal const float FrenziedLeapCooldown = 8f; internal const float BreathPoisonDuration = 10f; internal const float SpawnProtectionTail = 2f; internal static float GetBlightProcCoefficient(int totalStacks, int attackerStacks) { if (totalStacks <= 0 || attackerStacks <= 0) { return 0f; } return Math.Min(1f, (float)totalStacks * 0.1f) * (float)Math.Min(attackerStacks, totalStacks) / (float)totalStacks; } internal static string? GetDescription(string token) { return token switch { "CROCO_PASSIVE_ALT_DESCRIPTION" => "Attacks that apply <style=cIsHealing>Poison</style> apply stacking <style=cIsDamage>Blight</style> instead, dealing <style=cIsDamage>60% damage per second</style>. <color=#C586FF><b>Each stack lasts 8 seconds. Each Blight tick has 0.1 proc coefficient per stack, capped at 1.0 total per victim per tick across all attackers; ticks can trigger on-hit items.</b></color>", "CROCO_SECONDARY_DESCRIPTION" => "<style=cIsHealing>Poisonous</style>. Spit toxic bile for <style=cIsDamage>240% damage</style>. <color=#C586FF><b>Base cooldown: 2.5 seconds.</b></color>", "CROCO_UTILITY_ALT1_DESCRIPTION" => "<style=cIsDamage>Stunning</style>. Leap in the air, dealing <style=cIsDamage>550% damage</style>. <style=cIsUtility>Reduce</style> the cooldown by <style=cIsUtility>2s</style> for every enemy hit. <color=#C586FF><b>Poisonous. Holds 1 charge. Base cooldown: 8 seconds.</b></color>", "CROCO_SPECIAL_ALT_DESCRIPTION" => "<style=cIsHealing>Poisonous</style>. Emit a lingering cloud of toxic breath for <style=cIsDamage>240% damage per second</style>. <color=#C586FF><b>Uses your equipped passive: Poison applies every accepted tick; Blight applies on the first tick and every 4 ticks after that, per enemy and cloud.</b></color>", _ => null, }; } } internal sealed class BreathTickSequence { private int tick; internal bool NextAppliesBlight() { bool result = tick == 0; tick = (tick + 1) % 4; return result; } } internal sealed class BlightProcBudget<T> where T : notnull { private readonly Dictionary<T, int> stacks = new Dictionary<T, int>(); private readonly HashSet<T> consumed = new HashSet<T>(); private int totalStacks; internal void AddStack(T attacker) { totalStacks++; stacks.TryGetValue(attacker, out var value); stacks[attacker] = value + 1; } internal void AddUnattributedStack() { totalStacks++; } internal float TakeProc(T attacker) { if (!consumed.Add(attacker) || !stacks.TryGetValue(attacker, out var value)) { return 0f; } return AcridBalance.GetBlightProcCoefficient(totalStacks, value); } } internal sealed class AcridChanges : IDisposable { private sealed class BlightTickContext { internal readonly GameObject controllerObject; internal readonly BlightProcBudget<GameObject> budget = new BlightProcBudget<GameObject>(); internal BlightTickContext(GameObject controllerObject) { this.controllerObject = controllerObject; } } [CompilerGenerated] private static class <>O { public static hook_InflictDot_refInflictDotInfo <0>__BlightDuration; public static hook_TakeDamage <1>__BlightDamage; public static hook_GetBlastDamageType <2>__FrenziedLeapDamageType; public static hook_FireProjectile <3>__BreathProjectile; public static hook_GetDamageType <4>__CrocoDamageType; public static hook_GetLocalizedStringByToken <5>__Description; } [ThreadStatic] private static int breathProjectileSetupDepth; private readonly ManualLogSource log; private readonly List<Action> cleanup = new List<Action>(); private readonly Dictionary<Spawn, CharacterBody> protectedSpawns = new Dictionary<Spawn, CharacterBody>(); private SkillDef? neurotoxin; private SkillDef? frenziedLeap; private float originalNeurotoxinCooldown; private int originalFrenziedLeapStock; private float originalFrenziedLeapCooldown; private GameObject? breathProjectilePrefab; private ConditionalWeakTable<ProjectileController, ConditionalWeakTable<HealthComponent, BreathTickSequence>> breathTicks = new ConditionalWeakTable<ProjectileController, ConditionalWeakTable<HealthComponent, BreathTickSequence>>(); private FieldInfo? dotStacksField; private FieldInfo? stackIndexField; private FieldInfo? stackAttackerField; [ThreadStatic] private static BlightTickContext? activeBlightTick; internal AcridChanges(ManualLogSource log) { this.log = log; } internal void Enable() { try { dotStacksField = typeof(DotController).GetField("dotStackList", BindingFlags.Instance | BindingFlags.NonPublic) ?? throw new MissingFieldException("DotController.dotStackList"); Type type = dotStacksField.FieldType.GetGenericArguments()[0]; stackIndexField = type.GetField("dotIndex") ?? throw new MissingFieldException("DotStack.dotIndex"); stackAttackerField = type.GetField("attackerObject") ?? throw new MissingFieldException("DotStack.attackerObject"); Add(delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown SkillCatalog.SetSkillDefs += new hook_SetSkillDefs(SkillDefs); }, delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown SkillCatalog.SetSkillDefs -= new hook_SetSkillDefs(SkillDefs); }); Add(delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown ProjectileCatalog.SetProjectilePrefabs += new hook_SetProjectilePrefabs(Projectiles); }, delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown ProjectileCatalog.SetProjectilePrefabs -= new hook_SetProjectilePrefabs(Projectiles); }); Add(delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<0>__BlightDuration; if (obj == null) { hook_InflictDot_refInflictDotInfo val = BlightDuration; <>O.<0>__BlightDuration = val; obj = (object)val; } DotController.InflictDot_refInflictDotInfo += (hook_InflictDot_refInflictDotInfo)obj; }, delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<0>__BlightDuration; if (obj == null) { hook_InflictDot_refInflictDotInfo val = BlightDuration; <>O.<0>__BlightDuration = val; obj = (object)val; } DotController.InflictDot_refInflictDotInfo -= (hook_InflictDot_refInflictDotInfo)obj; }); Add(delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown DotController.EvaluateDotStacksForType += new hook_EvaluateDotStacksForType(BlightTick); }, delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown DotController.EvaluateDotStacksForType -= new hook_EvaluateDotStacksForType(BlightTick); }); Add(delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<1>__BlightDamage; if (obj == null) { hook_TakeDamage val = BlightDamage; <>O.<1>__BlightDamage = val; obj = (object)val; } HealthComponent.TakeDamage += (hook_TakeDamage)obj; }, delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<1>__BlightDamage; if (obj == null) { hook_TakeDamage val = BlightDamage; <>O.<1>__BlightDamage = val; obj = (object)val; } HealthComponent.TakeDamage -= (hook_TakeDamage)obj; }); Add(delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown Spawn.OnEnter += new hook_OnEnter(ProtectSpawn); }, delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown Spawn.OnEnter -= new hook_OnEnter(ProtectSpawn); }); Add(delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown Spawn.OnExit += new hook_OnExit(EndSpawnProtection); }, delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown Spawn.OnExit -= new hook_OnExit(EndSpawnProtection); }); Add(delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<2>__FrenziedLeapDamageType; if (obj == null) { hook_GetBlastDamageType val = FrenziedLeapDamageType; <>O.<2>__FrenziedLeapDamageType = val; obj = (object)val; } ChainableLeap.GetBlastDamageType += (hook_GetBlastDamageType)obj; }, delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<2>__FrenziedLeapDamageType; if (obj == null) { hook_GetBlastDamageType val = FrenziedLeapDamageType; <>O.<2>__FrenziedLeapDamageType = val; obj = (object)val; } ChainableLeap.GetBlastDamageType -= (hook_GetBlastDamageType)obj; }); Add(delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<3>__BreathProjectile; if (obj == null) { hook_FireProjectile val = BreathProjectile; <>O.<3>__BreathProjectile = val; obj = (object)val; } Breath.FireProjectile += (hook_FireProjectile)obj; }, delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<3>__BreathProjectile; if (obj == null) { hook_FireProjectile val = BreathProjectile; <>O.<3>__BreathProjectile = val; obj = (object)val; } Breath.FireProjectile -= (hook_FireProjectile)obj; }); Add(delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<4>__CrocoDamageType; if (obj == null) { hook_GetDamageType val = CrocoDamageType; <>O.<4>__CrocoDamageType = val; obj = (object)val; } CrocoDamageTypeController.GetDamageType += (hook_GetDamageType)obj; }, delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<4>__CrocoDamageType; if (obj == null) { hook_GetDamageType val = CrocoDamageType; <>O.<4>__CrocoDamageType = val; obj = (object)val; } CrocoDamageTypeController.GetDamageType -= (hook_GetDamageType)obj; }); Add(delegate { GlobalEventManager.onServerDamageDealt += DamageDealt; }, delegate { GlobalEventManager.onServerDamageDealt -= DamageDealt; }); Add(delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<5>__Description; if (obj == null) { hook_GetLocalizedStringByToken val = Description; <>O.<5>__Description = val; obj = (object)val; } Language.GetLocalizedStringByToken += (hook_GetLocalizedStringByToken)obj; }, delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<5>__Description; if (obj == null) { hook_GetLocalizedStringByToken val = Description; <>O.<5>__Description = val; obj = (object)val; } Language.GetLocalizedStringByToken -= (hook_GetLocalizedStringByToken)obj; }); log.LogInfo((object)"Acrid changes ENABLED: spawn protection, non-Poisonous Vicious Wounds finisher, 8s Blight with 0.1 proc per stack/capped 1.0 per tick, Neurotoxin cooldown 2.5s, one-charge Poisonous Frenzied Leap, and Cloying Breath Poison every tick or Blight on ticks 1/5/9 with no bonus roll."); } catch (Exception error) { Fail(error); } } private void Add(Action install, Action remove) { install(); cleanup.Add(remove); } private void Fail(Exception error) { Dispose(); log.LogError((object)$"Acrid setup failed; restored its values and removed its hooks. {error}"); } public void Dispose() { if (NetworkServer.active) { foreach (CharacterBody value in protectedSpawns.Values) { if (Object.op_Implicit((Object)(object)value)) { value.RemoveBuff(Buffs.HiddenInvincibility); } } } protectedSpawns.Clear(); if ((Object)(object)neurotoxin != (Object)null) { neurotoxin.baseRechargeInterval = originalNeurotoxinCooldown; } if ((Object)(object)frenziedLeap != (Object)null) { frenziedLeap.baseMaxStock = originalFrenziedLeapStock; frenziedLeap.baseRechargeInterval = originalFrenziedLeapCooldown; } neurotoxin = null; frenziedLeap = null; breathProjectilePrefab = null; breathProjectileSetupDepth = 0; breathTicks = new ConditionalWeakTable<ProjectileController, ConditionalWeakTable<HealthComponent, BreathTickSequence>>(); for (int num = cleanup.Count - 1; num >= 0; num--) { try { cleanup[num](); } catch (Exception arg) { log.LogError((object)$"Acrid hook cleanup failed: {arg}"); } } cleanup.Clear(); } private void SkillDefs(orig_SetSkillDefs orig, SkillDef[] skillDefs) { try { if ((Object)(object)neurotoxin == (Object)null || (Object)(object)frenziedLeap == (Object)null) { SkillDef val = skillDefs.Single((SkillDef s) => s.skillNameToken == "CROCO_SECONDARY_NAME"); SkillDef val2 = skillDefs.Single((SkillDef s) => s.skillNameToken == "CROCO_UTILITY_ALT1_NAME"); originalNeurotoxinCooldown = val.baseRechargeInterval; originalFrenziedLeapStock = val2.baseMaxStock; originalFrenziedLeapCooldown = val2.baseRechargeInterval; neurotoxin = val; frenziedLeap = val2; val.baseRechargeInterval = 2.5f; val2.baseMaxStock = 1; val2.baseRechargeInterval = 8f; } } catch (Exception error) { Fail(error); } orig.Invoke(skillDefs); } private void Projectiles(orig_SetProjectilePrefabs orig, GameObject[] prefabs) { try { if (!Object.op_Implicit((Object)(object)breathProjectilePrefab)) { GameObject val = prefabs.Single((GameObject p) => ((Object)p).name == "CrocoBreathProjectile"); if (!Object.op_Implicit((Object)(object)val.GetComponent<ProjectileController>()) || !Object.op_Implicit((Object)(object)val.GetComponent<ProjectileDotZone>())) { throw new InvalidOperationException("Cloying Breath's projectile layout changed."); } breathProjectilePrefab = val; } } catch (Exception error) { Fail(error); } orig.Invoke(prefabs); } private static void BlightDuration(orig_InflictDot_refInflictDotInfo orig, ref InflictDotInfo info) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)info.dotIndex == 5) { info.duration = 8f; } orig.Invoke(ref info); } private void BlightTick(orig_EvaluateDotStacksForType orig, DotController self, DotIndex index, float deltaTime, out int remainingActive) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Invalid comparison between Unknown and I4 //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_00ba: Unknown result type (might be due to invalid IL or missing references) if (!NetworkServer.active || (int)index != 5) { orig.Invoke(self, index, deltaTime, ref remainingActive); return; } IEnumerable obj = (IEnumerable)dotStacksField.GetValue(self); BlightTickContext blightTickContext = new BlightTickContext(((Component)self).gameObject); foreach (object item in obj) { if ((int)(DotIndex)stackIndexField.GetValue(item) == 5) { GameObject val = (GameObject)stackAttackerField.GetValue(item); if (Object.op_Implicit((Object)(object)val)) { blightTickContext.budget.AddStack(val); } else { blightTickContext.budget.AddUnattributedStack(); } } } BlightTickContext blightTickContext2 = activeBlightTick; activeBlightTick = blightTickContext; try { orig.Invoke(self, index, deltaTime, ref remainingActive); } finally { activeBlightTick = blightTickContext2; } } private static void BlightDamage(orig_TakeDamage orig, HealthComponent self, DamageInfo info) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Invalid comparison between Unknown and I4 BlightTickContext blightTickContext = activeBlightTick; int num; if (NetworkServer.active && blightTickContext != null && (int)info.dotIndex == 5) { num = (((Object)(object)info.inflictor == (Object)(object)blightTickContext.controllerObject) ? 1 : 0); if (num != 0 && Object.op_Implicit((Object)(object)info.attacker)) { info.procCoefficient = blightTickContext.budget.TakeProc(info.attacker); } } else { num = 0; } orig.Invoke(self, info); if (num != 0 && !info.rejected && Object.op_Implicit((Object)(object)info.attacker) && info.procCoefficient > 0f && Object.op_Implicit((Object)(object)GlobalEventManager.instance)) { GlobalEventManager.instance.OnHitEnemy(info, ((Component)self).gameObject); GlobalEventManager.instance.OnHitAll(info, ((Component)self).gameObject); } } private void ProtectSpawn(orig_OnEnter orig, Spawn self) { orig.Invoke(self); CharacterBody val = (Object.op_Implicit((Object)(object)((EntityState)self).outer) ? ((Component)((EntityState)self).outer).GetComponent<CharacterBody>() : null); if (NetworkServer.active && Object.op_Implicit((Object)(object)val) && !protectedSpawns.ContainsKey(self)) { val.AddBuff(Buffs.HiddenInvincibility); protectedSpawns.Add(self, val); } } private void EndSpawnProtection(orig_OnExit orig, Spawn self) { if (protectedSpawns.TryGetValue(self, out CharacterBody value)) { protectedSpawns.Remove(self); if (NetworkServer.active && Object.op_Implicit((Object)(object)value)) { value.RemoveBuff(Buffs.HiddenInvincibility); if (Object.op_Implicit((Object)(object)value.healthComponent) && value.healthComponent.alive) { value.AddTimedBuff(Buffs.HiddenInvincibility, 2f); } } } orig.Invoke(self); } private static DamageTypeCombo FrenziedLeapDamageType(orig_GetBlastDamageType orig, ChainableLeap self) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) DamageTypeCombo val = orig.Invoke(self); CrocoDamageTypeController component = ((Component)((EntityState)self).outer).GetComponent<CrocoDamageTypeController>(); if (Object.op_Implicit((Object)(object)component)) { val |= component.GetDamageType(); } return val; } private static void BreathProjectile(orig_FireProjectile orig, Breath self) { breathProjectileSetupDepth++; try { orig.Invoke(self); } finally { breathProjectileSetupDepth--; } } private static DamageTypeCombo CrocoDamageType(orig_GetDamageType orig, CrocoDamageTypeController self) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) if (breathProjectileSetupDepth <= 0) { return orig.Invoke(self); } return DamageTypeCombo.op_Implicit((DamageType)0); } private void DamageDealt(DamageReport report) { //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) if (!NetworkServer.active || !Object.op_Implicit((Object)(object)breathProjectilePrefab) || report.damageDealt <= 0f || report.damageInfo.rejected || !Object.op_Implicit((Object)(object)report.victimBody) || !Object.op_Implicit((Object)(object)report.attacker)) { return; } ProjectileController val = (Object.op_Implicit((Object)(object)report.damageInfo.inflictor) ? report.damageInfo.inflictor.GetComponent<ProjectileController>() : null); GameObject val2 = breathProjectilePrefab; if (val == null || !Object.op_Implicit((Object)(object)val) || (Object)(object)ProjectileCatalog.GetProjectilePrefab(val.catalogIndex) != (Object)(object)val2) { return; } CrocoDamageTypeController component = report.attacker.GetComponent<CrocoDamageTypeController>(); if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.passiveSkillSlot)) { bool flag = (Object)(object)component.passiveSkillSlot.skillDef == (Object)(object)component.blightSkillDef; if (!flag || breathTicks.GetValue(val, (ProjectileController _) => new ConditionalWeakTable<HealthComponent, BreathTickSequence>()).GetValue(report.victim, (HealthComponent _) => new BreathTickSequence()).NextAppliesBlight()) { InflictDotInfo val3 = new InflictDotInfo { victimObject = ((Component)report.victimBody).gameObject, attackerObject = report.attacker, dotIndex = (DotIndex)(flag ? 5 : 4), duration = (flag ? 8f : 10f), damageMultiplier = 1f }; DotController.InflictDot(ref val3); } } } private static string Description(orig_GetLocalizedStringByToken orig, Language self, string token) { return AcridBalance.GetDescription(token) ?? orig.Invoke(self, token); } } internal sealed class AfterDamageQueue<T> { private readonly Queue<T> pending = new Queue<T>(); private int depth; private bool draining; internal void Enter() { depth++; } internal void Enqueue(T hit) { pending.Enqueue(hit); } internal void Clear() { pending.Clear(); } internal void Exit(Action<T> apply) { if (--depth != 0 || draining) { return; } draining = true; try { while (pending.Count > 0) { apply(pending.Dequeue()); } } finally { draining = false; } } } internal static class ArtificerBalance { internal const float BaseAcceleration = 60f; internal const float PlasmaDamage = 3.1f; internal const float SnapfreezeDamage = 3f; internal const float SlowDuration = 2f; internal const float LaunchSpeed = 7f; internal const float FlameRange = 30f; internal const float FlameLengthScale = 1.5f; internal static void PatchWallDamage(MethodBody body) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) Instruction[] array = ((IEnumerable<Instruction>)body.Instructions).Where(delegate(Instruction i) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (i.OpCode == OpCodes.Ldsfld) { object operand = i.Operand; FieldReference val = (FieldReference)((operand is FieldReference) ? operand : null); if (val != null && ((MemberReference)((MemberReference)val).DeclaringType).FullName == "EntityStates.Mage.Weapon.PrepWall") { return ((MemberReference)val).Name == "damageCoefficient"; } } return false; }).ToArray(); if (array.Length != 2) { throw new InvalidOperationException("Snapfreeze's two wall damage reads changed."); } Instruction[] array2 = array; foreach (Instruction obj in array2) { obj.OpCode = OpCodes.Ldc_R4; obj.Operand = 3f; } } internal static float CappedLaunchSpeed(float moveSpeed) { return Math.Max(0f, Math.Min(14f, moveSpeed)); } internal static float TectonicPushMultiplier(float aimY) { double num = (1.0 - (double)Math.Max(-1f, Math.Min(1f, aimY))) / 2.0; return (float)(1.1571428571428573 * (1.0 - Math.Pow(20.25, 0.0 - num))); } internal static float FrozenExecuteFraction(string bodyName) { switch (bodyName) { case "BrotherBody": case "BrotherHurtBody": case "FalseSonBossBody": case "FalseSonBossBodyLunarShard": case "FalseSonBossBodyBrokenLunarShard": return 0.1f; default: return 0.3f; } } internal static Instruction TectonicPushSite(MethodBody body) { Instruction[] array = ((IEnumerable<Instruction>)body.Instructions).Where(delegate(Instruction i) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (i.OpCode == OpCodes.Ldsfld) { object operand2 = i.Operand; FieldReference val2 = (FieldReference)((operand2 is FieldReference) ? operand2 : null); if (val2 != null && ((MemberReference)((MemberReference)val2).DeclaringType).FullName == "EntityStates.Mage.Weapon.FireEarthShards") { return ((MemberReference)val2).Name == "selfKnockbackSpeed"; } } return false; }).ToArray(); if (array.Length == 1) { object operand = array[0].Next.Operand; MethodReference val = (MethodReference)((operand is MethodReference) ? operand : null); if (val != null && !(((MemberReference)val).Name != "op_Multiply")) { return array[0]; } } throw new InvalidOperationException("Tectonic Blast self-knockback layout changed."); } internal static Instruction[] FrozenExecuteSites(MethodBody body, bool healthBar) { Instruction[] array = body.Instructions.ToArray(); int num = Array.FindIndex(array, delegate(Instruction i) { object operand = i.Operand; MethodReference val = (MethodReference)((operand is MethodReference) ? operand : null); return val != null && ((MemberReference)val).Name == "get_isInFrozenState"; }); int num2 = Array.FindIndex(array, Math.Max(0, num), delegate(Instruction i) { object operand = i.Operand; FieldReference val = (FieldReference)((operand is FieldReference) ? operand : null); return val != null && ((!healthBar) ? (((MemberReference)((MemberReference)val).DeclaringType).FullName == "EntityStates.FrozenState" && ((MemberReference)val).Name == "executeEffectPrefab") : (((MemberReference)val).Name == "cullFraction")); }); if (num < 0 || num2 <= num) { throw new InvalidOperationException("Frozen execution block was not found."); } Instruction[] array2 = (from i in array.Skip(num).Take(num2 - num) where i.OpCode == OpCodes.Ldc_R4 && (float)i.Operand == 0.3f select i).ToArray(); if (array2.Length != (healthBar ? 1 : 2)) { throw new InvalidOperationException("Frozen execution threshold layout changed."); } return array2; } internal static string? GetDescription(string token) { return token switch { "MAGE_PRIMARY_LIGHTNING_DESCRIPTION" => "<style=cIsUtility>Rapid</style>. Fire a bolt for <style=cIsDamage><color=#C586FF><b>310%</b></color> damage</style> that <style=cIsDamage>explodes</style> in a small area. Hold up to 4. <color=#C586FF><b>Direct and splash hits slow enemies by 30% for 2 seconds.</b></color>", "MAGE_UTILITY_ICE_DESCRIPTION" => "<style=cIsUtility>Freezing</style>. Create a barrier that hurts enemies for <style=cIsDamage><color=#C586FF><b>300%</b></color> damage</style>. <color=#C586FF><b>Special slot.</b></color>", "MAGE_SPECIAL_LIGHTNING_DESCRIPTION" => "<style=cIsDamage>Stunning</style>. Burst into the sky, dealing <style=cIsDamage>800% damage</style>. <color=#C586FF><b>Utility slot. Launch distance scales with movement speed, capped at twice the vanilla base distance.</b></color>", "MAGE_SPECIAL_FIRE_DESCRIPTION" => "<style=cIsDamage>Ignite</style>. Burn all enemies in front of you for <style=cIsDamage>2000% damage</style>. <color=#C586FF><b>Reaches 30 meters; hand effects extend forward by 50%.</b></color>", "MAGE_UTILITY_ALT_DESCRIPTION" => "Fire a spread of shards that deal <style=cIsDamage>8x100% damage</style> and <style=cIsUtility>oil</style> enemies. <color=#C586FF><b>Aiming downward provides more aerial knockback.</b></color>", "MAGE_SECONDARY_ICE_DESCRIPTION" => "<style=cIsUtility>Freezing</style>. Charge up a <style=cIsDamage>piercing</style> nano-spear that deals <style=cIsDamage>400%-1200%</style> damage. <color=#C586FF><b>Frozen Mithrix and False Son bosses execute below 10% health; other enemies retain the 30% threshold.</b></color>", "KEYWORD_FREEZING" => "<style=cKeywordName>Freezing</style><style=cSub>Freeze enemies in place. Frozen enemies are <style=cIsHealth>instantly killed</style> if below <style=cIsHealth>30%</style> health.</style> <color=#C586FF><b>Frozen Mithrix and False Son bosses execute below 10% health; other enemies retain the 30% threshold.</b></color>", _ => null, }; } internal static void PatchWallInput(MethodBody body) { ReplaceField(body, "RoR2.InputBankTest", "skill3", "skill4"); } internal static void PatchWallRefund(MethodBody body) { ReplaceField(body, "RoR2.SkillLocator", "utility", "special"); } private static void ReplaceField(MethodBody body, string type, string from, string to) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected O, but got Unknown Instruction[] array = ((IEnumerable<Instruction>)body.Instructions).Where(delegate(Instruction i) { object operand = i.Operand; FieldReference val2 = (FieldReference)((operand is FieldReference) ? operand : null); return val2 != null && ((MemberReference)((MemberReference)val2).DeclaringType).FullName == type && ((MemberReference)val2).Name == from; }).ToArray(); if (array.Length != 1) { throw new InvalidOperationException($"Expected one {type}.{from}, found {array.Length}."); } FieldReference val = (FieldReference)array[0].Operand; array[0].Operand = (object)new FieldReference(to, val.FieldType, ((MemberReference)val).DeclaringType); } internal static Instruction LaunchSpeedSite(MethodBody body) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) Instruction[] array = ((IEnumerable<Instruction>)body.Instructions).Where(delegate(Instruction i) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (i.OpCode == OpCodes.Ldfld) { object operand = i.Operand; FieldReference val = (FieldReference)((operand is FieldReference) ? operand : null); if (val != null) { return ((MemberReference)val).Name == "moveSpeedStat"; } } return false; }).ToArray(); if (array.Length != 1 || array[0].Previous.OpCode != OpCodes.Ldarg_0) { throw new InvalidOperationException("Ion Surge movement layout changed."); } return array[0]; } internal static void PatchLaunchSource(MethodBody body) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) Instruction[] array = ((IEnumerable<Instruction>)body.Instructions).Where(delegate(Instruction i) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (i.OpCode == OpCodes.Stfld) { object operand = i.Operand; FieldReference val = (FieldReference)((operand is FieldReference) ? operand : null); if (val != null) { return ((MemberReference)val).FullName == "RoR2.DamageSource RoR2.DamageTypeCombo::damageSource"; } } return false; }).ToArray(); if (array.Length != 1 || array[0].Previous.OpCode != OpCodes.Ldc_I4_8) { throw new InvalidOperationException("Ion Surge damage source layout changed."); } array[0].Previous.OpCode = OpCodes.Ldc_I4_4; } } internal sealed class ArtificerChanges : IDisposable { [CompilerGenerated] private static class <>O { public static Manipulator <0>__TectonicPush; public static Manipulator <1>__WallInput; public static Manipulator <2>__WallRefund; public static Manipulator <3>__LaunchSpeed; public static Manipulator <4>__LaunchSource; public static Manipulator <5>__FlameVisuals; public static hook_OnEnter <6>__FlameEnter; public static hook_ModifyProjectileInfo <7>__Plasma; public static Action<DamageReport> <8>__Slow; public static hook_GetLocalizedStringByToken <9>__Description; public static Func<float, float> <10>__CappedLaunchSpeed; public static Func<GameObject, GameObject> <11>__ExtendFlame; } private readonly ManualLogSource log; private readonly List<Action> cleanup = new List<Action>(); private SkillFamily? utility; private SkillFamily? special; private Variant[]? originalUtility; private Variant[]? originalSpecial; private ProjectileDamage? wallDamage; private DamageTypeCombo originalWallDamageType; private CharacterBody? artificerBody; private float originalAcceleration; internal ArtificerChanges(ManualLogSource log) { this.log = log; } internal void Enable() { try { Add(delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown BodyCatalog.SetBodyPrefabs += new hook_SetBodyPrefabs(Bodies); }, delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown BodyCatalog.SetBodyPrefabs -= new hook_SetBodyPrefabs(Bodies); }); Add(delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<0>__TectonicPush; if (obj == null) { Manipulator val = TectonicPush; <>O.<0>__TectonicPush = val; obj = (object)val; } FireEarthShards.PlayAttackEffect += (Manipulator)obj; }, delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<0>__TectonicPush; if (obj == null) { Manipulator val = TectonicPush; <>O.<0>__TectonicPush = val; obj = (object)val; } FireEarthShards.PlayAttackEffect -= (Manipulator)obj; }); cleanup.Add(SharedFreezeChanges.Acquire().Dispose); Add(delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<1>__WallInput; if (obj == null) { Manipulator val = WallInput; <>O.<1>__WallInput = val; obj = (object)val; } PrepWall.FixedUpdate += (Manipulator)obj; }, delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<1>__WallInput; if (obj == null) { Manipulator val = WallInput; <>O.<1>__WallInput = val; obj = (object)val; } PrepWall.FixedUpdate -= (Manipulator)obj; }); Add(delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<2>__WallRefund; if (obj == null) { Manipulator val = WallRefund; <>O.<2>__WallRefund = val; obj = (object)val; } PrepWall.OnExit += (Manipulator)obj; }, delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<2>__WallRefund; if (obj == null) { Manipulator val = WallRefund; <>O.<2>__WallRefund = val; obj = (object)val; } PrepWall.OnExit -= (Manipulator)obj; }); Add(delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<3>__LaunchSpeed; if (obj == null) { Manipulator val = LaunchSpeed; <>O.<3>__LaunchSpeed = val; obj = (object)val; } FlyUpState.HandleMovements += (Manipulator)obj; }, delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<3>__LaunchSpeed; if (obj == null) { Manipulator val = LaunchSpeed; <>O.<3>__LaunchSpeed = val; obj = (object)val; } FlyUpState.HandleMovements -= (Manipulator)obj; }); Add(delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<4>__LaunchSource; if (obj == null) { Manipulator val = LaunchSource; <>O.<4>__LaunchSource = val; obj = (object)val; } FlyUpState.OnEnter += (Manipulator)obj; }, delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<4>__LaunchSource; if (obj == null) { Manipulator val = LaunchSource; <>O.<4>__LaunchSource = val; obj = (object)val; } FlyUpState.OnEnter -= (Manipulator)obj; }); Add(delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<5>__FlameVisuals; if (obj == null) { Manipulator val = FlameVisuals; <>O.<5>__FlameVisuals = val; obj = (object)val; } Flamethrower.FixedUpdate += (Manipulator)obj; }, delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<5>__FlameVisuals; if (obj == null) { Manipulator val = FlameVisuals; <>O.<5>__FlameVisuals = val; obj = (object)val; } Flamethrower.FixedUpdate -= (Manipulator)obj; }); Add(delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<6>__FlameEnter; if (obj == null) { hook_OnEnter val = FlameEnter; <>O.<6>__FlameEnter = val; obj = (object)val; } Flamethrower.OnEnter += (hook_OnEnter)obj; }, delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<6>__FlameEnter; if (obj == null) { hook_OnEnter val = FlameEnter; <>O.<6>__FlameEnter = val; obj = (object)val; } Flamethrower.OnEnter -= (hook_OnEnter)obj; }); Add(delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<7>__Plasma; if (obj == null) { hook_ModifyProjectileInfo val = Plasma; <>O.<7>__Plasma = val; obj = (object)val; } FireLightningBolt.ModifyProjectileInfo += (hook_ModifyProjectileInfo)obj; }, delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<7>__Plasma; if (obj == null) { hook_ModifyProjectileInfo val = Plasma; <>O.<7>__Plasma = val; obj = (object)val; } FireLightningBolt.ModifyProjectileInfo -= (hook_ModifyProjectileInfo)obj; }); Add(delegate { GlobalEventManager.onServerDamageDealt += Slow; }, delegate { GlobalEventManager.onServerDamageDealt -= Slow; }); Add(delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown SkillCatalog.SetSkillFamilies += new hook_SetSkillFamilies(SwapSkills); }, delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown SkillCatalog.SetSkillFamilies -= new hook_SetSkillFamilies(SwapSkills); }); Add(delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown ProjectileCatalog.SetProjectilePrefabs += new hook_SetProjectilePrefabs(WallDamageSource); }, delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown ProjectileCatalog.SetProjectilePrefabs -= new hook_SetProjectilePrefabs(WallDamageSource); }); Add(delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<9>__Description; if (obj == null) { hook_GetLocalizedStringByToken val = Description; <>O.<9>__Description = val; obj = (object)val; } Language.GetLocalizedStringByToken += (hook_GetLocalizedStringByToken)obj; }, delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<9>__Description; if (obj == null) { hook_GetLocalizedStringByToken val = Description; <>O.<9>__Description = val; obj = (object)val; } Language.GetLocalizedStringByToken -= (hook_GetLocalizedStringByToken)obj; }); log.LogInfo((object)"Artificer changes ENABLED: acceleration 60; Plasma Bolt 310%/30% slow for 2s, Snapfreeze Special/300% damage, Ion Surge Utility/move-speed scaling capped at 2x base distance, Flamethrower 30m, aim-scaled Tectonic Blast push, Mithrix/False Son boss freeze execution 10%."); } catch (Exception arg) { Dispose(); log.LogError((object)$"Could not enable the full Artificer patch; removed its hooks. {arg}"); } } private void Add(Action install, Action remove) { cleanup.Add(remove); install(); } public void Dispose() { //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)artificerBody)) { artificerBody.baseAcceleration = originalAcceleration; } artificerBody = null; if ((Object)(object)utility != (Object)null && originalUtility != null) { utility.variants = originalUtility; } if ((Object)(object)special != (Object)null && originalSpecial != null) { special.variants = originalSpecial; } if ((Object)(object)wallDamage != (Object)null) { wallDamage.damageType = originalWallDamageType; } wallDamage = null; originalUtility = (originalSpecial = null); for (int num = cleanup.Count - 1; num >= 0; num--) { try { cleanup[num](); } catch (Exception ex) { log.LogError((object)ex); } } cleanup.Clear(); } private static void WallInput(ILContext il) { ArtificerBalance.PatchWallInput(il.Body); } private static void WallRefund(ILContext il) { ArtificerBalance.PatchWallRefund(il.Body); ArtificerBalance.PatchWallDamage(il.Body); } private static void LaunchSpeed(ILContext il) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) ILCursor val = new ILCursor(il); val.Goto(ArtificerBalance.LaunchSpeedSite(il.Body), (MoveType)2, false); val.EmitDelegate<Func<float, float>>((Func<float, float>)ArtificerBalance.CappedLaunchSpeed); } private static void LaunchSource(ILContext il) { ArtificerBalance.PatchLaunchSource(il.Body); } private static void TectonicPush(ILContext il) { //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_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) FieldReference val = ((IEnumerable<Instruction>)il.Body.Instructions).Select((Instruction i) => i.Operand).OfType<FieldReference>().First((FieldReference f) => ((MemberReference)((MemberReference)f).DeclaringType).FullName == "EntityStates.Mage.Weapon.FireEarthShards" && ((MemberReference)f).Name == "aimVector"); ILCursor val2 = new ILCursor(il); val2.Goto(ArtificerBalance.TectonicPushSite(il.Body), (MoveType)2, false); val2.Emit(OpCodes.Ldarg_0); val2.Emit(OpCodes.Ldfld, val); val2.EmitDelegate<Func<float, Vector3, float>>((Func<float, Vector3, float>)((float speed, Vector3 direction) => speed * ArtificerBalance.TectonicPushMultiplier(direction.y))); } private void Bodies(orig_SetBodyPrefabs orig, GameObject[] prefabs) { try { if (!Object.op_Implicit((Object)(object)artificerBody)) { CharacterBody component = prefabs.Single((GameObject p) => ((Object)p).name == "MageBody").GetComponent<CharacterBody>(); if (!Object.op_Implicit((Object)(object)component)) { throw new InvalidOperationException("Artificer's body prefab was not found."); } originalAcceleration = component.baseAcceleration; artificerBody = component; component.baseAcceleration = 60f; } } catch (Exception arg) { Dispose(); log.LogError((object)$"Artificer stat patch failed; disabled Artificer changes. {arg}"); } orig.Invoke(prefabs); } private void SwapSkills(orig_SetSkillFamilies orig, SkillFamily[] families) { //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0102: 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) try { if (originalUtility == null) { SkillFamily val = families.Single((SkillFamily f) => ((Object)f).name == "MageBodyUtilityFamily"); SkillFamily val2 = families.Single((SkillFamily f) => ((Object)f).name == "MageBodySpecialFamily"); int num = Array.FindIndex(val.variants, (Variant v) => v.skillDef.skillNameToken == "MAGE_UTILITY_ICE_NAME"); int num2 = Array.FindIndex(val2.variants, (Variant v) => v.skillDef.skillNameToken == "MAGE_SPECIAL_LIGHTNING_NAME"); if (num < 0 || num2 < 0) { throw new InvalidOperationException("Artificer's original skill variants were not found."); } Variant[] array = (Variant[])val.variants.Clone(); Variant[] array2 = (Variant[])val2.variants.Clone(); array[num] = val2.variants[num2]; array2[num2] = val.variants[num]; utility = val; special = val2; originalUtility = val.variants; originalSpecial = val2.variants; val.variants = array; val2.variants = array2; log.LogInfo((object)"Artificer skill slots swapped; other variants and unlock requirements preserved."); } } catch (Exception arg) { Dispose(); log.LogError((object)$"Artificer skill swap failed; disabled Artificer changes. {arg}"); } orig.Invoke(families); } private void WallDamageSource(orig_SetProjectilePrefabs orig, GameObject[] prefabs) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)wallDamage == (Object)null) { ProjectileDamage component = prefabs.Single((GameObject p) => ((Object)p).name == "MageIcewallPillarProjectile").GetComponent<ProjectileDamage>(); if (!Object.op_Implicit((Object)(object)component)) { throw new InvalidOperationException("Snapfreeze projectile damage was not found."); } originalWallDamageType = component.damageType; wallDamage = component; component.damageType.damageSource = (DamageSource)8; } } catch (Exception arg) { Dispose(); log.LogError((object)$"Artificer projectile patch failed; disabled Artificer changes. {arg}"); } orig.Invoke(prefabs); } private static void Plasma(orig_ModifyProjectileInfo orig, FireLightningBolt self, ref FireProjectileInfo info) { orig.Invoke(self, ref info); CharacterBody component = ((Component)((EntityState)self).outer).GetComponent<CharacterBody>(); if (Object.op_Implicit((Object)(object)component)) { info.damage = component.damage * 3.1f; } } private static void Slow(DamageReport report) { if (!NetworkServer.active || !Object.op_Implicit((Object)(object)report.victimBody) || report.damageInfo.rejected || !Object.op_Implicit((Object)(object)report.damageInfo.inflictor)) { return; } ProjectileController component = report.damageInfo.inflictor.GetComponent<ProjectileController>(); if (Object.op_Implicit((Object)(object)component) && component.catalogIndex >= 0) { GameObject projectilePrefab = ProjectileCatalog.GetProjectilePrefab(component.catalogIndex); if (Object.op_Implicit((Object)(object)projectilePrefab) && ((Object)projectilePrefab).name == "MageLightningboltBasic") { report.victimBody.AddTimedBuff(Buffs.Slow30, 2f); } } } private static void FlameEnter(orig_OnEnter orig, Flamethrower self) { self.maxDistance = 30f; orig.Invoke(self); } private static void FlameVisuals(ILContext il) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) Instruction[] array = ((IEnumerable<Instruction>)il.Body.Instructions).Where(delegate(Instruction i) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (i.OpCode == OpCodes.Stfld) { object operand = i.Operand; FieldReference val3 = (FieldReference)((operand is FieldReference) ? operand : null); if (val3 != null) { if (!(((MemberReference)val3).Name == "leftFlamethrowerEffectInstance")) { return ((MemberReference)val3).Name == "rightFlamethrowerEffectInstance"; } return true; } } return false; }).ToArray(); if (array.Length != 2 || array.Any(delegate(Instruction i) { object operand = i.Previous.Operand; MethodReference val3 = (MethodReference)((operand is MethodReference) ? operand : null); return val3 == null || ((MemberReference)val3).Name != "Instantiate"; })) { throw new InvalidOperationException("Flamethrower effect creation layout changed."); } Instruction[] array2 = array; foreach (Instruction val in array2) { ILCursor val2 = new ILCursor(il); val2.Goto(val, (MoveType)0, false); val2.EmitDelegate<Func<GameObject, GameObject>>((Func<GameObject, GameObject>)ExtendFlame); } } private static GameObject ExtendFlame(GameObject effect) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)effect)) { return effect; } Vector3 localScale = effect.transform.localScale; localScale.z *= 1.5f; effect.transform.localScale = localScale; ParticleSystem[] componentsInChildren = effect.GetComponentsInChildren<ParticleSystem>(true); for (int i = 0; i < componentsInChildren.Length; i++) { MainModule main = componentsInChildren[i].main; ((MainModule)(ref main)).scalingMode = (ParticleSystemScalingMode)0; } return effect; } private static string Description(orig_GetLocalizedStringByToken orig, Language self, string token) { return ArtificerBalance.GetDescription(token) ?? orig.Invoke(self, token); } } internal static class BanditBalance { internal const int BlastBaseCharges = 6; internal const float BlastMinimumBaseInterval = 0.3f; internal const float BlastSpreadMultiplier = 0.5f; internal const float BlastBloomMultiplier = 0.5f; internal const float BlastRadiusMultiplier = 1.2f; internal const float StockPipSpacing = 8f; internal static float GetStockPipX(int pipIndex, int activeStockCount) { int num = Math.Max(1, Math.Min(activeStockCount, 6)); return ((float)pipIndex - (float)(num - 1) * 0.5f) * 8f; } internal static string? GetDescription(string token) { if (token == "BANDIT2_PRIMARY_ALT_DESCRIPTION") { return "Fire a rifle blast for <style=cIsDamage>330% damage</style>. Can hold up to <color=#C586FF><b>6 bullets</b></color>. <color=#C586FF><b>Pierces enemies, stopping at terrain. Shot radius is 20% larger. Spread and bloom are reduced by 50%. Fires at most once every 0.3 seconds, independent of attack speed, reloads and skill interrupts.</b></color>"; } return null; } } internal sealed class BlastShotClock { private float nextShot = float.NegativeInfinity; internal bool CanFire(float now) { return now >= nextShot; } internal void RecordShot(float now) { nextShot = now + 0.3f; } } internal sealed class BanditChanges : IDisposable { [CompilerGenerated] private static class <>O { public static hook_OnEnter <0>__FireInterval; public static hook_ModifyBullet <1>__ReduceSpread; public static hook_GetLocalizedStringByToken <2>__Description; } private readonly ManualLogSource log; private readonly List<Action> cleanup = new List<Action>(); private readonly ConditionalWeakTable<CrosshairController, Transform[]> stockPipLayouts = new ConditionalWeakTable<CrosshairController, Transform[]>(); private SkillDef? rifleSkill; private int originalMaxStock; private ConditionalWeakTable<CharacterBody, BlastShotClock> shotClocks = new ConditionalWeakTable<CharacterBody, BlastShotClock>(); internal BanditChanges(ManualLogSource log) { this.log = log; } internal void Enable() { try { Add(delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown SkillCatalog.SetSkillDefs += new hook_SetSkillDefs(SkillDefs); }, delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown SkillCatalog.SetSkillDefs -= new hook_SetSkillDefs(SkillDefs); }); Add(delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<0>__FireInterval; if (obj == null) { hook_OnEnter val = FireInterval; <>O.<0>__FireInterval = val; obj = (object)val; } Bandit2FirePrimaryBase.OnEnter += (hook_OnEnter)obj; }, delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<0>__FireInterval; if (obj == null) { hook_OnEnter val = FireInterval; <>O.<0>__FireInterval = val; obj = (object)val; } Bandit2FirePrimaryBase.OnEnter -= (hook_OnEnter)obj; }); Add(delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown GenericSkill.CanExecute += new hook_CanExecute(CanFireBlast); }, delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown GenericSkill.CanExecute -= new hook_CanExecute(CanFireBlast); }); Add(delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown GenericBulletBaseState.FireBullet += new hook_FireBullet(RecordBlastShot); }, delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown GenericBulletBaseState.FireBullet -= new hook_FireBullet(RecordBlastShot); }); Add(delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<1>__ReduceSpread; if (obj == null) { hook_ModifyBullet val = ReduceSpread; <>O.<1>__ReduceSpread = val; obj = (object)val; } Bandit2FireRifle.ModifyBullet += (hook_ModifyBullet)obj; }, delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<1>__ReduceSpread; if (obj == null) { hook_ModifyBullet val = ReduceSpread; <>O.<1>__ReduceSpread = val; obj = (object)val; } Bandit2FireRifle.ModifyBullet -= (hook_ModifyBullet)obj; }); Add(delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown CrosshairController.Awake += new hook_Awake(ExpandBanditStockDisplay); }, delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown CrosshairController.Awake -= new hook_Awake(ExpandBanditStockDisplay); }); Add(delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown CrosshairController.LateUpdate += new hook_LateUpdate(CenterBanditStockPips); }, delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown CrosshairController.LateUpdate -= new hook_LateUpdate(CenterBanditStockPips); }); Add(delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<2>__Description; if (obj == null) { hook_GetLocalizedStringByToken val = Description; <>O.<2>__Description = val; obj = (object)val; } Language.GetLocalizedStringByToken += (hook_GetLocalizedStringByToken)obj; }, delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<2>__Description; if (obj == null) { hook_GetLocalizedStringByToken val = Description; <>O.<2>__Description = val; obj = (object)val; } Language.GetLocalizedStringByToken -= (hook_GetLocalizedStringByToken)obj; }); log.LogInfo((object)"Bandit changes ENABLED: Blast has 6 rounds, a 0.3s minimum firing interval, 50% lower spread and bloom, 20% larger shot radius and enemy piercing."); } catch (Exception arg) { Dispose(); log.LogError((object)$"Could not enable the full Bandit patch; removed its hooks. {arg}"); } } private void Add(Action install, Action remove) { cleanup.Add(remove); install(); } public void Dispose() { if ((Object)(object)rifleSkill != (Object)null) { rifleSkill.baseMaxStock = originalMaxStock; } rifleSkill = null; for (int num = cleanup.Count - 1; num >= 0; num--) { try { cleanup[num](); } catch (Exception ex) { log.LogError((object)ex); } } cleanup.Clear(); shotClocks = new ConditionalWeakTable<CharacterBody, BlastShotClock>(); } private void SkillDefs(orig_SetSkillDefs orig, SkillDef[] skillDefs) { try { if ((Object)(object)rifleSkill == (Object)null) { SkillDef val = Array.Find(skillDefs, (SkillDef s) => s.skillNameToken == "BANDIT2_PRIMARY_ALT_NAME"); if (!Object.op_Implicit((Object)(object)val)) { throw new InvalidOperationException("Bandit Blast's rifle SkillDef was not found."); } rifleSkill = val; originalMaxStock = val.baseMaxStock; val.baseMaxStock = 6; } } catch (Exception arg) { Dispose(); log.LogError((object)$"Bandit stock patch failed; disabled Bandit changes. {arg}"); } orig.Invoke(skillDefs); } private static void FireInterval(orig_OnEnter orig, Bandit2FirePrimaryBase self) { if (((object)self).GetType() == typeof(Bandit2FireRifle)) { ((GenericBulletBaseState)self).spreadBloomValue = ((GenericBulletBaseState)self).spreadBloomValue * 0.5f; } orig.Invoke(self); } private bool CanFireBlast(orig_CanExecute orig, GenericSkill self) { CharacterBody characterBody = self.characterBody; if ((Object)(object)self.skillDef == (Object)(object)rifleSkill && Object.op_Implicit((Object)(object)characterBody) && shotClocks.TryGetValue(characterBody, out BlastShotClock value) && !value.CanFire(Time.fixedTime)) { return false; } return orig.Invoke(self); } private void RecordBlastShot(orig_FireBullet orig, GenericBulletBaseState self, Ray ray) { //IL_0096: Unknown result type (might be due to invalid IL or missing references) if (((object)self).GetType() == typeof(Bandit2FireRifle) && Object.op_Implicit((Object)(object)((EntityState)self).outer)) { CharacterBody component = ((Component)((EntityState)self).outer).GetComponent<CharacterBody>(); if (component != null && component.hasEffectiveAuthority) { CharacterBody component2 = ((Component)((EntityState)self).outer).GetComponent<CharacterBody>(); if (Object.op_Implicit((Object)(object)component2)) { BlastShotClock value = shotClocks.GetValue(component2, (CharacterBody _) => new BlastShotClock()); if (!value.CanFire(Time.fixedTime)) { return; } value.RecordShot(Time.fixedTime); } } } orig.Invoke(self, ray); } private static void ReduceSpread(orig_ModifyBullet orig, Bandit2FireRifle self, BulletAttack attack) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) orig.Invoke(self, attack); attack.spreadPitchScale *= 0.5f; attack.spreadYawScale *= 0.5f; attack.radius *= 1.2f; LayerIndex world = LayerIndex.world; attack.stopperMask = ((LayerIndex)(ref world)).mask; } private void ExpandBanditStockDisplay(orig_Awake orig, CrosshairController self) { //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: 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_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0132: 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_0117: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) orig.Invoke(self); if (!Object.op_Implicit((Object)(object)self) || !((Object)self).name.StartsWith("Bandit2Crosshair", StringComparison.Ordinal)) { return; } try { SkillStockSpriteDisplay[] skillStockSpriteDisplays = self.skillStockSpriteDisplays; int[] array = new int[4]; int stock; for (stock = 1; stock <= 4; stock++) { int num = Array.FindIndex(skillStockSpriteDisplays, (SkillStockSpriteDisplay display) => Object.op_Implicit((Object)(object)display.target) && ((Object)display.target).name == $"Stock, {stock}"); if (num < 0) { throw new InvalidOperationException($"Reticle stock pip {stock} was not found."); } array[stock - 1] = num; } int num2 = Array.FindIndex(skillStockSpriteDisplays, (SkillStockSpriteDisplay display) => Object.op_Implicit((Object)(object)display.target) && ((Object)display.target).name == "Center, Available"); if (num2 < 0) { throw new InvalidOperationException("Reticle center marker was not found."); } int num3 = array[3]; for (int num4 = 0; num4 < skillStockSpriteDisplays.Length; num4++) { SkillStockSpriteDisplay val = skillStockSpriteDisplays[num4]; if (Object.op_Implicit((Object)(object)val.target) && (Array.IndexOf(array, num4) >= 0 || num4 == num2)) { val.maximumStockCountToBeValid = -1; skillStockSpriteDisplays[num4] = val; } } SkillStockSpriteDisplay val2 = skillStockSpriteDisplays[num3]; Transform parent = val2.target.transform.parent; Array.Resize(ref self.skillStockSpriteDisplays, skillStockSpriteDisplays.Length + 2); for (int num5 = 5; num5 <= 6; num5++) { GameObject val3 = Object.Instantiate<GameObject>(val2.target, parent, false); ((Object)val3).name = $"Stock, {num5}"; val3.SetActive(false); SkillStockSpriteDisplay val4 = val2; val4.target = val3; val4.minimumStockCountToBeValid = num5; val4.maximumStockCountToBeValid = -1; self.skillStockSpriteDisplays[skillStockSpriteDisplays.Length + num5 - 5] = val4; } Transform[] array2 = (Transform[])(object)new Transform[6]; for (int num6 = 0; num6 < array.Length; num6++) { array2[num6] = skillStockSpriteDisplays[array[num6]].target.transform; } for (int num7 = 5; num7 <= 6; num7++) { array2[num7 - 1] = self.skillStockSpriteDisplays[skillStockSpriteDisplays.Length + num7 - 5].target.transform; } stockPipLayouts.Add(self, array2); } catch (Exception arg) { log.LogError((object)$"Could not extend Bandit's Blast reticle to six stock pips. {arg}"); } } private void CenterBanditStockPips(orig_LateUpdate orig, CrosshairController self) { //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) orig.Invoke(self); if (!Object.op_Implicit((Object)(object)self) || !stockPipLayouts.TryGetValue(self, out Transform[] value) || !Object.op_Implicit((Object)(object)self.hudElement)) { return; } CharacterBody targetCharacterBody = self.hudElement.targetCharacterBody; if (!Object.op_Implicit((Object)(object)targetCharacterBody)) { return; } SkillLocator skillLocator = targetCharacterBody.skillLocator; if (!Object.op_Implicit((Object)(object)skillLocator)) { return; } GenericSkill primary = skillLocator.primary; if (!Object.op_Implicit((Object)(object)primary)) { return; } int maxStock = primary.maxStock; for (int i = 0; i < value.Length; i++) { if (Object.op_Implicit((Object)(object)value[i])) { Vector3 localPosition = value[i].localPosition; localPosition.x = BanditBalance.GetStockPipX(i, maxStock); value[i].localPosition = localPosition; } } } private static string Description(orig_GetLocalizedStringByToken orig, Language self, string token) { return BanditBalance.GetDescription(token) ?? orig.Invoke(self, token); } } internal static class CaptainBalance { internal const float HealingBeaconBarrierFraction = 0.2f; internal const float TaserSlowDuration = 5f; internal static bool IsHealingWardName(string name) { if (!(name == "CaptainHealingWard")) { return name == "CaptainHealingWard(Clone)"; } return true; } internal static float GetBarrierGrant(float currentBarrier, float fullHealth, float healingTick) { float val = Math.Max(0f, fullHealth * 0.2f - currentBarrier); return Math.Min(Math.Max(0f, healingTick), val); } internal static string? GetDescription(string token) { return token switch { "CAPTAIN_SECONDARY_DESCRIPTION" => "<style=cIsDamage>Shocking</style>. Fire a fast tazer that deals <style=cIsDamage>100% damage</style>. Travels farther if bounced. <color=#C586FF><b>Enemies that cannot be shocked are slowed by 50% for 5 seconds instead.</b></color>", "CAPTAIN_SUPPLY_HEAL_DESCRIPTION" => "<style=cIsHealing>Heal</style> all nearby allies for <style=cIsHealing>10%</style> of their <style=cIsHealing>maximum health</style> every second. <color=#C586FF><b>Allies already at full combined health instead gain each healing tick as barrier, up to 20% maximum health. Existing barrier is never removed.</b></color>", "CAPTAIN_UTILITY_DESCRIPTION" => "<style=cIsDamage>Stunning</style>. Request up to <style=cIsDamage>3</style> Orbital Probes from the <style=cIsDamage>UES Safe Travels</style>. Each probe deals <style=cIsDamage>1000% damage</style>. <color=#C586FF><b>Available in hidden realms.</b></color>", "CAPTAIN_UTILITY_ALT1_DESCRIPTION" => "<style=cIsDamage>Stunning</style>. Request a <style=cIsDamage>kinetic strike</style> from the <style=cIsDamage>UES Safe Travels</style>. After <style=cIsUtility>20 seconds</style>, it deals <style=cIsDamage>40,000% damage</style> to ALL characters. <color=#C586FF><b>Available in hidden realms.</b></color>", "CAPTAIN_SPECIAL_DESCRIPTION" => "Request a <style=cIsUtility>permanent</style> Supply Beacon. Can only be requested <style=cIsUtility>twice per stage</style>. <color=#C586FF><b>Available in hidden realms.</b></color>", _ => null, }; } } internal sealed class CaptainChanges : IDisposable { [CompilerGenerated] private static class <>O { public static Action<DamageReport> <0>__TaserSlow; public static hook_GetCurrentIcon <1>__OrbitalIcon; public static hook_GetCurrentNameToken <2>__OrbitalName; public static hook_GetCurrentDescriptionToken <3>__OrbitalDescription; public static hook_CanExecute <4>__OrbitalCanExecute; public static hook_IsReady <5>__OrbitalIsReady; public static hook_HealOccupants <6>__HealingBeacon; public static hook_GetLocalizedStringByToken <7>__Description; } private readonly ManualLogSource log; private readonly List<Action> cleanup = new List<Action>(); internal CaptainChanges(ManualLogSource log) { this.log = log; } internal void Enable() { try { Add(delegate { GlobalEventManager.onServerDamageDealt += TaserSlow; }, delegate { GlobalEventManager.onServerDamageDealt -= TaserSlow; }); Add(delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<1>__OrbitalIcon; if (obj == null) { hook_GetCurrentIcon val = OrbitalIcon; <>O.<1>__OrbitalIcon = val; obj = (object)val; } CaptainOrbitalSkillDef.GetCurrentIcon += (hook_GetCurrentIcon)obj; }, delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<1>__OrbitalIcon; if (obj == null) { hook_GetCurrentIcon val = OrbitalIcon; <>O.<1>__OrbitalIcon = val; obj = (object)val; } CaptainOrbitalSkillDef.GetCurrentIcon -= (hook_GetCurrentIcon)obj; }); Add(delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<2>__OrbitalName; if (obj == null) { hook_GetCurrentNameToken val = OrbitalName; <>O.<2>__OrbitalName = val; obj = (object)val; } CaptainOrbitalSkillDef.GetCurrentNameToken += (hook_GetCurrentNameToken)obj; }, delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<2>__OrbitalName; if (obj == null) { hook_GetCurrentNameToken val = OrbitalName; <>O.<2>__OrbitalName = val; obj = (object)val; } CaptainOrbitalSkillDef.GetCurrentNameToken -= (hook_GetCurrentNameToken)obj; }); Add(delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<3>__OrbitalDescription; if (obj == null) { hook_GetCurrentDescriptionToken val = OrbitalDescription; <>O.<3>__OrbitalDescription = val; obj = (object)val; } CaptainOrbitalSkillDef.GetCurrentDescriptionToken += (hook_GetCurrentDescriptionToken)obj; }, delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<3>__OrbitalDescription; if (obj == null) { hook_GetCurrentDescriptionToken val = OrbitalDescription; <>O.<3>__OrbitalDescription = val; obj = (object)val; } CaptainOrbitalSkillDef.GetCurrentDescriptionToken -= (hook_GetCurrentDescriptionToken)obj; }); Add(delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<4>__OrbitalCanExecute; if (obj == null) { hook_CanExecute val = OrbitalCanExecute; <>O.<4>__OrbitalCanExecute = val; obj = (object)val; } CaptainOrbitalSkillDef.CanExecute += (hook_CanExecute)obj; }, delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<4>__OrbitalCanExecute; if (obj == null) { hook_CanExecute val = OrbitalCanExecute; <>O.<4>__OrbitalCanExecute = val; obj = (object)val; } CaptainOrbitalSkillDef.CanExecute -= (hook_CanExecute)obj; }); Add(delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<5>__OrbitalIsReady; if (obj == null) { hook_IsReady val = OrbitalIsReady; <>O.<5>__OrbitalIsReady = val; obj = (object)val; } CaptainOrbitalSkillDef.IsReady += (hook_IsReady)obj; }, delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<5>__OrbitalIsReady; if (obj == null) { hook_IsReady val = OrbitalIsReady; <>O.<5>__OrbitalIsReady = val; obj = (object)val; } CaptainOrbitalSkillDef.IsReady -= (hook_IsReady)obj; }); Add(delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<6>__HealingBeacon; if (obj == null) { hook_HealOccupants val = HealingBeacon; <>O.<6>__HealingBeacon = val; obj = (object)val; } HealingWard.HealOccupants += (hook_HealOccupants)obj; }, delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<6>__HealingBeacon; if (obj == null) { hook_HealOccupants val = HealingBeacon; <>O.<6>__HealingBeacon = val; obj = (object)val; } HealingWard.HealOccupants -= (hook_HealOccupants)obj; }); Add(delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<7>__Description; if (obj == null) { hook_GetLocalizedStringByToken val = Description; <>O.<7>__Description = val; obj = (object)val; } Language.GetLocalizedStringByToken += (hook_GetLocalizedStringByToken)obj; }, delegate { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<7>__Description; if (obj == null) { hook_GetLocalizedStringByToken val = Description; <>O.<7>__Description = val; obj = (object)val; } Language.GetLocalizedStringByToken -= (hook_GetLocalizedStringByToken)obj; }); log.LogInfo((object)"Captain changes ENABLED: taser slows shock-immune enemies by 50% for 5s; orbital Utility/Special available in hidden realms; Healing Beacon converts full-health ticks into barrier up to 20% maximum health."); } catch (Exception arg) { Dispose(); log.LogError((object)$"Could not enable the full Captain patch; removed its hooks. {arg}"); } } private void Add(Action install, Action remove) { cleanup.Add(remove); install(); } public void Dispose() { for (int num = cleanup.Count - 1; num >= 0; num--) { try { cleanup[num](); } catch (Exception arg) { log.LogError((object)$"Captain hook cleanup failed: {arg}"); } } cleanup.Clear(); } private static T WithoutOrbitalBlock<T>(Func<T> action) { SceneDef mostRecentSceneDef = SceneCatalog.mostRecentSceneDef; if (!Object.op_Implicit((Object)(object)mostRecentSceneDef) || !mostRecentSceneDef.blockOrbitalSkills) { return action(); } mostRecentSceneDef.blockOrbitalSkills = false; try { return action(); } finally { mostRecentSceneDef.blockOrbitalSkills = true; } } private static Sprite OrbitalIcon(orig_GetCurrentIcon orig, CaptainOrbitalSkillDef self, GenericSkill slot) { return WithoutOrbitalBlock(() => orig.Invoke(self, slot)); } private static string OrbitalName(orig_GetCurrentNameToken orig, CaptainOrbitalSkillDef self, GenericSkill slot) { return WithoutOrbitalBlock(() => orig.Invoke(self, slot)); } private static string OrbitalDescription(orig_GetCurrentDescriptionToken orig, CaptainOrbitalSkillDef self, GenericSkill slot) { return WithoutOrbitalBlock(() => orig.Invoke(self, slot)); } private static bool OrbitalCanExecute(orig_CanExecute orig, CaptainOrbitalSkillDef self, GenericSkill slot) { return WithoutOrbitalBlock(() => orig.Invoke(self, slot)); } private static bool OrbitalIsReady(orig_IsReady orig, CaptainOrbitalSkillDef self, GenericSkill slot) { return WithoutOrbitalBlock(() => orig.Invoke(self, slot)); } private static bool IsCaptainHealingBeacon(HealingWard ward) { return CaptainBalance.IsHealingWardName(((Object)((Component)ward).gameObject).name); } private static void TaserSlow(DamageReport report) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Invalid comparison between Unknown and I4 //IL_007c: 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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Invalid comparison between Unknown and I4 //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) if (!NetworkServer.active || !Object.op_Implicit((Object)(object)report.attackerBody) || !Object.op_Implicit((Object)(object)report.victimBody) || !report.victim.alive || report.damageInfo.rejected || report.attackerTeamIndex == report.victimTeamIndex) { return; } DamageInfo damageInfo = report.damageInfo; if (!(report.attackerBody.baseNameToken != "CAPTAIN_BODY_NAME") && (int)damageInfo.damageType.damageSource == 2 && (damageInfo.damageType.damageType & 0x1000000) != 0 && (int)damageInfo.dotIndex == -1 && !(damageInfo.procCoefficient <= 0f) && ((ProcChainMask)(ref damageInfo.procChainMask)).Equals(default(ProcChainMask))) { SetStateOnHurt component = ((Component)report.victimBody).GetComponent<SetStateOnHurt>(); if (!Object.op_Implicit((Object)(object)component) || !component.canBeStunned || !Object.op_Implicit((Object)(object)component.targetStateMachine)) { report.victimBody.AddTimedBuff(Buffs.Slow50, 5f); } } } private static void HealingBeacon(orig_HealOccupants orig, HealingWard self) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_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) if (!NetworkServer.active || !IsCaptainHealingBeacon(self)) { orig.Invoke(self); return; } List<HealthComponent> list = new List<HealthComponent>(); TeamFilter component = ((Component)self).GetComponent<TeamFilter>(); if (Object.op_Implicit((Object)(object)component)) { float num = self.radius * self.radius; Vector3 position = ((Component)self).transform.position; foreach (TeamComponent teamMember in TeamComponent.GetTeamMembers(component.teamIndex)) { HealthComponent val = (Object.op_Implicit((Object)(object)teamMember) ? ((Component)teamMember).GetComponent<HealthComponent>() : null); if (Object.op_Implicit((Object)(object)val) && val.alive) { Vector3 val2 = ((Component)teamMember).transform.position - position; if (!(((Vector3)(ref val2)).sqrMagnitude > num) && val.combinedHealth >= val.fullCombinedHealth) { list.Add(val); } } } } orig.Invoke(self); foreach (HealthComponent item in list) { if (Object.op_Implicit((Object)(object)item) && item.alive) { float healingTick = self.healPoints + item.fullHealth * self.healFraction; float barrierGrant = CaptainBalance.GetBarrierGrant(item.barrier, item.fullHealth, healingTick); if (barrierGrant > 0f) { item.AddBarrier(barrierGrant); } } } } private static string Description(orig_GetLocalizedStringByToken orig, Language self, string token) { return CaptainBalance.GetDescription(token) ?? orig.Invoke(self, token); } } internal static class ChefBalance { internal const float IceCubeSpreadDegrees = 2.5f; internal const float RollSlopeLimit = 60f; internal const float BoostedIceDamage = 10f; internal static bool CancelCrestLift(bool wasGrounded, bool grounded, bool forcedUnground) { if (wasGrounded && !grounded) { return !forcedUnground; } return false; } internal static float CollisionUpSpeed(float before, float after) { return Math.Min(after, Math.Max(0f, before)); } internal static string? GetDescription(string token) { return token switch { "CHEF_SECONDARY_ALT_DESCRIPTION" => "<style=cIsUtility>Frost</style>. Launch ice cubes for <style=cIsDamage>3x150% damage</style>. <color=#C586FF><b>One randomly selected cube flies straight; the other two each have independent random spread within a 2.5-degree cone.</b></color>", "CHEF_SECONDARY_ALT_BOOST_DESCRIPTION" => "<style=cKeywordName>Boost</style><style=cSub><style=cIsUtility>Freezing</style>. Boosting Ice Box launches 1 large ice cube for <style=cIsDamage><color=#C586FF><b>1000%</b></color> damage</style>.</style>", "CHEF_SECONDARY_ALT_BOOST_DESCRIPTION_SKILL" => "<style=cSub><style=cIsUtility>Freezing</style>. Launches 1 large ice cube for <style=cIsDamage><color=#C586FF><b>1000%</b></color> damage</style>.</style>", "CHEF_UTILITY_DESCRIPTION" => "<style=cIsDamage>Stunning</style>. Charge the rolling pin to <style=cIsUtility>speed</style> forward, dealing <style=cIsDamage>300%-600% damage</style>. <color=#C586FF><b>Automatic step climbing is disabled with a 60-degree walkable slope limit (or the original motor limit if lower) while rolling. Steep collisions and ramp crests cannot create upward launch speed; deliberate jumps remain available.</b></color>", "CHEF_SPECIAL_ALT1_DESCRIPTION" => "Emit a blast attack dealing <style=cIsDamage>400%</style> damage, inflicting <style=cIsDamage>Ignite</style> or <style=cIsUtility>Frost</style>. <style=cIsUtility>Boosts</style> the next Skill used. <color=#C586FF><b>Can be used during Roll without ending it.</b></color>", _ => null, }; } } internal sealed class IceBoxVolley { private readonly (float pitch, float yaw)[] offsets = new(float, float)[3]; internal IceBoxVolley(Random random) { int num = random.Next(3); for (int i = 0; i < offsets.Length; i++) { if (i != num) { double num2 = random.NextDouble() * Math.PI * 2.0; double num3 = 0.5 + random.NextDouble() * 2.0; offsets[i] = (pitch: (float)(Math.Sin(num2) * num3), yaw: (float)(Math.Cos(num2) * num3)); } } } internal (float pitch, float yaw) Offset(int firedCount) { return offsets[Math.Clamp(firedCount - 1, 0, 2)]; } } internal sealed class ChefChanges : IDisposable { private delegate Vector3 ObstructionOrig(KinematicCharacterMotor self, Vector3 normal, bool stable); private delegate Vector3 ObstructionHook(ObstructionOrig orig, KinematicCharacterMotor self, Vector3 normal, bool stable); private delegate void ProjectionOrig(KinematicCharacterMotor self, ref Vector3 velocity, Vector3 normal, bool stable); private delegate void ProjectionHook(ProjectionOrig orig, KinematicCharacterMotor self, ref Vector3 velocity, Vector3 normal, bool stable); [CompilerGenerated] private static class <>O { public static Manipulator <0>__BoostedDamage; public static Manipulator <1>__PreserveRoll; public static hook_HandleMovements <2>__YesChefMovement; public static hook_PerformInputs <3>__YesChefInputs; public static hook_GetLocalizedStringByToken <4>__Description; public static ObstructionHook <5>__RollObstruction; public static ProjectionHook <6>__RollProjection; } private readonly ManualLogSource log; private readonly List<Action> cleanup = new List<Action>(); private ConditionalWeakTable<IceBox, IceBoxVolley> iceVolleys = new ConditionalWeakTable<IceBox, IceBoxVolley>(); private readonly Random spreadRandom = new Random(); private readonly Dictionary<KinematicCharacterMotor, (StepHandlingMethod step, float slope)> rollMotors = new Dictionary<KinematicCharacterMotor, (StepHandlingMethod, float)>(); internal ChefChanges(ManualLogSource log) { this.log = log; } internal void Enable() { //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Expected O, but got Unknown //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Expected O, but got Unknown try { Add(delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown RolyPoly.StartRolyPoly += new hook_StartRolyPoly(RollStarted); }, delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown RolyPoly.StartRolyPoly -= new hook_StartRolyPoly(RollStarted); }); Add(delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown RolyPoly.OnExit += new hook_OnExit(RollExited); }, delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown RolyPoly.OnExit -= new hook_OnExit(RollExited); }); Add(delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown CharacterMotor.AfterCharacterUpdate += new hook_AfterCharacterUpdate(RollAfterMovement); }, delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O