using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using FMOD.Studio; using HarmonyLib; using Lamb.UI; using MMBiomeGeneration; using MMRoomGeneration; using Microsoft.CodeAnalysis; using Rewired; using Spine; using Spine.Unity; using TMPro; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.Events; using UnityEngine.ResourceManagement.AsyncOperations; using UnityEngine.UI; using src.UINavigator; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("PlayableBishops")] [assembly: AssemblyDescription("Playable bishop aspects for Cult of the Lamb")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("PlayableBishops")] [assembly: ComVisible(false)] [assembly: Guid("c641d23c-12f9-497d-b527-468e741a0d5a")] [assembly: AssemblyFileVersion("0.7.52.0")] [assembly: AssemblyVersion("0.7.52.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [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 PlayableBishops { [BepInPlugin("com.cotl.playablebishops", "PlayableBishops", "0.7.52")] public sealed class PlayableBishopsPlugin : BaseUnityPlugin { public const string PluginGuid = "com.cotl.playablebishops"; public const string PluginName = "PlayableBishops"; public const string PluginVersion = "0.7.52"; internal static ManualLogSource Log; internal static BishopAspectController Controller; internal static readonly BishopAspectController[] Controllers = new BishopAspectController[2]; private Harmony _harmony; private void Awake() { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; PlayableBishopsConfig.Bind(((BaseUnityPlugin)this).Config); for (int i = 0; i < Controllers.Length; i++) { BishopAspectController bishopAspectController = ((Component)this).gameObject.AddComponent(); bishopAspectController.Initialize(i); Controllers[i] = bishopAspectController; } Controller = Controllers[0]; _harmony = new Harmony("com.cotl.playablebishops"); Patch(AccessTools.Method(typeof(EnemyWormBoss), "Start", (Type[])null, (Type[])null), typeof(EnemyWormBossStartPatch), "Prefix"); Patch(AccessTools.Method(typeof(EnemyWormBoss), "Update", (Type[])null, (Type[])null), typeof(EnemyWormBossUpdatePatch), "Prefix"); Patch(AccessTools.Method(typeof(EnemyWormBoss), "OnDie", (Type[])null, (Type[])null), typeof(EnemyWormBossOnDiePatch), "Prefix"); Patch(AccessTools.Method(typeof(EnemyWormBoss), "OnDamageTriggerEnter", (Type[])null, (Type[])null), typeof(PlayableLeshyDamagePatch), "Prefix"); Patch(AccessTools.Method(typeof(EnemyFrogBoss), "Start", (Type[])null, (Type[])null), typeof(EnemyFrogBossStartPatch), "Prefix"); Patch(AccessTools.Method(typeof(EnemyFrogBoss), "Update", (Type[])null, (Type[])null), typeof(EnemyFrogBossUpdatePatch), "Prefix"); Patch(AccessTools.Method(typeof(EnemyFrogBoss), "OnDie", (Type[])null, (Type[])null), typeof(EnemyFrogBossOnDiePatch), "Prefix"); Patch(AccessTools.Method(typeof(EnemyFrogBoss), "OnDestroy", (Type[])null, (Type[])null), typeof(EnemyFrogBossOnDestroyPatch), "Prefix"); Patch(AccessTools.Method(typeof(EnemyTentacleMonster), "Start", (Type[])null, (Type[])null), typeof(EnemyTentacleMonsterStartPatch), "Prefix"); Patch(AccessTools.Method(typeof(EnemyTentacleMonster), "OnEnable", (Type[])null, (Type[])null), typeof(EnemyTentacleMonsterOnEnablePatch), "Prefix"); Patch(AccessTools.Method(typeof(EnemyTentacleMonster), "Update", (Type[])null, (Type[])null), typeof(EnemyTentacleMonsterUpdatePatch), "Prefix"); Patch(AccessTools.Method(typeof(EnemyTentacleMonster), "OnDie", (Type[])null, (Type[])null), typeof(EnemyTentacleMonsterOnDiePatch), "Prefix"); Patch(AccessTools.Method(typeof(EnemyTentacleMonster), "OnDestroy", (Type[])null, (Type[])null), typeof(EnemyTentacleMonsterOnDestroyPatch), "Prefix"); Patch(AccessTools.Method(typeof(EnemySpiderMonster), "Awake", (Type[])null, (Type[])null), typeof(EnemySpiderMonsterAwakePatch), "Prefix"); PatchPostfix(AccessTools.Method(typeof(EnemySpiderMonster), "Awake", (Type[])null, (Type[])null), typeof(EnemySpiderMonsterAwakePostPatch), "Postfix"); Patch(AccessTools.Method(typeof(EnemySpiderMonster), "Start", (Type[])null, (Type[])null), typeof(EnemySpiderMonsterStartPatch), "Prefix"); Patch(AccessTools.Method(typeof(EnemySpiderMonster), "OnEnable", (Type[])null, (Type[])null), typeof(EnemySpiderMonsterOnEnablePatch), "Prefix"); PatchPostfix(AccessTools.Method(typeof(EnemySpiderMonster), "OnEnable", (Type[])null, (Type[])null), typeof(EnemySpiderMonsterOnEnablePatch), "Postfix"); Patch(AccessTools.Method(typeof(EnemySpiderMonster), "OnDie", (Type[])null, (Type[])null), typeof(EnemySpiderMonsterOnDiePatch), "Prefix"); Patch(AccessTools.Method(typeof(SkeletonRenderer), "GenerateMesh", (Type[])null, (Type[])null), typeof(PlayableShamuraMeshGuardPatch), "Prefix"); Patch(AccessTools.Method(typeof(HealthPlayer), "DealDamage", new Type[7] { typeof(float), typeof(GameObject), typeof(Vector3), typeof(bool), typeof(AttackTypes), typeof(bool), typeof(AttackFlags) }, (Type[])null), typeof(PlayableLeshyTunnelDamageImmunityPatch), "Prefix"); Patch(AccessTools.Method(typeof(GrenadeBullet), "Play", new Type[8] { typeof(float), typeof(float), typeof(float), typeof(float), typeof(Team), typeof(bool), typeof(string), typeof(SkeletonAnimation) }, (Type[])null), typeof(GrenadeBulletPlayPatch), "Prefix"); Patch(AccessTools.Method(typeof(GrenadeBullet), "OnDamageTriggerEnter", (Type[])null, (Type[])null), typeof(GrenadeBulletDamagePatch), "Prefix"); PatchPostfix(AccessTools.Method(typeof(GrenadeBullet), "DoCollision", (Type[])null, (Type[])null), typeof(GrenadeBulletDoCollisionPatch), "Postfix"); Patch(AccessTools.Method(typeof(FrogBossTongue), "OnTriggerEnterEvent", (Type[])null, (Type[])null), typeof(PlayableHeketTongueDamagePatch), "Prefix"); Patch(AccessTools.Method(typeof(Explosion), "CreateExplosion", (Type[])null, (Type[])null), typeof(PlayableHeketExplosionDamagePatch), "Prefix"); PatchPostfix(AccessTools.Method(typeof(RewiredGameplayInputSource), "GetAttackButtonDown", new Type[1] { typeof(PlayerFarming) }, (Type[])null), typeof(PlayableBishopBasicAttackDownPatch), "Postfix"); Patch(AccessTools.Method(typeof(RewiredGameplayInputSource), "GetAttackButtonHeld", new Type[1] { typeof(PlayerFarming) }, (Type[])null), typeof(PlayableBishopBasicAttackHeldPatch), "Prefix"); PatchPostfix(AccessTools.Method(typeof(RewiredGameplayInputSource), "GetCurseButtonDown", new Type[1] { typeof(PlayerFarming) }, (Type[])null), typeof(PlayableBishopSecondaryAttackDownPatch), "Postfix"); Patch(AccessTools.Method(typeof(RewiredGameplayInputSource), "GetCurseButtonHeld", new Type[1] { typeof(PlayerFarming) }, (Type[])null), typeof(PlayableBishopCombatInputHeldPatch), "Prefix"); Patch(AccessTools.Method(typeof(RewiredGameplayInputSource), "GetCurseButtonUp", new Type[1] { typeof(PlayerFarming) }, (Type[])null), typeof(PlayableBishopCombatInputUpPatch), "Prefix"); PatchPostfix(AccessTools.Method(typeof(RewiredGameplayInputSource), "GetHeavyAttackButtonDown", new Type[1] { typeof(PlayerFarming) }, (Type[])null), typeof(PlayableBishopSignatureAttackDownPatch), "Postfix"); Patch(AccessTools.Method(typeof(RewiredGameplayInputSource), "GetHeavyAttackButtonHeld", new Type[1] { typeof(PlayerFarming) }, (Type[])null), typeof(PlayableBishopCombatInputHeldPatch), "Prefix"); PatchPostfix(AccessTools.Method(typeof(RewiredGameplayInputSource), "GetDodgeButtonDown", new Type[1] { typeof(PlayerFarming) }, (Type[])null), typeof(PlayableBishopDodgeDownPatch), "Postfix"); Patch(AccessTools.Method(typeof(RewiredGameplayInputSource), "GetDodgeButtonHeld", new Type[1] { typeof(PlayerFarming) }, (Type[])null), typeof(PlayableBishopDodgeHeldPatch), "Prefix"); PatchPostfix(AccessTools.Method(typeof(UIPlayerUpgradesMenuController), "Start", (Type[])null, (Type[])null), typeof(UIPlayerUpgradesMenuStartPatch), "Postfix"); Log.LogInfo((object)"PlayableBishops 0.7.52 loaded with global per-instance Shamura straight-alpha rendering and restored Kallamar dodge-teleport travel."); } internal static int GetPlayerSlot(PlayerFarming player) { if ((Object)(object)player != (Object)null) { for (int i = 0; i < PlayerFarming.players.Count && i < Controllers.Length; i++) { if ((Object)(object)PlayerFarming.players[i] == (Object)(object)player) { return i; } } if (player.playerID >= 0 && player.playerID < Controllers.Length) { return player.playerID; } } return 0; } internal static BishopAspectController GetController(PlayerFarming player) { int playerSlot = GetPlayerSlot(player); if (playerSlot < 0 || playerSlot >= Controllers.Length) { return null; } return Controllers[playerSlot]; } internal static BishopAspectController GetController(int playerSlot) { if (playerSlot < 0 || playerSlot >= Controllers.Length) { return null; } return Controllers[playerSlot]; } private void Patch(MethodBase original, Type patchType, string patchName) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown if (original == null) { Log.LogError((object)("Could not find required game method for " + patchType.Name + ".")); } else { _harmony.Patch(original, new HarmonyMethod(patchType, patchName, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } private void PatchPostfix(MethodBase original, Type patchType, string patchName) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown if (original == null) { Log.LogError((object)("Could not find required game method for " + patchType.Name + ".")); } else { _harmony.Patch(original, (HarmonyMethod)null, new HarmonyMethod(patchType, patchName, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } private void OnDestroy() { for (int i = 0; i < Controllers.Length; i++) { if ((Object)(object)Controllers[i] != (Object)null) { Controllers[i].Shutdown(); Controllers[i] = null; } } Controller = null; if (_harmony != null) { _harmony.UnpatchSelf(); } } } internal static class PlayableBishopsLog { internal static void Debug(string message) { if (PlayableBishopsConfig.DebugLogging != null && PlayableBishopsConfig.DebugLogging.Value && PlayableBishopsPlugin.Log != null) { PlayableBishopsPlugin.Log.LogInfo((object)message); } } } internal enum ControllerToggleStick { LeftStick, RightStick } internal static class PlayableBishopsConfig { internal static ConfigEntry Enabled; internal static ConfigEntry AllowOutsideDungeons; internal static ConfigEntry AutoActivateInDungeons; internal static ConfigEntry CultLeaderFormsOutsideDungeons; internal static ConfigEntry CultLeaderTransitionDuration; internal static ConfigEntry CultLeaderLeshyScale; internal static ConfigEntry CultLeaderHeketScale; internal static ConfigEntry CultLeaderKallamarScale; internal static ConfigEntry CultLeaderShamuraScale; internal static ConfigEntry BossDamageMultiplier; internal static ConfigEntry SelectedAspect; internal static ConfigEntry SelectedAspectP2; internal static ConfigEntry ToggleKey; internal static ConfigEntry SpikeKey; internal static ConfigEntry VolleyKey; internal static ConfigEntry RoarKey; internal static ConfigEntry SignatureMouseButton; internal static ConfigEntry ResetKey; internal static ConfigEntry ControllerToggleChord; internal static ConfigEntry ControllerToggleStickChoice; internal static ConfigEntry ProjectileAimAssist; internal static ConfigEntry ProjectileAimAssistMouseRadius; internal static ConfigEntry ProjectileAimAssistControllerCone; internal static ConfigEntry VisualScale; internal static ConfigEntry SpikeCooldown; internal static ConfigEntry SpikeBaseDamage; internal static ConfigEntry SpikeLineReach; internal static ConfigEntry SpikeLineHalfWidth; internal static ConfigEntry VolleyCooldown; internal static ConfigEntry VolleyProjectileBaseDamage; internal static ConfigEntry VolleyShotCount; internal static ConfigEntry VolleyFocusedShots; internal static ConfigEntry VolleySpreadRadius; internal static ConfigEntry RoarCooldown; internal static ConfigEntry RoarRadius; internal static ConfigEntry RoarDamage; internal static ConfigEntry TunnelDamage; internal static ConfigEntry TunnelHitCooldown; internal static ConfigEntry HeketVisualScale; internal static ConfigEntry HeketTongueCooldown; internal static ConfigEntry HeketMortarCooldown; internal static ConfigEntry HeketMortarCount; internal static ConfigEntry HeketSlamCooldown; internal static ConfigEntry HeketSlamRadius; internal static ConfigEntry HeketSlamDamage; internal static ConfigEntry HeketLocomotionHopRadius; internal static ConfigEntry HeketLocomotionHopDamage; internal static ConfigEntry HeketBurpCooldown; internal static ConfigEntry HeketTongueBaseDamage; internal static ConfigEntry HeketTongueImpactRadius; internal static ConfigEntry HeketMortarBaseDamage; internal static ConfigEntry HeketBurpProjectileBaseDamage; internal static ConfigEntry KallamarVisualScale; internal static ConfigEntry KallamarDaggerCooldown; internal static ConfigEntry KallamarDaggerRadius; internal static ConfigEntry KallamarDaggerDamage; internal static ConfigEntry KallamarDaggerReach; internal static ConfigEntry KallamarProjectileCooldown; internal static ConfigEntry KallamarProjectileBaseDamage; internal static ConfigEntry KallamarSwordCooldown; internal static ConfigEntry KallamarSwordRadius; internal static ConfigEntry KallamarSwordDamage; internal static ConfigEntry KallamarMovementDestructionRadius; internal static ConfigEntry KallamarTeleportCooldown; internal static ConfigEntry KallamarTeleportDistance; internal static ConfigEntry KallamarChargedTeleportDistance; internal static ConfigEntry ShamuraVisualScale; internal static ConfigEntry ShamuraSlashCooldown; internal static ConfigEntry ShamuraSlashRadius; internal static ConfigEntry ShamuraSlashBaseDamage; internal static ConfigEntry ShamuraBombCooldown; internal static ConfigEntry ShamuraBombCount; internal static ConfigEntry ShamuraBombFocusedCount; internal static ConfigEntry ShamuraBombSpreadRadius; internal static ConfigEntry ShamuraBombBaseDamage; internal static ConfigEntry ShamuraJumpCooldown; internal static ConfigEntry ShamuraJumpRadius; internal static ConfigEntry ShamuraJumpBaseDamage; internal static ConfigEntry DebugLogging; internal static void Bind(ConfigFile config) { //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Expected O, but got Unknown //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Expected O, but got Unknown //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Expected O, but got Unknown //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Expected O, but got Unknown //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Expected O, but got Unknown //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Expected O, but got Unknown //IL_03c2: Unknown result type (might be due to invalid IL or missing references) //IL_03cc: Expected O, but got Unknown //IL_03fa: Unknown result type (might be due to invalid IL or missing references) //IL_0404: Expected O, but got Unknown //IL_040e: Unknown result type (might be due to invalid IL or missing references) //IL_0418: Invalid comparison between Unknown and I4 //IL_042e: Unknown result type (might be due to invalid IL or missing references) //IL_0438: Invalid comparison between Unknown and I4 //IL_044e: Unknown result type (might be due to invalid IL or missing references) //IL_0458: Invalid comparison between Unknown and I4 //IL_046e: Unknown result type (might be due to invalid IL or missing references) //IL_0478: Invalid comparison between Unknown and I4 //IL_04dd: Unknown result type (might be due to invalid IL or missing references) //IL_04e7: Expected O, but got Unknown //IL_0515: Unknown result type (might be due to invalid IL or missing references) //IL_051f: Expected O, but got Unknown //IL_054d: Unknown result type (might be due to invalid IL or missing references) //IL_0557: Expected O, but got Unknown //IL_0585: Unknown result type (might be due to invalid IL or missing references) //IL_058f: Expected O, but got Unknown //IL_05bd: Unknown result type (might be due to invalid IL or missing references) //IL_05c7: Expected O, but got Unknown //IL_05f5: Unknown result type (might be due to invalid IL or missing references) //IL_05ff: Expected O, but got Unknown //IL_062d: Unknown result type (might be due to invalid IL or missing references) //IL_0637: Expected O, but got Unknown //IL_065c: Unknown result type (might be due to invalid IL or missing references) //IL_0666: Expected O, but got Unknown //IL_068a: Unknown result type (might be due to invalid IL or missing references) //IL_0694: Expected O, but got Unknown //IL_06c2: Unknown result type (might be due to invalid IL or missing references) //IL_06cc: Expected O, but got Unknown //IL_0747: Unknown result type (might be due to invalid IL or missing references) //IL_0751: Expected O, but got Unknown //IL_077f: Unknown result type (might be due to invalid IL or missing references) //IL_0789: Expected O, but got Unknown //IL_07b7: Unknown result type (might be due to invalid IL or missing references) //IL_07c1: Expected O, but got Unknown //IL_07ef: Unknown result type (might be due to invalid IL or missing references) //IL_07f9: Expected O, but got Unknown //IL_0827: Unknown result type (might be due to invalid IL or missing references) //IL_0831: Expected O, but got Unknown //IL_08a9: Unknown result type (might be due to invalid IL or missing references) //IL_08b3: Expected O, but got Unknown //IL_08e1: Unknown result type (might be due to invalid IL or missing references) //IL_08eb: Expected O, but got Unknown //IL_0919: Unknown result type (might be due to invalid IL or missing references) //IL_0923: Expected O, but got Unknown //IL_0945: Unknown result type (might be due to invalid IL or missing references) //IL_094f: Expected O, but got Unknown //IL_097d: Unknown result type (might be due to invalid IL or missing references) //IL_0987: Expected O, but got Unknown //IL_09b5: Unknown result type (might be due to invalid IL or missing references) //IL_09bf: Expected O, but got Unknown //IL_09ed: Unknown result type (might be due to invalid IL or missing references) //IL_09f7: Expected O, but got Unknown //IL_0a25: Unknown result type (might be due to invalid IL or missing references) //IL_0a2f: Expected O, but got Unknown //IL_0a5d: Unknown result type (might be due to invalid IL or missing references) //IL_0a67: Expected O, but got Unknown //IL_0a95: Unknown result type (might be due to invalid IL or missing references) //IL_0a9f: Expected O, but got Unknown //IL_0acd: Unknown result type (might be due to invalid IL or missing references) //IL_0ad7: Expected O, but got Unknown //IL_0b05: Unknown result type (might be due to invalid IL or missing references) //IL_0b0f: Expected O, but got Unknown //IL_0b3d: Unknown result type (might be due to invalid IL or missing references) //IL_0b47: Expected O, but got Unknown //IL_0b75: Unknown result type (might be due to invalid IL or missing references) //IL_0b7f: Expected O, but got Unknown //IL_0c1c: Unknown result type (might be due to invalid IL or missing references) //IL_0c26: Expected O, but got Unknown //IL_0c54: Unknown result type (might be due to invalid IL or missing references) //IL_0c5e: Expected O, but got Unknown //IL_0c8c: Unknown result type (might be due to invalid IL or missing references) //IL_0c96: Expected O, but got Unknown //IL_0cc4: Unknown result type (might be due to invalid IL or missing references) //IL_0cce: Expected O, but got Unknown //IL_0cfc: Unknown result type (might be due to invalid IL or missing references) //IL_0d06: Expected O, but got Unknown //IL_0d34: Unknown result type (might be due to invalid IL or missing references) //IL_0d3e: Expected O, but got Unknown //IL_0d6c: Unknown result type (might be due to invalid IL or missing references) //IL_0d76: Expected O, but got Unknown //IL_0da4: Unknown result type (might be due to invalid IL or missing references) //IL_0dae: Expected O, but got Unknown //IL_0ddc: Unknown result type (might be due to invalid IL or missing references) //IL_0de6: Expected O, but got Unknown //IL_0e14: Unknown result type (might be due to invalid IL or missing references) //IL_0e1e: Expected O, but got Unknown //IL_0e4c: Unknown result type (might be due to invalid IL or missing references) //IL_0e56: Expected O, but got Unknown //IL_0e84: Unknown result type (might be due to invalid IL or missing references) //IL_0e8e: Expected O, but got Unknown //IL_0ebc: Unknown result type (might be due to invalid IL or missing references) //IL_0ec6: Expected O, but got Unknown //IL_0ef4: Unknown result type (might be due to invalid IL or missing references) //IL_0efe: Expected O, but got Unknown //IL_102f: Unknown result type (might be due to invalid IL or missing references) //IL_1039: Expected O, but got Unknown //IL_1067: Unknown result type (might be due to invalid IL or missing references) //IL_1071: Expected O, but got Unknown //IL_109f: Unknown result type (might be due to invalid IL or missing references) //IL_10a9: Expected O, but got Unknown //IL_10d7: Unknown result type (might be due to invalid IL or missing references) //IL_10e1: Expected O, but got Unknown //IL_110f: Unknown result type (might be due to invalid IL or missing references) //IL_1119: Expected O, but got Unknown //IL_113d: Unknown result type (might be due to invalid IL or missing references) //IL_1147: Expected O, but got Unknown //IL_116a: Unknown result type (might be due to invalid IL or missing references) //IL_1174: Expected O, but got Unknown //IL_11a2: Unknown result type (might be due to invalid IL or missing references) //IL_11ac: Expected O, but got Unknown //IL_11da: Unknown result type (might be due to invalid IL or missing references) //IL_11e4: Expected O, but got Unknown //IL_1212: Unknown result type (might be due to invalid IL or missing references) //IL_121c: Expected O, but got Unknown //IL_124a: Unknown result type (might be due to invalid IL or missing references) //IL_1254: Expected O, but got Unknown //IL_1282: Unknown result type (might be due to invalid IL or missing references) //IL_128c: Expected O, but got Unknown Enabled = config.Bind("General", "Enabled", true, "Enable Playable Bishops."); AllowOutsideDungeons = config.Bind("General", "AllowOutsideDungeons", false, "Allow the prototype aspect at the cult and other non-combat locations."); AutoActivateInDungeons = config.Bind("General", "AutoActivateInDungeons", true, "Automatically activate the altar-selected bishop when a dungeon player becomes available."); CultLeaderFormsOutsideDungeons = config.Bind("General", "CultLeaderFormsOutsideDungeons", true, "Use the selected bishop's pre-boss cult-leader rig when toggled outside a dungeon."); CultLeaderTransitionDuration = config.Bind("General", "CultLeaderTransitionDuration", 0.35f, new ConfigDescription("Seconds used for the local warp and cult-leader crossfade.", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 1.5f), Array.Empty())); SelectedAspect = config.Bind("Selection", "SelectedAspect", "Leshy", "Saved bishop aspect selection from the altar row."); SelectedAspectP2 = config.Bind("Selection", "SelectedAspectP2", "None", "Saved Player 2 bishop aspect selection from the altar row."); BossDamageMultiplier = config.Bind("Balance", "BossDamageMultiplier", 1.35f, new ConfigDescription("Final multiplier applied after playable-bishop attacks use the game's player weapon-level, run, fleece, relic, trinket, and difficulty scaling.", (AcceptableValueBase)(object)new AcceptableValueRange(0.25f, 5f), Array.Empty())); CultLeaderLeshyScale = config.Bind("Cult Leaders", "LeshyScale", 0.8f, new ConfigDescription("Scale applied to Leshy's non-dungeon cult-leader form.", (AcceptableValueBase)(object)new AcceptableValueRange(0.2f, 2.5f), Array.Empty())); CultLeaderHeketScale = config.Bind("Cult Leaders", "HeketScale", 0.8f, new ConfigDescription("Scale applied to Heket's non-dungeon cult-leader form.", (AcceptableValueBase)(object)new AcceptableValueRange(0.2f, 2.5f), Array.Empty())); CultLeaderKallamarScale = config.Bind("Cult Leaders", "KallamarScale", 0.8f, new ConfigDescription("Scale applied to Kallamar's non-dungeon cult-leader form.", (AcceptableValueBase)(object)new AcceptableValueRange(0.2f, 2.5f), Array.Empty())); CultLeaderShamuraScale = config.Bind("Cult Leaders", "ShamuraScale", 0.8f, new ConfigDescription("Scale applied to Shamura's non-dungeon cult-leader form.", (AcceptableValueBase)(object)new AcceptableValueRange(0.2f, 2.5f), Array.Empty())); if (Mathf.Approximately(CultLeaderLeshyScale.Value, 1f)) { CultLeaderLeshyScale.Value = 0.8f; } if (Mathf.Approximately(CultLeaderHeketScale.Value, 1f)) { CultLeaderHeketScale.Value = 0.8f; } if (Mathf.Approximately(CultLeaderKallamarScale.Value, 1f)) { CultLeaderKallamarScale.Value = 0.8f; } if (Mathf.Approximately(CultLeaderShamuraScale.Value, 1f)) { CultLeaderShamuraScale.Value = 0.8f; } ToggleKey = config.Bind("Controls", "ToggleAspect", (KeyCode)282, "Toggle the selected bishop aspect."); SpikeKey = config.Bind("Controls", "PrimaryAbility", (KeyCode)283, "Use the selected bishop's primary ability."); VolleyKey = config.Bind("Controls", "SecondaryAbility", (KeyCode)284, "Use the selected bishop's secondary ability."); RoarKey = config.Bind("Controls", "SignatureAbility", (KeyCode)285, "Use the selected bishop's signature ability."); SignatureMouseButton = config.Bind("Controls", "SignatureMouseButton", (KeyCode)325, "Mouse fallback for the selected bishop's signature ability. Mouse2 is the middle mouse button."); ResetKey = config.Bind("Controls", "ResetAspect", (KeyCode)286, "Reset the playable avatar to its idle render state."); ControllerToggleChord = config.Bind("Controls", "ControllerToggleChord", true, "Allow each controller player to toggle their selected bishop with the configured stick-click and D-pad Up chord."); ControllerToggleStickChoice = config.Bind("Controls", "ControllerToggleStick", ControllerToggleStick.LeftStick, "Stick click used with D-pad Up to toggle bishop form. LeftStick avoids conflicts with controller mod menus that use Right Stick Click."); ProjectileAimAssist = config.Bind("Controls", "ProjectileAimAssist", true, "Aim projectile attacks toward nearby active enemies."); ProjectileAimAssistMouseRadius = config.Bind("Controls", "ProjectileAimAssistMouseRadius", 3f, new ConfigDescription("Maximum world-space distance from the mouse target at which a projectile attack snaps to an enemy.", (AcceptableValueBase)(object)new AcceptableValueRange(0.25f, 8f), Array.Empty())); ProjectileAimAssistControllerCone = config.Bind("Controls", "ProjectileAimAssistControllerCone", 55f, new ConfigDescription("Half-angle of the preferred controller aim-assist cone in degrees. If no enemy is inside it, controller attacks fall back to the nearest enemy in range.", (AcceptableValueBase)(object)new AcceptableValueRange(5f, 90f), Array.Empty())); if ((int)ToggleKey.Value == 289) { ToggleKey.Value = (KeyCode)282; } if ((int)SpikeKey.Value == 287) { SpikeKey.Value = (KeyCode)283; } if ((int)VolleyKey.Value == 288) { VolleyKey.Value = (KeyCode)284; } if ((int)RoarKey.Value == 290) { RoarKey.Value = (KeyCode)285; } if (Mathf.Approximately(ProjectileAimAssistControllerCone.Value, 38f)) { ProjectileAimAssistControllerCone.Value = 55f; } config.Save(); VisualScale = config.Bind("Leshy", "VisualScale", 0.72f, new ConfigDescription("Scale applied to Leshy's boss form.", (AcceptableValueBase)(object)new AcceptableValueRange(0.3f, 1.5f), Array.Empty())); SpikeCooldown = config.Bind("Leshy", "SpikeCooldown", 2f, new ConfigDescription("Seconds between spike attacks.", (AcceptableValueBase)(object)new AcceptableValueRange(0.25f, 10f), Array.Empty())); SpikeBaseDamage = config.Bind("Leshy", "SpikeBaseDamage", 1.5f, new ConfigDescription("Base damage of each Leshy spike hit before game combat scaling.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 20f), Array.Empty())); SpikeLineReach = config.Bind("Leshy", "SpikeLineReach", 11.5f, new ConfigDescription("Reliable damage and destruction reach behind Leshy's visual spike line.", (AcceptableValueBase)(object)new AcceptableValueRange(2f, 20f), Array.Empty())); SpikeLineHalfWidth = config.Bind("Leshy", "SpikeLineHalfWidth", 1.65f, new ConfigDescription("Half-width of Leshy's spike-line damage corridor.", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 4f), Array.Empty())); VolleyCooldown = config.Bind("Leshy", "VolleyCooldown", 3f, new ConfigDescription("Seconds between projectile volleys.", (AcceptableValueBase)(object)new AcceptableValueRange(0.25f, 15f), Array.Empty())); VolleyProjectileBaseDamage = config.Bind("Leshy", "VolleyProjectileBaseDamage", 1.25f, new ConfigDescription("Base damage of each Leshy volley grenade before game combat scaling.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 20f), Array.Empty())); VolleyShotCount = config.Bind("Leshy", "VolleyShotCount", 42, new ConfigDescription("Total grenades in Leshy's native fan-shaped volley.", (AcceptableValueBase)(object)new AcceptableValueRange(10, 60), Array.Empty())); VolleyFocusedShots = config.Bind("Leshy", "VolleyFocusedShots", 28, new ConfigDescription("Randomly distributed volley shots that directly target active enemies inside the aimed sector.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 42), Array.Empty())); VolleySpreadRadius = config.Bind("Leshy", "VolleySpreadRadius", 2.25f, new ConfigDescription("Radius used by the non-focused portion of Leshy's volley.", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 6f), Array.Empty())); if (VolleyShotCount.Value == 14) { VolleyShotCount.Value = 42; } if (VolleyFocusedShots.Value == 8) { VolleyFocusedShots.Value = 10; } if (VolleyFocusedShots.Value == 10) { VolleyFocusedShots.Value = 28; } RoarCooldown = config.Bind("Leshy", "RoarCooldown", 5f, new ConfigDescription("Seconds between roar bursts.", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 20f), Array.Empty())); RoarRadius = config.Bind("Leshy", "RoarRadius", 8f, new ConfigDescription("Damage and destruction radius of Leshy's middle-mouse roar shockwave.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 16f), Array.Empty())); RoarDamage = config.Bind("Leshy", "RoarDamage", 4f, new ConfigDescription("Base damage dealt by Leshy's middle-mouse roar shockwave before game combat scaling.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 20f), Array.Empty())); TunnelDamage = config.Bind("Leshy", "TunnelDamage", 0.5f, new ConfigDescription("Damage dealt when Leshy's tunnel trail contacts an enemy.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 5f), Array.Empty())); TunnelHitCooldown = config.Bind("Leshy", "TunnelHitCooldown", 0.35f, new ConfigDescription("Minimum seconds before tunneling can damage the same enemy again.", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 2f), Array.Empty())); if (Mathf.Approximately(RoarRadius.Value, 4.5f)) { RoarRadius.Value = 8f; } if (Mathf.Approximately(RoarDamage.Value, 2f)) { RoarDamage.Value = 4f; } HeketVisualScale = config.Bind("Heket", "VisualScale", 0.68f, new ConfigDescription("Scale applied to Heket's boss form.", (AcceptableValueBase)(object)new AcceptableValueRange(0.3f, 1.5f), Array.Empty())); HeketTongueCooldown = config.Bind("Heket", "TongueCooldown", 2f, new ConfigDescription("Seconds between cursor-targeted tongue strikes.", (AcceptableValueBase)(object)new AcceptableValueRange(0.25f, 10f), Array.Empty())); HeketMortarCooldown = config.Bind("Heket", "MortarCooldown", 3.5f, new ConfigDescription("Seconds between cursor-targeted mortar bursts.", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 15f), Array.Empty())); HeketMortarCount = config.Bind("Heket", "MortarCount", 3, new ConfigDescription("Mortars spawned by each burst.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 7), Array.Empty())); HeketSlamCooldown = config.Bind("Heket", "SlamCooldown", 5f, new ConfigDescription("Seconds between hop shockwaves.", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 20f), Array.Empty())); HeketSlamRadius = config.Bind("Heket", "SlamRadius", 15f, new ConfigDescription("Damage and destruction radius of Heket's manual dodge-hop landing.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 20f), Array.Empty())); HeketSlamDamage = config.Bind("Heket", "SlamDamage", 4f, new ConfigDescription("Base damage of Heket's large Dodge-hop landing before game combat scaling.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 20f), Array.Empty())); HeketLocomotionHopRadius = config.Bind("Heket", "LocomotionHopRadius", 2.25f, new ConfigDescription("Damage radius of Heket's normal traversal-hop landing.", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 6f), Array.Empty())); HeketLocomotionHopDamage = config.Bind("Heket", "LocomotionHopDamage", 0.5f, new ConfigDescription("Base damage of Heket's normal traversal-hop landing before game combat scaling.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 5f), Array.Empty())); HeketBurpCooldown = config.Bind("Heket", "BurpCooldown", 4f, new ConfigDescription("Seconds between Heket's projectile-burp barrages.", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 15f), Array.Empty())); HeketTongueBaseDamage = config.Bind("Heket", "TongueBaseDamage", 4.25f, new ConfigDescription("Base damage of Heket's tongue impact shockwave before game combat scaling.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 20f), Array.Empty())); HeketTongueImpactRadius = config.Bind("Heket", "TongueImpactRadius", 3.75f, new ConfigDescription("Damage and destruction radius at Heket's tongue endpoint.", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 8f), Array.Empty())); HeketMortarBaseDamage = config.Bind("Heket", "MortarBaseDamage", 3f, new ConfigDescription("Base damage of each Heket mortar before game combat scaling.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 20f), Array.Empty())); HeketBurpProjectileBaseDamage = config.Bind("Heket", "BurpProjectileBaseDamage", 1.5f, new ConfigDescription("Base damage of each Heket burp projectile before game combat scaling.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 20f), Array.Empty())); if (Mathf.Approximately(HeketSlamRadius.Value, 4f)) { HeketSlamRadius.Value = 15f; } if (Mathf.Approximately(HeketSlamDamage.Value, 2f)) { HeketSlamDamage.Value = 4f; } if (Mathf.Approximately(HeketTongueBaseDamage.Value, 3.5f)) { HeketTongueBaseDamage.Value = 4.25f; } KallamarVisualScale = config.Bind("Kallamar", "VisualScale", 0.68f, new ConfigDescription("Scale applied to Kallamar's boss form.", (AcceptableValueBase)(object)new AcceptableValueRange(0.3f, 1.5f), Array.Empty())); KallamarDaggerCooldown = config.Bind("Kallamar", "DaggerCooldown", 0.45f, new ConfigDescription("Minimum seconds between dagger strikes. The native clip length, clamped to a short playable recovery, remains the practical repeat limit.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 10f), Array.Empty())); KallamarDaggerRadius = config.Bind("Kallamar", "DaggerRadius", 2.3f, new ConfigDescription("Half-width of Kallamar's forgiving mirrored dagger-hit corridor.", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 5f), Array.Empty())); KallamarDaggerDamage = config.Bind("Kallamar", "DaggerDamage", 2f, new ConfigDescription("Base damage of Kallamar's dagger strike before game combat scaling.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 20f), Array.Empty())); KallamarDaggerReach = config.Bind("Kallamar", "DaggerReach", 5.5f, new ConfigDescription("Reach on each side of Kallamar's mirrored dagger hit area.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 10f), Array.Empty())); KallamarProjectileCooldown = config.Bind("Kallamar", "ProjectileCooldown", 3.5f, new ConfigDescription("Seconds between aimed projectile circles.", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 15f), Array.Empty())); KallamarProjectileBaseDamage = config.Bind("Kallamar", "ProjectileBaseDamage", 1.25f, new ConfigDescription("Base damage of each Kallamar circle projectile before game combat scaling.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 20f), Array.Empty())); KallamarSwordCooldown = config.Bind("Kallamar", "SwordCooldown", 5f, new ConfigDescription("Seconds between charged sword cleaves.", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 20f), Array.Empty())); KallamarSwordRadius = config.Bind("Kallamar", "SwordRadius", 4f, new ConfigDescription("360-degree damage and destruction radius of Kallamar's middle-mouse sword swipe.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 8f), Array.Empty())); KallamarSwordDamage = config.Bind("Kallamar", "SwordDamage", 2.5f, new ConfigDescription("Damage dealt by Kallamar's sword cleave.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 20f), Array.Empty())); KallamarMovementDestructionRadius = config.Bind("Kallamar", "MovementDestructionRadius", 1.65f, new ConfigDescription("Radius in which moving Kallamar crushes rubble and destructible props.", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 4f), Array.Empty())); KallamarTeleportCooldown = config.Bind("Kallamar", "TeleportCooldown", 0.3f, new ConfigDescription("Recovery between Kallamar dodge-teleports; 0.3 seconds matches the vanilla Lamb dodge.", (AcceptableValueBase)(object)new AcceptableValueRange(0.05f, 5f), Array.Empty())); KallamarTeleportDistance = config.Bind("Kallamar", "TeleportDistance", 6f, new ConfigDescription("Directional travel distance of a tapped Kallamar dodge-teleport.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 12f), Array.Empty())); KallamarChargedTeleportDistance = config.Bind("Kallamar", "ChargedTeleportDistance", 7.5f, new ConfigDescription("Maximum room-safe travel distance reached by holding Kallamar's dodge through the vanish animation.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 15f), Array.Empty())); if (Mathf.Approximately(KallamarTeleportCooldown.Value, 2.5f)) { KallamarTeleportCooldown.Value = 0.3f; } if (Mathf.Approximately(KallamarDaggerCooldown.Value, 1.4f)) { KallamarDaggerCooldown.Value = 0.2f; } if (Mathf.Approximately(KallamarDaggerCooldown.Value, 0.2f)) { KallamarDaggerCooldown.Value = 0.45f; } if (Mathf.Approximately(KallamarDaggerDamage.Value, 1.25f)) { KallamarDaggerDamage.Value = 2f; } if (Mathf.Approximately(KallamarDaggerRadius.Value, 1.7f)) { KallamarDaggerRadius.Value = 2.3f; } if (Mathf.Approximately(KallamarDaggerReach.Value, 4.5f)) { KallamarDaggerReach.Value = 5.5f; } if (Mathf.Approximately(KallamarSwordRadius.Value, 3f)) { KallamarSwordRadius.Value = 4f; } ShamuraVisualScale = config.Bind("Shamura", "VisualScale", 0.68f, new ConfigDescription("Scale applied to Shamura's boss form.", (AcceptableValueBase)(object)new AcceptableValueRange(0.3f, 1.5f), Array.Empty())); ShamuraSlashCooldown = config.Bind("Shamura", "SlashCooldown", 1.25f, new ConfigDescription("Seconds between Shamura's local melee slashes.", (AcceptableValueBase)(object)new AcceptableValueRange(0.2f, 10f), Array.Empty())); ShamuraSlashRadius = config.Bind("Shamura", "SlashRadius", 3.8f, new ConfigDescription("Damage and destruction radius around Shamura during the melee slash.", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 7f), Array.Empty())); ShamuraSlashBaseDamage = config.Bind("Shamura", "SlashBaseDamage", 2.25f, new ConfigDescription("Base damage of Shamura's melee slash before game combat scaling.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 20f), Array.Empty())); ShamuraBombCooldown = config.Bind("Shamura", "BombCooldown", 3.8f, new ConfigDescription("Seconds between Shamura's aimed grenade spreads.", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 15f), Array.Empty())); ShamuraBombCount = config.Bind("Shamura", "BombCount", 28, new ConfigDescription("Grenades launched by Shamura's aimed spread.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 40), Array.Empty())); ShamuraBombFocusedCount = config.Bind("Shamura", "BombFocusedCount", 8, new ConfigDescription("Grenades in each Shamura spread that directly target active enemies.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 24), Array.Empty())); ShamuraBombSpreadRadius = config.Bind("Shamura", "BombSpreadRadius", 3.2f, new ConfigDescription("Radius used by Shamura's collateral grenade landings around the aimed point.", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 7f), Array.Empty())); ShamuraBombBaseDamage = config.Bind("Shamura", "BombBaseDamage", 1.1f, new ConfigDescription("Base damage of each Shamura grenade before game combat scaling.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 20f), Array.Empty())); ShamuraJumpCooldown = config.Bind("Shamura", "JumpCooldown", 5.5f, new ConfigDescription("Seconds between Shamura's three-impact jump barrage.", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 20f), Array.Empty())); ShamuraJumpRadius = config.Bind("Shamura", "JumpRadius", 3.4f, new ConfigDescription("Local damage and destruction radius of each Shamura jump landing.", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 8f), Array.Empty())); ShamuraJumpBaseDamage = config.Bind("Shamura", "JumpBaseDamage", 2f, new ConfigDescription("Base damage of each Shamura jump landing before game combat scaling.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 20f), Array.Empty())); if (Mathf.Approximately(ShamuraSlashRadius.Value, 1.8f)) { ShamuraSlashRadius.Value = 3.8f; } if (Mathf.Approximately(ShamuraJumpRadius.Value, 2.35f)) { ShamuraJumpRadius.Value = 3.4f; } if (ShamuraBombCount.Value == 7) { ShamuraBombCount.Value = 28; } if (ShamuraBombFocusedCount.Value == 3) { ShamuraBombFocusedCount.Value = 8; } DebugLogging = config.Bind("Debug", "DebugLogging", false, "Write verbose aspect lifecycle messages to the BepInEx log."); config.Save(); } internal static string GetSelectedAspect(int playerSlot) { if (playerSlot != 1 || SelectedAspectP2 == null) { return SelectedAspect.Value; } return SelectedAspectP2.Value; } internal static void SetSelectedAspect(int playerSlot, string aspectId) { if (playerSlot == 1 && SelectedAspectP2 != null) { SelectedAspectP2.Value = aspectId; } else { SelectedAspect.Value = aspectId; } } } internal static class BishopAspectIds { internal const int LeshyFleece = 20001; internal const int HeketFleece = 20002; internal const int KallamarFleece = 20003; internal const int ShamuraFleece = 20004; internal const int NarinderFleece = 20005; } internal sealed class BishopAspectController : MonoBehaviour { private sealed class PlayerRendererState { internal Renderer Renderer; internal bool ForceRenderingOff; } private const int AttackActionId = 2; private const int CurseActionId = 13; private const int DodgeActionId = 16; private const int HeavyAttackActionId = 94; private readonly LeshyAspect _leshy = new LeshyAspect(); private readonly HeketAspect _heket = new HeketAspect(); private readonly KallamarAspect _kallamar = new KallamarAspect(); private readonly ShamuraAspect _shamura = new ShamuraAspect(); private readonly CultLeaderPuppet _cultLeader = new CultLeaderPuppet(); private readonly List _playerRendererStates = new List(); private BishopAspect _activeAspect; private PlayerFarming _player; private bool _activationPending; private int _lastCapturedAttackFrame = -1; private int _lastCapturedSecondaryFrame = -1; private int _lastCapturedSignatureFrame = -1; private int _lastCapturedDodgeFrame = -1; private bool _autoActivationBlockedUntilDungeonExit; private float _nextAutoActivationTime; private bool _deathPresentationInProgress; private bool _lifecycleTransitionInProgress; private bool _deactivationPending; private bool _leaderActivationPending; private bool _leaderDeactivationPending; private bool _leaderDesiredOutside; private bool _leaderRestorePending; private bool _leaderToBossPending; private bool _formTransitionInProgress; private bool _locationModeInitialized; private bool _wasInDungeon; private bool _transformedThisDungeon; private int _playerSlot; internal bool IsActive { get { if (_activeAspect != null) { return _activeAspect.IsActive; } return false; } } internal bool IsCultLeaderActive => _cultLeader.IsActive; internal PlayerFarming CurrentPlayer => _player; internal int PlayerSlot => _playerSlot; private string PlayerLabel => "P" + (_playerSlot + 1); internal bool ProtectsWithLeshyTunnel(Health health) { if ((Object)(object)health != (Object)null && (Object)(object)_player != (Object)null && (Object)(object)_player.health == (Object)(object)health && _activeAspect == _leshy) { return _leshy.IsTunneling; } return false; } internal void Initialize(int playerSlot) { _playerSlot = Mathf.Clamp(playerSlot, 0, 1); } private void Update() { //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) if (!PlayableBishopsConfig.Enabled.Value) { if (IsActive) { Deactivate(); } if (IsCultLeaderActive || _leaderActivationPending || _leaderDeactivationPending || _formTransitionInProgress) { _leaderDesiredOutside = false; DeactivateCultLeaderImmediate(restorePlayer: true); } return; } UpdateLocationMode(); UpdateAutomaticActivation(); PlayerFarming player = (((Object)(object)_player != (Object)null) ? _player : GetSlotPlayer()); if ((_playerSlot == 0 && Input.GetKeyDown(PlayableBishopsConfig.ToggleKey.Value)) || IsControllerTogglePressed(player)) { Toggle(); } if (!IsActive) { if (IsCultLeaderActive && !IsPlayerUsable(_player)) { PlayableBishopsPlugin.Log.LogWarning((object)("Automatically hiding the cult-leader form because its player became unavailable: " + DescribePlayer(_player))); DeactivateCultLeaderImmediate(restorePlayer: true); _leaderRestorePending = _leaderDesiredOutside && !GameManager.IsDungeon(PlayerFarming.Location); } } else if (!IsPlayerUsable(_player)) { if ((Object)(object)_player != (Object)null && (Object)(object)_player.health != (Object)null && ((Health)_player.health).HP <= 0f) { BeginDeathPresentation(); return; } PlayableBishopsPlugin.Log.LogWarning((object)("Automatically disabling " + _activeAspect.DisplayName + " because the player became unusable: " + DescribePlayer(_player))); Deactivate(); } else if (!_activeAspect.IsValid) { PlayableBishopsPlugin.Log.LogWarning((object)("Automatically disabling " + _activeAspect.DisplayName + " because the retained boss puppet became invalid.")); DeactivateImmediate(); } else if (!_activationPending && !_lifecycleTransitionInProgress && !_deathPresentationInProgress) { if (_playerSlot == 0 && Input.GetKeyDown(PlayableBishopsConfig.SpikeKey.Value)) { _activeAspect.TryPrimary(_player); } if (_playerSlot == 0 && Input.GetKeyDown(PlayableBishopsConfig.VolleyKey.Value)) { _activeAspect.TrySecondary(_player); } if (_playerSlot == 0 && (Input.GetKeyDown(PlayableBishopsConfig.RoarKey.Value) || Input.GetKeyDown(PlayableBishopsConfig.SignatureMouseButton.Value))) { _activeAspect.TrySignature((MonoBehaviour)(object)this, _player); } if (_playerSlot == 0 && Input.GetKeyDown(PlayableBishopsConfig.ResetKey.Value)) { _activeAspect.ResetVisualState(); } PollControllerCombatInput(_player); } } private bool IsControllerTogglePressed(PlayerFarming player) { if (PlayableBishopsConfig.ControllerToggleChord == null || !PlayableBishopsConfig.ControllerToggleChord.Value || (Object)(object)player == (Object)null || player.rewiredPlayer == null || Time.timeScale <= 0.01f) { return false; } foreach (Joystick joystick in player.rewiredPlayer.controllers.Joysticks) { if (joystick == null || !((Controller)joystick).isConnected || !((Controller)joystick).enabled) { continue; } IGamepadTemplate template = ((Controller)joystick).GetTemplate(); if (template == null || template.dPad == null || template.dPad.up == null) { continue; } IControllerTemplateButton val = ((PlayableBishopsConfig.ControllerToggleStickChoice.Value != ControllerToggleStick.RightStick) ? ((template.leftStick != null) ? template.leftStick.press : null) : ((template.rightStick != null) ? template.rightStick.press : null)); if (val != null) { bool value = val.value; bool value2 = template.dPad.up.value; if ((value && template.dPad.up.justPressed) || (value2 && val.justPressed)) { return true; } } } return false; } private void PollControllerCombatInput(PlayerFarming player) { if (!((Object)(object)player == (Object)null) && player.rewiredPlayer != null && player.rewiredPlayer.controllers.Joysticks.Count != 0) { Player rewiredPlayer = player.rewiredPlayer; if (rewiredPlayer.GetButtonDown(2)) { CaptureBasicAttack(player); } if (rewiredPlayer.GetButtonDown(13)) { CaptureSecondaryAttack(player); } if (rewiredPlayer.GetButtonDown(94)) { CaptureSignatureAttack(player); } if (rewiredPlayer.GetButtonDown(16)) { CaptureDodge(player); } } } private void LateUpdate() { if (IsActive && IsPlayerUsable(_player)) { _activeAspect.Follow(_player); KeepPlayerHidden(); } else if (IsCultLeaderActive && IsPlayerUsable(_player)) { _cultLeader.Follow(_player); KeepPlayerHidden(); } } private void Toggle() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) if (_activationPending || _leaderActivationPending || _leaderDeactivationPending || _lifecycleTransitionInProgress || _deathPresentationInProgress || _formTransitionInProgress) { PlayableBishopsLog.Debug("Aspect toggle ignored while a lifecycle presentation is running."); return; } if (!GameManager.IsDungeon(PlayerFarming.Location) && PlayableBishopsConfig.CultLeaderFormsOutsideDungeons.Value) { ToggleCultLeader(); return; } BishopAspectDefinition bishopAspectDefinition = BishopAspectRegistry.Get(PlayableBishopsConfig.GetSelectedAspect(_playerSlot)); PlayableBishopsPlugin.Log.LogInfo((object)(PlayerLabel + " " + bishopAspectDefinition.DisplayName + " toggle requested; current state is " + (IsActive ? "active" : "inactive") + ".")); if (IsActive) { _autoActivationBlockedUntilDungeonExit = GameManager.IsDungeon(PlayerFarming.Location); Deactivate(); return; } if (_activationPending) { PlayableBishopsLog.Debug("Aspect activation is already pending."); return; } PlayerFarming slotPlayer = GetSlotPlayer(); if (!IsPlayerUsable(slotPlayer)) { PlayableBishopsPlugin.Log.LogWarning((object)(bishopAspectDefinition.DisplayName + " aspect needs an active player.")); return; } if (!PlayableBishopsConfig.AllowOutsideDungeons.Value && !GameManager.IsDungeon(PlayerFarming.Location)) { PlayableBishopsPlugin.Log.LogWarning((object)(bishopAspectDefinition.DisplayName + " aspect is currently limited to dungeon locations. Set AllowOutsideDungeons=true to override.")); return; } if (string.Equals(bishopAspectDefinition.Id, "None", StringComparison.OrdinalIgnoreCase)) { PlayableBishopsPlugin.Log.LogInfo((object)"No Bishop Aspect is selected. Choose one from the altar row."); return; } BishopAspect bishopAspect = ResolveAspect(bishopAspectDefinition.Id); if (!bishopAspectDefinition.Implemented || bishopAspect == null) { PlayableBishopsPlugin.Log.LogWarning((object)(bishopAspectDefinition.DisplayName + " is registered but does not have a playable controller yet.")); return; } _autoActivationBlockedUntilDungeonExit = false; BeginActivation(slotPlayer, bishopAspect, automatic: false, playSpawnPresentation: true); } private void ToggleCultLeader() { BishopAspectDefinition bishopAspectDefinition = BishopAspectRegistry.Get(PlayableBishopsConfig.GetSelectedAspect(_playerSlot)); PlayableBishopsPlugin.Log.LogInfo((object)(PlayerLabel + " " + bishopAspectDefinition.DisplayName + " cult-leader toggle requested; current state is " + (IsCultLeaderActive ? "active" : "inactive") + ".")); if (IsCultLeaderActive) { _leaderDesiredOutside = false; BeginCultLeaderDeactivation(); return; } if (string.Equals(bishopAspectDefinition.Id, "None", StringComparison.OrdinalIgnoreCase)) { PlayableBishopsPlugin.Log.LogInfo((object)"No Bishop Aspect is selected. Choose one from the altar row."); return; } PlayerFarming slotPlayer = GetSlotPlayer(); if (!IsPlayerUsable(slotPlayer)) { PlayableBishopsPlugin.Log.LogWarning((object)(bishopAspectDefinition.DisplayName + " cult-leader form needs an active player.")); return; } CultLeaderDefinition cultLeaderDefinition = CultLeaderRegistry.Get(bishopAspectDefinition.Id); if (!bishopAspectDefinition.Implemented || cultLeaderDefinition == null) { PlayableBishopsPlugin.Log.LogWarning((object)(bishopAspectDefinition.DisplayName + " does not have a cult-leader presentation configured.")); return; } _leaderDesiredOutside = true; _leaderRestorePending = false; BeginCultLeaderActivation(slotPlayer, cultLeaderDefinition, playPlayerWarp: true); } private void BeginCultLeaderActivation(PlayerFarming player, CultLeaderDefinition definition, bool playPlayerWarp) { if (!_leaderActivationPending && !_formTransitionInProgress) { _leaderActivationPending = true; ((MonoBehaviour)this).StartCoroutine(CultLeaderActivationRoutine(player, definition, playPlayerWarp)); } } private IEnumerator CultLeaderActivationRoutine(PlayerFarming player, CultLeaderDefinition definition, bool playPlayerWarp) { bool created = false; string error = null; _player = player; yield return _cultLeader.Activate((MonoBehaviour)(object)this, player, definition, delegate(bool success, string reason) { created = success; error = reason; }); if (!created || !IsPlayerUsable(player) || GameManager.IsDungeon(PlayerFarming.Location)) { _leaderActivationPending = false; _cultLeader.Deactivate(); RestorePlayer(); if (!created) { _leaderDesiredOutside = false; PlayableBishopsPlugin.Log.LogError((object)("Could not activate " + definition.DisplayName + " cult-leader form: " + (error ?? "unknown asset error"))); } yield break; } _cultLeader.Follow(player); _cultLeader.SetAlpha(0f); float transitionDuration = Mathf.Max(0.1f, PlayableBishopsConfig.CultLeaderTransitionDuration.Value); if (playPlayerWarp) { PlayPlayerWarp(player, warpOut: true); yield return WaitForCultLeader(player, transitionDuration); } if (!IsPlayerUsable(player) || GameManager.IsDungeon(PlayerFarming.Location)) { _leaderActivationPending = false; _cultLeader.Deactivate(); RestorePlayer(); yield break; } HidePlayer(player); _cultLeader.Follow(player); _cultLeader.BeginReveal(); yield return BishopPresentation.Fade(_cultLeader.Spine, 0f, 1f, transitionDuration); _leaderActivationPending = false; PlayableBishopsPlugin.Log.LogInfo((object)(PlayerLabel + " " + definition.DisplayName + " cult-leader form active outside the dungeon.")); } private void BeginCultLeaderDeactivation() { if (!_leaderDeactivationPending) { _leaderDeactivationPending = true; ((MonoBehaviour)this).StartCoroutine(CultLeaderDeactivationRoutine()); } } private IEnumerator CultLeaderDeactivationRoutine() { PlayerFarming player = _player; float duration = Mathf.Max(0.1f, PlayableBishopsConfig.CultLeaderTransitionDuration.Value); if (_cultLeader.IsValid) { yield return BishopPresentation.Fade(_cultLeader.Spine, 1f, 0f, duration); } _cultLeader.Deactivate(); RestorePlayer(); if (IsPlayerUsable(player)) { PlayPlayerWarp(player, warpOut: false); } _leaderDeactivationPending = false; PlayableBishopsLog.Debug("Cult-leader form inactive."); } private IEnumerator WaitForCultLeader(PlayerFarming player, float duration) { float elapsed = 0f; while (IsPlayerUsable(player)) { float num; elapsed = (num = elapsed + Time.unscaledDeltaTime); if (num < duration) { _cultLeader.Follow(player); yield return null; continue; } break; } } private static void PlayPlayerWarp(PlayerFarming player, bool warpOut) { //IL_00a5: Unknown result type (might be due to invalid IL or missing references) if (!IsPlayerUsable(player)) { return; } try { string text = (warpOut ? "warp-out-down" : "warp-in-up"); if ((Object)(object)player.Spine != (Object)null && ((SkeletonRenderer)player.Spine).Skeleton != null && ((SkeletonRenderer)player.Spine).Skeleton.Data.FindAnimation(text) != null) { player.Spine.AnimationState.SetAnimation(0, text, false); player.Spine.AnimationState.AddAnimation(0, "idle", true, 0f); } if ((Object)(object)AudioManager.Instance != (Object)null) { AudioManager.Instance.PlayOneShot(warpOut ? "event:/enemy/teleport_away" : "event:/enemy/teleport_appear", ((Component)player).transform.position); } } catch (Exception ex) { PlayableBishopsLog.Debug("Player cult-leader warp presentation failed: " + ex.GetBaseException().Message); } } private void UpdateLocationMode() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) bool flag = GameManager.IsDungeon(PlayerFarming.Location); if (!_locationModeInitialized) { _locationModeInitialized = true; _wasInDungeon = flag; } else { if (_wasInDungeon == flag) { return; } _wasInDungeon = flag; if (flag) { _transformedThisDungeon = false; _leaderToBossPending = _leaderDesiredOutside; _leaderRestorePending = false; _autoActivationBlockedUntilDungeonExit = false; if (IsCultLeaderActive || _leaderActivationPending || _leaderDeactivationPending) { DeactivateCultLeaderImmediate(restorePlayer: true); } PlayableBishopsLog.Debug("Entered a dungeon; controller switched to boss-form toggling."); return; } _leaderToBossPending = false; _transformedThisDungeon = false; _autoActivationBlockedUntilDungeonExit = false; _nextAutoActivationTime = 0f; if (_formTransitionInProgress) { DeactivateCultLeaderImmediate(restorePlayer: true); } if (IsActive || _activationPending || _deactivationPending) { DeactivateImmediate(); } _leaderRestorePending = _leaderDesiredOutside; PlayableBishopsLog.Debug("Left the dungeon; controller switched to cult-leader toggling."); } } private void BeginLeaderToBossHandoff(PlayerFarming player, BishopAspect aspect, CultLeaderDefinition definition) { if (!_formTransitionInProgress) { _formTransitionInProgress = true; ((MonoBehaviour)this).StartCoroutine(LeaderToBossHandoffRoutine(player, aspect, definition)); } } private IEnumerator LeaderToBossHandoffRoutine(PlayerFarming player, BishopAspect aspect, CultLeaderDefinition definition) { bool created = false; string error = null; yield return _cultLeader.Activate((MonoBehaviour)(object)this, player, definition, delegate(bool success, string reason) { created = success; error = reason; }); if (created && IsPlayerUsable(player) && GameManager.IsDungeon(PlayerFarming.Location)) { _player = player; HidePlayer(player); _cultLeader.Follow(player); _cultLeader.SetAlpha(1f); float num = _cultLeader.BeginTransformation(); if (num <= 0f) { num = Mathf.Max(0.1f, PlayableBishopsConfig.CultLeaderTransitionDuration.Value); yield return BishopPresentation.Fade(_cultLeader.Spine, 1f, 0f, num); } else { yield return WaitForCultLeader(player, num); } _cultLeader.Deactivate(); } else if (!created) { PlayableBishopsPlugin.Log.LogWarning((object)(definition.DisplayName + " cult-leader transformation could not be shown: " + (error ?? "asset unavailable") + ". Activating the boss directly.")); } else { _cultLeader.Deactivate(); } _leaderToBossPending = false; _transformedThisDungeon = true; _formTransitionInProgress = false; if (!IsPlayerUsable(player) || !GameManager.IsDungeon(PlayerFarming.Location)) { RestorePlayer(); } else { BeginActivation(player, aspect, automatic: true, playSpawnPresentation: false); } } private void DeactivateCultLeaderImmediate(bool restorePlayer) { ((MonoBehaviour)this).StopAllCoroutines(); _leaderActivationPending = false; _leaderDeactivationPending = false; _formTransitionInProgress = false; _cultLeader.Deactivate(); if (restorePlayer) { RestorePlayer(); } } private void BeginActivation(PlayerFarming player, BishopAspect aspect, bool automatic, bool playSpawnPresentation) { _activationPending = true; ((MonoBehaviour)this).StartCoroutine(ActivateRoutine(player, aspect, automatic, playSpawnPresentation)); } private IEnumerator ActivateRoutine(PlayerFarming player, BishopAspect aspect, bool automatic, bool playSpawnPresentation) { bool created = false; string error = null; _player = player; _activeAspect = aspect; yield return aspect.Activate(this, player, delegate(bool success, string reason) { created = success; error = reason; }); _activationPending = false; if (!created || !IsPlayerUsable(player)) { aspect.Deactivate(); if (_activeAspect == aspect) { _activeAspect = null; } RestorePlayer(); PlayableBishopsPlugin.Log.LogError((object)("Could not activate " + aspect.DisplayName + " aspect: " + (error ?? "player became unavailable"))); if (automatic) { _autoActivationBlockedUntilDungeonExit = true; } yield break; } HidePlayer(player); aspect.Follow(player); _lifecycleTransitionInProgress = true; float num = 0f; try { if (playSpawnPresentation) { num = aspect.BeginSpawnPresentation(); } } catch (Exception ex) { PlayableBishopsPlugin.Log.LogError((object)(aspect.DisplayName + " spawn presentation failed: " + ex.GetBaseException().Message)); } yield return WaitForPresentation(aspect, Mathf.Max(0f, num)); if (_activeAspect == aspect) { try { aspect.CompleteSpawnPresentation(); } catch (Exception ex2) { PlayableBishopsPlugin.Log.LogError((object)(aspect.DisplayName + " spawn completion failed: " + ex2.GetBaseException().Message)); } _lifecycleTransitionInProgress = false; PlayableBishopsPlugin.Log.LogInfo((object)(aspect.DisplayName + " aspect active.")); } } private void UpdateAutomaticActivation() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if (!GameManager.IsDungeon(PlayerFarming.Location)) { _autoActivationBlockedUntilDungeonExit = false; _nextAutoActivationTime = 0f; if (_leaderRestorePending && _leaderDesiredOutside && PlayableBishopsConfig.CultLeaderFormsOutsideDungeons.Value && !IsCultLeaderActive && !_leaderActivationPending && !_leaderDeactivationPending && !_formTransitionInProgress) { PlayerFarming slotPlayer = GetSlotPlayer(); CultLeaderDefinition cultLeaderDefinition = CultLeaderRegistry.Get(BishopAspectRegistry.Get(PlayableBishopsConfig.GetSelectedAspect(_playerSlot)).Id); if (IsPlayerUsable(slotPlayer) && cultLeaderDefinition != null) { _leaderRestorePending = false; BeginCultLeaderActivation(slotPlayer, cultLeaderDefinition, playPlayerWarp: false); } } } else { if (IsActive || _activationPending || _lifecycleTransitionInProgress || _formTransitionInProgress || _autoActivationBlockedUntilDungeonExit || Time.time < _nextAutoActivationTime) { return; } PlayerFarming slotPlayer2 = GetSlotPlayer(); if (!IsPlayerUsable(slotPlayer2)) { return; } BishopAspectDefinition bishopAspectDefinition = BishopAspectRegistry.Get(PlayableBishopsConfig.GetSelectedAspect(_playerSlot)); if (string.Equals(bishopAspectDefinition.Id, "None", StringComparison.OrdinalIgnoreCase)) { _leaderToBossPending = false; return; } BishopAspect bishopAspect = ResolveAspect(bishopAspectDefinition.Id); if (!bishopAspectDefinition.Implemented || bishopAspect == null) { _leaderToBossPending = false; return; } if (_leaderToBossPending && !_transformedThisDungeon) { CultLeaderDefinition cultLeaderDefinition2 = CultLeaderRegistry.Get(bishopAspectDefinition.Id); if (cultLeaderDefinition2 != null) { _nextAutoActivationTime = Time.time + 2f; PlayableBishopsPlugin.Log.LogInfo((object)("Transforming " + PlayerLabel + " " + bishopAspectDefinition.DisplayName + " from cult-leader form into the dungeon boss form.")); BeginLeaderToBossHandoff(slotPlayer2, bishopAspect, cultLeaderDefinition2); return; } _leaderToBossPending = false; } if (PlayableBishopsConfig.AutoActivateInDungeons.Value) { _nextAutoActivationTime = Time.time + 2f; PlayableBishopsPlugin.Log.LogInfo((object)("Automatically activating " + PlayerLabel + " Bishop Aspect: " + bishopAspectDefinition.DisplayName + ".")); BeginActivation(slotPlayer2, bishopAspect, automatic: true, playSpawnPresentation: true); } } } private void HidePlayer(PlayerFarming player) { if (!((Object)(object)player == (Object)null) && !((Object)(object)player.Spine == (Object)null)) { RecoverPlayerAttackState(player); RestorePlayerRenderers(); ((Component)player.Spine).gameObject.SetActive(true); Renderer[] componentsInChildren = ((Component)player.Spine).gameObject.GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { _playerRendererStates.Add(new PlayerRendererState { Renderer = val, ForceRenderingOff = val.forceRenderingOff }); val.forceRenderingOff = true; } } } private void KeepPlayerHidden() { for (int i = 0; i < _playerRendererStates.Count; i++) { Renderer renderer = _playerRendererStates[i].Renderer; if ((Object)(object)renderer != (Object)null) { renderer.forceRenderingOff = true; } } } private void RestorePlayer() { RestorePlayerRenderers(); RecoverPlayerAttackState(_player); _player = null; } private void RestorePlayerRenderers() { for (int i = 0; i < _playerRendererStates.Count; i++) { PlayerRendererState playerRendererState = _playerRendererStates[i]; if ((Object)(object)playerRendererState.Renderer != (Object)null) { playerRendererState.Renderer.forceRenderingOff = playerRendererState.ForceRenderingOff; } } _playerRendererStates.Clear(); } private static void RecoverPlayerAttackState(PlayerFarming player) { //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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Invalid comparison between Unknown and I4 //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Invalid comparison between Unknown and I4 //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Invalid comparison between Unknown and I4 //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Invalid comparison between Unknown and I4 //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Invalid comparison between Unknown and I4 if ((Object)(object)player == (Object)null) { return; } if ((Object)(object)player.playerWeapon != (Object)null) { player.playerWeapon.StopAttackRoutine(); } player.HoldingAttack = false; if ((Object)(object)player.state == (Object)null) { return; } State cURRENT_STATE = player.state.CURRENT_STATE; if ((int)cURRENT_STATE == 2 || (int)cURRENT_STATE == 4 || (int)cURRENT_STATE == 5 || (int)cURRENT_STATE == 46 || (int)cURRENT_STATE == 54) { player.state.CURRENT_STATE = (State)0; if ((Object)(object)player.playerController != (Object)null) { player.playerController.speed = player.playerController.GetPlayerMaxSpeed(); } PlayableBishopsPlugin.Log.LogInfo((object)"Recovered the underlying player from a weapon attack state."); } } internal bool BlocksBasicAttack(PlayerFarming player) { if (IsActive && (Object)(object)_player != (Object)null) { return (Object)(object)player == (Object)(object)_player; } return false; } internal bool BlocksCombatInput(PlayerFarming player) { return BlocksBasicAttack(player); } internal bool BlocksDodgeInput(PlayerFarming player) { if (BlocksBasicAttack(player) && _activeAspect != null) { return _activeAspect.UsesDodgeAbility; } return false; } internal void CaptureBasicAttack(PlayerFarming player) { if (CanCaptureCombatInput(player) && _lastCapturedAttackFrame != Time.frameCount) { _lastCapturedAttackFrame = Time.frameCount; _activeAspect.TryPrimary(_player); } } internal void CaptureSecondaryAttack(PlayerFarming player) { if (CanCaptureCombatInput(player) && _lastCapturedSecondaryFrame != Time.frameCount) { _lastCapturedSecondaryFrame = Time.frameCount; _activeAspect.TrySecondary(_player); } } internal void CaptureSignatureAttack(PlayerFarming player) { if (CanCaptureCombatInput(player) && _lastCapturedSignatureFrame != Time.frameCount) { _lastCapturedSignatureFrame = Time.frameCount; _activeAspect.TrySignature((MonoBehaviour)(object)this, _player); } } internal void CaptureDodge(PlayerFarming player) { if (CanCaptureCombatInput(player) && BlocksDodgeInput(player) && _lastCapturedDodgeFrame != Time.frameCount) { _lastCapturedDodgeFrame = Time.frameCount; _activeAspect.TryDodge((MonoBehaviour)(object)this, _player); } } internal void SelectAspect(string aspectId) { BishopAspectDefinition bishopAspectDefinition = BishopAspectRegistry.Get(aspectId); _leaderDesiredOutside = false; _leaderRestorePending = false; _leaderToBossPending = false; if (IsCultLeaderActive || _leaderActivationPending || _leaderDeactivationPending) { DeactivateCultLeaderImmediate(restorePlayer: true); } if (IsActive) { Deactivate(); } PlayableBishopsConfig.SetSelectedAspect(_playerSlot, bishopAspectDefinition.Id); PlayableBishopsPlugin.Log.LogInfo((object)("Selected " + PlayerLabel + " Bishop Aspect: " + bishopAspectDefinition.DisplayName + ".")); } internal void Deactivate() { if (!_deactivationPending && !_deathPresentationInProgress) { BishopAspect activeAspect = _activeAspect; if (activeAspect == null) { DeactivateImmediate(); return; } ((MonoBehaviour)this).StopAllCoroutines(); _activationPending = false; _lifecycleTransitionInProgress = true; _deactivationPending = true; ((MonoBehaviour)this).StartCoroutine(DeactivateRoutine(activeAspect)); } } private IEnumerator DeactivateRoutine(BishopAspect aspect) { float num = 0f; try { num = aspect.BeginDespawnPresentation(); } catch (Exception ex) { PlayableBishopsPlugin.Log.LogError((object)(aspect.DisplayName + " despawn presentation failed: " + ex.GetBaseException().Message)); } yield return WaitForPresentation(aspect, Mathf.Max(0f, num)); CompleteDeactivation(aspect); } private IEnumerator WaitForPresentation(BishopAspect aspect, float duration) { float elapsed = 0f; while (_activeAspect == aspect) { float num; elapsed = (num = elapsed + Time.unscaledDeltaTime); if (num < duration) { if (IsPlayerUsable(_player)) { KeepPlayerHidden(); } yield return null; continue; } break; } } private bool CanCaptureCombatInput(PlayerFarming player) { if (BlocksBasicAttack(player) && (Object)(object)_player != (Object)null && !_activationPending && !_lifecycleTransitionInProgress) { return !_deathPresentationInProgress; } return false; } private void DeactivateImmediate() { ((MonoBehaviour)this).StopAllCoroutines(); CompleteDeactivation(_activeAspect); } private void CompleteDeactivation(BishopAspect aspect) { _deathPresentationInProgress = false; _lifecycleTransitionInProgress = false; _deactivationPending = false; _activationPending = false; if (_activeAspect == aspect) { _activeAspect = null; } if (aspect != null) { try { aspect.Deactivate(); } catch (Exception ex) { PlayableBishopsPlugin.Log.LogError((object)(aspect.DisplayName + " cleanup failed: " + ex.GetBaseException().Message)); } } RestorePlayer(); PlayableBishopsLog.Debug("Bishop aspect inactive."); } internal void Shutdown() { DeactivateImmediate(); _cultLeader.Dispose(); _leshy.Dispose(); _heket.Dispose(); _kallamar.Dispose(); _shamura.Dispose(); } private BishopAspect ResolveAspect(string aspectId) { if (string.Equals(aspectId, "Leshy", StringComparison.OrdinalIgnoreCase)) { return _leshy; } if (string.Equals(aspectId, "Heket", StringComparison.OrdinalIgnoreCase)) { return _heket; } if (string.Equals(aspectId, "Kallamar", StringComparison.OrdinalIgnoreCase)) { return _kallamar; } if (string.Equals(aspectId, "Shamura", StringComparison.OrdinalIgnoreCase)) { return _shamura; } return null; } private void BeginDeathPresentation() { if (!_deathPresentationInProgress && _activeAspect != null) { _deathPresentationInProgress = true; _lifecycleTransitionInProgress = true; _deactivationPending = false; _activationPending = false; ((MonoBehaviour)this).StopAllCoroutines(); float num = 0f; try { num = _activeAspect.BeginDeathPresentation(); } catch (Exception ex) { PlayableBishopsPlugin.Log.LogError((object)(_activeAspect.DisplayName + " death presentation failed: " + ex.GetBaseException().Message)); } PlayableBishopsPlugin.Log.LogInfo((object)("Playing " + _activeAspect.DisplayName + " death presentation.")); ((MonoBehaviour)this).StartCoroutine(DeathPresentationRoutine(Mathf.Max(0.1f, num))); } } private IEnumerator DeathPresentationRoutine(float duration) { float elapsed = 0f; while (_activeAspect != null) { float num; elapsed = (num = elapsed + Time.unscaledDeltaTime); if (!(num < duration)) { break; } KeepPlayerHidden(); yield return null; } CompleteDeactivation(_activeAspect); } private static bool IsPlayerUsable(PlayerFarming player) { if ((Object)(object)player != (Object)null && (Object)(object)((Component)player).gameObject != (Object)null && ((Component)player).gameObject.activeInHierarchy && (Object)(object)player.health != (Object)null) { return ((Health)player.health).HP > 0f; } return false; } private PlayerFarming GetSlotPlayer() { if (PlayerFarming.players == null || _playerSlot < 0 || _playerSlot >= PlayerFarming.players.Count) { return null; } return PlayerFarming.players[_playerSlot]; } private static string DescribePlayer(PlayerFarming player) { if ((Object)(object)player == (Object)null) { return "PlayerFarming reference is null"; } if ((Object)(object)((Component)player).gameObject == (Object)null) { return "player GameObject is missing"; } if (!((Component)player).gameObject.activeInHierarchy) { return "player GameObject is inactive"; } if ((Object)(object)player.health == (Object)null) { return "player Health is missing"; } return "player HP is " + ((Health)player.health).HP.ToString("F2"); } } internal abstract class BishopAspect { internal abstract string Id { get; } internal abstract string DisplayName { get; } internal abstract bool IsActive { get; } internal abstract bool IsValid { get; } internal virtual bool UsesDodgeAbility => false; internal abstract IEnumerator Activate(BishopAspectController controller, PlayerFarming player, Action completed); internal abstract void Follow(PlayerFarming player); internal abstract void TryPrimary(PlayerFarming player); internal abstract void TrySecondary(PlayerFarming player); internal abstract void TrySignature(MonoBehaviour host, PlayerFarming player); internal virtual void TryDodge(MonoBehaviour host, PlayerFarming player) { } internal virtual float BeginSpawnPresentation() { return 0f; } internal virtual void CompleteSpawnPresentation() { } internal virtual float BeginDespawnPresentation() { return 0f; } internal virtual float BeginDeathPresentation() { return 0f; } internal abstract void ResetVisualState(); internal abstract void Deactivate(); internal abstract void Dispose(); } internal static class BishopPresentation { internal static float GetAnimationDuration(SkeletonAnimation spine, string animationName, float fallback, float minimum, float maximum) { if ((Object)(object)spine == (Object)null || ((SkeletonRenderer)spine).Skeleton == null || ((SkeletonRenderer)spine).Skeleton.Data == null || string.IsNullOrEmpty(animationName)) { return fallback; } Animation val = ((SkeletonRenderer)spine).Skeleton.Data.FindAnimation(animationName); if (val == null) { return fallback; } return Mathf.Clamp(val.Duration, minimum, maximum); } internal static void SetAlpha(SkeletonAnimation spine, float alpha) { if ((Object)(object)spine != (Object)null && ((SkeletonRenderer)spine).Skeleton != null) { ((SkeletonRenderer)spine).Skeleton.A = Mathf.Clamp01(alpha); } } internal static IEnumerator Fade(SkeletonAnimation spine, float from, float to, float duration) { if ((Object)(object)spine == (Object)null || ((SkeletonRenderer)spine).Skeleton == null) { yield break; } duration = Mathf.Max(0.01f, duration); float elapsed = 0f; SetAlpha(spine, from); while ((Object)(object)spine != (Object)null && ((SkeletonRenderer)spine).Skeleton != null) { float num; elapsed = (num = elapsed + Time.unscaledDeltaTime); if (!(num < duration)) { break; } SetAlpha(spine, Mathf.Lerp(from, to, elapsed / duration)); yield return null; } SetAlpha(spine, to); } } internal static class BishopAim { private const float TeleportPathSampleSpacing = 0.2f; private static readonly Vector2[] TeleportEndpointProbeDirections = (Vector2[])(object)new Vector2[8] { Vector2.up, Vector2.down, Vector2.left, Vector2.right, new Vector2(0.7071068f, 0.7071068f), new Vector2(-0.7071068f, 0.7071068f), new Vector2(0.7071068f, -0.7071068f), new Vector2(-0.7071068f, -0.7071068f) }; internal static Vector3 GetDirection(PlayerFarming player) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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) float num = (((Object)(object)player != (Object)null && (Object)(object)player.state != (Object)null) ? player.state.facingAngle : 0f); if (TryGetMouseCamera(player, out var camera, out var mouseScreen)) { num = Utils.GetAngle(camera.WorldToScreenPoint(((Component)player).transform.position), mouseScreen); } float num2 = num * ((float)Math.PI / 180f); Vector3 val = new Vector3(Mathf.Cos(num2), Mathf.Sin(num2), 0f); return ((Vector3)(ref val)).normalized; } internal static Vector3 GetPoint(PlayerFarming player, float fallbackDistance) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0051: 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) if (TryGetMouseCamera(player, out var camera, out var mouseScreen)) { Ray val = camera.ScreenPointToRay(mouseScreen); Plane val2 = default(Plane); ((Plane)(ref val2))..ctor(Vector3.forward, Vector3.zero); float num = default(float); if (((Plane)(ref val2)).Raycast(val, ref num)) { return ((Ray)(ref val)).GetPoint(num); } } return (((Object)(object)player != (Object)null) ? ((Component)player).transform.position : Vector3.zero) + GetDirection(player) * fallbackDistance; } internal static Vector3 GetAssistedPoint(PlayerFarming player, float fallbackDistance, float maxRange) { //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_0024: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) Vector3 point = GetPoint(player, fallbackDistance); if ((Object)(object)player == (Object)null || PlayableBishopsConfig.ProjectileAimAssist == null || !PlayableBishopsConfig.ProjectileAimAssist.Value) { return point; } Vector3 position = ((Component)player).transform.position; Camera camera; Vector3 mouseScreen; bool flag = TryGetMouseCamera(player, out camera, out mouseScreen); Vector3 direction = GetDirection(player); float value = PlayableBishopsConfig.ProjectileAimAssistMouseRadius.Value; float num = Mathf.Cos(PlayableBishopsConfig.ProjectileAimAssistControllerCone.Value * ((float)Math.PI / 180f)); Health val = null; float num2 = float.MaxValue; Health val2 = null; float num3 = float.MaxValue; for (int num4 = Health.team2.Count - 1; num4 >= 0; num4--) { Health val3 = Health.team2[num4]; if ((Object)(object)val3 == (Object)null || (Object)(object)((Component)val3).gameObject == (Object)null || !((Component)val3).gameObject.activeInHierarchy || !((Behaviour)val3).enabled || val3.HP <= 0f || val3.InanimateObject) { continue; } Vector3 val4 = ((Component)val3).transform.position - position; val4.z = 0f; float magnitude = ((Vector3)(ref val4)).magnitude; if (magnitude < 0.05f || magnitude > maxRange) { continue; } float num5; if (flag) { Vector3 val5 = ((Component)val3).transform.position - point; val5.z = 0f; float magnitude2 = ((Vector3)(ref val5)).magnitude; if (magnitude2 > value) { continue; } num5 = magnitude2 + magnitude * 0.01f; } else { float num6 = Vector3.Dot(val4 / magnitude, direction); float num7 = magnitude + (1f - num6) * maxRange * 0.35f; if (num7 < num3) { num3 = num7; val2 = val3; } if (num6 < num) { continue; } num5 = (1f - num6) * maxRange * 3f + magnitude * 0.08f; } if (num5 < num2) { num2 = num5; val = val3; } } if ((Object)(object)val != (Object)null) { return ((Component)val).transform.position; } if (flag || !((Object)(object)val2 != (Object)null)) { return point; } return ((Component)val2).transform.position; } internal static List GetTargetsInSector(Vector3 origin, Vector3 direction, float maxRange, float halfAngle) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) List list = new List(); direction.z = 0f; direction = ((((Vector3)(ref direction)).sqrMagnitude > 0.01f) ? ((Vector3)(ref direction)).normalized : Vector3.right); float num = Mathf.Cos(Mathf.Clamp(halfAngle, 1f, 180f) * ((float)Math.PI / 180f)); float num2 = maxRange * maxRange; for (int num3 = Health.team2.Count - 1; num3 >= 0; num3--) { Health val = Health.team2[num3]; if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null) && ((Component)val).gameObject.activeInHierarchy && ((Behaviour)val).enabled && !(val.HP <= 0f) && !val.InanimateObject) { Vector3 val2 = ((Component)val).transform.position - origin; val2.z = 0f; if (((Vector3)(ref val2)).sqrMagnitude > 0.01f && ((Vector3)(ref val2)).sqrMagnitude <= num2 && Vector3.Dot(direction, ((Vector3)(ref val2)).normalized) >= num) { list.Add(val); } } } list.Sort(delegate(Health left, Health right) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) Vector3 val3 = ((Component)left).transform.position - origin; float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude; val3 = ((Component)right).transform.position - origin; return sqrMagnitude.CompareTo(((Vector3)(ref val3)).sqrMagnitude); }); return list; } internal static Vector3 ClampToCurrentRoomFloor(Vector3 origin, Vector3 desired, float inwardMargin) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) desired.z = origin.z; BiomeGenerator instance = BiomeGenerator.Instance; if ((Object)(object)instance == (Object)null || instance.CurrentRoom == null || (Object)(object)instance.CurrentRoom.generateRoom == (Object)null || instance.CurrentRoom.generateRoom.Pieces == null) { return desired; } PolygonCollider2D val = null; List pieces = instance.CurrentRoom.generateRoom.Pieces; for (int i = 0; i < pieces.Count; i++) { PolygonCollider2D val2 = (((Object)(object)pieces[i] != (Object)null) ? pieces[i].Collider : null); if ((Object)(object)val2 != (Object)null && ((Collider2D)val2).OverlapPoint(Vector2.op_Implicit(origin))) { val = val2; break; } } if ((Object)(object)val == (Object)null || ((Collider2D)val).OverlapPoint(Vector2.op_Implicit(desired))) { return desired; } Vector2 val3 = ((Collider2D)val).ClosestPoint(Vector2.op_Implicit(desired)); Vector2 val4 = Vector2.op_Implicit(origin) - val3; if (((Vector2)(ref val4)).sqrMagnitude > 0.0001f) { val3 += ((Vector2)(ref val4)).normalized * Mathf.Max(0f, inwardMargin); } return new Vector3(val3.x, val3.y, origin.z); } internal static Vector3 ClampTeleportRouteToCurrentRoomFloor(Vector3 origin, Vector3 desired, float inwardMargin) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) desired.z = origin.z; Collider2D val = FindCurrentRoomFloor(origin); if ((Object)(object)val == (Object)null) { return ClampTeleportRouteToRoomBoundsOnly(origin, desired); } Vector2 val2 = Vector2.op_Implicit(origin); Vector2 val3 = Vector2.op_Implicit(desired); float num = Vector2.Distance(val2, val3); if (num <= 0.001f) { return origin; } int num2 = Mathf.Max(1, Mathf.CeilToInt(num / 0.2f)); float num3 = 0f; float num4 = 1f; bool flag = false; for (int i = 1; i <= num2; i++) { float num5 = (float)i / (float)num2; Vector2 point = Vector2.Lerp(val2, val3, num5); if (!IsTeleportRoutePointValid(val, point)) { num4 = num5; flag = true; break; } num3 = num5; } if (flag) { for (int j = 0; j < 8; j++) { float num6 = (num3 + num4) * 0.5f; if (IsTeleportRoutePointValid(val, Vector2.Lerp(val2, val3, num6))) { num3 = num6; } else { num4 = num6; } } } else { num3 = 1f; } float num7 = Mathf.Min(0.25f, 0.2f / num); Vector2 val4 = val2; bool flag2 = false; for (float num8 = num3; num8 > 0f; num8 -= num7) { Vector2 val5 = Vector2.Lerp(val2, val3, num8); if (IsSafeTeleportEndpoint(val, val5, inwardMargin)) { return new Vector3(val5.x, val5.y, origin.z); } if (!flag2 && IsTeleportRoutePointValid(val, val5)) { val4 = val5; flag2 = true; } } if (flag2) { return new Vector3(val4.x, val4.y, origin.z); } return origin; } private static Vector3 ClampTeleportRouteToRoomBoundsOnly(Vector3 origin, Vector3 desired) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: 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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_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_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) if (!GameManager.IsDungeon(PlayerFarming.Location)) { return desired; } Vector2 val = Vector2.op_Implicit(origin); Vector2 val2 = Vector2.op_Implicit(desired); float num = Vector2.Distance(val, val2); if (num <= 0.001f) { return origin; } int num2 = Mathf.Max(1, Mathf.CeilToInt(num / 0.2f)); Vector2 val3 = val; bool flag = false; for (int i = 1; i <= num2; i++) { Vector2 val4 = Vector2.Lerp(val, val2, (float)i / (float)num2); if (IsOutOfTeleportRoom(val4)) { break; } val3 = val4; flag = true; } if (flag) { return new Vector3(val3.x, val3.y, origin.z); } for (int num3 = num2; num3 >= 1; num3--) { Vector2 val5 = Vector2.Lerp(val, val2, (float)num3 / (float)num2); if (!IsOutOfTeleportRoom(val5)) { return new Vector3(val5.x, val5.y, origin.z); } } return origin; } private static Collider2D FindCurrentRoomFloor(Vector3 origin) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) BiomeGenerator instance = BiomeGenerator.Instance; if ((Object)(object)instance == (Object)null || instance.CurrentRoom == null || (Object)(object)instance.CurrentRoom.generateRoom == (Object)null) { return null; } GenerateRoom generateRoom = instance.CurrentRoom.generateRoom; if (IsFloorPoint((Collider2D)(object)generateRoom.RoomTransform, Vector2.op_Implicit(origin))) { return (Collider2D)(object)generateRoom.RoomTransform; } List pieces = generateRoom.Pieces; if (pieces == null) { return null; } for (int i = 0; i < pieces.Count; i++) { PolygonCollider2D val = (((Object)(object)pieces[i] != (Object)null) ? pieces[i].Collider : null); if (IsFloorPoint((Collider2D)(object)val, Vector2.op_Implicit(origin))) { return (Collider2D)(object)val; } } return null; } private static bool IsTeleportRoutePointValid(Collider2D floor, Vector2 point) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (IsFloorPoint(floor, point)) { return !IsOutOfTeleportRoom(point); } return false; } private static bool IsSafeTeleportEndpoint(Collider2D floor, Vector2 point, float inwardMargin) { //IL_0001: 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_0023: 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_002e: Unknown result type (might be due to invalid IL or missing references) if (!IsTeleportRoutePointValid(floor, point)) { return false; } float num = Mathf.Max(0f, inwardMargin); for (int i = 0; i < TeleportEndpointProbeDirections.Length; i++) { if (!(num > 0f)) { break; } if (!IsFloorPoint(floor, point + TeleportEndpointProbeDirections[i] * num)) { return false; } } return true; } private static bool IsFloorPoint(Collider2D floor, Vector2 point) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)floor != (Object)null && ((Behaviour)floor).enabled && ((Component)floor).gameObject.activeInHierarchy) { return floor.OverlapPoint(point); } return false; } private static bool IsOutOfTeleportRoom(Vector2 point) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) try { return RoomLockController.IsPositionOutOfRoom(Vector2.op_Implicit(point), true); } catch { return false; } } private static bool TryGetMouseCamera(PlayerFarming player, out Camera camera, out Vector3 mouseScreen) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) camera = null; mouseScreen = Vector3.zero; if ((Object)(object)player == (Object)null || !player.canUseKeyboard || !InputManager.General.MouseInputActive) { return false; } GameManager instance = GameManager.GetInstance(); if ((Object)(object)instance == (Object)null || (Object)(object)instance.CamFollowTarget == (Object)null) { return false; } camera = ((Component)instance.CamFollowTarget).GetComponent(); if ((Object)(object)camera == (Object)null) { return false; } mouseScreen = Vector2.op_Implicit(InputManager.General.GetMousePosition(player)); return true; } } internal static class BishopDamage { private const int DestructionBufferSize = 96; private static readonly Collider2D[] DestructionBuffer = (Collider2D[])(object)new Collider2D[96]; private static readonly HashSet ProcessedBreakables = new HashSet(); private static readonly HashSet ProcessedHealth = new HashSet(); private static readonly HashSet ReportedDamageFailures = new HashSet(); private static readonly MethodInfo BreakableObjectCollideMethod = AccessTools.Method(typeof(BreakableObject), "Collide", (Type[])null, (Type[])null); internal static float Scale(float baseDamage, PlayerFarming player) { if (baseDamage <= 0f) { return 0f; } float num = ((PlayableBishopsConfig.BossDamageMultiplier != null) ? PlayableBishopsConfig.BossDamageMultiplier.Value : 1f); if ((Object)(object)player == (Object)null) { return baseDamage * num; } try { return PlayerWeapon.GetDamage(baseDamage, Mathf.Max(1, player.currentWeaponLevel), player) * num; } catch (Exception ex) { PlayableBishopsLog.Debug("Boss damage scaling fell back to base damage: " + ex.GetBaseException().Message); return baseDamage * num; } } internal static float Cooldown(float baseCooldown, PlayerFarming player) { if ((Object)(object)player == (Object)null) { return baseCooldown; } return baseCooldown / Mathf.Max(0.25f, 1f + TrinketManager.GetAttackRateMultiplier(player)); } internal static AttackFlags GetTarotAttackFlags(PlayerFarming player, ref float damage) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0026: 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) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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_0043: 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) AttackFlags val = (AttackFlags)0; if ((Object)(object)player == (Object)null) { return val; } float weaponCritChanceIncrease = TrinketManager.GetWeaponCritChanceIncrease(player); if (Random.value < weaponCritChanceIncrease) { damage *= 3f; val = (AttackFlags)(val | 1); } if (TrinketManager.HasTrinket((Card)17, player)) { val = (AttackFlags)(val | 2); } if (TrinketManager.HasTrinket((Card)8, player)) { val = (AttackFlags)(val | 4); } return val; } internal static void DamageTarget(Health target, float baseDamage, GameObject attacker, AttackTypes attackType) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)target == (Object)null) && !(target.HP <= 0f)) { PlayerFarming player = ResolvePlayer(attacker); float damage = Scale(baseDamage, player); AttackFlags tarotAttackFlags = GetTarotAttackFlags(player, ref damage); DealDamageSafely(target, damage, attacker, attackType, force: false, tarotAttackFlags); } } internal static void DamageDirectional(Vector3 origin, Vector3 direction, float reach, float halfWidth, float rearAllowance, float damage, GameObject attacker) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: 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_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_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_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) direction.z = 0f; ((Vector3)(ref direction)).Normalize(); if (((Vector3)(ref direction)).sqrMagnitude < 0.5f || damage <= 0f) { return; } PlayerFarming player = ResolvePlayer(attacker); damage = Scale(damage, player); AttackFlags tarotAttackFlags = GetTarotAttackFlags(player, ref damage); for (int num = Health.team2.Count - 1; num >= 0; num--) { Health val = Health.team2[num]; if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null) && ((Component)val).gameObject.activeInHierarchy) { Vector3 val2 = ((Component)val).transform.position - origin; val2.z = 0f; float num2 = Vector3.Dot(val2, direction); if (!(num2 < 0f - rearAllowance) && !(num2 > reach)) { Vector3 val3 = val2 - direction * num2; if (!(((Vector3)(ref val3)).sqrMagnitude > halfWidth * halfWidth)) { DealDamageSafely(val, damage, attacker, (AttackTypes)0, force: false, tarotAttackFlags); } } } } DestroyPropsDirectional(origin, direction, reach, halfWidth, rearAllowance, attacker); } internal static void DamageBidirectional(Vector3 origin, Vector3 direction, float reach, float halfWidth, float damage, GameObject attacker) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: 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_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_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_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) direction.z = 0f; ((Vector3)(ref direction)).Normalize(); if (((Vector3)(ref direction)).sqrMagnitude < 0.5f || damage <= 0f) { return; } PlayerFarming player = ResolvePlayer(attacker); damage = Scale(damage, player); AttackFlags tarotAttackFlags = GetTarotAttackFlags(player, ref damage); for (int num = Health.team2.Count - 1; num >= 0; num--) { Health val = Health.team2[num]; if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null) && ((Component)val).gameObject.activeInHierarchy) { Vector3 val2 = ((Component)val).transform.position - origin; val2.z = 0f; if (!(Mathf.Abs(Vector3.Dot(val2, direction)) > reach)) { Vector3 val3 = val2 - direction * Vector3.Dot(val2, direction); if (!(((Vector3)(ref val3)).sqrMagnitude > halfWidth * halfWidth)) { DealDamageSafely(val, damage, attacker, (AttackTypes)0, force: false, tarotAttackFlags); } } } } DestroyPropsBidirectional(origin, direction, reach, halfWidth, attacker); } internal static void DamageAndDestroyAtPosition(Vector3 position, float radius, float damage, GameObject attacker) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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) AttackFlags tarotAttackFlags = GetTarotAttackFlags(ResolvePlayer(attacker), ref damage); float num = radius * radius; for (int num2 = Health.team2.Count - 1; num2 >= 0; num2--) { Health val = Health.team2[num2]; if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null) && ((Component)val).gameObject.activeInHierarchy && !(val.HP <= 0f)) { Vector3 val2 = ((Component)val).transform.position - position; if (!(((Vector3)(ref val2)).sqrMagnitude > num)) { DealDamageSafely(val, damage, attacker, (AttackTypes)1, force: true, tarotAttackFlags); } } } DestroyPropsAtPosition(position, radius, attacker); } internal static void DestroyPropsAtPosition(Vector3 position, float radius, GameObject attacker) { //IL_0014: 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) ProcessedBreakables.Clear(); ProcessedHealth.Clear(); int num = Physics2D.OverlapCircleNonAlloc(Vector2.op_Implicit(position), radius, DestructionBuffer); for (int i = 0; i < num; i++) { Collider2D collider = DestructionBuffer[i]; DestructionBuffer[i] = null; ProcessDestructible(collider, attacker); } } private static void DestroyPropsDirectional(Vector3 origin, Vector3 direction, float reach, float halfWidth, float rearAllowance, GameObject attacker) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_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_0092: 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_009c: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) ProcessedBreakables.Clear(); ProcessedHealth.Clear(); float num = (reach - rearAllowance) * 0.5f; float num2 = (reach + rearAllowance) * 0.5f; float num3 = Mathf.Sqrt(num2 * num2 + halfWidth * halfWidth); int num4 = Physics2D.OverlapCircleNonAlloc(Vector2.op_Implicit(origin + direction * num), num3, DestructionBuffer); for (int i = 0; i < num4; i++) { Collider2D val = DestructionBuffer[i]; DestructionBuffer[i] = null; if (!((Object)(object)val == (Object)null)) { Vector3 val2 = ((Component)val).transform.position - origin; val2.z = 0f; float num5 = Vector3.Dot(val2, direction); Vector3 val3 = val2 - direction * num5; if (num5 >= 0f - rearAllowance && num5 <= reach && ((Vector3)(ref val3)).sqrMagnitude <= halfWidth * halfWidth) { ProcessDestructible(val, attacker); } } } } private static void DestroyPropsBidirectional(Vector3 origin, Vector3 direction, float reach, float halfWidth, GameObject attacker) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) ProcessedBreakables.Clear(); ProcessedHealth.Clear(); float num = Mathf.Sqrt(reach * reach + halfWidth * halfWidth); int num2 = Physics2D.OverlapCircleNonAlloc(Vector2.op_Implicit(origin), num, DestructionBuffer); for (int i = 0; i < num2; i++) { Collider2D val = DestructionBuffer[i]; DestructionBuffer[i] = null; if (!((Object)(object)val == (Object)null)) { Vector3 val2 = ((Component)val).transform.position - origin; val2.z = 0f; float num3 = Mathf.Abs(Vector3.Dot(val2, direction)); Vector3 val3 = val2 - direction * Vector3.Dot(val2, direction); if (num3 <= reach && ((Vector3)(ref val3)).sqrMagnitude <= halfWidth * halfWidth) { ProcessDestructible(val, attacker); } } } } private static void ProcessDestructible(Collider2D collider, GameObject attacker) { if ((Object)(object)collider == (Object)null) { return; } Health componentInParent = ((Component)collider).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null && ProcessedHealth.Add(componentInParent) && componentInParent.HP > 0f && IsDestructible(componentInParent)) { DealDamageSafely(componentInParent, Mathf.Max(componentInParent.HP, componentInParent.totalHP), attacker, (AttackTypes)1, force: true, (AttackFlags)2048); return; } BreakableObject componentInParent2 = ((Component)collider).GetComponentInParent(); if (!((Object)(object)componentInParent2 == (Object)null) && ProcessedBreakables.Add(componentInParent2) && !(BreakableObjectCollideMethod == null)) { if (componentInParent2.hasHealth) { componentInParent2.HP = 0; } PlayerFarming val = ResolvePlayer(attacker); Health val2 = (Health)(object)(((Object)(object)val != (Object)null) ? val.health : null); if ((Object)(object)val2 == (Object)null && (Object)(object)attacker != (Object)null) { val2 = attacker.GetComponentInParent(); } if ((Object)(object)val2 != (Object)null) { BreakableObjectCollideMethod.Invoke(componentInParent2, new object[1] { val2 }); } } } private static bool IsDestructible(Health target) { if (!((Component)target).CompareTag("BreakableDecoration") && !((Object)(object)((Component)target).GetComponentInParent() != (Object)null) && !((Object)(object)((Component)target).GetComponentInParent() != (Object)null) && !((Object)(object)((Component)target).GetComponentInParent() != (Object)null)) { return (Object)(object)((Component)target).GetComponentInParent() != (Object)null; } return true; } private static void DealDamageSafely(Health target, float damage, GameObject attacker, AttackTypes attackType, bool force, AttackFlags flags) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)target == (Object)null) { return; } string fullName = ((object)target).GetType().FullName; string text = (((Object)(object)((Component)target).gameObject != (Object)null) ? ((Object)((Component)target).gameObject).name : ""); try { target.DealDamage(damage, attacker, ((Component)target).transform.position, false, attackType, force, flags); } catch (Exception ex) { Exception baseException = ex.GetBaseException(); string item = fullName + "|" + baseException.GetType().FullName; if (ReportedDamageFailures.Add(item)) { PlayableBishopsPlugin.Log.LogWarning((object)("Ignored an enemy damage callback failure from " + fullName + " ('" + text + "'): " + baseException.GetType().Name + ": " + baseException.Message)); } } } private static PlayerFarming ResolvePlayer(GameObject attacker) { return PlayableBossIdentity.GetOwnerPlayer(attacker); } } internal sealed class CultLeaderDefinition { internal string Id; internal string DisplayName; internal string AssetAddress; internal string SkeletonAssetName; internal string[] SourcePrefabAddresses; internal string[] IdleAnimations; internal string[] MovementAnimations; internal string[] EnterAnimations; internal string PreferredSkin; internal bool ProceduralLocomotionOnly; internal bool PreserveSourceOffset; internal bool SuppressStoryRoomMaterialOverride; internal bool NormalizeRendererTint; internal bool FaceCameraRotation; internal string TransformAnimation; internal string TransformAudio; internal float TransformTailDuration; internal Func VisualScale; } internal static class CultLeaderRegistry { private static readonly CultLeaderDefinition Leshy = new CultLeaderDefinition { Id = "Leshy", DisplayName = "Leshy", AssetAddress = "Assets/Art/Spine/NPCs/ForestCultLeader/ForestCultLeader_SkeletonData.asset", SkeletonAssetName = "ForestCultLeader", SourcePrefabAddresses = new string[4] { "Assets/_Rooms/Dungeon 1 Story Room Leader 1.prefab", "Assets/_Rooms/Dungeon 1 Story Room Leader 2.prefab", "Assets/_Rooms/Dungeon 1 Story Room Leader 3.prefab", "Assets/_Rooms/Dungeon 1 Story Room Leader 4.prefab" }, IdleAnimations = new string[1] { "idle" }, MovementAnimations = new string[3] { "run-fast", "run", "walk" }, EnterAnimations = new string[2] { "enter", "idle" }, PreferredSkin = "Normal", TransformAnimation = "transform", TransformAudio = "event:/boss/worm/transform", TransformTailDuration = 0f, VisualScale = () => PlayableBishopsConfig.CultLeaderLeshyScale.Value }; private static readonly CultLeaderDefinition Heket = new CultLeaderDefinition { Id = "Heket", DisplayName = "Heket", AssetAddress = "Assets/Art/Spine/NPCs/CultLeaders/FrogCultLeader.asset", SkeletonAssetName = "FrogCultLeader", SourcePrefabAddresses = new string[4] { "Assets/_Rooms/Dungeon 2 Story Room Leader 1.prefab", "Assets/_Rooms/Dungeon 2 Story Room Leader 2.prefab", "Assets/_Rooms/Dungeon 2 Story Room Leader 3.prefab", "Assets/_Rooms/Dungeon 2 Story Room Leader 4.prefab" }, IdleAnimations = new string[1] { "idle" }, MovementAnimations = new string[3] { "run-fast", "run", "walk" }, EnterAnimations = new string[2] { "enter", "idle" }, PreferredSkin = "Normal", TransformAnimation = "transform", TransformAudio = "event:/boss/frog/transform_sequence", TransformTailDuration = 0f, VisualScale = () => PlayableBishopsConfig.CultLeaderHeketScale.Value }; private static readonly CultLeaderDefinition Kallamar = new CultLeaderDefinition { Id = "Kallamar", DisplayName = "Kallamar", AssetAddress = "Assets/Art/Spine/Enemies/Tentacle/JellyCultLeader.asset", SkeletonAssetName = "JellyCultLeader", SourcePrefabAddresses = new string[6] { "Assets/Resources_moved/Enemies/Dungeon 3/Enemy Jellyfish Boss.prefab", "Assets/Prefabs/Enemies/Dungeon 3/Enemy Jellyfish Boss.prefab", "Assets/_Rooms/Dungeon 3 Story Room Leader 1.prefab", "Assets/_Rooms/Dungeon 3 Story Room Leader 2.prefab", "Assets/_Rooms/Dungeon 3 Story Room Leader 3.prefab", "Assets/_Rooms/Dungeon 3 Story Room Leader 4.prefab" }, IdleAnimations = new string[3] { "leader/idle", "idle", "animation" }, MovementAnimations = new string[4] { "leader/run", "run-fast", "run", "walk" }, EnterAnimations = new string[3] { "enter", "leader/idle", "idle" }, PreferredSkin = "Normal", PreserveSourceOffset = true, SuppressStoryRoomMaterialOverride = true, NormalizeRendererTint = true, FaceCameraRotation = true, TransformAnimation = "transform", TransformAudio = "event:/boss/jellyfish/transform", TransformTailDuration = 2f, VisualScale = () => PlayableBishopsConfig.CultLeaderKallamarScale.Value }; private static readonly CultLeaderDefinition Shamura = new CultLeaderDefinition { Id = "Shamura", DisplayName = "Shamura", AssetAddress = "Assets/Art/Spine/Enemies/Spider/SpiderCultLeader.asset", SkeletonAssetName = "SpiderCultLeader", SourcePrefabAddresses = new string[4] { "Assets/_Rooms/Dungeon 4 Story Room Leader 1.prefab", "Assets/_Rooms/Dungeon 4 Story Room Leader 2.prefab", "Assets/_Rooms/Dungeon 4 Story Room Leader 3.prefab", "Assets/_Rooms/Dungeon 4 Story Room Leader 4.prefab" }, IdleAnimations = new string[2] { "idle", "idle-boss" }, MovementAnimations = new string[3] { "run-fast", "run", "walk" }, EnterAnimations = new string[2] { "enter", "idle" }, PreferredSkin = "Mask", ProceduralLocomotionOnly = true, TransformAnimation = "mutate", TransformAudio = "event:/boss/spider/transform_sequence", TransformTailDuration = 2f, VisualScale = () => PlayableBishopsConfig.CultLeaderShamuraScale.Value }; internal static CultLeaderDefinition Get(string aspectId) { if (string.Equals(aspectId, Leshy.Id, StringComparison.OrdinalIgnoreCase)) { return Leshy; } if (string.Equals(aspectId, Heket.Id, StringComparison.OrdinalIgnoreCase)) { return Heket; } if (string.Equals(aspectId, Kallamar.Id, StringComparison.OrdinalIgnoreCase)) { return Kallamar; } if (string.Equals(aspectId, Shamura.Id, StringComparison.OrdinalIgnoreCase)) { return Shamura; } return null; } } internal sealed class CultLeaderPuppet { private static readonly FieldInfo LeaderSpineField = AccessTools.Field(typeof(DungeonLeaderMechanics), "leaderSpine"); private static readonly FieldInfo LeaderOldMaterialField = AccessTools.Field(typeof(DungeonLeaderMechanics), "leaderOldMaterial"); private static readonly FieldInfo LeaderNewMaterialField = AccessTools.Field(typeof(DungeonLeaderMechanics), "leaderNewMaterial"); private AsyncOperationHandle _sourcePrefabHandle; private bool _hasSourcePrefabHandle; private CultLeaderDefinition _definition; private GameObject _root; private SkeletonAnimation _spine; private Transform _visualTransform; private Vector3 _visualRestPosition; private Quaternion _visualRestRotation = Quaternion.identity; private Vector3 _visualRestScale = Vector3.one; private float _baseScaleX = 1f; private Material _runtimeMaterial; private bool _moving; private bool _proceduralLocomotion; internal bool IsActive { get { if ((Object)(object)_root != (Object)null && _root.activeSelf) { return (Object)(object)_spine != (Object)null; } return false; } } internal bool IsValid { get { if ((Object)(object)_root != (Object)null && (Object)(object)_spine != (Object)null) { return ((SkeletonRenderer)_spine).Skeleton != null; } return false; } } internal string CurrentId { get { if (_definition == null) { return null; } return _definition.Id; } } internal SkeletonAnimation Spine => _spine; internal unsafe IEnumerator Activate(MonoBehaviour host, PlayerFarming player, CultLeaderDefinition definition, Action completed) { if (definition == null) { completed(arg1: false, "no cult-leader definition exists for the selected aspect"); yield break; } if (IsValid && string.Equals(CurrentId, definition.Id, StringComparison.OrdinalIgnoreCase)) { _root.SetActive(true); _moving = false; _proceduralLocomotion = false; ResetVisualPose(); Follow(player); PlayIdle(); completed(arg1: true, null); yield break; } DisposeVisual(); _definition = definition; SkeletonAnimation sourceSpine = null; Material oldMaterial = null; Material newMaterial = null; Vector3 sourceOffset = Vector3.zero; if (definition.SourcePrefabAddresses != null) { for (int i = 0; i < definition.SourcePrefabAddresses.Length; i++) { _sourcePrefabHandle = Addressables.LoadAssetAsync((object)definition.SourcePrefabAddresses[i]); _hasSourcePrefabHandle = true; yield return _sourcePrefabHandle; if ((int)_sourcePrefabHandle.Status == 1 && (Object)(object)_sourcePrefabHandle.Result != (Object)null) { sourceSpine = FindLeaderSpine(_sourcePrefabHandle.Result, definition.SkeletonAssetName, out oldMaterial, out newMaterial, out sourceOffset); if ((Object)(object)sourceSpine != (Object)null && (Object)(object)((SkeletonRenderer)sourceSpine).skeletonDataAsset != (Object)null) { PlayableBishopsLog.Debug("Resolved " + definition.DisplayName + " cult-leader skeleton from " + definition.SourcePrefabAddresses[i] + "."); break; } } ReleaseSourcePrefab(); } } if ((Object)(object)sourceSpine == (Object)null || (Object)(object)((SkeletonRenderer)sourceSpine).skeletonDataAsset == (Object)null) { string arg = "no matching " + definition.SkeletonAssetName + " skeleton was found in its addressable story-room prefab"; DisposeVisual(); completed(arg1: false, arg); yield break; } try { _root = new GameObject("PlayableBishops." + definition.DisplayName + "CultLeaderRoot"); if ((Object)(object)host != (Object)null) { _root.transform.SetParent(((Component)host).transform, true); } GameObject val = Object.Instantiate(((Component)sourceSpine).gameObject, _root.transform, false); ((Object)val).name = "PlayableBishops." + definition.DisplayName + "CultLeaderVisual"; val.SetActive(true); val.transform.localPosition = (definition.PreserveSourceOffset ? sourceOffset : Vector3.zero); val.transform.localRotation = ((Component)sourceSpine).transform.rotation; if (definition.FaceCameraRotation) { ApplyCameraFacingRotation(val.transform); } Vector3 lossyScale = ((Component)sourceSpine).transform.lossyScale; val.transform.localScale = lossyScale * Mathf.Max(0.05f, definition.VisualScale()); _visualTransform = val.transform; _visualRestPosition = val.transform.localPosition; _visualRestRotation = val.transform.localRotation; _visualRestScale = val.transform.localScale; ManualLogSource log = PlayableBishopsPlugin.Log; string[] obj = new string[10] { definition.DisplayName, " cult-leader source transform: offset=", null, null, null, null, null, null, null, null }; Vector3 val2 = sourceOffset; obj[2] = ((object)(*(Vector3*)(&val2))/*cast due to .constrained prefix*/).ToString(); obj[3] = ", source rotation="; Quaternion val3 = ((Component)sourceSpine).transform.rotation; obj[4] = ((object)((Quaternion)(ref val3)).eulerAngles/*cast due to .constrained prefix*/).ToString(); obj[5] = ", applied rotation="; val3 = val.transform.localRotation; obj[6] = ((object)((Quaternion)(ref val3)).eulerAngles/*cast due to .constrained prefix*/).ToString(); obj[7] = ", scale="; val2 = lossyScale; obj[8] = ((object)(*(Vector3*)(&val2))/*cast due to .constrained prefix*/).ToString(); obj[9] = "."; log.LogInfo((object)string.Concat(obj)); _spine = val.GetComponent(); if ((Object)(object)_spine == (Object)null) { throw new InvalidOperationException("the story-room leader visual did not contain a SkeletonAnimation"); } ((SkeletonRenderer)_spine).Initialize(true); if (((SkeletonRenderer)_spine).Skeleton == null) { throw new InvalidOperationException("the loaded SkeletonDataAsset did not initialize a skeleton"); } ((Behaviour)_spine).enabled = true; _spine.ForceVisible = true; SkeletonAnimationLODManager componentInChildren = val.GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.DisableLODManager(true); ((Behaviour)componentInChildren).enabled = false; } MeshRenderer component = ((Component)_spine).GetComponent(); if ((Object)(object)component != (Object)null) { ((Renderer)component).enabled = true; ((Renderer)component).forceRenderingOff = false; } ((SkeletonRenderer)_spine).CustomMaterialOverride.Clear(); if (!definition.SuppressStoryRoomMaterialOverride && (Object)(object)oldMaterial != (Object)null && (Object)(object)newMaterial != (Object)null) { ((SkeletonRenderer)_spine).CustomMaterialOverride.Add(oldMaterial, newMaterial); PlayableBishopsPlugin.Log.LogInfo((object)(definition.DisplayName + " cult-leader material override: " + ((Object)oldMaterial).name + " -> " + ((Object)newMaterial).name + ".")); } else if (definition.SuppressStoryRoomMaterialOverride && (Object)(object)oldMaterial != (Object)null && (Object)(object)newMaterial != (Object)null) { PlayableBishopsPlugin.Log.LogInfo((object)(definition.DisplayName + " cult-leader retained its original " + ((Object)oldMaterial).name + " material for cult rendering.")); } if (definition.NormalizeRendererTint) { NormalizeRendererTint(component); } DisableLeaderColliders(val); _baseScaleX = Mathf.Abs(((SkeletonRenderer)_spine).Skeleton.ScaleX); if (_baseScaleX < 0.01f) { _baseScaleX = 1f; } ApplyLeaderSkin(); CopyPlayerSorting(player); LogAnimationInventory(); LogSkinInventory(); Follow(player); SetAlpha(0f); PlayIdle(); completed(arg1: true, null); } catch (Exception ex) { string message = ex.GetBaseException().Message; DisposeVisual(); completed(arg1: false, message); } } internal void Follow(PlayerFarming player) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) if (IsValid && !((Object)(object)player == (Object)null)) { _root.transform.position = ((Component)player).transform.position; if (_definition.FaceCameraRotation) { ApplyCameraFacingRotation(_visualTransform); _visualRestRotation = _visualTransform.localRotation; } bool flag = (Object)(object)player.playerController != (Object)null && (Mathf.Abs(player.playerController.xDir) > 0.05f || Mathf.Abs(player.playerController.yDir) > 0.05f); if (flag != _moving) { _moving = flag; PlayLocomotion(flag); } UpdateProceduralLocomotion(flag); float num = (((Object)(object)player.playerController != (Object)null) ? player.playerController.xDir : 0f); if (Mathf.Abs(num) < 0.05f && (Object)(object)player.state != (Object)null) { num = Mathf.Cos(player.state.facingAngle * ((float)Math.PI / 180f)); } if (Mathf.Abs(num) > 0.05f) { ((SkeletonRenderer)_spine).Skeleton.ScaleX = _baseScaleX * ((num > 0f) ? (-1f) : 1f); } } } internal float BeginReveal() { if (!IsValid) { return 0f; } string text = FindAnimation(_definition.IdleAnimations); string text2 = FindAnimation(_definition.EnterAnimations); if (!string.IsNullOrEmpty(text2) && !string.Equals(text2, text, StringComparison.OrdinalIgnoreCase)) { TrackEntry val = _spine.AnimationState.SetAnimation(0, text2, false); if (!string.IsNullOrEmpty(text)) { _spine.AnimationState.AddAnimation(0, text, true, 0f); } if (val == null || val.Animation == null) { return 0.35f; } return Mathf.Clamp(val.Animation.Duration, 0.15f, 1.2f); } PlayIdle(); return 0.25f; } internal float BeginTransformation() { if (!IsValid || string.IsNullOrEmpty(_definition.TransformAnimation)) { return 0f; } Animation val = ((SkeletonRenderer)_spine).Skeleton.Data.FindAnimation(_definition.TransformAnimation); if (val == null) { PlayableBishopsPlugin.Log.LogWarning((object)(_definition.DisplayName + " cult-leader rig has no '" + _definition.TransformAnimation + "' animation; using a visual crossfade.")); return 0f; } TrackEntry val2 = _spine.AnimationState.SetAnimation(0, _definition.TransformAnimation, false); float num = val.Duration; if (_definition.TransformTailDuration > 0f && num > _definition.TransformTailDuration + 0.25f) { val2.TrackTime = num - _definition.TransformTailDuration; num = _definition.TransformTailDuration; } try { if ((Object)(object)AudioManager.Instance != (Object)null && !string.IsNullOrEmpty(_definition.TransformAudio)) { AudioManager.Instance.PlayOneShot(_definition.TransformAudio); } } catch (Exception ex) { PlayableBishopsLog.Debug(_definition.DisplayName + " cult-leader transform sound failed: " + ex.GetBaseException().Message); } return Mathf.Clamp(num, 0.45f, 2.5f); } internal void SetAlpha(float alpha) { BishopPresentation.SetAlpha(_spine, alpha); } internal void Deactivate() { _proceduralLocomotion = false; ResetVisualPose(); if ((Object)(object)_spine != (Object)null) { _spine.timeScale = 1f; } if ((Object)(object)_root != (Object)null) { _root.SetActive(false); } _moving = false; } internal void Dispose() { DisposeVisual(); } private void PlayLocomotion(bool moving) { if (!moving) { _proceduralLocomotion = false; if ((Object)(object)_spine != (Object)null) { _spine.timeScale = 1f; } ResetVisualPose(); PlayIdle(); return; } string text = (_definition.ProceduralLocomotionOnly ? null : FindAnimation(_definition.MovementAnimations)); if (string.IsNullOrEmpty(text)) { _proceduralLocomotion = true; PlayIdle(); _spine.timeScale = 1.12f; } else { _proceduralLocomotion = false; _spine.timeScale = 1f; ResetVisualPose(); _spine.AnimationState.SetAnimation(0, text, true); } } private void UpdateProceduralLocomotion(bool moving) { //IL_0058: 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_0073: 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_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_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_visualTransform == (Object)null) && moving && _proceduralLocomotion) { float num = Time.time * 8f; float num2 = Mathf.Abs(Mathf.Sin(num)); float num3 = Mathf.Sin(num) * 1.1f; float num4 = Mathf.Sin(num * 2f) * 0.018f; _visualTransform.localPosition = _visualRestPosition + new Vector3(0f, num2 * 0.085f, 0f); _visualTransform.localRotation = _visualRestRotation * Quaternion.Euler(0f, 0f, num3); _visualTransform.localScale = Vector3.Scale(_visualRestScale, new Vector3(1f + num4, 1f - num4, 1f)); } } private void ResetVisualPose() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_visualTransform == (Object)null)) { _visualTransform.localPosition = _visualRestPosition; _visualTransform.localRotation = _visualRestRotation; _visualTransform.localScale = _visualRestScale; } } private void PlayIdle() { if (IsValid && _definition != null) { string text = FindAnimation(_definition.IdleAnimations); if (!string.IsNullOrEmpty(text)) { _spine.AnimationState.SetAnimation(0, text, true); } } } private string FindAnimation(string[] candidates) { if (!IsValid || candidates == null) { return null; } for (int i = 0; i < candidates.Length; i++) { if (((SkeletonRenderer)_spine).Skeleton.Data.FindAnimation(candidates[i]) != null) { return candidates[i]; } } return null; } private void ApplyLeaderSkin() { string[] array = new string[5] { _definition.PreferredSkin, "Normal", "normal", "Default", "default" }; for (int i = 0; i < array.Length; i++) { if (!string.IsNullOrEmpty(array[i]) && ((SkeletonRenderer)_spine).Skeleton.Data.FindSkin(array[i]) != null) { ((SkeletonRenderer)_spine).Skeleton.SetSkin(array[i]); ((SkeletonRenderer)_spine).Skeleton.SetSlotsToSetupPose(); PlayableBishopsPlugin.Log.LogInfo((object)(_definition.DisplayName + " cult-leader skin: " + array[i] + ".")); break; } } } private unsafe void NormalizeRendererTint(MeshRenderer renderer) { //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Expected O, but got Unknown //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_spine == (Object)null || ((SkeletonRenderer)_spine).Skeleton == null) { return; } Color val = default(Color); ((Color)(ref val))..ctor(((SkeletonRenderer)_spine).Skeleton.R, ((SkeletonRenderer)_spine).Skeleton.G, ((SkeletonRenderer)_spine).Skeleton.B, ((SkeletonRenderer)_spine).Skeleton.A); ((SkeletonRenderer)_spine).Skeleton.R = 1f; ((SkeletonRenderer)_spine).Skeleton.G = 1f; ((SkeletonRenderer)_spine).Skeleton.B = 1f; Color val2; if ((Object)(object)renderer == (Object)null || (Object)(object)((Renderer)renderer).sharedMaterial == (Object)null) { ManualLogSource log = PlayableBishopsPlugin.Log; string displayName = _definition.DisplayName; val2 = val; log.LogInfo((object)(displayName + " cult-leader normalized skeleton tint from " + ((object)(*(Color*)(&val2))/*cast due to .constrained prefix*/).ToString() + "; no renderer material was available.")); return; } Material sharedMaterial = ((Renderer)renderer).sharedMaterial; Color val3 = (sharedMaterial.HasProperty("_Color") ? sharedMaterial.GetColor("_Color") : Color.white); _runtimeMaterial = new Material(sharedMaterial); ((Object)_runtimeMaterial).name = "PlayableBishops." + _definition.DisplayName + ".CultLeaderMaterial"; if (_runtimeMaterial.HasProperty("_Color")) { _runtimeMaterial.SetColor("_Color", Color.white); } ((SkeletonRenderer)_spine).CustomMaterialOverride[sharedMaterial] = _runtimeMaterial; ManualLogSource log2 = PlayableBishopsPlugin.Log; string[] obj = new string[10] { _definition.DisplayName, " cult-leader normalized skeleton tint from ", null, null, null, null, null, null, null, null }; val2 = val; obj[2] = ((object)(*(Color*)(&val2))/*cast due to .constrained prefix*/).ToString(); obj[3] = " and material "; obj[4] = ((Object)sharedMaterial).name; obj[5] = " color from "; val2 = val3; obj[6] = ((object)(*(Color*)(&val2))/*cast due to .constrained prefix*/).ToString(); obj[7] = " using shader "; obj[8] = ((Object)sharedMaterial.shader).name; obj[9] = "."; log2.LogInfo((object)string.Concat(obj)); } private static void ApplyCameraFacingRotation(Transform visual) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) Camera main = Camera.main; if (!((Object)(object)visual == (Object)null) && !((Object)(object)main == (Object)null)) { visual.rotation = Quaternion.LookRotation(((Component)main).transform.forward, ((Component)main).transform.up); } } private void CopyPlayerSorting(PlayerFarming player) { if (!((Object)(object)player == (Object)null) && !((Object)(object)player.Spine == (Object)null) && !((Object)(object)_spine == (Object)null)) { MeshRenderer component = ((Component)player.Spine).GetComponent(); MeshRenderer component2 = ((Component)_spine).GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component2 != (Object)null) { ((Renderer)component2).sortingLayerID = ((Renderer)component).sortingLayerID; ((Renderer)component2).sortingOrder = ((Renderer)component).sortingOrder; } } } private static SkeletonAnimation FindLeaderSpine(GameObject prefab, string expectedName, out Material oldMaterial, out Material newMaterial, out Vector3 sourceOffset) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) oldMaterial = null; newMaterial = null; sourceOffset = Vector3.zero; if ((Object)(object)prefab == (Object)null) { return null; } DungeonLeaderMechanics componentInChildren = prefab.GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null && LeaderSpineField != null) { object? value = LeaderSpineField.GetValue(componentInChildren); SkeletonAnimation val = (SkeletonAnimation)((value is SkeletonAnimation) ? value : null); if ((Object)(object)val != (Object)null && (Object)(object)((SkeletonRenderer)val).skeletonDataAsset != (Object)null) { oldMaterial = (Material)((LeaderOldMaterialField != null) ? /*isinst with value type is only supported in some contexts*/: null); newMaterial = (Material)((LeaderNewMaterialField != null) ? /*isinst with value type is only supported in some contexts*/: null); sourceOffset = ((Component)val).transform.localPosition; return val; } } SkeletonAnimation[] componentsInChildren = prefab.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { SkeletonDataAsset val2 = (((Object)(object)componentsInChildren[i] != (Object)null) ? ((SkeletonRenderer)componentsInChildren[i]).skeletonDataAsset : null); if ((Object)(object)val2 != (Object)null && ((Object)val2).name.IndexOf(expectedName, StringComparison.OrdinalIgnoreCase) >= 0) { sourceOffset = ((Component)componentsInChildren[i]).transform.localPosition; return componentsInChildren[i]; } } return null; } private static void DisableLeaderColliders(GameObject visual) { Collider2D[] componentsInChildren = visual.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { ((Behaviour)componentsInChildren[i]).enabled = false; } } private void LogAnimationInventory() { if (!IsValid || _definition == null) { return; } StringBuilder stringBuilder = new StringBuilder(); ExposedList animations = ((SkeletonRenderer)_spine).Skeleton.Data.Animations; for (int i = 0; i < animations.Count; i++) { if (i > 0) { stringBuilder.Append(", "); } stringBuilder.Append(animations.Items[i].Name); } PlayableBishopsPlugin.Log.LogInfo((object)(_definition.DisplayName + " cult-leader animations: " + stringBuilder)); } private void LogSkinInventory() { if (!IsValid || _definition == null) { return; } StringBuilder stringBuilder = new StringBuilder(); ExposedList skins = ((SkeletonRenderer)_spine).Skeleton.Data.Skins; for (int i = 0; i < skins.Count; i++) { if (i > 0) { stringBuilder.Append(", "); } stringBuilder.Append(skins.Items[i].Name); } PlayableBishopsPlugin.Log.LogInfo((object)(_definition.DisplayName + " cult-leader skins: " + stringBuilder)); } private void DisposeVisual() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)_root); } _root = null; if ((Object)(object)_runtimeMaterial != (Object)null) { Object.Destroy((Object)(object)_runtimeMaterial); _runtimeMaterial = null; } _spine = null; _visualTransform = null; _visualRestPosition = Vector3.zero; _visualRestRotation = Quaternion.identity; _visualRestScale = Vector3.one; _definition = null; _moving = false; _proceduralLocomotion = false; ReleaseSourcePrefab(); } private void ReleaseSourcePrefab() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (_hasSourcePrefabHandle && _sourcePrefabHandle.IsValid()) { Addressables.Release(_sourcePrefabHandle); } _hasSourcePrefabHandle = false; } } internal sealed class BishopAspectDefinition { internal readonly string Id; internal readonly string DisplayName; internal readonly Color AccentColor; internal readonly bool Implemented; internal BishopAspectDefinition(string id, string displayName, Color accentColor, bool implemented) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) Id = id; DisplayName = displayName; AccentColor = accentColor; Implemented = implemented; } } internal static class BishopAspectRegistry { internal const string NoneId = "None"; internal const string LeshyId = "Leshy"; internal const string HeketId = "Heket"; internal const string KallamarId = "Kallamar"; internal const string ShamuraId = "Shamura"; internal const string NarinderId = "Narinder"; private static readonly BishopAspectDefinition[] Definitions = new BishopAspectDefinition[6] { new BishopAspectDefinition("None", "None", new Color(0.55f, 0.55f, 0.55f, 1f), implemented: true), new BishopAspectDefinition("Leshy", "Leshy", new Color(0.42f, 0.78f, 0.24f, 1f), implemented: true), new BishopAspectDefinition("Heket", "Heket", new Color(0.94f, 0.72f, 0.18f, 1f), implemented: true), new BishopAspectDefinition("Kallamar", "Kallamar", new Color(0.24f, 0.62f, 0.86f, 1f), implemented: true), new BishopAspectDefinition("Shamura", "Shamura", new Color(0.62f, 0.38f, 0.74f, 1f), implemented: true), new BishopAspectDefinition("Narinder", "Narinder", new Color(0.78f, 0.16f, 0.18f, 1f), implemented: false) }; internal static BishopAspectDefinition[] GetSelectableDefinitions() { int num = 0; for (int i = 0; i < Definitions.Length; i++) { if (Definitions[i].Implemented) { num++; } } BishopAspectDefinition[] array = new BishopAspectDefinition[num]; int num2 = 0; for (int j = 0; j < Definitions.Length; j++) { if (Definitions[j].Implemented) { array[num2++] = Definitions[j]; } } return array; } internal static BishopAspectDefinition Get(string id) { for (int i = 0; i < Definitions.Length; i++) { if (string.Equals(Definitions[i].Id, id, StringComparison.OrdinalIgnoreCase)) { return Definitions[i]; } } return Definitions[1]; } } internal static class BishopAspectAltarUi { private static readonly FieldInfo FleeceItemsField = AccessTools.Field(typeof(UIPlayerUpgradesMenuController), "_fleeceItems"); private static readonly FieldInfo FleeceHeaderField = AccessTools.Field(typeof(UIPlayerUpgradesMenuController), "_fleeceHeader"); private static readonly FieldInfo FleeceContainerField = AccessTools.Field(typeof(UIPlayerUpgradesMenuController), "_fleeceContainer"); private static readonly FieldInfo IconField = AccessTools.Field(typeof(FleeceItemBuyable), "_icon"); private static readonly FieldInfo OutlineField = AccessTools.Field(typeof(FleeceItemBuyable), "_outline"); private static readonly FieldInfo CostTextField = AccessTools.Field(typeof(FleeceItemBuyable), "_costText"); private static readonly FieldInfo AlertField = AccessTools.Field(typeof(FleeceItemBuyable), "_alert"); private static readonly FieldInfo FlashIconField = AccessTools.Field(typeof(FleeceItemBuyable), "_flashIcon"); private static readonly FieldInfo DlcStarField = AccessTools.Field(typeof(FleeceItemBuyable), "_DLCStar"); private static readonly FieldInfo TransmogContainerField = AccessTools.Field(typeof(FleeceItemBuyable), "_transmogFleeceContainer"); internal static void Attach(UIPlayerUpgradesMenuController menu) { if ((Object)(object)menu == (Object)null || (Object)(object)((Component)menu).GetComponent() != (Object)null) { return; } try { FleeceItemBuyable[] array = FleeceItemsField.GetValue(menu) as FleeceItemBuyable[]; object? value = FleeceHeaderField.GetValue(menu); GameObject val = (GameObject)((value is GameObject) ? value : null); object? value2 = FleeceContainerField.GetValue(menu); GameObject val2 = (GameObject)((value2 is GameObject) ? value2 : null); if (array == null || array.Length == 0 || (Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { PlayableBishopsPlugin.Log.LogWarning((object)"Bishop Aspect row could not find the altar fleece templates."); return; } FleeceItemBuyable val3 = FindTemplate(array); if ((Object)(object)val3 == (Object)null) { PlayableBishopsPlugin.Log.LogWarning((object)"Bishop Aspect row could not find an active fleece card template."); return; } BishopAspectAltarMarker bishopAspectAltarMarker = ((Component)menu).gameObject.AddComponent(); GameObject val4 = Object.Instantiate(val, val.transform.parent, false); ((Object)val4).name = "PlayableBishops.BishopAspectHeader"; ConfigureHeader(val4); val4.transform.SetAsLastSibling(); GameObject val5 = Object.Instantiate(val2, val2.transform.parent, false); ((Object)val5).name = "PlayableBishops.BishopAspectContainer"; ClearChildren(val5.transform); val5.transform.SetAsLastSibling(); BishopAspectAltarRow bishopAspectAltarRow = val5.AddComponent(); BishopAspectDefinition[] selectableDefinitions = BishopAspectRegistry.GetSelectableDefinitions(); for (int i = 0; i < selectableDefinitions.Length; i++) { BishopAspectCard bishopAspectCard = CreateCard(val3, val5.transform, selectableDefinitions[i], bishopAspectAltarRow); if ((Object)(object)bishopAspectCard != (Object)null) { bishopAspectAltarRow.Add(bishopAspectCard); } } bishopAspectAltarRow.Refresh(); bishopAspectAltarMarker.Header = val4; bishopAspectAltarMarker.Container = val5; bishopAspectAltarMarker.Row = bishopAspectAltarRow; val4.SetActive(val.activeSelf); val5.SetActive(val2.activeSelf); Canvas.ForceUpdateCanvases(); Transform parent = val5.transform.parent; RectTransform val6 = (RectTransform)(object)((parent is RectTransform) ? parent : null); if ((Object)(object)val6 != (Object)null) { LayoutRebuilder.ForceRebuildLayoutImmediate(val6); } PlayableBishopsPlugin.Log.LogInfo((object)"Added the independent Bishop Aspect row to the altar."); } catch (Exception ex) { PlayableBishopsPlugin.Log.LogError((object)("Bishop Aspect altar row failed: " + ex.GetBaseException().Message)); } } private static FleeceItemBuyable FindTemplate(FleeceItemBuyable[] items) { for (int i = 0; i < items.Length; i++) { if ((Object)(object)items[i] != (Object)null && ((Component)items[i]).gameObject.activeSelf) { return items[i]; } } return items[0]; } private static void ConfigureHeader(GameObject header) { TextMeshProUGUI[] componentsInChildren = header.GetComponentsInChildren(true); if (componentsInChildren.Length != 0) { ((TMP_Text)componentsInChildren[0]).text = "BISHOP ASPECTS"; } for (int i = 1; i < componentsInChildren.Length; i++) { if (((Object)componentsInChildren[i]).name.IndexOf("count", StringComparison.OrdinalIgnoreCase) >= 0) { ((TMP_Text)componentsInChildren[i]).text = "1 / 1"; } } } private static void ClearChildren(Transform parent) { while (parent.childCount > 0) { Transform child = parent.GetChild(0); child.SetParent((Transform)null, false); ((Component)child).gameObject.SetActive(false); Object.Destroy((Object)(object)((Component)child).gameObject); } } private static BishopAspectCard CreateCard(FleeceItemBuyable template, Transform parent, BishopAspectDefinition definition, BishopAspectAltarRow row) { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Expected O, but got Unknown //IL_0175: Unknown result type (might be due to invalid IL or missing references) GameObject val = Object.Instantiate(((Component)template).gameObject, parent, false); ((Object)val).name = "PlayableBishops.AspectCard." + definition.Id; val.SetActive(false); FleeceItemBuyable component = val.GetComponent(); if ((Object)(object)component == (Object)null || (Object)(object)component.Button == (Object)null) { Object.Destroy((Object)(object)val); return null; } MMButton button = component.Button; ((UnityEventBase)((Button)button).onClick).RemoveAllListeners(); ((Selectable)button).interactable = true; button.Confirmable = true; Navigation navigation = ((Selectable)button).navigation; ((Navigation)(ref navigation)).mode = (Mode)3; ((Selectable)button).navigation = navigation; object? value = IconField.GetValue(component); Image val2 = (Image)((value is Image) ? value : null); object? value2 = OutlineField.GetValue(component); Image val3 = (Image)((value2 is Image) ? value2 : null); object? value3 = CostTextField.GetValue(component); TextMeshProUGUI val4 = (TextMeshProUGUI)((value3 is TextMeshProUGUI) ? value3 : null); object? value4 = AlertField.GetValue(component); SetInactive((GameObject)((value4 is GameObject) ? value4 : null)); object? value5 = FlashIconField.GetValue(component); object? obj = ((value5 is Component) ? value5 : null); SetInactive((obj != null) ? ((Component)obj).gameObject : null); object? value6 = DlcStarField.GetValue(component); object? obj2 = ((value6 is Component) ? value6 : null); SetInactive((obj2 != null) ? ((Component)obj2).gameObject : null); object? value7 = TransmogContainerField.GetValue(component); SetInactive((GameObject)((value7 is GameObject) ? value7 : null)); if ((Object)(object)val2 != (Object)null) { ((Graphic)val2).color = definition.AccentColor; } if ((Object)(object)val3 != (Object)null) { ((Graphic)val3).color = definition.AccentColor; } if ((Object)(object)val4 != (Object)null) { ((TMP_Text)val4).text = definition.DisplayName.ToUpperInvariant(); ((Graphic)val4).color = Color.white; ((Graphic)val4).raycastTarget = false; ((TMP_Text)val4).enableWordWrapping = false; ((TMP_Text)val4).fontSize = Mathf.Max(16f, ((TMP_Text)val4).fontSize); } ((Behaviour)component).enabled = false; BishopAspectCard bishopAspectCard = val.AddComponent(); bishopAspectCard.Configure(definition, button, val3, row); ((UnityEvent)((Button)button).onClick).AddListener(new UnityAction(bishopAspectCard.Select)); Object.Destroy((Object)(object)component); val.SetActive(true); return bishopAspectCard; } private static void SetInactive(GameObject gameObject) { if ((Object)(object)gameObject != (Object)null) { gameObject.SetActive(false); } } } internal sealed class BishopAspectAltarMarker : MonoBehaviour { internal GameObject Header; internal GameObject Container; internal BishopAspectAltarRow Row; private PlayerFarming _lastPlayer; private void Update() { PlayerFarming val = (((Object)(object)Row != (Object)null) ? Row.CurrentPlayer : null); if ((Object)(object)val == (Object)(object)_lastPlayer) { return; } _lastPlayer = val; if ((Object)(object)Row != (Object)null) { Row.Refresh(); } if ((Object)(object)Header != (Object)null && (Object)(object)val != (Object)null) { TextMeshProUGUI[] componentsInChildren = Header.GetComponentsInChildren(true); if (componentsInChildren.Length != 0) { ((TMP_Text)componentsInChildren[0]).text = "P" + (PlayableBishopsPlugin.GetPlayerSlot(val) + 1) + " BISHOP ASPECTS"; } } if ((Object)(object)val != (Object)null) { if ((Object)(object)Header != (Object)null) { Header.SetActive(true); } if ((Object)(object)Container != (Object)null) { Container.SetActive(true); } } } } internal sealed class BishopAspectAltarRow : MonoBehaviour { private readonly List _cards = new List(); internal PlayerFarming CurrentPlayer { get { UINavigatorNew instance = MonoSingleton.Instance; if ((Object)(object)instance != (Object)null && (Object)(object)instance.AllowInputOnlyFromPlayer != (Object)null) { return instance.AllowInputOnlyFromPlayer; } return PlayerFarming.Instance; } } internal void Add(BishopAspectCard card) { _cards.Add(card); } internal void Refresh() { string selectedAspect = PlayableBishopsConfig.GetSelectedAspect(PlayableBishopsPlugin.GetPlayerSlot(CurrentPlayer)); for (int i = 0; i < _cards.Count; i++) { _cards[i].SetSelected(string.Equals(_cards[i].AspectId, selectedAspect, StringComparison.OrdinalIgnoreCase)); } } } internal sealed class BishopAspectCard : MonoBehaviour { private BishopAspectDefinition _definition; private MMButton _button; private Image _outline; private BishopAspectAltarRow _row; internal string AspectId => _definition.Id; internal void Configure(BishopAspectDefinition definition, MMButton button, Image outline, BishopAspectAltarRow row) { _definition = definition; _button = button; _outline = outline; _row = row; } internal void Select() { if (_definition != null) { int playerSlot = PlayableBishopsPlugin.GetPlayerSlot(((Object)(object)_row != (Object)null) ? _row.CurrentPlayer : PlayerFarming.Instance); BishopAspectController controller = PlayableBishopsPlugin.GetController(playerSlot); if ((Object)(object)controller != (Object)null) { controller.SelectAspect(_definition.Id); } else { PlayableBishopsConfig.SetSelectedAspect(playerSlot, _definition.Id); } AudioManager.Instance.PlayOneShot("event:/ui/confirm_selection"); _row.Refresh(); } } internal void SetSelected(bool selected) { if ((Object)(object)_outline != (Object)null) { ((Component)_outline).gameObject.SetActive(selected); } if ((Object)(object)_button != (Object)null) { _button.Confirmable = true; } } } internal sealed class LeshyAspect : BishopAspect { private sealed class TrailVisual { internal GameObject Root; internal Collider2D[] Colliders; internal ColliderEvents Events; } private const string PrefabAddress = "Assets/Resources_moved/Enemies/Dungeon 1/Enemy Forest Worm Boss.prefab"; private const int InitialSpikePoolSize = 36; private const int TunnelTrailPoolSize = 32; private const float BurrowHideDelay = 0.9f; private const float MovementInputThreshold = 0.05f; private const float TunnelTrailInterval = 0.2f; private const float TunnelContactInterval = 0.08f; private const float TunnelContactRadius = 1.35f; private const int TunnelContactBufferSize = 64; private static readonly MethodInfo InitializeSpikesMethod = AccessTools.Method(typeof(EnemyWormBoss), "InitializeSpawnedSpikes", (Type[])null, (Type[])null); private static readonly MethodInfo InitializeBulletsMethod = AccessTools.Method(typeof(EnemyWormBoss), "InitializeGranadeBullets", (Type[])null, (Type[])null); private static readonly FieldInfo StartingSpikesField = AccessTools.Field(typeof(EnemyWormBoss), "startingSpawnedSpikes"); private static readonly FieldInfo ActiveField = AccessTools.Field(typeof(EnemyWormBoss), "active"); private static readonly FieldInfo IdleAnimationField = AccessTools.Field(typeof(EnemyWormBoss), "idleAnimation"); private static readonly FieldInfo EnragedAnimationField = AccessTools.Field(typeof(EnemyWormBoss), "enragedAnimation"); private static readonly FieldInfo PopInAnimationField = AccessTools.Field(typeof(EnemyWormBoss), "popInAnimation"); private static readonly FieldInfo PopOutAnimationField = AccessTools.Field(typeof(EnemyWormBoss), "popOutAnimation"); private static readonly FieldInfo ShootAnimationField = AccessTools.Field(typeof(EnemyWormBoss), "shootAnimation"); private static readonly FieldInfo SpikeAnimationField = AccessTools.Field(typeof(EnemyWormBoss), "spikeAnimation"); private static readonly FieldInfo ShootAnticipationField = AccessTools.Field(typeof(EnemyWormBoss), "shootAnticipation"); private static readonly FieldInfo DelayBetweenShotsField = AccessTools.Field(typeof(EnemyWormBoss), "delayBetweenShots"); private static readonly FieldInfo BulletPrefabField = AccessTools.Field(typeof(EnemyWormBoss), "bulletPrefab"); private static readonly FieldInfo GravSpeedField = AccessTools.Field(typeof(EnemyWormBoss), "gravSpeed"); private static readonly FieldInfo ArcField = AccessTools.Field(typeof(EnemyWormBoss), "arc"); private static readonly FieldInfo RandomArcOffsetField = AccessTools.Field(typeof(EnemyWormBoss), "randomArcOffset"); private static readonly FieldInfo ShootDistanceRangeField = AccessTools.Field(typeof(EnemyWormBoss), "shootDistanceRange"); private static readonly FieldInfo ShootBoneField = AccessTools.Field(typeof(EnemyWormBoss), "ShootBone"); private static readonly FieldInfo TrailSpikePrefabField = AccessTools.Field(typeof(EnemyWormBoss), "trailSpikePrefab"); private static readonly FieldInfo SpikeAnticipationField = AccessTools.Field(typeof(EnemyWormBoss), "spikeAnticipation"); private static readonly FieldInfo LayerToCheckField = AccessTools.Field(typeof(EnemyWormBoss), "layerToCheck"); private static readonly FieldInfo GroundImpactVfxField = AccessTools.Field(typeof(EnemyWormBoss), "groundImpactVFX"); private static readonly MethodInfo BreakableObjectCollideMethod = AccessTools.Method(typeof(BreakableObject), "Collide", (Type[])null, (Type[])null); private AsyncOperationHandle _prefabHandle; private bool _hasPrefabHandle; private GameObject _root; private EnemyWormBoss _boss; private bool _isActive; private float _nextSpikeTime; private float _nextVolleyTime; private float _nextRoarTime; private bool _roarRunning; private int _animationSequence; private int _roarSequence; private readonly TrailVisual[] _trailVisuals = new TrailVisual[32]; private readonly Dictionary _tunnelHitCooldowns = new Dictionary(); private readonly Collider2D[] _tunnelContactBuffer = (Collider2D[])(object)new Collider2D[64]; private readonly HashSet _brokenTunnelObjects = new HashSet(); private bool _trailVisualsInitialized; private float _nextTrailVisualTime; private float _nextTunnelContactTime; private bool _hasLastPlayerPosition; private Vector3 _lastPlayerPosition; private bool _locomotionMoving; private bool _burrowHidden; private float _burrowHideTime; private float _locomotionLockedUntil; private bool _burrowDisappearSoundPlayed; private EventInstance _tunnelLoopInstance; private bool _tunnelLoopActive; private bool _facingScaleCaptured; private float _spineBaseScaleX = 1f; internal override string Id => "Leshy"; internal override string DisplayName => "Leshy"; internal override bool IsActive { get { if (_isActive && (Object)(object)_root != (Object)null) { return (Object)(object)_boss != (Object)null; } return false; } } internal override bool IsValid { get { if ((Object)(object)_root != (Object)null && (Object)(object)_boss != (Object)null) { return (Object)(object)((Component)_boss).gameObject != (Object)null; } return false; } } internal override bool UsesDodgeAbility => true; internal bool IsTunneling { get { if (_isActive) { return _locomotionMoving; } return false; } } internal override IEnumerator Activate(BishopAspectController controller, PlayerFarming player, Action completed) { if ((Object)(object)_root != (Object)null && (Object)(object)_boss != (Object)null) { _isActive = true; ConfigureFriendlyState(); ResetLocomotion(showSpine: true); PrepareSpineRendering(_boss.Spine); CaptureFacingScale(); PlayIdleAnimation(); ResetCooldowns(); PlayableBishopsPlugin.Log.LogInfo((object)"Reactivated the initialized Leshy puppet."); completed(arg1: true, null); yield break; } _root = null; _boss = null; ClearTunnelTrailReferences(); if (!_hasPrefabHandle) { _prefabHandle = Addressables.LoadAssetAsync((object)"Assets/Resources_moved/Enemies/Dungeon 1/Enemy Forest Worm Boss.prefab"); _hasPrefabHandle = true; yield return _prefabHandle; } if ((int)_prefabHandle.Status != 1 || (Object)(object)_prefabHandle.Result == (Object)null) { completed(arg1: false, "the Leshy Addressables prefab did not load"); yield break; } _root = new GameObject("PlayableBishops.LeshyAspectRoot"); if ((Object)(object)((Component)player).transform.parent != (Object)null) { _root.transform.SetParent(((Component)player).transform.parent, true); } GameObject val = Object.Instantiate(_prefabHandle.Result, ((Component)player).transform.position, Quaternion.identity, _root.transform); ((Object)val).name = "PlayableBishops.LeshyAvatar"; val.AddComponent().Controller = controller; val.SetActive(false); _boss = val.GetComponent(); if ((Object)(object)_boss == (Object)null) { _boss = val.GetComponentInChildren(true); } if ((Object)(object)_boss == (Object)null) { Object.Destroy((Object)(object)_root); _root = null; completed(arg1: false, "the loaded prefab has no EnemyWormBoss component"); yield break; } string text = null; try { DisableBodyColliders(val); val.transform.localScale = val.transform.localScale * PlayableBishopsConfig.VisualScale.Value; ActiveField.SetValue(_boss, false); StartingSpikesField.SetValue(_boss, 36); val.SetActive(true); ((MonoBehaviour)_boss).StopAllCoroutines(); ConfigureFriendlyState(); PrepareSpineRendering(_boss.Spine); CaptureFacingScale(); InitializeSpikesMethod.Invoke(_boss, null); InitializeBulletsMethod.Invoke(_boss, null); InitializeTunnelTrail(); _isActive = true; ResetLocomotion(showSpine: true); PlayIdleAnimation(); ResetCooldowns(); } catch (Exception ex) { text = ex.GetBaseException().Message; } if (text != null) { Object.Destroy((Object)(object)_root); _root = null; _boss = null; _isActive = false; ClearTunnelTrailReferences(); completed(arg1: false, "Leshy prefab setup failed: " + text); } else { completed(arg1: true, null); } } private void ConfigureFriendlyState() { if (!((Object)(object)_boss == (Object)null) && !((Object)(object)((UnitObject)_boss).health == (Object)null)) { ActiveField.SetValue(_boss, false); ((UnitObject)_boss).health.SetTeam((Team)1); ((UnitObject)_boss).health.invincible = true; ((UnitObject)_boss).health.untouchable = true; if ((Object)(object)_boss.Spine != (Object)null) { _boss.Spine.ForceVisible = true; ((Component)_boss.Spine).gameObject.SetActive(true); } } } private static void DisableBodyColliders(GameObject avatar) { Collider2D[] componentsInChildren = avatar.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { ((Behaviour)componentsInChildren[i]).enabled = false; } } private static void PrepareSpineRendering(SkeletonAnimation spine, bool writeLog = true) { if ((Object)(object)spine == (Object)null) { if (writeLog) { PlayableBishopsPlugin.Log.LogWarning((object)"Leshy render setup could not find the primary Spine component."); } return; } SkeletonAnimationLODManager component = ((Component)spine).GetComponent(); if ((Object)(object)component != (Object)null) { component.IgnoreCulling = true; if ((Object)(object)component.SkeletonAnimation != (Object)null) { component.DisableLODManager(true); } ((Behaviour)component).enabled = false; } spine.ForceVisible = true; ((Behaviour)spine).enabled = true; Renderer component2 = ((Component)spine).GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.forceRenderingOff = false; component2.enabled = true; } if (writeLog) { PlayableBishopsPlugin.Log.LogInfo((object)("Leshy render setup: primary Spine ready, LOD manager " + (((Object)(object)component == (Object)null) ? "not present" : "disabled") + ".")); } } private void ApplyVanillaSkinAndSetupPose() { if (!((Object)(object)_boss == (Object)null) && !((Object)(object)_boss.Spine == (Object)null) && ((SkeletonRenderer)_boss.Spine).Skeleton != null) { ((SkeletonRenderer)_boss.Spine).Skeleton.SetSkin("Normal"); ((SkeletonRenderer)_boss.Spine).Skeleton.SetBonesToSetupPose(); ((SkeletonRenderer)_boss.Spine).Skeleton.SetSlotsToSetupPose(); PlayableBishopsLog.Debug("Leshy Spine skin applied: Normal."); } } private void PlayIdleAnimation() { if (!((Object)(object)_boss == (Object)null) && !((Object)(object)_boss.Spine == (Object)null)) { ApplyVanillaSkinAndSetupPose(); string text = IdleAnimationField.GetValue(_boss) as string; if (!string.IsNullOrEmpty(text)) { _boss.Spine.AnimationState.SetAnimation(0, text, true); } } } private void CaptureFacingScale() { if (!_facingScaleCaptured && !((Object)(object)_boss == (Object)null) && !((Object)(object)_boss.Spine == (Object)null) && ((SkeletonRenderer)_boss.Spine).Skeleton != null) { _spineBaseScaleX = Mathf.Abs(((SkeletonRenderer)_boss.Spine).Skeleton.ScaleX); if (_spineBaseScaleX < 0.01f) { _spineBaseScaleX = 1f; } _facingScaleCaptured = true; } } internal override void Follow(PlayerFarming player) { //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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_boss == (Object)null) && !((Object)(object)player == (Object)null)) { Vector3 position = ((Component)player).transform.position; int num; if (_hasLastPlayerPosition) { Vector3 val = position - _lastPlayerPosition; num = ((((Vector3)(ref val)).sqrMagnitude > 2.5E-05f) ? 1 : 0); } else { num = 0; } bool flag = (byte)num != 0; bool flag2 = (Object)(object)player.playerController != (Object)null && (Mathf.Abs(player.playerController.xDir) > 0.05f || Mathf.Abs(player.playerController.yDir) > 0.05f); _lastPlayerPosition = position; _hasLastPlayerPosition = true; ((Component)_boss).transform.position = position; if ((Object)(object)((UnitObject)_boss).rb != (Object)null) { ((UnitObject)_boss).rb.velocity = Vector2.zero; } if ((Object)(object)((UnitObject)_boss).state != (Object)null && (Object)(object)player.state != (Object)null) { ((UnitObject)_boss).state.facingAngle = player.state.facingAngle; } UpdateLocomotion(flag || flag2); UpdateTunnelContacts(player); UpdateHorizontalFacing(player); } } private void UpdateHorizontalFacing(PlayerFarming player) { if (!((Object)(object)_boss == (Object)null) && !((Object)(object)_boss.Spine == (Object)null) && ((SkeletonRenderer)_boss.Spine).Skeleton != null && !((Object)(object)player == (Object)null)) { float num = 0f; if ((Object)(object)player.playerController != (Object)null) { num = player.playerController.xDir; } if (Mathf.Abs(num) <= 0.05f && (Object)(object)player.state != (Object)null) { num = Mathf.Cos(player.state.facingAngle * ((float)Math.PI / 180f)); } ApplyHorizontalFacing(num); } } private void ApplyHorizontalFacing(float horizontal) { if (!(Mathf.Abs(horizontal) < 0.15f) && !((Object)(object)_boss == (Object)null) && !((Object)(object)_boss.Spine == (Object)null) && ((SkeletonRenderer)_boss.Spine).Skeleton != null) { CaptureFacingScale(); ((SkeletonRenderer)_boss.Spine).Skeleton.ScaleX = _spineBaseScaleX * ((horizontal < 0f) ? (-1f) : 1f); } } private void UpdateLocomotion(bool moving) { if ((Object)(object)_boss == (Object)null || (Object)(object)_boss.Spine == (Object)null || Time.time < _locomotionLockedUntil) { return; } if (moving) { if (!_locomotionMoving) { BeginBurrowMovement(); } else if (!_burrowHidden && Time.time >= _burrowHideTime) { ((Component)_boss.Spine).gameObject.SetActive(false); _burrowHidden = true; if (!_burrowDisappearSoundPlayed) { _burrowDisappearSoundPlayed = true; PlayLeshySound("event:/enemy/tunnel_worm/tunnel_worm_disappear_underground"); StartTunnelLoop(); } } if (Time.time >= _burrowHideTime - 0.35f) { SpawnTunnelTrailVisual(); } } else if (_locomotionMoving) { EndBurrowMovement(); } } private void BeginBurrowMovement() { _locomotionMoving = true; _burrowHidden = false; _burrowHideTime = Time.time + 0.9f; _nextTrailVisualTime = Time.time; _nextTunnelContactTime = Time.time; _burrowDisappearSoundPlayed = false; ((Component)_boss.Spine).gameObject.SetActive(true); PrepareSpineRendering(_boss.Spine, writeLog: false); PlayLeshySound("event:/enemy/tunnel_worm/tunnel_worm_burst_out_of_ground"); string text = PopOutAnimationField.GetValue(_boss) as string; if (!string.IsNullOrEmpty(text)) { _boss.Spine.AnimationState.SetAnimation(0, text, false); } } private void EndBurrowMovement() { _locomotionMoving = false; _burrowHidden = false; StopTunnelLoop(); ((Component)_boss.Spine).gameObject.SetActive(true); PrepareSpineRendering(_boss.Spine, writeLog: false); ApplyVanillaSkinAndSetupPose(); PlayLeshySound("event:/enemy/tunnel_worm/tunnel_worm_burst_out_of_ground"); string text = PopInAnimationField.GetValue(_boss) as string; string text2 = IdleAnimationField.GetValue(_boss) as string; if (!string.IsNullOrEmpty(text)) { _boss.Spine.AnimationState.SetAnimation(0, text, false); if (!string.IsNullOrEmpty(text2)) { _boss.Spine.AnimationState.AddAnimation(0, text2, true, 0f); } } else { PlayIdleAnimation(); } } private void PrepareForAction(float lockDuration) { bool locomotionMoving = _locomotionMoving; _locomotionLockedUntil = Time.time + lockDuration; _locomotionMoving = false; _burrowHidden = false; StopTunnelLoop(); if ((Object)(object)_boss != (Object)null && (Object)(object)_boss.Spine != (Object)null) { ((Component)_boss.Spine).gameObject.SetActive(true); PrepareSpineRendering(_boss.Spine, writeLog: false); } if (locomotionMoving) { PlayLeshySound("event:/enemy/tunnel_worm/tunnel_worm_burst_out_of_ground"); } } private void ResetLocomotion(bool showSpine) { _hasLastPlayerPosition = false; _locomotionMoving = false; _burrowHidden = false; _burrowHideTime = 0f; _locomotionLockedUntil = 0f; _burrowDisappearSoundPlayed = false; StopTunnelLoop(); if ((Object)(object)_boss != (Object)null && (Object)(object)_boss.Spine != (Object)null) { ((Component)_boss.Spine).gameObject.SetActive(showSpine); } if (!showSpine) { HideTunnelTrailVisuals(); } } private void InitializeTunnelTrail() { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Expected O, but got Unknown if (_trailVisualsInitialized || (Object)(object)_boss == (Object)null || (Object)(object)_root == (Object)null) { return; } object? value = TrailSpikePrefabField.GetValue(_boss); GameObject val = (GameObject)((value is GameObject) ? value : null); if ((Object)(object)val == (Object)null) { PlayableBishopsPlugin.Log.LogWarning((object)"Leshy's tunnel trail prefab was not assigned."); return; } for (int i = 0; i < _trailVisuals.Length; i++) { GameObject val2 = Object.Instantiate(val, ((Component)_boss).transform.position, Quaternion.identity, _root.transform); ((Object)val2).name = "PlayableBishops.LeshyTunnelTrail"; val2.SetActive(false); Collider2D[] componentsInChildren = val2.GetComponentsInChildren(true); for (int j = 0; j < componentsInChildren.Length; j++) { ((Behaviour)componentsInChildren[j]).enabled = false; } ColliderEvents componentInChildren = val2.GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.OnTriggerEnterEvent += new TriggerEvent(OnTunnelTrailTriggerEnter); } PrepareSpineRendering(val2.GetComponentInChildren(true), writeLog: false); _trailVisuals[i] = new TrailVisual { Root = val2, Colliders = componentsInChildren, Events = componentInChildren }; } _trailVisualsInitialized = true; PlayableBishopsPlugin.Log.LogInfo((object)("Initialized " + _trailVisuals.Length + " controlled Leshy tunnel trail visual(s).")); } private void SpawnTunnelTrailVisual() { //IL_0079: Unknown result type (might be due to invalid IL or missing references) if (!_trailVisualsInitialized || (Object)(object)_boss == (Object)null || Time.time < _nextTrailVisualTime) { return; } _nextTrailVisualTime = Time.time + 0.2f; for (int i = 0; i < _trailVisuals.Length; i++) { TrailVisual trailVisual = _trailVisuals[i]; if (trailVisual == null || (Object)(object)trailVisual.Root == (Object)null || trailVisual.Root.activeSelf) { continue; } trailVisual.Root.transform.position = ((Component)_boss).transform.position; trailVisual.Root.SetActive(true); for (int j = 0; j < trailVisual.Colliders.Length; j++) { if ((Object)(object)trailVisual.Colliders[j] != (Object)null) { ((Behaviour)trailVisual.Colliders[j]).enabled = true; } } break; } } private void UpdateTunnelContacts(PlayerFarming player) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) if (_isActive && _locomotionMoving && !((Object)(object)_boss == (Object)null) && !(Time.time < _nextTunnelContactTime)) { _nextTunnelContactTime = Time.time + 0.08f; int num = Physics2D.OverlapCircleNonAlloc(Vector2.op_Implicit(((Component)_boss).transform.position), 1.35f, _tunnelContactBuffer); for (int i = 0; i < num; i++) { Collider2D collider = _tunnelContactBuffer[i]; _tunnelContactBuffer[i] = null; ProcessTunnelContact(collider, player); } } } private void OnTunnelTrailTriggerEnter(Collider2D collider) { ProcessTunnelContact(collider, PlayableBossIdentity.GetOwnerPlayer((Component)(object)_boss)); } private void ProcessTunnelContact(Collider2D collider, PlayerFarming player) { //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Invalid comparison between Unknown and I4 //IL_00a3: Unknown result type (might be due to invalid IL or missing references) if (!_isActive || !_locomotionMoving || (Object)(object)_boss == (Object)null || (Object)(object)collider == (Object)null) { return; } Health componentInParent = ((Component)collider).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null && (Object)(object)componentInParent != (Object)(object)((UnitObject)_boss).health && ((Object)(object)player == (Object)null || (Object)(object)componentInParent != (Object)(object)player.health) && componentInParent.HP > 0f) { if (IsTunnelDestructible(componentInParent)) { componentInParent.DealDamage(Mathf.Max(componentInParent.HP, componentInParent.totalHP), ((Component)_boss).gameObject, ((Component)componentInParent).transform.position, true, (AttackTypes)1, true, (AttackFlags)2048); PlayableBishopsLog.Debug("Leshy tunnel destroyed " + ((Object)componentInParent).name + "."); return; } if ((int)componentInParent.team == 2 && PlayableBishopsConfig.TunnelDamage.Value > 0f) { DamageTunnelTarget(componentInParent, player); return; } } BreakableObject componentInParent2 = ((Component)collider).GetComponentInParent(); if (!((Object)(object)componentInParent2 == (Object)null) && !_brokenTunnelObjects.Contains(componentInParent2) && !(BreakableObjectCollideMethod == null)) { _brokenTunnelObjects.Add(componentInParent2); if (componentInParent2.hasHealth) { componentInParent2.HP = 0; } Health val = (Health)(((Object)(object)player != (Object)null) ? ((object)player.health) : ((object)((UnitObject)_boss).health)); BreakableObjectCollideMethod.Invoke(componentInParent2, new object[1] { val }); PlayableBishopsLog.Debug("Leshy tunnel broke " + ((Object)componentInParent2).name + "."); } } private static bool IsTunnelDestructible(Health target) { if (!((Component)target).CompareTag("BreakableDecoration") && !((Object)(object)((Component)target).GetComponentInParent() != (Object)null) && !((Object)(object)((Component)target).GetComponentInParent() != (Object)null) && !((Object)(object)((Component)target).GetComponentInParent() != (Object)null)) { return (Object)(object)((Component)target).GetComponentInParent() != (Object)null; } return true; } private void DamageTunnelTarget(Health target, PlayerFarming player) { if (!((Object)(object)target == (Object)null) && !(target.HP <= 0f) && (!_tunnelHitCooldowns.TryGetValue(target, out var value) || !(Time.time < value))) { _tunnelHitCooldowns[target] = Time.time + PlayableBishopsConfig.TunnelHitCooldown.Value; BishopDamage.DamageTarget(target, PlayableBishopsConfig.TunnelDamage.Value, ((Component)_boss).gameObject, (AttackTypes)0); PlayableBishopsLog.Debug("Leshy tunnel damaged " + ((Object)target).name + "."); } } private void HideTunnelTrailVisuals() { for (int i = 0; i < _trailVisuals.Length; i++) { TrailVisual trailVisual = _trailVisuals[i]; if (trailVisual == null || !((Object)(object)trailVisual.Root != (Object)null)) { continue; } for (int j = 0; j < trailVisual.Colliders.Length; j++) { if ((Object)(object)trailVisual.Colliders[j] != (Object)null) { ((Behaviour)trailVisual.Colliders[j]).enabled = false; } } trailVisual.Root.SetActive(false); } } private void ClearTunnelTrailReferences() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown for (int i = 0; i < _trailVisuals.Length; i++) { if (_trailVisuals[i] != null && (Object)(object)_trailVisuals[i].Events != (Object)null) { _trailVisuals[i].Events.OnTriggerEnterEvent -= new TriggerEvent(OnTunnelTrailTriggerEnter); } _trailVisuals[i] = null; } _trailVisualsInitialized = false; _brokenTunnelObjects.Clear(); _tunnelHitCooldowns.Clear(); } internal void TrySpikes(PlayerFarming player) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_boss == (Object)null || Time.time < _nextSpikeTime) { return; } try { PrepareForAction(2f); _animationSequence++; Vector3 assistedPoint = BishopAim.GetAssistedPoint(player, 6f, PlayableBishopsConfig.SpikeLineReach.Value); PlayLeshySound("event:/boss/worm/spike_attack"); ((MonoBehaviour)_boss).StartCoroutine(DirectedSpikeRoutine(player, assistedPoint, _animationSequence)); _nextSpikeTime = Time.time + BishopDamage.Cooldown(PlayableBishopsConfig.SpikeCooldown.Value, player); PlayableBishopsLog.Debug("Leshy spikes started."); } catch (Exception exception) { ReportAttackFailure("spikes", exception); } } private IEnumerator DirectedSpikeRoutine(PlayerFarming player, Vector3 aimedPoint, int animationSequence) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) float duration = ((SpikeAnticipationField != null) ? Mathf.Max(0f, (float)SpikeAnticipationField.GetValue(_boss)) : 0.62f); string text = ((SpikeAnimationField != null) ? (SpikeAnimationField.GetValue(_boss) as string) : null); string text2 = IdleAnimationField.GetValue(_boss) as string; if (!string.IsNullOrEmpty(text) && (Object)(object)_boss != (Object)null && (Object)(object)_boss.Spine != (Object)null) { _boss.Spine.AnimationState.SetAnimation(0, text, false); if (!string.IsNullOrEmpty(text2)) { _boss.Spine.AnimationState.AddAnimation(0, text2, true, 0f); } } yield return WaitForSpineSeconds(duration); if ((Object)(object)_boss == (Object)null || !_isActive || animationSequence != _animationSequence) { yield break; } Vector3 position = ((Component)_boss).transform.position; Vector3 val = aimedPoint - position; val.z = 0f; val = ((((Vector3)(ref val)).sqrMagnitude > 0.01f) ? ((Vector3)(ref val)).normalized : BishopAim.GetDirection(player)); Health val2 = FindSpikeAssistTarget(position, aimedPoint, val); if ((Object)(object)val2 != (Object)null) { val = ((Component)val2).transform.position - position; val.z = 0f; if (((Vector3)(ref val)).sqrMagnitude > 0.01f) { ((Vector3)(ref val)).Normalize(); } } ApplyHorizontalFacing(val.x); ((MonoBehaviour)_boss).StartCoroutine(_boss.ShootSpikesInDirectionIE(val, 0.045f, 0.38f, false)); yield return SpikeLineDamageRoutine(val, animationSequence); } private Health FindSpikeAssistTarget(Vector3 origin, Vector3 aimedPoint, Vector3 direction) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) if (PlayableBishopsConfig.ProjectileAimAssist == null || !PlayableBishopsConfig.ProjectileAimAssist.Value) { return null; } List targetsInSector = BishopAim.GetTargetsInSector(origin, direction, PlayableBishopsConfig.SpikeLineReach.Value + 2f, 50f); Health result = null; float num = float.MaxValue; for (int i = 0; i < targetsInSector.Count; i++) { Health val = targetsInSector[i]; if (!((Object)(object)val == (Object)null)) { Vector3 val2 = ((Component)val).transform.position - aimedPoint; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; val2 = ((Component)val).transform.position - origin; float num2 = sqrMagnitude + ((Vector3)(ref val2)).sqrMagnitude * 0.02f; if (num2 < num) { num = num2; result = val; } } } return result; } private IEnumerator SpikeLineDamageRoutine(Vector3 direction, int animationSequence) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) int stepCount = Mathf.Min(30, Mathf.CeilToInt(PlayableBishopsConfig.SpikeLineReach.Value / 0.38f)); float radiusSquared = PlayableBishopsConfig.SpikeLineHalfWidth.Value * PlayableBishopsConfig.SpikeLineHalfWidth.Value; PlayerFarming ownerPlayer = PlayableBossIdentity.GetOwnerPlayer((Component)(object)_boss); float damage = BishopDamage.Scale(PlayableBishopsConfig.SpikeBaseDamage.Value, ownerPlayer); AttackFlags flags = BishopDamage.GetTarotAttackFlags(ownerPlayer, ref damage); HashSet hitTargets = new HashSet(); Vector3 position = ((Component)_boss).transform.position; int layerMask = GetSpikeLayerMask(); for (int step = 0; step < stepCount; step++) { if (!((Object)(object)_boss != (Object)null)) { break; } if (!_isActive) { break; } if (animationSequence != _animationSequence) { break; } for (int num = Health.team2.Count - 1; num >= 0; num--) { Health val = Health.team2[num]; if (!((Object)(object)val == (Object)null) && !hitTargets.Contains(val) && !((Object)(object)((Component)val).gameObject == (Object)null) && ((Component)val).gameObject.activeInHierarchy && !(val.HP <= 0f)) { Vector3 val2 = ((Component)val).transform.position - position; if (!(((Vector3)(ref val2)).sqrMagnitude > radiusSquared)) { hitTargets.Add(val); val.DealDamage(damage, ((Component)_boss).gameObject, ((Component)val).transform.position, false, (AttackTypes)0, false, flags); } } } BishopDamage.DestroyPropsAtPosition(position, PlayableBishopsConfig.SpikeLineHalfWidth.Value, ((Component)_boss).gameObject); position += direction * 0.38f; if (layerMask == 0 || !RaycastHit2D.op_Implicit(Physics2D.Raycast(Vector2.op_Implicit(position), Vector2.op_Implicit(direction), 1f, layerMask))) { yield return WaitForSpineSeconds(0.045f); continue; } break; } } private int GetSpikeLayerMask() { //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) if (LayerToCheckField == null || (Object)(object)_boss == (Object)null) { return 0; } object value = LayerToCheckField.GetValue(_boss); if (!(value is LayerMask val)) { return Convert.ToInt32(value); } return ((LayerMask)(ref val)).value; } private IEnumerator WaitForSpineSeconds(float duration) { float elapsed = 0f; while ((Object)(object)_boss != (Object)null) { float num; elapsed = (num = elapsed + Time.deltaTime * (((Object)(object)_boss.Spine != (Object)null) ? _boss.Spine.timeScale : 1f)); if (num < duration) { yield return null; continue; } break; } } internal unsafe void TryVolley(PlayerFarming player) { //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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_boss == (Object)null || Time.time < _nextVolleyTime) { return; } try { PrepareForAction(2.2f); int animationSequence = ++_animationSequence; Vector3 direction = BishopAim.GetDirection(player); ApplyHorizontalFacing(direction.x); Vector3 val = BishopAim.GetAssistedPoint(player, 5.5f, 9f); Vector3 val2 = val - ((Component)player).transform.position; val2.z = 0f; if (((Vector3)(ref val2)).sqrMagnitude > 64f) { val = ((Component)player).transform.position + ((Vector3)(ref val2)).normalized * 8f; } val = BishopAim.ClampToCurrentRoomFloor(((Component)player).transform.position, val, 0.65f); ((MonoBehaviour)_boss).StartCoroutine(DirectedVolleyRoutine(player, direction, val, animationSequence)); _nextVolleyTime = Time.time + BishopDamage.Cooldown(PlayableBishopsConfig.VolleyCooldown.Value, player); Vector3 val3 = val; PlayableBishopsLog.Debug("Leshy room-safe directed volley started toward " + ((object)(*(Vector3*)(&val3))/*cast due to .constrained prefix*/).ToString() + "."); } catch (Exception exception) { ReportAttackFailure("volley", exception); } } private IEnumerator DirectedVolleyRoutine(PlayerFarming player, Vector3 aimedDirection, Vector3 landingCenter, int animationSequence) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: 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_001d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_boss == (Object)null) { yield break; } PlayLeshySound("event:/boss/worm/spit_projectiles"); string text = ShootAnimationField.GetValue(_boss) as string; string text2 = IdleAnimationField.GetValue(_boss) as string; if (!string.IsNullOrEmpty(text) && (Object)(object)_boss.Spine != (Object)null) { _boss.Spine.AnimationState.SetAnimation(0, text, false); if (!string.IsNullOrEmpty(text2)) { _boss.Spine.AnimationState.AddAnimation(0, text2, true, 0f); } } float anticipation = (float)ShootAnticipationField.GetValue(_boss); float elapsed = 0f; while ((Object)(object)_boss != (Object)null) { float num; elapsed = (num = elapsed + Time.deltaTime * _boss.Spine.timeScale); if (!(num < anticipation)) { break; } yield return null; } if ((Object)(object)_boss == (Object)null || animationSequence != _animationSequence) { yield break; } Vector2 val = (Vector2)DelayBetweenShotsField.GetValue(_boss); List volleyTargets = GetVolleyTargets(player, aimedDirection); int num2 = Mathf.Max(1, PlayableBishopsConfig.VolleyShotCount.Value); int num3 = ((volleyTargets.Count > 0) ? Mathf.Clamp(PlayableBishopsConfig.VolleyFocusedShots.Value, 0, num2) : 0); HashSet hashSet = new HashSet(); while (hashSet.Count < num3) { hashSet.Add(Random.Range(0, num2)); } for (int i = 0; i < num2; i++) { Health focusedTarget = null; if (hashSet.Contains(i)) { focusedTarget = volleyTargets[Random.Range(0, Mathf.Min(4, volleyTargets.Count))]; } Vector2 val2 = Random.insideUnitCircle * PlayableBishopsConfig.VolleySpreadRadius.Value; Vector3 desired = landingCenter + new Vector3(val2.x, val2.y, 0f); desired = BishopAim.ClampToCurrentRoomFloor(((Component)player).transform.position, desired, 0.55f); float delay = Random.Range(val.x, val.y); ((MonoBehaviour)_boss).StartCoroutine(VolleyBulletRoutine(((Component)player).transform.position, desired, focusedTarget, delay, i)); } PlayableBishopsLog.Debug("Leshy volley launched " + num2 + " short-arc shots with " + num3 + " focused toward " + volleyTargets.Count + " aimed-sector target(s)."); yield return (object)new WaitForSeconds(1f); if ((Object)(object)_boss != (Object)null && animationSequence == _animationSequence) { PlayIdleAnimation(); } } private List GetVolleyTargets(PlayerFarming player, Vector3 aimedDirection) { //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_004b: 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_0050: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: 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_0118: Unknown result type (might be due to invalid IL or missing references) List list = new List(); if ((Object)(object)player == (Object)null) { return list; } Vector3 origin = ((Component)player).transform.position; aimedDirection.z = 0f; aimedDirection = ((((Vector3)(ref aimedDirection)).sqrMagnitude > 0.01f) ? ((Vector3)(ref aimedDirection)).normalized : Vector3.right); float num = Mathf.Cos(PlayableBishopsConfig.ProjectileAimAssistControllerCone.Value * ((float)Math.PI / 180f)); for (int num2 = Health.team2.Count - 1; num2 >= 0; num2--) { Health val = Health.team2[num2]; if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null) && ((Component)val).gameObject.activeInHierarchy && ((Behaviour)val).enabled && !(val.HP <= 0f) && !val.InanimateObject) { Vector3 val2 = ((Component)val).transform.position - origin; val2.z = 0f; if (((Vector3)(ref val2)).sqrMagnitude <= 196f && ((Vector3)(ref val2)).sqrMagnitude > 0.01f && Vector3.Dot(aimedDirection, ((Vector3)(ref val2)).normalized) >= num) { list.Add(val); } } } list.Sort(delegate(Health left, Health right) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) Vector3 val3 = ((Component)left).transform.position - origin; float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude; val3 = ((Component)right).transform.position - origin; float sqrMagnitude2 = ((Vector3)(ref val3)).sqrMagnitude; return sqrMagnitude.CompareTo(sqrMagnitude2); }); return list; } private IEnumerator VolleyBulletRoutine(Vector3 roomOrigin, Vector3 collateralLanding, Health focusedTarget, float delay, int shotIndex) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) float elapsed = 0f; while ((Object)(object)_boss != (Object)null) { float num; elapsed = (num = elapsed + Time.deltaTime * _boss.Spine.timeScale); if (!(num < delay)) { break; } yield return null; } if ((Object)(object)_boss == (Object)null) { yield break; } object? value = BulletPrefabField.GetValue(_boss); GameObject val = (GameObject)((value is GameObject) ? value : null); object? value2 = ShootBoneField.GetValue(_boss); GameObject val2 = (GameObject)((value2 is GameObject) ? value2 : null); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { yield break; } Vector3 position = val2.transform.position; Vector3 desired = collateralLanding; if ((Object)(object)focusedTarget != (Object)null && (Object)(object)((Component)focusedTarget).gameObject != (Object)null && ((Component)focusedTarget).gameObject.activeInHierarchy && ((Behaviour)focusedTarget).enabled && focusedTarget.HP > 0f) { Vector2 val3 = Random.insideUnitCircle * 0.25f; desired = ((Component)focusedTarget).transform.position + new Vector3(val3.x, val3.y, 0f); } desired = BishopAim.ClampToCurrentRoomFloor(roomOrigin, desired, 0.55f); Vector3 val4 = desired - position; val4.z = 0f; float num2 = Mathf.Atan2(val4.y, val4.x) * 57.29578f; float num3 = Random.Range(0.68f, 0.92f); float num4 = num3 * 4.44949f; float num5 = ((Vector3)(ref val4)).magnitude / num3; GrenadeBullet component = ObjectPool.Spawn(val, position, Quaternion.identity).GetComponent(); if ((Object)(object)component != (Object)null) { component.SetOwner(((Component)_boss).gameObject); component.Play(-6f, num2, num5, num4, (Team)1, false, "", _boss.Spine); if (shotIndex % 7 == 0) { PlayLeshySound("event:/enemy/spit_gross_projectile"); } } } private void StartTunnelLoop() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) if (_tunnelLoopActive || (Object)(object)_boss == (Object)null) { return; } try { _tunnelLoopInstance = AudioManager.Instance.CreateLoop("event:/enemy/tunnel_worm/tunnel_worm_underground_loop", ((Component)_boss).gameObject, true, true); _tunnelLoopActive = true; } catch (Exception ex) { PlayableBishopsLog.Debug("Leshy tunnel loop failed: " + ex.GetBaseException().Message); } } private void StopTunnelLoop() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) if (_tunnelLoopActive) { try { AudioManager.Instance.StopLoop(_tunnelLoopInstance, (STOP_MODE)0); } catch (Exception ex) { PlayableBishopsLog.Debug("Leshy tunnel loop stop failed: " + ex.GetBaseException().Message); } _tunnelLoopActive = false; } } internal void TryRoar(MonoBehaviour host) { if (!((Object)(object)_boss == (Object)null) && !(Time.time < _nextRoarTime) && !_roarRunning) { _roarRunning = true; PrepareForAction(2f); PlayLeshySound("event:/boss/worm/roar"); host.StartCoroutine(RoarRoutine(++_animationSequence, ++_roarSequence)); PlayerFarming ownerPlayer = PlayableBossIdentity.GetOwnerPlayer((Component)(object)_boss); _nextRoarTime = Time.time + BishopDamage.Cooldown(PlayableBishopsConfig.RoarCooldown.Value, ownerPlayer); } } private IEnumerator RoarRoutine(int animationSequence, int roarSequence) { if ((Object)(object)_boss == (Object)null) { if (roarSequence == _roarSequence) { _roarRunning = false; } yield break; } string text = EnragedAnimationField.GetValue(_boss) as string; string text2 = IdleAnimationField.GetValue(_boss) as string; float presentationDuration = BishopPresentation.GetAnimationDuration(_boss.Spine, text, 1.05f, 0.75f, 1.5f); if (!string.IsNullOrEmpty(text) && (Object)(object)_boss.Spine != (Object)null) { _boss.Spine.AnimationState.SetAnimation(0, text, false); if (!string.IsNullOrEmpty(text2)) { _boss.Spine.AnimationState.AddAnimation(0, text2, true, 0f); } } float impactDelay = Mathf.Clamp(presentationDuration * 0.65f, 0.45f, 0.85f); yield return WaitForSpineSeconds(impactDelay); if ((Object)(object)_boss != (Object)null && animationSequence == _animationSequence) { try { PlayRoarImpactVfx(); if ((Object)(object)CameraManager.instance != (Object)null) { CameraManager.instance.ShakeCameraForDuration(0.85f, 1.8f, 0.8f, true); } BishopDamage.DamageAndDestroyAtPosition(((Component)_boss).transform.position, PlayableBishopsConfig.RoarRadius.Value, BishopDamage.Scale(PlayableBishopsConfig.RoarDamage.Value, PlayableBossIdentity.GetOwnerPlayer((Component)(object)_boss)), ((Component)_boss).gameObject); PlayableBishopsLog.Debug("Leshy roar damage applied."); } catch (Exception exception) { ReportAttackFailure("roar", exception); } } yield return WaitForSpineSeconds(Mathf.Max(0.1f, presentationDuration - impactDelay)); if ((Object)(object)_boss != (Object)null && animationSequence == _animationSequence) { PlayIdleAnimation(); } if (roarSequence == _roarSequence) { _roarRunning = false; } } private void PlayRoarImpactVfx() { GameObject val = (GameObject)((GroundImpactVfxField != null && (Object)(object)_boss != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val == (Object)null) { return; } val.SetActive(true); ParticleSystem[] componentsInChildren = val.GetComponentsInChildren(true); foreach (ParticleSystem val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null)) { val2.Stop(true, (ParticleSystemStopBehavior)0); val2.Play(true); } } } internal override void ResetVisualState() { if (!((Object)(object)_boss == (Object)null)) { _animationSequence++; _roarSequence++; _roarRunning = false; ((MonoBehaviour)_boss).StopAllCoroutines(); ResetLocomotion(showSpine: true); _locomotionLockedUntil = Time.time + 1.5f; _locomotionLockedUntil = Time.time + 0.25f; ConfigureFriendlyState(); PrepareSpineRendering(_boss.Spine); PlayIdleAnimation(); PlayableBishopsPlugin.Log.LogInfo((object)"Leshy visual and attack state reset."); } } private void ReportAttackFailure(string attack, Exception exception) { string text = ((exception == null) ? "unknown error" : exception.GetBaseException().Message); PlayableBishopsPlugin.Log.LogError((object)("Leshy " + attack + " failed: " + text)); ResetVisualState(); } private void PlayLeshySound(string eventPath) { if ((Object)(object)_boss == (Object)null || string.IsNullOrEmpty(eventPath)) { return; } try { AudioManager.Instance.PlayOneShot(eventPath, ((Component)_boss).gameObject); } catch (Exception ex) { PlayableBishopsLog.Debug("Leshy sound failed for " + eventPath + ": " + ex.GetBaseException().Message); } } internal override float BeginSpawnPresentation() { if ((Object)(object)_boss == (Object)null || (Object)(object)_boss.Spine == (Object)null) { return 0f; } _animationSequence++; _roarSequence++; _roarRunning = false; ((MonoBehaviour)_boss).StopAllCoroutines(); ResetLocomotion(showSpine: true); _locomotionLockedUntil = Time.time + 1.5f; ConfigureFriendlyState(); PrepareSpineRendering(_boss.Spine, writeLog: false); ApplyVanillaSkinAndSetupPose(); BishopPresentation.SetAlpha(_boss.Spine, 1f); string text = PopInAnimationField.GetValue(_boss) as string; string text2 = IdleAnimationField.GetValue(_boss) as string; if (!string.IsNullOrEmpty(text)) { _boss.Spine.AnimationState.SetAnimation(0, text, false); if (!string.IsNullOrEmpty(text2)) { _boss.Spine.AnimationState.AddAnimation(0, text2, true, 0f); } } else { PlayIdleAnimation(); } PlayLeshySound("event:/enemy/tunnel_worm/tunnel_worm_burst_out_of_ground"); return BishopPresentation.GetAnimationDuration(_boss.Spine, text, 1f, 0.65f, 1.5f); } internal override float BeginDespawnPresentation() { if ((Object)(object)_boss == (Object)null || (Object)(object)_boss.Spine == (Object)null) { return 0f; } _animationSequence++; _roarSequence++; _roarRunning = false; ((MonoBehaviour)_boss).StopAllCoroutines(); ResetLocomotion(showSpine: true); _locomotionLockedUntil = Time.time + 1.25f; PrepareSpineRendering(_boss.Spine, writeLog: false); BishopPresentation.SetAlpha(_boss.Spine, 1f); string text = PopOutAnimationField.GetValue(_boss) as string; if (!string.IsNullOrEmpty(text)) { _boss.Spine.AnimationState.SetAnimation(0, text, false); } PlayLeshySound("event:/enemy/tunnel_worm/tunnel_worm_disappear_underground"); return BishopPresentation.GetAnimationDuration(_boss.Spine, text, 1f, 0.65f, 1.25f); } internal override float BeginDeathPresentation() { if ((Object)(object)_boss == (Object)null || (Object)(object)_boss.Spine == (Object)null) { return 0f; } _animationSequence++; _roarSequence++; _roarRunning = false; ((MonoBehaviour)_boss).StopAllCoroutines(); ResetLocomotion(showSpine: true); BishopPresentation.SetAlpha(_boss.Spine, 1f); _boss.Spine.AnimationState.SetAnimation(0, "die-noheart", false); _boss.Spine.AnimationState.AddAnimation(0, "dead-noheart", true, 0f); PlayLeshySound("event:/boss/worm/death"); return 3.2f; } internal override void Deactivate() { if (!_isActive && (Object)(object)_root != (Object)null) { return; } _isActive = false; _animationSequence++; _roarSequence++; _roarRunning = false; if ((Object)(object)_boss != (Object)null) { ((MonoBehaviour)_boss).StopAllCoroutines(); if ((Object)(object)((UnitObject)_boss).health != (Object)null) { ((UnitObject)_boss).health.SetTeam((Team)0); } ResetLocomotion(showSpine: false); } ResetCooldowns(); PlayableBishopsPlugin.Log.LogInfo((object)"Leshy aspect disabled; initialized puppet retained for reuse."); } private void ResetCooldowns() { _nextSpikeTime = 0f; _nextVolleyTime = 0f; _nextRoarTime = 0f; } internal override void Dispose() { //IL_0044: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)_root); _root = null; _boss = null; } _isActive = false; ClearTunnelTrailReferences(); _facingScaleCaptured = false; if (_hasPrefabHandle) { Addressables.Release(_prefabHandle); _hasPrefabHandle = false; } } internal override void TryPrimary(PlayerFarming player) { TrySpikes(player); } internal override void TrySecondary(PlayerFarming player) { TryVolley(player); } internal override void TrySignature(MonoBehaviour host, PlayerFarming player) { TryRoar(host); } internal override void TryDodge(MonoBehaviour host, PlayerFarming player) { } } internal sealed class HeketAspect : BishopAspect { private enum LocomotionPhase { Idle, Anticipating, Airborne, Landing } private static readonly string[] PrefabAddresses = new string[2] { "Assets/Resources_moved/Enemies/Dungeon 2/Enemy Forest Frog Boss.prefab", "Assets/Prefabs/Enemies/Dungeon 2/Enemy Forest Frog Boss.prefab" }; private static readonly FieldInfo ActiveField = AccessTools.Field(typeof(EnemyFrogBoss), "active"); private static readonly FieldInfo FacePlayerField = AccessTools.Field(typeof(EnemyFrogBoss), "facePlayer"); private static readonly FieldInfo IdleAnimationField = AccessTools.Field(typeof(EnemyFrogBoss), "idleAnimation"); private static readonly FieldInfo TongueAttackAnimationField = AccessTools.Field(typeof(EnemyFrogBoss), "tongueAttackAnimation"); private static readonly FieldInfo TongueEndAnimationField = AccessTools.Field(typeof(EnemyFrogBoss), "tongueEndAnimation"); private static readonly FieldInfo TongueSpitDelayField = AccessTools.Field(typeof(EnemyFrogBoss), "tongueSpitDelay"); private static readonly FieldInfo TongueWhipAnticipationField = AccessTools.Field(typeof(EnemyFrogBoss), "tongueWhipAnticipation"); private static readonly FieldInfo TongueWhipDurationField = AccessTools.Field(typeof(EnemyFrogBoss), "tongueWhipDuration"); private static readonly FieldInfo TongueRetrieveDelayField = AccessTools.Field(typeof(EnemyFrogBoss), "tongueRetrieveDelay"); private static readonly FieldInfo TongueRetrieveDurationField = AccessTools.Field(typeof(EnemyFrogBoss), "tongueRetrieveDuration"); private static readonly FieldInfo MortarStrikeAnimationField = AccessTools.Field(typeof(EnemyFrogBoss), "mortarStrikeAnimation"); private static readonly FieldInfo BurpAnimationField = AccessTools.Field(typeof(EnemyFrogBoss), "burpAnimation"); private static readonly FieldInfo TargetedMortarPrefabField = AccessTools.Field(typeof(EnemyFrogBoss), "targetedMortarPrefab"); private static readonly FieldInfo TargetedMortarDurationField = AccessTools.Field(typeof(EnemyFrogBoss), "targetedMortarDuration"); private static readonly FieldInfo BurpPositionField = AccessTools.Field(typeof(EnemyFrogBoss), "burpPosition"); private static readonly FieldInfo BurpAnticipationField = AccessTools.Field(typeof(EnemyFrogBoss), "burpAnticipation"); private static readonly FieldInfo ProjectilesToSpawnField = AccessTools.Field(typeof(EnemyFrogBoss), "projectilesToSpawn"); private static readonly FieldInfo ProjectileDelayBetweenSpawnField = AccessTools.Field(typeof(EnemyFrogBoss), "projectileDelayBetweenSpawn"); private static readonly FieldInfo ProjectilePrefabField = AccessTools.Field(typeof(EnemyFrogBoss), "projectilePrefab"); private static readonly FieldInfo ProjectileTargetField = AccessTools.Field(typeof(Projectile), "targetObject"); private static readonly FieldInfo TonguesField = AccessTools.Field(typeof(EnemyFrogBoss), "tongues"); private static readonly FieldInfo HopAnticipationAnimationField = AccessTools.Field(typeof(EnemyFrogBoss), "hopAnticipationAnimation"); private static readonly FieldInfo HopAnimationField = AccessTools.Field(typeof(EnemyFrogBoss), "hopAnimation"); private static readonly FieldInfo HopEndAnimationField = AccessTools.Field(typeof(EnemyFrogBoss), "hopEndAnimation"); private static readonly FieldInfo HopDurationField = AccessTools.Field(typeof(EnemyFrogBoss), "hopDuration"); private static readonly FieldInfo AoeParticlesField = AccessTools.Field(typeof(EnemyFrogBoss), "aoeParticles"); private static readonly MethodInfo GetTongueMethod = AccessTools.Method(typeof(EnemyFrogBoss), "GetTongue", (Type[])null, (Type[])null); private AsyncOperationHandle _prefabHandle; private bool _hasPrefabHandle; private GameObject _root; private EnemyFrogBoss _boss; private GameObject _burpProjectilePrefab; private Projectile _baseBurpProjectile; private bool _isActive; private float _nextPrimaryTime; private float _nextSecondaryTime; private float _nextSignatureTime; private float _nextDodgeTime; private int _actionSequence; private bool _actionInProgress; private bool _hasLastPlayerPosition; private Vector3 _lastPlayerPosition; private LocomotionPhase _locomotionPhase; private float _locomotionPhaseStarted; private bool _locomotionRequested; private bool _locomotionAnimationLogged; private bool _facingScaleCaptured; private float _spineBaseScaleX = 1f; internal override string Id => "Heket"; internal override string DisplayName => "Heket"; internal override bool IsActive { get { if (_isActive && (Object)(object)_root != (Object)null) { return (Object)(object)_boss != (Object)null; } return false; } } internal override bool IsValid { get { if ((Object)(object)_root != (Object)null && (Object)(object)_boss != (Object)null) { return (Object)(object)((Component)_boss).gameObject != (Object)null; } return false; } } internal override bool UsesDodgeAbility => true; internal override IEnumerator Activate(BishopAspectController controller, PlayerFarming player, Action completed) { if ((Object)(object)_root != (Object)null && (Object)(object)_boss != (Object)null) { _isActive = true; ConfigureFriendlyState(); CleanupTongues(); PrepareBurpProjectiles(); PrepareSpineRendering(); PlayIdleAnimation(); ResetCooldowns(); ResetLocomotionState(); PlayableBishopsPlugin.Log.LogInfo((object)"Reactivated the initialized Heket puppet."); completed(arg1: true, null); yield break; } string loadError = null; yield return LoadPrefab(delegate(string error) { loadError = error; }); if (!_hasPrefabHandle || (int)_prefabHandle.Status != 1 || (Object)(object)_prefabHandle.Result == (Object)null) { completed(arg1: false, loadError ?? "the Heket Addressables prefab did not load"); yield break; } _root = new GameObject("PlayableBishops.HeketAspectRoot"); if ((Object)(object)((Component)player).transform.parent != (Object)null) { _root.transform.SetParent(((Component)player).transform.parent, true); } GameObject val; try { val = Object.Instantiate(_prefabHandle.Result, ((Component)player).transform.position, Quaternion.identity, _root.transform); ((Object)val).name = "PlayableBishops.HeketAvatar"; val.AddComponent().Controller = controller; } catch (Exception ex) { Object.Destroy((Object)(object)_root); _root = null; completed(arg1: false, "Heket prefab instantiation failed: " + ex.GetBaseException().Message); yield break; } val.SetActive(false); _boss = val.GetComponent(); if ((Object)(object)_boss == (Object)null) { _boss = val.GetComponentInChildren(true); } if ((Object)(object)_boss == (Object)null) { Object.Destroy((Object)(object)_root); _root = null; completed(arg1: false, "the loaded prefab has no EnemyFrogBoss component"); yield break; } string text = null; try { DisableBodyColliders(val); val.transform.localScale = val.transform.localScale * PlayableBishopsConfig.HeketVisualScale.Value; SetField(ActiveField, _boss, false); SetField(FacePlayerField, _boss, false); val.SetActive(true); ((MonoBehaviour)_boss).StopAllCoroutines(); ConfigureFriendlyState(); PrepareBurpProjectiles(); PrepareSpineRendering(); CaptureFacingScale(); PlayIdleAnimation(); ResetCooldowns(); ResetLocomotionState(); _isActive = true; } catch (Exception ex2) { text = ex2.GetBaseException().Message; } if (text != null) { Object.Destroy((Object)(object)_root); _root = null; _boss = null; _isActive = false; completed(arg1: false, "Heket prefab setup failed: " + text); } else { completed(arg1: true, null); } } private IEnumerator LoadPrefab(Action completed) { string obj = null; for (int i = 0; i < PrefabAddresses.Length; i++) { _prefabHandle = Addressables.LoadAssetAsync((object)PrefabAddresses[i]); _hasPrefabHandle = true; yield return _prefabHandle; if ((int)_prefabHandle.Status == 1 && (Object)(object)_prefabHandle.Result != (Object)null) { PlayableBishopsLog.Debug("Loaded Heket prefab from " + PrefabAddresses[i] + "."); completed(null); yield break; } obj = "address failed: " + PrefabAddresses[i]; Addressables.Release(_prefabHandle); _hasPrefabHandle = false; } completed(obj); } private void ConfigureFriendlyState() { if (!((Object)(object)_boss == (Object)null)) { SetField(ActiveField, _boss, false); SetField(FacePlayerField, _boss, false); if ((Object)(object)((UnitObject)_boss).health != (Object)null) { ((UnitObject)_boss).health.SetTeam((Team)1); ((UnitObject)_boss).health.invincible = true; ((UnitObject)_boss).health.untouchable = true; } if ((Object)(object)_boss.Spine != (Object)null) { _boss.Spine.ForceVisible = true; ((Component)_boss.Spine).gameObject.SetActive(true); } } } private static void SetField(FieldInfo field, object instance, object value) { if (field != null) { field.SetValue(instance, value); } } private static void DisableBodyColliders(GameObject avatar) { Collider2D[] componentsInChildren = avatar.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { ((Behaviour)componentsInChildren[i]).enabled = false; } } private void PrepareBurpProjectiles() { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_boss == (Object)null)) { _burpProjectilePrefab = (GameObject)((ProjectilePrefabField != null) ? /*isinst with value type is only supported in some contexts*/: null); _baseBurpProjectile = (((Object)(object)_burpProjectilePrefab != (Object)null) ? _burpProjectilePrefab.GetComponent() : null); if (!((Object)(object)_burpProjectilePrefab == (Object)null) && !((Object)(object)_baseBurpProjectile == (Object)null)) { Vector2 vector = GetVector2(ProjectilesToSpawnField, new Vector2(4f, 6f)); ObjectPool.CreatePool(_burpProjectilePrefab, Mathf.Max(4, Mathf.CeilToInt(vector.y * 1.6f)), false, true); } } } private void PrepareSpineRendering() { if (!((Object)(object)_boss == (Object)null) && !((Object)(object)_boss.Spine == (Object)null) && ((SkeletonRenderer)_boss.Spine).Skeleton != null) { SkeletonAnimationLODGlobalManager instance = SkeletonAnimationLODGlobalManager.Instance; if ((Object)(object)instance != (Object)null) { instance.DisableCulling(((Component)_boss.Spine).transform, _boss.Spine); } _boss.Spine.ForceVisible = true; ((Component)_boss.Spine).gameObject.SetActive(true); ((SkeletonRenderer)_boss.Spine).Skeleton.SetSkin("Normal"); ((SkeletonRenderer)_boss.Spine).Skeleton.SetBonesToSetupPose(); ((SkeletonRenderer)_boss.Spine).Skeleton.SetSlotsToSetupPose(); } } private void PlayIdleAnimation() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_boss == (Object)null) && !((Object)(object)_boss.Spine == (Object)null)) { ((Component)_boss.Spine).transform.localPosition = Vector3.zero; PrepareSpineRendering(); string text = GetString(IdleAnimationField); if (!string.IsNullOrEmpty(text)) { _boss.Spine.AnimationState.SetAnimation(0, text, true); } } } internal override void Follow(PlayerFarming player) { //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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: 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_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_boss == (Object)null) && !((Object)(object)player == (Object)null)) { Vector3 position = ((Component)player).transform.position; int num; if (_hasLastPlayerPosition) { Vector3 val = position - _lastPlayerPosition; num = ((((Vector3)(ref val)).sqrMagnitude > 2.5E-05f) ? 1 : 0); } else { num = 0; } bool flag = (byte)num != 0; bool flag2 = (Object)(object)player.playerController != (Object)null && (Mathf.Abs(player.playerController.xDir) > 0.05f || Mathf.Abs(player.playerController.yDir) > 0.05f); UpdateLocomotion(flag || flag2); _lastPlayerPosition = position; _hasLastPlayerPosition = true; ((Component)_boss).transform.position = position; if ((Object)(object)((UnitObject)_boss).rb != (Object)null) { ((UnitObject)_boss).rb.velocity = Vector2.zero; } if ((Object)(object)((UnitObject)_boss).state != (Object)null && (Object)(object)player.state != (Object)null) { ((UnitObject)_boss).state.facingAngle = player.state.facingAngle; ((UnitObject)_boss).state.LookAngle = player.state.facingAngle; } float num2 = (((Object)(object)player.playerController != (Object)null) ? player.playerController.xDir : 0f); if (Mathf.Abs(num2) < 0.05f && (Object)(object)player.state != (Object)null) { num2 = Mathf.Cos(player.state.facingAngle * ((float)Math.PI / 180f)); } ApplyHorizontalFacing(num2); } } internal override void TryPrimary(PlayerFarming player) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_boss == (Object)null || Time.time < _nextPrimaryTime) { return; } try { Vector3 val = ClampTarget(((Component)player).transform.position, BishopAim.GetAssistedPoint(player, 7f, 10f), 10f); ApplyHorizontalFacing(val.x - ((Component)player).transform.position.x); int sequence = ++_actionSequence; BeginAction(); ((MonoBehaviour)_boss).StartCoroutine(TongueRoutine(val, sequence)); _nextPrimaryTime = Time.time + BishopDamage.Cooldown(PlayableBishopsConfig.HeketTongueCooldown.Value, player); } catch (Exception exception) { ReportAttackFailure("tongue", exception); } } private IEnumerator TongueRoutine(Vector3 target, int sequence) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) SetAnimation(GetString(TongueAttackAnimationField), loop: false); PlayHeketSound("event:/boss/frog/tongue_attack"); float duration = GetFloat(TongueWhipAnticipationField, 0.65f); yield return WaitForSpineSeconds(duration); if (!ActionIsCurrent(sequence)) { yield break; } FrogBossTongue val; try { val = (FrogBossTongue)((GetTongueMethod != null) ? /*isinst with value type is only supported in some contexts*/: null); } catch (Exception exception) { ReportAttackFailure("tongue", exception); yield break; } if ((Object)(object)val == (Object)null) { ReportAttackFailure("tongue", new InvalidOperationException("Heket tongue prefab was unavailable")); yield break; } if ((Object)(object)((UnitObject)val).health != (Object)null) { ((UnitObject)val).health.SetTeam((Team)1); ((UnitObject)val).health.invincible = true; } float num = GetFloat(TongueSpitDelayField, 0.15f); float num2 = GetFloat(TongueWhipDurationField, 0.5f); float retrieveDelay = Mathf.Min(GetFloat(TongueRetrieveDelayField, 0.6f), 0.8f); float retrieveDuration = GetFloat(TongueRetrieveDurationField, 0.15f); ((MonoBehaviour)_boss).StartCoroutine(val.SpitTongueIE(target, num, num2, retrieveDelay, retrieveDuration)); yield return WaitForSpineSeconds(num + num2); if (ActionIsCurrent(sequence)) { BishopDamage.DamageAndDestroyAtPosition(target, PlayableBishopsConfig.HeketTongueImpactRadius.Value, BishopDamage.Scale(PlayableBishopsConfig.HeketTongueBaseDamage.Value, PlayableBossIdentity.GetOwnerPlayer((Component)(object)_boss)), ((Component)_boss).gameObject); PlayHeketSound("event:/boss/frog/land"); yield return WaitForSpineSeconds(retrieveDelay + retrieveDuration + 0.2f); if (ActionIsCurrent(sequence)) { PlayHeketSound("event:/boss/frog/tongue_return"); SetAnimation(GetString(TongueEndAnimationField), loop: false); yield return WaitForSpineSeconds(0.25f); FinishAction(sequence); } } } internal override void TrySecondary(PlayerFarming player) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_boss == (Object)null || Time.time < _nextSecondaryTime) { return; } try { Vector3 val = ClampTarget(((Component)player).transform.position, BishopAim.GetAssistedPoint(player, 8f, 13f), 13f); ApplyHorizontalFacing(val.x - ((Component)player).transform.position.x); int sequence = ++_actionSequence; BeginAction(); ((MonoBehaviour)_boss).StartCoroutine(MortarRoutine(val, sequence)); _nextSecondaryTime = Time.time + BishopDamage.Cooldown(PlayableBishopsConfig.HeketMortarCooldown.Value, player); } catch (Exception exception) { ReportAttackFailure("mortar", exception); } } private IEnumerator MortarRoutine(Vector3 target, int sequence) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) MortarBomb prefab = (MortarBomb)((TargetedMortarPrefabField != null) ? /*isinst with value type is only supported in some contexts*/: null); GameObject burpPosition = (GameObject)((BurpPositionField != null) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)prefab == (Object)null || (Object)(object)burpPosition == (Object)null) { ReportAttackFailure("mortar", new InvalidOperationException("Heket mortar prefab was unavailable")); yield break; } SetAnimation(GetString(MortarStrikeAnimationField), loop: false); PlayHeketSound("event:/boss/frog/mortar_spit"); yield return WaitForSpineSeconds(0.35f); if (!ActionIsCurrent(sequence)) { yield break; } int count = PlayableBishopsConfig.HeketMortarCount.Value; Vector3 val = target - ((Component)_boss).transform.position; Vector3 normalized = ((Vector3)(ref val)).normalized; Vector3 perpendicular = new Vector3(0f - normalized.y, normalized.x, 0f); for (int i = 0; i < count; i++) { float num = ((float)i - (float)(count - 1) * 0.5f) * 1.1f; Vector3 val2 = target + perpendicular * num; try { MortarBomb obj = ObjectPool.Spawn(prefab, (Transform)null, val2, Quaternion.identity, true); obj.destroyOnFinish = false; obj.Play(burpPosition.transform.position, GetFloat(TargetedMortarDurationField, 1.2f), (Team)1, ((UnitObject)_boss).health, true, "", _boss.Spine, false); } catch (Exception exception) { ReportAttackFailure("mortar", exception); yield break; } PlayHeketSound("event:/boss/frog/mortar_spawn"); yield return WaitForSpineSeconds(0.16f); if (!ActionIsCurrent(sequence)) { yield break; } } yield return WaitForSpineSeconds(0.35f); FinishAction(sequence); } internal override void TrySignature(MonoBehaviour host, PlayerFarming player) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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_007f: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_boss == (Object)null || _actionInProgress || Time.time < _nextSignatureTime) { return; } try { if ((Object)(object)_burpProjectilePrefab == (Object)null || (Object)(object)_baseBurpProjectile == (Object)null) { throw new InvalidOperationException("Heket projectile-burp prefab was unavailable"); } Vector3 val = ClampTarget(((Component)player).transform.position, BishopAim.GetAssistedPoint(player, 8f, 12f), 12f); ApplyHorizontalFacing(val.x - ((Component)player).transform.position.x); int sequence = ++_actionSequence; BeginAction(); host.StartCoroutine(BurpRoutine(val, sequence)); _nextSignatureTime = Time.time + BishopDamage.Cooldown(PlayableBishopsConfig.HeketBurpCooldown.Value, player); } catch (Exception exception) { ReportAttackFailure("projectile burp", exception); } } private IEnumerator BurpRoutine(Vector3 targetPoint, int sequence) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) GameObject burpPosition = (GameObject)((BurpPositionField != null) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)burpPosition == (Object)null) { ReportAttackFailure("projectile burp", new InvalidOperationException("Heket burp origin was unavailable")); yield break; } SetAnimation(GetString(BurpAnimationField), loop: false); yield return WaitForSpineSeconds(GetFloat(BurpAnticipationField, 0.65f)); if (!ActionIsCurrent(sequence)) { yield break; } Vector2 vector = GetVector2(ProjectilesToSpawnField, new Vector2(4f, 6f)); Vector2 delayRange = GetVector2(ProjectileDelayBetweenSpawnField, new Vector2(0.08f, 0.16f)); int amount = Mathf.Max(1, (int)Random.Range(vector.x, vector.y)); Health targetHealth = ((UnitObject)_boss).GetClosestTarget(targetPoint - ((Component)_boss).transform.position, false, true, true, false); float aimAngle = Utils.GetAngle(((Component)_boss).transform.position, targetPoint); for (int i = 0; i < amount; i++) { try { Projectile component = ObjectPool.Spawn(_burpProjectilePrefab, ((Component)_boss).transform.parent).GetComponent(); SetField(ProjectileTargetField, component, null); component.UseDelay = true; component.CollideOnlyTarget = (Object)(object)targetHealth != (Object)null; component.CollideOnlyTargets = false; ((Component)component).transform.position = new Vector3(burpPosition.transform.position.x, burpPosition.transform.position.y, 0f); component.ModifyingZ = true; component.Angle = aimAngle + Random.Range(-25f, 25f); component.team = (Team)1; component.Speed = _baseBurpProjectile.Speed + Random.Range(-0.5f, 0.5f); component.turningSpeed = _baseBurpProjectile.turningSpeed + Random.Range(-0.1f, 0.1f); component.angleNoiseFrequency = _baseBurpProjectile.angleNoiseFrequency + Random.Range(-0.1f, 0.1f); component.LifeTime = _baseBurpProjectile.LifeTime + Random.Range(0f, 0.3f); PlayerFarming ownerPlayer = PlayableBossIdentity.GetOwnerPlayer((Component)(object)_boss); float damage = BishopDamage.Scale(PlayableBishopsConfig.HeketBurpProjectileBaseDamage.Value, ownerPlayer); component.AttackFlags = BishopDamage.GetTarotAttackFlags(ownerPlayer, ref damage); component.Damage = damage; component.Owner = ((UnitObject)_boss).health; component.InvincibleTime = 1f; if ((Object)(object)targetHealth != (Object)null) { component.SetTarget(targetHealth); } } catch (Exception exception) { ReportAttackFailure("projectile burp", exception); yield break; } yield return WaitForSpineSeconds(Random.Range(delayRange.x, delayRange.y)); if (!ActionIsCurrent(sequence)) { yield break; } } yield return WaitForSpineSeconds(0.45f); FinishAction(sequence); } internal override void TryDodge(MonoBehaviour host, PlayerFarming player) { if ((Object)(object)_boss == (Object)null || _actionInProgress || Time.time < _nextDodgeTime) { return; } try { int sequence = ++_actionSequence; BeginAction(); host.StartCoroutine(SlamRoutine(sequence)); _nextDodgeTime = Time.time + BishopDamage.Cooldown(PlayableBishopsConfig.HeketSlamCooldown.Value, player); } catch (Exception exception) { ReportAttackFailure("dodge hop", exception); } } private IEnumerator SlamRoutine(int sequence) { SetAnimation(GetString(HopAnticipationAnimationField), loop: false); yield return WaitForSpineSeconds(0.35f); if (!ActionIsCurrent(sequence)) { yield break; } SetAnimation(GetString(HopAnimationField), loop: false); PlayHeketSound("event:/boss/frog/jump"); float duration = 0.55f; float elapsed = 0f; while (ActionIsCurrent(sequence) && elapsed < duration) { elapsed += Time.deltaTime; float num = Mathf.Sin(Mathf.Clamp01(elapsed / duration) * (float)Math.PI) * 4f; ((Component)_boss.Spine).transform.localPosition = -Vector3.forward * num; yield return null; } if (ActionIsCurrent(sequence)) { ((Component)_boss.Spine).transform.localPosition = Vector3.zero; SetAnimation(GetString(HopEndAnimationField), loop: false); PlayHeketSound("event:/boss/frog/land"); ParticleSystem val = (ParticleSystem)((AoeParticlesField != null) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val != (Object)null) { val.Play(); } try { BishopDamage.DamageAndDestroyAtPosition(((Component)_boss).transform.position, PlayableBishopsConfig.HeketSlamRadius.Value, BishopDamage.Scale(PlayableBishopsConfig.HeketSlamDamage.Value, PlayableBossIdentity.GetOwnerPlayer((Component)(object)_boss)), ((Component)_boss).gameObject); } catch (Exception exception) { ReportAttackFailure("slam", exception); yield break; } yield return WaitForSpineSeconds(0.35f); FinishAction(sequence); } } private void BeginAction() { ResetLocomotionVisual(); _actionInProgress = true; } private void FinishAction(int sequence) { if (ActionIsCurrent(sequence)) { _actionInProgress = false; PlayIdleAnimation(); } } private void UpdateLocomotion(bool moving) { //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_boss == (Object)null || (Object)(object)_boss.Spine == (Object)null || _actionInProgress) { return; } _locomotionRequested = moving; float num = Time.time - _locomotionPhaseStarted; if (_locomotionPhase == LocomotionPhase.Idle) { if (moving) { BeginLocomotionAnticipation(); } } else if (_locomotionPhase == LocomotionPhase.Anticipating) { if (num >= 0.5f) { _locomotionPhase = LocomotionPhase.Airborne; _locomotionPhaseStarted = Time.time; SetAnimation(GetString(HopAnimationField), loop: false); } } else if (_locomotionPhase == LocomotionPhase.Airborne) { float num2 = Mathf.Max(0.2f, GetFloat(HopDurationField, 0.45f)); float num3 = Mathf.Clamp01((num - 0.1f) / num2); ((Component)_boss.Spine).transform.localPosition = -Vector3.forward * (Mathf.Sin(num3 * (float)Math.PI) * 1.25f); if (num >= num2 + 0.1f) { ((Component)_boss.Spine).transform.localPosition = Vector3.zero; _locomotionPhase = LocomotionPhase.Landing; _locomotionPhaseStarted = Time.time; SetAnimation(GetString(HopEndAnimationField), loop: false); DoLocomotionLanding(); } } else if (_locomotionPhase == LocomotionPhase.Landing && num >= 0.5f) { ((Component)_boss.Spine).transform.localPosition = Vector3.zero; if (_locomotionRequested) { BeginLocomotionAnticipation(); return; } _locomotionPhase = LocomotionPhase.Idle; PlayIdleAnimation(); } } private void BeginLocomotionAnticipation() { _locomotionPhase = LocomotionPhase.Anticipating; _locomotionPhaseStarted = Time.time; SetAnimation(GetString(HopAnticipationAnimationField), loop: false); if (!_locomotionAnimationLogged) { _locomotionAnimationLogged = true; PlayableBishopsPlugin.Log.LogInfo((object)"Heket locomotion using the boss routine's native anticipation, hop-duration, and landing timing."); } } private void DoLocomotionLanding() { //IL_0058: Unknown result type (might be due to invalid IL or missing references) if (!_isActive || (Object)(object)_boss == (Object)null) { return; } ParticleSystem val = (ParticleSystem)((AoeParticlesField != null) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val != (Object)null) { val.Play(); } try { BishopDamage.DamageAndDestroyAtPosition(((Component)_boss).transform.position, PlayableBishopsConfig.HeketLocomotionHopRadius.Value, BishopDamage.Scale(PlayableBishopsConfig.HeketLocomotionHopDamage.Value, PlayableBossIdentity.GetOwnerPlayer((Component)(object)_boss)), ((Component)_boss).gameObject); } catch (Exception ex) { PlayableBishopsPlugin.Log.LogError((object)("Heket traversal-hop shockwave failed: " + ex.GetBaseException().Message)); } } private void ResetLocomotionVisual() { //IL_003f: Unknown result type (might be due to invalid IL or missing references) _locomotionPhase = LocomotionPhase.Idle; _locomotionRequested = false; if ((Object)(object)_boss != (Object)null && (Object)(object)_boss.Spine != (Object)null) { ((Component)_boss.Spine).transform.localPosition = Vector3.zero; } } private void ResetLocomotionState() { _actionInProgress = false; _hasLastPlayerPosition = false; ResetLocomotionVisual(); } private IEnumerator WaitForSpineSeconds(float duration) { float elapsed = 0f; while ((Object)(object)_boss != (Object)null) { float num; elapsed = (num = elapsed + Time.deltaTime * (((Object)(object)_boss.Spine != (Object)null) ? _boss.Spine.timeScale : 1f)); if (num < duration) { yield return null; continue; } break; } } private bool ActionIsCurrent(int sequence) { if (_isActive && (Object)(object)_boss != (Object)null) { return sequence == _actionSequence; } return false; } private void SetAnimation(string animationName, bool loop) { if ((Object)(object)_boss != (Object)null && (Object)(object)_boss.Spine != (Object)null && !string.IsNullOrEmpty(animationName)) { _boss.Spine.AnimationState.SetAnimation(0, animationName, loop); } } private string GetString(FieldInfo field) { if (!(field != null) || !((Object)(object)_boss != (Object)null)) { return null; } return field.GetValue(_boss) as string; } private float GetFloat(FieldInfo field, float fallback) { if (!(field != null) || !((Object)(object)_boss != (Object)null)) { return fallback; } return (float)field.GetValue(_boss); } private Vector2 GetVector2(FieldInfo field, Vector2 fallback) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) if (!(field != null) || !((Object)(object)_boss != (Object)null)) { return fallback; } return (Vector2)field.GetValue(_boss); } private static Vector3 ClampTarget(Vector3 origin, Vector3 target, float maxDistance) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //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_0037: 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_0020: 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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) Vector3 val = target - origin; val.z = 0f; if (((Vector3)(ref val)).sqrMagnitude > maxDistance * maxDistance) { target = origin + ((Vector3)(ref val)).normalized * maxDistance; } target.z = origin.z; return target; } private void CaptureFacingScale() { if (!_facingScaleCaptured && !((Object)(object)_boss == (Object)null) && !((Object)(object)_boss.Spine == (Object)null) && ((SkeletonRenderer)_boss.Spine).Skeleton != null) { _spineBaseScaleX = Mathf.Max(0.01f, Mathf.Abs(((SkeletonRenderer)_boss.Spine).Skeleton.ScaleX)); _facingScaleCaptured = true; } } private void ApplyHorizontalFacing(float horizontal) { if (!(Mathf.Abs(horizontal) < 0.15f) && !((Object)(object)_boss == (Object)null) && !((Object)(object)_boss.Spine == (Object)null) && ((SkeletonRenderer)_boss.Spine).Skeleton != null) { CaptureFacingScale(); ((SkeletonRenderer)_boss.Spine).Skeleton.ScaleX = _spineBaseScaleX * ((horizontal < 0f) ? 1f : (-1f)); } } private void PlayHeketSound(string eventPath) { if ((Object)(object)_boss == (Object)null || string.IsNullOrEmpty(eventPath)) { return; } try { AudioManager.Instance.PlayOneShot(eventPath, ((Component)_boss).gameObject); } catch (Exception ex) { PlayableBishopsLog.Debug("Heket sound failed for " + eventPath + ": " + ex.GetBaseException().Message); } } private void ReportAttackFailure(string attack, Exception exception) { PlayableBishopsPlugin.Log.LogError((object)("Heket " + attack + " failed: " + exception.GetBaseException().Message)); ResetVisualState(); } private void CleanupTongues() { if ((Object)(object)_boss == (Object)null || TonguesField == null || !(TonguesField.GetValue(_boss) is IList list)) { return; } for (int i = 0; i < list.Count; i++) { object? obj = list[i]; FrogBossTongue val = (FrogBossTongue)((obj is FrogBossTongue) ? obj : null); if (!((Object)(object)val == (Object)null)) { ((MonoBehaviour)val).StopAllCoroutines(); ((Component)val).gameObject.SetActive(false); } } } internal override float BeginSpawnPresentation() { //IL_006f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_boss == (Object)null || (Object)(object)_boss.Spine == (Object)null) { return 0f; } ResetLocomotionState(); _actionSequence++; _actionInProgress = true; ((MonoBehaviour)_boss).StopAllCoroutines(); CleanupTongues(); ConfigureFriendlyState(); PrepareSpineRendering(); ((Component)_boss.Spine).transform.localPosition = Vector3.zero; string animationName = GetString(HopEndAnimationField); string text = GetString(IdleAnimationField); SetAnimation(animationName, loop: false); if (!string.IsNullOrEmpty(text)) { _boss.Spine.AnimationState.AddAnimation(0, text, true, 0f); } PlayHeketSound("event:/boss/frog/land"); ((MonoBehaviour)_boss).StartCoroutine(BishopPresentation.Fade(_boss.Spine, 0f, 1f, 0.55f)); return 0.55f; } internal override void CompleteSpawnPresentation() { _actionInProgress = false; BishopPresentation.SetAlpha(((Object)(object)_boss != (Object)null) ? _boss.Spine : null, 1f); PlayIdleAnimation(); } internal override float BeginDespawnPresentation() { if ((Object)(object)_boss == (Object)null || (Object)(object)_boss.Spine == (Object)null) { return 0f; } ResetLocomotionState(); _actionSequence++; _actionInProgress = true; ((MonoBehaviour)_boss).StopAllCoroutines(); CleanupTongues(); PrepareSpineRendering(); string animationName = GetString(HopAnticipationAnimationField); SetAnimation(animationName, loop: false); PlayHeketSound("event:/boss/frog/jump"); ((MonoBehaviour)_boss).StartCoroutine(BishopPresentation.Fade(_boss.Spine, 1f, 0f, 0.55f)); return 0.55f; } internal override float BeginDeathPresentation() { //IL_0063: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_boss == (Object)null || (Object)(object)_boss.Spine == (Object)null) { return 0f; } _actionSequence++; ResetLocomotionState(); _actionInProgress = true; ((MonoBehaviour)_boss).StopAllCoroutines(); CleanupTongues(); ((Component)_boss.Spine).transform.localPosition = Vector3.zero; BishopPresentation.SetAlpha(_boss.Spine, 1f); _boss.Spine.AnimationState.SetAnimation(0, "die-noheart", false); _boss.Spine.AnimationState.AddAnimation(0, "dead-noheart", true, 0f); PlayHeketSound("event:/boss/frog/death"); return 3f; } internal override void ResetVisualState() { if (!((Object)(object)_boss == (Object)null)) { _actionSequence++; ResetLocomotionState(); ((MonoBehaviour)_boss).StopAllCoroutines(); CleanupTongues(); ConfigureFriendlyState(); PrepareSpineRendering(); BishopPresentation.SetAlpha(_boss.Spine, 1f); PlayIdleAnimation(); PlayableBishopsPlugin.Log.LogInfo((object)"Heket visual and attack state reset."); } } internal override void Deactivate() { //IL_005d: Unknown result type (might be due to invalid IL or missing references) _isActive = false; _actionSequence++; ResetLocomotionState(); if ((Object)(object)_boss != (Object)null) { ((MonoBehaviour)_boss).StopAllCoroutines(); CleanupTongues(); if ((Object)(object)_boss.Spine != (Object)null) { ((Component)_boss.Spine).transform.localPosition = Vector3.zero; ((Component)_boss.Spine).gameObject.SetActive(false); } if ((Object)(object)((UnitObject)_boss).health != (Object)null) { ((UnitObject)_boss).health.SetTeam((Team)0); } } ResetCooldowns(); PlayableBishopsPlugin.Log.LogInfo((object)"Heket aspect disabled; initialized puppet retained for reuse."); } private void ResetCooldowns() { _nextPrimaryTime = 0f; _nextSecondaryTime = 0f; _nextSignatureTime = 0f; _nextDodgeTime = 0f; } internal override void Dispose() { //IL_0058: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_root != (Object)null) { CleanupTongues(); Object.Destroy((Object)(object)_root); _root = null; _boss = null; _burpProjectilePrefab = null; _baseBurpProjectile = null; } _isActive = false; _facingScaleCaptured = false; ResetLocomotionState(); if (_hasPrefabHandle) { Addressables.Release(_prefabHandle); _hasPrefabHandle = false; } } } internal sealed class KallamarAspect : BishopAspect { private const float MovementDestructionInterval = 0.1f; private const float MovementInputThreshold = 0.05f; private const int DodgeActionId = 16; private const float TeleportChargeDuration = 0.18f; private static readonly string[] PrefabAddresses = new string[2] { "Assets/Resources_moved/Enemies/Dungeon 3/Enemy Jellyfish Boss.prefab", "Assets/Prefabs/Enemies/Dungeon 3/Enemy Jellyfish Boss.prefab" }; private static readonly FieldInfo ActivatedField = AccessTools.Field(typeof(EnemyTentacleMonster), "activated"); private static readonly FieldInfo FacePlayerField = AccessTools.Field(typeof(EnemyTentacleMonster), "facePlayer"); private static readonly FieldInfo MovingField = AccessTools.Field(typeof(EnemyTentacleMonster), "m"); private static readonly FieldInfo AttackingField = AccessTools.Field(typeof(EnemyTentacleMonster), "attacking"); private static readonly FieldInfo IdleAnimationField = AccessTools.Field(typeof(EnemyTentacleMonster), "idleAnimation"); private static readonly FieldInfo ShootAnimationField = AccessTools.Field(typeof(EnemyTentacleMonster), "shootProjectilesAnimation"); private static readonly FieldInfo DaggerAnimationField = AccessTools.Field(typeof(EnemyTentacleMonster), "daggerAttackAnimation"); private static readonly FieldInfo SwordAnticipationAnimationField = AccessTools.Field(typeof(EnemyTentacleMonster), "swordAnticipationAnimation"); private static readonly FieldInfo SwordLoopAnimationField = AccessTools.Field(typeof(EnemyTentacleMonster), "swordLoopAnimation"); private static readonly FieldInfo SwordAttackAnimationField = AccessTools.Field(typeof(EnemyTentacleMonster), "swordAttackAnimation"); private static readonly FieldInfo TeleportAnimationField = AccessTools.Field(typeof(EnemyTentacleMonster), "teleportAnimation"); private static readonly FieldInfo ProjectileCircleField = AccessTools.Field(typeof(EnemyTentacleMonster), "projectilePatternCircle"); private static readonly FieldInfo PatternHealthField = AccessTools.Field(typeof(ProjectilePattern), "health"); private static readonly FieldInfo PatternTargetPlayerField = AccessTools.Field(typeof(ProjectilePattern), "targetPlayer"); private static readonly FieldInfo PatternRecalculateField = AccessTools.Field(typeof(ProjectilePattern), "recalculatePlayerEachWave"); private static readonly FieldInfo PatternLoopField = AccessTools.Field(typeof(ProjectilePattern), "loop"); private AsyncOperationHandle _prefabHandle; private bool _hasPrefabHandle; private GameObject _root; private EnemyTentacleMonster _boss; private ProjectilePattern _projectileCircle; private bool _projectileEventsHooked; private bool _isActive; private bool _actionInProgress; private int _actionSequence; private float _nextPrimaryTime; private float _nextSecondaryTime; private float _nextSignatureTime; private float _nextDodgeTime; private float _nextMovementDestructionTime; private bool _hasLastPlayerPosition; private Vector3 _lastPlayerPosition; private bool _facingScaleCaptured; private float _spineBaseScaleX = 1f; private bool _spineRestPositionCaptured; private Vector3 _spineRestLocalPosition; private float _bobPhase; internal override string Id => "Kallamar"; internal override string DisplayName => "Kallamar"; internal override bool IsActive { get { if (_isActive && (Object)(object)_root != (Object)null) { return (Object)(object)_boss != (Object)null; } return false; } } internal override bool IsValid { get { if ((Object)(object)_root != (Object)null && (Object)(object)_boss != (Object)null) { return (Object)(object)((Component)_boss).gameObject != (Object)null; } return false; } } internal override bool UsesDodgeAbility => true; internal override IEnumerator Activate(BishopAspectController controller, PlayerFarming player, Action completed) { if ((Object)(object)_root != (Object)null && (Object)(object)_boss != (Object)null) { _isActive = true; ConfigureFriendlyState(); PrepareSpineRendering(); PlayIdleAnimation(); ResetCooldowns(); PlayableBishopsPlugin.Log.LogInfo((object)"Reactivated the initialized Kallamar puppet."); completed(arg1: true, null); yield break; } string loadError = null; yield return LoadPrefab(delegate(string error) { loadError = error; }); if (!_hasPrefabHandle || (int)_prefabHandle.Status != 1 || (Object)(object)_prefabHandle.Result == (Object)null) { completed(arg1: false, loadError ?? "the Kallamar Addressables prefab did not load"); yield break; } _root = new GameObject("PlayableBishops.KallamarAspectRoot"); if ((Object)(object)((Component)player).transform.parent != (Object)null) { _root.transform.SetParent(((Component)player).transform.parent, true); } GameObject val = null; GameObject result = _prefabHandle.Result; bool activeSelf = result.activeSelf; try { if (activeSelf) { result.SetActive(false); } val = Object.Instantiate(result, ((Component)player).transform.position, Quaternion.identity, _root.transform); ((Object)val).name = "PlayableBishops.KallamarAvatar"; val.AddComponent().Controller = controller; } catch (Exception ex) { Object.Destroy((Object)(object)_root); _root = null; completed(arg1: false, "Kallamar prefab instantiation failed: " + ex.GetBaseException().Message); yield break; } finally { if (activeSelf && (Object)(object)result != (Object)null) { result.SetActive(true); } } val.SetActive(false); _boss = val.GetComponent(); if ((Object)(object)_boss == (Object)null) { _boss = val.GetComponentInChildren(true); } if ((Object)(object)_boss == (Object)null) { Object.Destroy((Object)(object)_root); _root = null; completed(arg1: false, "the loaded prefab has no EnemyTentacleMonster component"); yield break; } string text = null; try { DisableBodyColliders(val); val.transform.localScale = val.transform.localScale * PlayableBishopsConfig.KallamarVisualScale.Value; SetField(ActivatedField, _boss, false); SetField(FacePlayerField, _boss, false); SetField(MovingField, _boss, false); val.SetActive(true); ((MonoBehaviour)_boss).StopAllCoroutines(); _projectileCircle = (ProjectilePattern)((ProjectileCircleField != null) ? /*isinst with value type is only supported in some contexts*/: null); ConfigureFriendlyState(); ConfigureProjectilePattern(); PrepareSpineRendering(); CaptureSpineRestPosition(); CaptureFacingScale(); PlayIdleAnimation(); ResetCooldowns(); _isActive = true; } catch (Exception ex2) { text = ex2.GetBaseException().Message; } if (text != null) { Object.Destroy((Object)(object)_root); _root = null; _boss = null; _projectileCircle = null; _isActive = false; completed(arg1: false, "Kallamar prefab setup failed: " + text); } else { completed(arg1: true, null); } } private IEnumerator LoadPrefab(Action completed) { string obj = null; for (int i = 0; i < PrefabAddresses.Length; i++) { _prefabHandle = Addressables.LoadAssetAsync((object)PrefabAddresses[i]); _hasPrefabHandle = true; yield return _prefabHandle; if ((int)_prefabHandle.Status == 1 && (Object)(object)_prefabHandle.Result != (Object)null) { PlayableBishopsLog.Debug("Loaded Kallamar prefab from " + PrefabAddresses[i] + "."); completed(null); yield break; } obj = "address failed: " + PrefabAddresses[i]; Addressables.Release(_prefabHandle); _hasPrefabHandle = false; } completed(obj); } private void ConfigureFriendlyState() { if (!((Object)(object)_boss == (Object)null)) { SetField(ActivatedField, _boss, false); SetField(FacePlayerField, _boss, false); SetField(MovingField, _boss, false); SetField(AttackingField, _boss, false); if ((Object)(object)((UnitObject)_boss).health != (Object)null) { ((UnitObject)_boss).health.SetTeam((Team)1); ((UnitObject)_boss).health.invincible = true; ((UnitObject)_boss).health.untouchable = true; } if ((Object)(object)_boss.spine != (Object)null) { _boss.spine.ForceVisible = true; ((Component)_boss.spine).gameObject.SetActive(true); } ConfigureProjectilePattern(); } } private void ConfigureProjectilePattern() { //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Expected O, but got Unknown if (!((Object)(object)_projectileCircle == (Object)null)) { SetField(PatternHealthField, _projectileCircle, ((Object)(object)_boss != (Object)null) ? ((UnitObject)_boss).health : null); SetField(PatternTargetPlayerField, _projectileCircle, true); SetField(PatternRecalculateField, _projectileCircle, false); SetField(PatternLoopField, _projectileCircle, false); if (!_projectileEventsHooked) { _projectileCircle.OnProjectileWaveShot += new ProjectileWaveEvent(OnProjectileWaveShot); _projectileEventsHooked = true; } } } private void OnProjectileWaveShot(BulletWave wave) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) if (wave.SpawnedProjectiles == null) { return; } for (int i = 0; i < wave.SpawnedProjectiles.Length; i++) { Projectile val = wave.SpawnedProjectiles[i]; if (!((Object)(object)val == (Object)null)) { PlayerFarming ownerPlayer = PlayableBossIdentity.GetOwnerPlayer((Component)(object)_boss); float damage = BishopDamage.Scale(PlayableBishopsConfig.KallamarProjectileBaseDamage.Value, ownerPlayer); val.AttackFlags = BishopDamage.GetTarotAttackFlags(ownerPlayer, ref damage); val.Damage = damage; val.team = (Team)1; } } } private static void SetField(FieldInfo field, object instance, object value) { if (field != null && instance != null) { field.SetValue(instance, value); } } private static void DisableBodyColliders(GameObject avatar) { Collider2D[] componentsInChildren = avatar.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { ((Behaviour)componentsInChildren[i]).enabled = false; } } private void PrepareSpineRendering() { if (!((Object)(object)_boss == (Object)null) && !((Object)(object)_boss.spine == (Object)null) && ((SkeletonRenderer)_boss.spine).Skeleton != null) { SkeletonAnimationLODGlobalManager instance = SkeletonAnimationLODGlobalManager.Instance; if ((Object)(object)instance != (Object)null) { instance.DisableCulling(((Component)_boss.spine).transform, _boss.spine); } _boss.spine.ForceVisible = true; ((Component)_boss.spine).gameObject.SetActive(true); if (((SkeletonRenderer)_boss.spine).Skeleton.Data.FindSkin("Normal") != null) { ((SkeletonRenderer)_boss.spine).Skeleton.SetSkin("Normal"); } ((SkeletonRenderer)_boss.spine).Skeleton.SetBonesToSetupPose(); ((SkeletonRenderer)_boss.spine).Skeleton.SetSlotsToSetupPose(); } } private void PlayIdleAnimation() { if (!((Object)(object)_boss == (Object)null) && !((Object)(object)_boss.spine == (Object)null)) { PrepareSpineRendering(); SetAnimation(GetString(IdleAnimationField), loop: true); } } internal override void Follow(PlayerFarming player) { //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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_boss == (Object)null) && !((Object)(object)player == (Object)null)) { Vector3 position = ((Component)player).transform.position; int num; if (_hasLastPlayerPosition) { Vector3 val = position - _lastPlayerPosition; num = ((((Vector3)(ref val)).sqrMagnitude > 2.5E-05f) ? 1 : 0); } else { num = 0; } bool flag = (byte)num != 0; bool flag2 = (Object)(object)player.playerController != (Object)null && (Mathf.Abs(player.playerController.xDir) > 0.05f || Mathf.Abs(player.playerController.yDir) > 0.05f); _lastPlayerPosition = position; _hasLastPlayerPosition = true; ((Component)_boss).transform.position = position; if ((Object)(object)((UnitObject)_boss).rb != (Object)null) { ((UnitObject)_boss).rb.velocity = Vector2.zero; } if ((Object)(object)((UnitObject)_boss).state != (Object)null && (Object)(object)player.state != (Object)null) { ((UnitObject)_boss).state.facingAngle = player.state.facingAngle; ((UnitObject)_boss).state.LookAngle = player.state.facingAngle; } float num2 = (((Object)(object)player.playerController != (Object)null) ? player.playerController.xDir : 0f); if (Mathf.Abs(num2) < 0.05f && (Object)(object)player.state != (Object)null) { num2 = Mathf.Cos(player.state.facingAngle * ((float)Math.PI / 180f)); } ApplyHorizontalFacing(num2); UpdateVisualBob(flag || flag2); if ((flag || flag2) && Time.time >= _nextMovementDestructionTime) { _nextMovementDestructionTime = Time.time + 0.1f; BishopDamage.DestroyPropsAtPosition(((Component)_boss).transform.position, PlayableBishopsConfig.KallamarMovementDestructionRadius.Value, ((Component)_boss).gameObject); } } } internal override void TryPrimary(PlayerFarming player) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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)(object)_boss == (Object)null || _actionInProgress || Time.time < _nextPrimaryTime) { return; } try { Vector3 direction = BishopAim.GetDirection(player); ApplyHorizontalFacing(direction.x); int sequence = BeginAction(); ((MonoBehaviour)_boss).StartCoroutine(DaggerRoutine(direction, sequence)); _nextPrimaryTime = Time.time + BishopDamage.Cooldown(PlayableBishopsConfig.KallamarDaggerCooldown.Value, player); } catch (Exception exception) { ReportAttackFailure("dagger", exception); } } private IEnumerator DaggerRoutine(Vector3 direction, int sequence) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) string animationName = GetString(DaggerAnimationField); SetAnimation(animationName, loop: false); PlayKallamarSound("event:/boss/jellyfish/dagger_attack"); yield return WaitForSpineSeconds(0.6f); if (ActionIsCurrent(sequence)) { BishopDamage.DamageBidirectional(((Component)_boss).transform.position, direction, PlayableBishopsConfig.KallamarDaggerReach.Value, Mathf.Max(1.5f, PlayableBishopsConfig.KallamarDaggerRadius.Value), PlayableBishopsConfig.KallamarDaggerDamage.Value, ((Component)_boss).gameObject); yield return WaitForSpineSeconds(0.2f); FinishAction(sequence); } } internal override void TrySecondary(PlayerFarming player) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_boss == (Object)null || _actionInProgress || Time.time < _nextSecondaryTime) { return; } try { if ((Object)(object)_projectileCircle == (Object)null) { throw new InvalidOperationException("Kallamar projectile-circle pattern was unavailable"); } Vector3 val = ClampTarget(((Component)player).transform.position, BishopAim.GetAssistedPoint(player, 8f, 14f), 14f); ApplyHorizontalFacing(val.x - ((Component)player).transform.position.x); int sequence = BeginAction(); ((MonoBehaviour)_boss).StartCoroutine(ProjectileRoutine(val, sequence)); _nextSecondaryTime = Time.time + BishopDamage.Cooldown(PlayableBishopsConfig.KallamarProjectileCooldown.Value, player); } catch (Exception exception) { ReportAttackFailure("projectile circle", exception); } } private IEnumerator ProjectileRoutine(Vector3 target, int sequence) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) SetAnimation(GetString(ShootAnimationField), loop: true); PlayKallamarSound("event:/boss/jellyfish/grenade_spawn"); yield return WaitForSpineSeconds(0.55f); if (ActionIsCurrent(sequence)) { ConfigureProjectilePattern(); _projectileCircle.Shoot(0f, target, (Transform)null); PlayKallamarSound("event:/boss/jellyfish/grenade_mass_launch"); yield return WaitForSpineSeconds(1.15f); if (ActionIsCurrent(sequence)) { PlayKallamarSound("event:/boss/jellyfish/grenade_end"); FinishAction(sequence); } } } internal override void TrySignature(MonoBehaviour host, PlayerFarming player) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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) if ((Object)(object)_boss == (Object)null || _actionInProgress || Time.time < _nextSignatureTime) { return; } try { Vector3 direction = BishopAim.GetDirection(player); ApplyHorizontalFacing(direction.x); int sequence = BeginAction(); host.StartCoroutine(SwordRoutine(direction, sequence)); _nextSignatureTime = Time.time + BishopDamage.Cooldown(PlayableBishopsConfig.KallamarSwordCooldown.Value, player); } catch (Exception exception) { ReportAttackFailure("sword", exception); } } internal override void TryDodge(MonoBehaviour host, PlayerFarming player) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_boss == (Object)null || (Object)(object)player == (Object)null || _actionInProgress || Time.time < _nextDodgeTime) { return; } try { Vector3 position = ((Component)player).transform.position; Vector3 teleportDirection = GetTeleportDirection(player); ApplyHorizontalFacing(teleportDirection.x); int sequence = BeginAction(); _nextDodgeTime = Time.time + Mathf.Max(0.05f, PlayableBishopsConfig.KallamarTeleportCooldown.Value); ((MonoBehaviour)(((Object)(object)host != (Object)null) ? ((object)host) : ((object)_boss))).StartCoroutine(TeleportRoutine(player, position, teleportDirection, sequence)); } catch (Exception exception) { ReportAttackFailure("dodge teleport", exception); } } private unsafe IEnumerator TeleportRoutine(PlayerFarming player, Vector3 origin, Vector3 direction, int sequence) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: 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_001d: Unknown result type (might be due to invalid IL or missing references) string teleportAnimation = GetString(TeleportAnimationField); ResetVisualBob(); SetAnimation(teleportAnimation, loop: false); QueueAnimation(GetString(IdleAnimationField), loop: true); PlayKallamarSound("event:/boss/jellyfish/teleport_away"); float heldDuration = 0f; bool stillCharging = true; IEnumerator fadeOut = BishopPresentation.Fade(_boss.spine, 1f, 0f, 0.18f); while (fadeOut.MoveNext()) { if (!ActionIsCurrent(sequence) || (Object)(object)player == (Object)null) { yield break; } if (stillCharging && IsDodgeHeld(player)) { heldDuration = Mathf.Min(0.18f, heldDuration + Time.deltaTime); } else { stillCharging = false; } yield return fadeOut.Current; } if (ActionIsCurrent(sequence) && !((Object)(object)player == (Object)null)) { float value = PlayableBishopsConfig.KallamarTeleportDistance.Value; float num = Mathf.Max(value, PlayableBishopsConfig.KallamarChargedTeleportDistance.Value); float num2 = Mathf.Lerp(value, num, Mathf.Clamp01(heldDuration / 0.18f)); Vector3 val = origin + direction * num2; Vector3 val2 = BishopAim.ClampTeleportRouteToCurrentRoomFloor(origin, val, 0.65f); float num3 = Vector2.Distance(Vector2.op_Implicit(origin), Vector2.op_Implicit(val2)); if (num3 < Mathf.Min(1f, num2 * 0.35f)) { string[] obj = new string[11] { "Kallamar teleport resolved to a short move. origin=", null, null, null, null, null, null, null, null, null, null }; Vector3 val3 = origin; obj[1] = ((object)(*(Vector3*)(&val3))/*cast due to .constrained prefix*/).ToString(); obj[2] = ", requested="; val3 = val; obj[3] = ((object)(*(Vector3*)(&val3))/*cast due to .constrained prefix*/).ToString(); obj[4] = ", resolved="; val3 = val2; obj[5] = ((object)(*(Vector3*)(&val3))/*cast due to .constrained prefix*/).ToString(); obj[6] = ", requestedDistance="; obj[7] = num2.ToString(); obj[8] = ", resolvedDistance="; obj[9] = num3.ToString(); obj[10] = "."; PlayableBishopsLog.Debug(string.Concat(obj)); } ((Component)player).transform.position = val2; ((Component)_boss).transform.position = val2; if ((Object)(object)((UnitObject)_boss).rb != (Object)null) { ((UnitObject)_boss).rb.velocity = Vector2.zero; } _lastPlayerPosition = val2; _hasLastPlayerPosition = true; SetAnimation(teleportAnimation, loop: false); QueueAnimation(GetString(IdleAnimationField), loop: true); PlayKallamarSound("event:/boss/jellyfish/teleport_return"); yield return BishopPresentation.Fade(_boss.spine, 0f, 1f, 0.12f); yield return WaitForSpineSeconds(0.03f); FinishAction(sequence); } } private static bool IsDodgeHeld(PlayerFarming player) { try { return (Object)(object)player != (Object)null && player.rewiredPlayer != null && player.rewiredPlayer.GetButton(16); } catch { return false; } } private IEnumerator SwordRoutine(Vector3 direction, int sequence) { SetAnimation(GetString(SwordAnticipationAnimationField), loop: false); QueueAnimation(GetString(SwordLoopAnimationField), loop: true); PlayKallamarSound("event:/boss/jellyfish/sword_charge"); yield return WaitForSpineSeconds(0.85f); if (ActionIsCurrent(sequence)) { SetAnimation(GetString(SwordAttackAnimationField), loop: false); PlayKallamarSound("event:/boss/jellyfish/sword_attack"); yield return WaitForSpineSeconds(0.12f); if (ActionIsCurrent(sequence)) { BishopDamage.DamageAndDestroyAtPosition(((Component)_boss).transform.position, PlayableBishopsConfig.KallamarSwordRadius.Value, BishopDamage.Scale(PlayableBishopsConfig.KallamarSwordDamage.Value, PlayableBossIdentity.GetOwnerPlayer((Component)(object)_boss)), ((Component)_boss).gameObject); yield return WaitForSpineSeconds(0.55f); FinishAction(sequence); } } } private int BeginAction() { _actionInProgress = true; SetField(AttackingField, _boss, false); return ++_actionSequence; } private void FinishAction(int sequence) { if (ActionIsCurrent(sequence)) { _actionInProgress = false; PlayIdleAnimation(); } } private bool ActionIsCurrent(int sequence) { if (_isActive && (Object)(object)_boss != (Object)null) { return sequence == _actionSequence; } return false; } private IEnumerator WaitForSpineSeconds(float duration) { float elapsed = 0f; while ((Object)(object)_boss != (Object)null) { float num; elapsed = (num = elapsed + Time.deltaTime * (((Object)(object)_boss.spine != (Object)null) ? _boss.spine.timeScale : 1f)); if (num < duration) { yield return null; continue; } break; } } private void SetAnimation(string animationName, bool loop) { if ((Object)(object)_boss != (Object)null && (Object)(object)_boss.spine != (Object)null && !string.IsNullOrEmpty(animationName)) { _boss.spine.AnimationState.SetAnimation(0, animationName, loop); } } private void QueueAnimation(string animationName, bool loop) { if ((Object)(object)_boss != (Object)null && (Object)(object)_boss.spine != (Object)null && !string.IsNullOrEmpty(animationName)) { _boss.spine.AnimationState.AddAnimation(0, animationName, loop, 0f); } } private string GetString(FieldInfo field) { if (!(field != null) || !((Object)(object)_boss != (Object)null)) { return null; } return field.GetValue(_boss) as string; } private static Vector3 ClampTarget(Vector3 origin, Vector3 target, float maxDistance) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //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_0037: 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_0020: 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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) Vector3 val = target - origin; val.z = 0f; if (((Vector3)(ref val)).sqrMagnitude > maxDistance * maxDistance) { target = origin + ((Vector3)(ref val)).normalized * maxDistance; } target.z = origin.z; return target; } private static Vector3 GetTeleportDirection(PlayerFarming player) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player != (Object)null && (Object)(object)player.playerController != (Object)null) { Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(player.playerController.xDir, player.playerController.yDir, 0f); if (((Vector3)(ref val)).sqrMagnitude > 0.01f) { return ((Vector3)(ref val)).normalized; } } return BishopAim.GetDirection(player); } private void CaptureFacingScale() { if (!_facingScaleCaptured && !((Object)(object)_boss == (Object)null) && !((Object)(object)_boss.spine == (Object)null) && ((SkeletonRenderer)_boss.spine).Skeleton != null) { _spineBaseScaleX = Mathf.Max(0.01f, Mathf.Abs(((SkeletonRenderer)_boss.spine).Skeleton.ScaleX)); _facingScaleCaptured = true; } } private void ApplyHorizontalFacing(float horizontal) { if (!(Mathf.Abs(horizontal) < 0.15f) && !((Object)(object)_boss == (Object)null) && !((Object)(object)_boss.spine == (Object)null) && ((SkeletonRenderer)_boss.spine).Skeleton != null) { CaptureFacingScale(); ((SkeletonRenderer)_boss.spine).Skeleton.ScaleX = _spineBaseScaleX * ((horizontal < 0f) ? (-1f) : 1f); } } private void CaptureSpineRestPosition() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) if (!_spineRestPositionCaptured && !((Object)(object)_boss == (Object)null) && !((Object)(object)_boss.spine == (Object)null)) { _spineRestLocalPosition = ((Component)_boss.spine).transform.localPosition; _spineRestPositionCaptured = true; } } private void UpdateVisualBob(bool moving) { //IL_007a: 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_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_boss == (Object)null) && !((Object)(object)_boss.spine == (Object)null)) { CaptureSpineRestPosition(); if (_actionInProgress) { ResetVisualBob(); return; } _bobPhase += Time.deltaTime * (moving ? 7.5f : 5.25f); float num = (moving ? 0.1f : 0.075f); ((Component)_boss.spine).transform.localPosition = _spineRestLocalPosition + Vector3.up * (Mathf.Sin(_bobPhase) * num); } } private void ResetVisualBob() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) if (_spineRestPositionCaptured && (Object)(object)_boss != (Object)null && (Object)(object)_boss.spine != (Object)null) { ((Component)_boss.spine).transform.localPosition = _spineRestLocalPosition; } } private void PlayKallamarSound(string eventPath) { if ((Object)(object)_boss == (Object)null || string.IsNullOrEmpty(eventPath)) { return; } try { AudioManager.Instance.PlayOneShot(eventPath, ((Component)_boss).gameObject); } catch (Exception ex) { PlayableBishopsLog.Debug("Kallamar sound failed for " + eventPath + ": " + ex.GetBaseException().Message); } } private void ReportAttackFailure(string attack, Exception exception) { PlayableBishopsPlugin.Log.LogError((object)("Kallamar " + attack + " failed: " + exception.GetBaseException().Message)); ResetVisualState(); } internal override float BeginSpawnPresentation() { if ((Object)(object)_boss == (Object)null || (Object)(object)_boss.spine == (Object)null) { return 0f; } _actionSequence++; _actionInProgress = true; ResetVisualBob(); ((MonoBehaviour)_boss).StopAllCoroutines(); if ((Object)(object)_projectileCircle != (Object)null) { ((MonoBehaviour)_projectileCircle).StopAllCoroutines(); } ConfigureFriendlyState(); PrepareSpineRendering(); string animationName = GetString(TeleportAnimationField); SetAnimation(animationName, loop: false); QueueAnimation(GetString(IdleAnimationField), loop: true); PlayKallamarSound("event:/boss/jellyfish/teleport_return"); ((MonoBehaviour)_boss).StartCoroutine(BishopPresentation.Fade(_boss.spine, 0f, 1f, 0.55f)); return 0.55f; } internal override void CompleteSpawnPresentation() { _actionInProgress = false; BishopPresentation.SetAlpha(((Object)(object)_boss != (Object)null) ? _boss.spine : null, 1f); PlayIdleAnimation(); } internal override float BeginDespawnPresentation() { if ((Object)(object)_boss == (Object)null || (Object)(object)_boss.spine == (Object)null) { return 0f; } _actionSequence++; _actionInProgress = true; ResetVisualBob(); ((MonoBehaviour)_boss).StopAllCoroutines(); if ((Object)(object)_projectileCircle != (Object)null) { ((MonoBehaviour)_projectileCircle).StopAllCoroutines(); } PrepareSpineRendering(); string animationName = GetString(TeleportAnimationField); SetAnimation(animationName, loop: false); PlayKallamarSound("event:/boss/jellyfish/teleport_away"); ((MonoBehaviour)_boss).StartCoroutine(BishopPresentation.Fade(_boss.spine, 1f, 0f, 0.5f)); return BishopPresentation.GetAnimationDuration(_boss.spine, animationName, 0.5f, 0.45f, 0.75f); } internal override float BeginDeathPresentation() { if ((Object)(object)_boss == (Object)null || (Object)(object)_boss.spine == (Object)null) { return 0f; } _actionSequence++; _actionInProgress = true; ResetVisualBob(); ((MonoBehaviour)_boss).StopAllCoroutines(); if ((Object)(object)_projectileCircle != (Object)null) { ((MonoBehaviour)_projectileCircle).StopAllCoroutines(); } BishopPresentation.SetAlpha(_boss.spine, 1f); _boss.spine.AnimationState.SetAnimation(0, "die-noheart", false); _boss.spine.AnimationState.AddAnimation(0, "dead-noheart", true, 0f); PlayKallamarSound("event:/boss/jellyfish/death"); return 3.2f; } internal override void ResetVisualState() { if (!((Object)(object)_boss == (Object)null)) { _actionSequence++; _actionInProgress = false; ResetVisualBob(); ((MonoBehaviour)_boss).StopAllCoroutines(); if ((Object)(object)_projectileCircle != (Object)null) { ((MonoBehaviour)_projectileCircle).StopAllCoroutines(); } ConfigureFriendlyState(); PrepareSpineRendering(); BishopPresentation.SetAlpha(_boss.spine, 1f); PlayIdleAnimation(); PlayableBishopsPlugin.Log.LogInfo((object)"Kallamar visual and attack state reset."); } } internal override void Deactivate() { _isActive = false; _actionSequence++; _actionInProgress = false; ResetVisualBob(); if ((Object)(object)_boss != (Object)null) { ((MonoBehaviour)_boss).StopAllCoroutines(); if ((Object)(object)_projectileCircle != (Object)null) { ((MonoBehaviour)_projectileCircle).StopAllCoroutines(); } if ((Object)(object)_boss.spine != (Object)null) { ((Component)_boss.spine).gameObject.SetActive(false); } if ((Object)(object)((UnitObject)_boss).health != (Object)null) { ((UnitObject)_boss).health.SetTeam((Team)0); } } ResetCooldowns(); PlayableBishopsPlugin.Log.LogInfo((object)"Kallamar aspect disabled; initialized puppet retained for reuse."); } private void ResetCooldowns() { _nextPrimaryTime = 0f; _nextSecondaryTime = 0f; _nextSignatureTime = 0f; _nextDodgeTime = 0f; _nextMovementDestructionTime = 0f; _hasLastPlayerPosition = false; } internal override void Dispose() { //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_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_009d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_projectileCircle != (Object)null && _projectileEventsHooked) { _projectileCircle.OnProjectileWaveShot -= new ProjectileWaveEvent(OnProjectileWaveShot); } _projectileEventsHooked = false; if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)_root); _root = null; _boss = null; _projectileCircle = null; } _isActive = false; _actionInProgress = false; _facingScaleCaptured = false; _spineRestPositionCaptured = false; _spineRestLocalPosition = Vector3.zero; _bobPhase = 0f; if (_hasPrefabHandle) { Addressables.Release(_prefabHandle); _hasPrefabHandle = false; } } } internal sealed class ShamuraAspect : BishopAspect { private const string PlayableMonsterSkinName = "NoMask"; private const string SanitizedPlayableSkinName = "PlayableBishops_NativeShamuraClean"; private const float ActionWatchdogSeconds = 6f; private const float JumpBarrageInvincibilitySeconds = 2.7f; private static readonly string[] SlamAttachmentNames = new string[6] { "Other/slam_effect0001", "Other/slam_effect0002", "Other/slam_effect0003", "Other/slam_effect0004", "Other/slam_effect0005", "Other/slam_effect0006" }; private static readonly string[] PrefabAddresses = new string[2] { "Assets/Resources_moved/Enemies/Dungeon 4/Enemy Spider Monster.prefab", "Assets/Prefabs/Enemies/Dungeon 4/Enemy Spider Monster.prefab" }; private static readonly FieldInfo ActiveField = AccessTools.Field(typeof(EnemySpiderMonster), "active"); private static readonly FieldInfo BulletPrefabField = AccessTools.Field(typeof(EnemySpiderMonster), "bulletPrefab"); private static readonly FieldInfo RandomArcOffsetField = AccessTools.Field(typeof(EnemySpiderMonster), "randomArcOffset"); private static readonly FieldInfo ShootDistanceRangeField = AccessTools.Field(typeof(EnemySpiderMonster), "shootDistanceRange"); private static readonly FieldInfo GravSpeedField = AccessTools.Field(typeof(EnemySpiderMonster), "gravSpeed"); private static readonly FieldInfo ShootBoneField = AccessTools.Field(typeof(EnemySpiderMonster), "ShootBone"); private static readonly FieldInfo SpineUseMultithreadingField = AccessTools.Field(typeof(SkeletonRenderer), "useMultithreading"); private AsyncOperationHandle _prefabHandle; private bool _hasPrefabHandle; private GameObject _root; private EnemySpiderMonster _boss; private GameObject _grenadePrefab; private BishopAspectController _routineHost; private Coroutine _actionRoutine; private Coroutine _presentationRoutine; private bool _isActive; private bool _actionInProgress; private int _actionSequence; private float _nextPrimaryTime; private float _nextSecondaryTime; private float _nextSignatureTime; private float _nextLocomotionAnimationTime; private float _actionDeadline; private bool _locomotionMoving; private bool _hasLastPlayerPosition; private Vector3 _lastPlayerPosition; private bool _facingScaleCaptured; private float _spineBaseScaleX = 1f; private string _locomotionAnimation; private bool _skinInventoryLogged; private bool _activeAttachmentInventoryLogged; private bool _nativeRenderSettingsLogged; private bool _nativeSkinLogged; private bool _nativeBossBrainDetached; private bool _spineUpdaterOwnershipLogged; private bool _locomotionCorrectionLogged; private bool _rendererIsolationLogged; private Skin _sanitizedPlayableSkin; private SkeletonData _sanitizedPlayableSkinData; private Skin _sanitizedPlayableBaseSkin; private Renderer[] _suppressedAuxiliaryRenderers; internal override string Id => "Shamura"; internal override string DisplayName => "Shamura"; internal override bool IsActive { get { if (_isActive && IsValid) { return ((Component)_boss).gameObject.activeInHierarchy; } return false; } } internal override bool IsValid { get { if ((Object)(object)_root != (Object)null && (Object)(object)_boss != (Object)null) { return (Object)(object)((Component)_boss).gameObject != (Object)null; } return false; } } internal override IEnumerator Activate(BishopAspectController controller, PlayerFarming player, Action completed) { _routineHost = controller; if (IsValid) { _isActive = true; _root.SetActive(true); ((Component)_boss).gameObject.SetActive(true); DetachNativeBossBrain(); ConfigureFriendlyState(); RebuildMonsterPresentation(); PrepareSpineRendering(); PlayIdleAnimation(); ResetCooldowns(); PlayableBishopsPlugin.Log.LogInfo((object)"Reactivated the initialized Shamura puppet."); completed(arg1: true, null); yield break; } string loadError = null; yield return LoadPrefab(delegate(string error) { loadError = error; }); if (!_hasPrefabHandle || (int)_prefabHandle.Status != 1 || (Object)(object)_prefabHandle.Result == (Object)null) { completed(arg1: false, loadError ?? "the Shamura Addressables prefab did not load"); yield break; } _root = new GameObject("PlayableBishops.ShamuraAspectRoot"); if ((Object)(object)((Component)player).transform.parent != (Object)null) { _root.transform.SetParent(((Component)player).transform.parent, true); } _root.AddComponent().Controller = controller; _root.SetActive(false); GameObject result = _prefabHandle.Result; GameObject val; try { val = Object.Instantiate(result, ((Component)player).transform.position, Quaternion.identity, _root.transform); ((Object)val).name = "PlayableBishops.ShamuraAvatar"; val.SetActive(true); } catch (Exception ex) { Object.Destroy((Object)(object)_root); _root = null; completed(arg1: false, "Shamura prefab instantiation failed: " + ex.GetBaseException().Message); yield break; } _boss = val.GetComponent(); if ((Object)(object)_boss == (Object)null) { _boss = val.GetComponentInChildren(true); } if ((Object)(object)_boss == (Object)null) { Object.Destroy((Object)(object)_root); _root = null; completed(arg1: false, "the loaded prefab has no EnemySpiderMonster component"); yield break; } val.SetActive(false); string text = null; try { DisableBodyColliders(val); val.transform.localScale = val.transform.localScale * PlayableBishopsConfig.ShamuraVisualScale.Value; SetField(ActiveField, _boss, false); DetachNativeBossBrain(); _grenadePrefab = (GameObject)((BulletPrefabField != null) ? /*isinst with value type is only supported in some contexts*/: null); PrepareGrenadePool(); val.SetActive(true); ConfigureFriendlyState(); RebuildMonsterPresentation(); PrepareSpineRendering(); CaptureFacingScale(); ResolveLocomotionAnimation(); PlayIdleAnimation(); ResetCooldowns(); _isActive = true; _root.SetActive(true); DetachNativeBossBrain(); ConfigureFriendlyState(); } catch (Exception ex2) { text = ex2.GetBaseException().Message; } if (text != null) { Object.Destroy((Object)(object)_root); _root = null; _boss = null; _isActive = false; completed(arg1: false, "Shamura prefab setup failed: " + text); } else { completed(arg1: true, null); } } private IEnumerator LoadPrefab(Action completed) { string obj = null; for (int i = 0; i < PrefabAddresses.Length; i++) { _prefabHandle = Addressables.LoadAssetAsync((object)PrefabAddresses[i]); _hasPrefabHandle = true; yield return _prefabHandle; if ((int)_prefabHandle.Status == 1 && (Object)(object)_prefabHandle.Result != (Object)null) { PlayableBishopsLog.Debug("Loaded Shamura prefab from " + PrefabAddresses[i] + "."); completed(null); yield break; } obj = "address failed: " + PrefabAddresses[i]; Addressables.Release(_prefabHandle); _hasPrefabHandle = false; } completed(obj); } private void ConfigureFriendlyState() { if ((Object)(object)_boss == (Object)null) { return; } SetField(ActiveField, _boss, false); ((UnitObject)_boss).speed = 0f; if ((Object)(object)((UnitObject)_boss).health != (Object)null) { ((UnitObject)_boss).health.SetTeam((Team)1); ((UnitObject)_boss).health.invincible = true; ((UnitObject)_boss).health.untouchable = true; } if ((Object)(object)_boss.simpleSpineAnimator != (Object)null && (Object)(object)_boss.simpleSpineAnimator.anim != (Object)null) { _boss.simpleSpineAnimator.AutomaticallySetFacing = false; ((Behaviour)_boss.simpleSpineAnimator).enabled = false; _boss.simpleSpineAnimator.anim.ForceVisible = true; ((Behaviour)_boss.simpleSpineAnimator.anim).enabled = true; ((Component)_boss.simpleSpineAnimator.anim).gameObject.SetActive(true); Renderer component = ((Component)_boss.simpleSpineAnimator.anim).GetComponent(); if ((Object)(object)component != (Object)null) { component.enabled = true; component.forceRenderingOff = false; } } } private void DetachNativeBossBrain() { if (!((Object)(object)_boss == (Object)null)) { ((MonoBehaviour)_boss).StopAllCoroutines(); ((Behaviour)_boss).enabled = false; if ((Object)(object)_boss.simpleSpineAnimator != (Object)null) { ((MonoBehaviour)_boss.simpleSpineAnimator).StopAllCoroutines(); _boss.simpleSpineAnimator.AutomaticallySetFacing = false; ((Behaviour)_boss.simpleSpineAnimator).enabled = false; } if (!_nativeBossBrainDetached) { _nativeBossBrainDetached = true; PlayableBishopsPlugin.Log.LogInfo((object)"Shamura's native prefab renderer is active; EnemySpiderMonster updates remain disabled for playable control."); } } } private static void SetField(FieldInfo field, object instance, object value) { if (field != null && instance != null) { field.SetValue(instance, value); } } private static void DisableBodyColliders(GameObject avatar) { Collider2D[] componentsInChildren = avatar.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { ((Behaviour)componentsInChildren[i]).enabled = false; } } private void PrepareGrenadePool() { if ((Object)(object)_grenadePrefab == (Object)null) { throw new InvalidOperationException("Shamura's prefab has no grenade projectile prefab"); } int num = Mathf.Max(32, PlayableBishopsConfig.ShamuraBombCount.Value * 2); ObjectPool.CreatePool(_grenadePrefab, num, false, true); } private void PrepareSpineRendering() { SkeletonAnimation spine = GetSpine(); if (!((Object)(object)spine == (Object)null) && ((SkeletonRenderer)spine).Skeleton != null) { spine.ForceVisible = true; ((Component)spine).gameObject.SetActive(true); ApplySanitizedPlayableSkin(spine); ConfigureSingleSpineUpdater(spine); Renderer component = ((Component)spine).GetComponent(); if ((Object)(object)component != (Object)null) { component.enabled = true; component.forceRenderingOff = false; } ConfigureNativeRendererIsolation(spine); if (!_actionInProgress) { ((SkeletonRenderer)spine).Skeleton.SetBonesToSetupPose(); ((SkeletonRenderer)spine).Skeleton.SetSlotsToSetupPose(); SuppressTransientEffectSlots(spine); } } } private void ConfigureNativeRendererIsolation(SkeletonAnimation spine) { //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Expected O, but got Unknown if ((Object)(object)_boss == (Object)null || (Object)(object)spine == (Object)null) { return; } Renderer component = ((Component)spine).GetComponent(); if (_suppressedAuxiliaryRenderers == null) { Renderer[] componentsInChildren = ((Component)_boss).GetComponentsInChildren(true); List list = new List(); string text = string.Empty; foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)component)) { list.Add(val); if (text.Length > 0) { text += ", "; } text = text + ((Object)((Component)val).gameObject).name + ":" + ((object)val).GetType().Name; } } _suppressedAuxiliaryRenderers = list.ToArray(); StencilLighting_DecalSprite[] componentsInChildren2 = ((Component)_boss).GetComponentsInChildren(true); for (int j = 0; j < componentsInChildren2.Length; j++) { if ((Object)(object)componentsInChildren2[j] != (Object)null) { ((Behaviour)componentsInChildren2[j]).enabled = false; } } SimpleSpineFlash[] componentsInChildren3 = ((Component)_boss).GetComponentsInChildren(true); for (int k = 0; k < componentsInChildren3.Length; k++) { if ((Object)(object)componentsInChildren3[k] != (Object)null) { ((Behaviour)componentsInChildren3[k]).enabled = false; } } if ((Object)(object)component != (Object)null) { component.SetPropertyBlock(new MaterialPropertyBlock()); } if (!_rendererIsolationLogged) { _rendererIsolationLogged = true; PlayableBishopsPlugin.Log.LogInfo((object)("Playable Shamura renderer isolation forced off " + _suppressedAuxiliaryRenderers.Length + " auxiliary renderer(s) [" + text + "], " + componentsInChildren2.Length + " stencil helper(s), and " + componentsInChildren3.Length + " Spine flash helper(s).")); } } SuppressAuxiliaryRenderers(); ShamuraStraightAlphaMaterialFix.Attach(_boss); } private void SuppressAuxiliaryRenderers() { if (_suppressedAuxiliaryRenderers == null) { return; } for (int i = 0; i < _suppressedAuxiliaryRenderers.Length; i++) { Renderer val = _suppressedAuxiliaryRenderers[i]; if ((Object)(object)val != (Object)null) { val.enabled = false; val.forceRenderingOff = true; } } } private void ConfigureSingleSpineUpdater(SkeletonAnimation spine) { if ((Object)(object)spine == (Object)null || (Object)(object)_boss == (Object)null) { return; } ForceSpineOntoMainThread(spine); SkeletonAnimationLODManager[] componentsInChildren = ((Component)_boss).GetComponentsInChildren(true); SkeletonAnimationLODManager val = null; foreach (SkeletonAnimationLODManager val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2.SkeletonAnimation != (Object)(object)spine) && ((Object)(object)val == (Object)null || (Object)(object)((Component)val2).gameObject == (Object)(object)((Component)_boss).gameObject)) { val = val2; } } int num = 0; foreach (SkeletonAnimationLODManager val3 in componentsInChildren) { if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val3 == (Object)(object)val) && !((Object)(object)val3.SkeletonAnimation != (Object)(object)spine)) { val3.DisableLODManager(true); ((Behaviour)val3).enabled = false; num++; } } if ((Object)(object)val != (Object)null) { val.IgnoreCulling = true; val.forceMainThread = true; ((Behaviour)val).enabled = true; val.ManualEnable(); val.DisableLODManager(false); ((Behaviour)spine).enabled = false; } else { spine.ForceNoLimitUpdate = true; spine.UpdateInterval = 1; ((Behaviour)spine).enabled = true; } if (!_spineUpdaterOwnershipLogged) { _spineUpdaterOwnershipLogged = true; PlayableBishopsPlugin.Log.LogInfo((object)("Playable Shamura uses one native Spine updater; disabled " + num + " competing LOD manager(s), main-thread animation=" + ((SpineUseMultithreadingField != null) ? "forced" : "unavailable") + ".")); } } private static void ForceSpineOntoMainThread(SkeletonAnimation spine) { if (!((Object)(object)spine == (Object)null) && !(SpineUseMultithreadingField == null)) { spine.InitializeThreading(); SpineUseMultithreadingField.SetValue(spine, false); } } private void RebuildMonsterPresentation() { SkeletonAnimation spine = GetSpine(); if ((Object)(object)spine == (Object)null || (Object)(object)((SkeletonRenderer)spine).skeletonDataAsset == (Object)null) { throw new InvalidOperationException("Shamura's monster SkeletonDataAsset is unavailable"); } string initialSkinName = ((SkeletonRenderer)spine).initialSkinName; SkeletonData val = ((((SkeletonRenderer)spine).Skeleton != null) ? ((SkeletonRenderer)spine).Skeleton.Data : ((SkeletonRenderer)spine).skeletonDataAsset.GetSkeletonData(false)); if (val == null) { throw new InvalidOperationException("Shamura's monster SkeletonData could not be loaded"); } DetachNativeBossBrain(); LogNativeRenderSettingsOnce(spine); spine.AnimationState.ClearTracks(); PlayableShamuraMeshGuardPatch.Register((SkeletonRenderer)(object)spine); string text = (GameManager.Layer2 ? "Beaten" : initialSkinName); Skin val2 = val.FindSkin(text); if (val2 == null) { val2 = val.FindSkin("NoMask"); } if (val2 == null) { throw new InvalidOperationException("Shamura's monster rig has no usable native skin"); } ((SkeletonRenderer)spine).initialSkinName = val2.Name; ((SkeletonRenderer)spine).Skeleton.SetSkin(GetOrCreateSanitizedPlayableSkin(val, val2)); ((SkeletonRenderer)spine).Skeleton.SetBonesToSetupPose(); ((SkeletonRenderer)spine).Skeleton.SetSlotsToSetupPose(); SuppressTransientEffectSlots(spine); ((SkeletonRenderer)spine).Skeleton.UpdateWorldTransform(); LogActiveAttachmentsOnce(spine); if (!_nativeSkinLogged) { _nativeSkinLogged = true; string text2 = ((((SkeletonRenderer)spine).Skeleton.Skin != null) ? ((SkeletonRenderer)spine).Skeleton.Skin.Name : ""); PlayableBishopsPlugin.Log.LogInfo((object)("Shamura is using the native prefab Spine renderer with sanitized active skin '" + text2 + "'.")); } if (_skinInventoryLogged) { return; } _skinInventoryLogged = true; string text3 = string.Empty; ExposedList skins = ((SkeletonRenderer)spine).Skeleton.Data.Skins; for (int i = 0; i < skins.Count; i++) { if (i > 0) { text3 += ", "; } text3 += skins.Items[i].Name; } string text4 = ((((SkeletonRenderer)spine).Skeleton.Data.DefaultSkin != null) ? ((SkeletonRenderer)spine).Skeleton.Data.DefaultSkin.Name : ""); string text5 = ((((SkeletonRenderer)spine).Skeleton.Skin != null) ? ((SkeletonRenderer)spine).Skeleton.Skin.Name : ""); PlayableBishopsPlugin.Log.LogInfo((object)("Restored Shamura's native monster presentation: serialized initial skin='" + initialSkinName + "', active skin='" + text5 + "', default skin='" + text4 + "', PMA vertex colors=" + ((SkeletonRenderer)spine).pmaVertexColors + ", clipping=" + ((SkeletonRenderer)spine).useClipping + ", available skins=[" + text3 + "].")); } private void ApplySanitizedPlayableSkin(SkeletonAnimation spine) { if (!((Object)(object)spine == (Object)null) && ((SkeletonRenderer)spine).Skeleton != null && _sanitizedPlayableSkin != null) { if (((SkeletonRenderer)spine).Skeleton.Skin != _sanitizedPlayableSkin) { ((SkeletonRenderer)spine).Skeleton.SetSkin(_sanitizedPlayableSkin); ((SkeletonRenderer)spine).Skeleton.SetSlotsToSetupPose(); } SuppressTransientEffectSlots(spine); } } private Skin GetOrCreateSanitizedPlayableSkin(SkeletonData sourceData, Skin nativeSkin) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown if (_sanitizedPlayableSkin != null && _sanitizedPlayableSkinData == sourceData && _sanitizedPlayableBaseSkin == nativeSkin) { return _sanitizedPlayableSkin; } Skin val = new Skin("PlayableBishops_NativeShamuraClean"); val.AddSkin(nativeSkin); ShadowRenderableAttachment(sourceData, val, "Other/ATTACK_EFFECT", "Other/ATTACK_EFFECT"); for (int i = 0; i < SlamAttachmentNames.Length; i++) { ShadowRenderableAttachment(sourceData, val, "slam", SlamAttachmentNames[i]); } _sanitizedPlayableSkin = val; _sanitizedPlayableSkinData = sourceData; _sanitizedPlayableBaseSkin = nativeSkin; return val; } private static void ShadowRenderableAttachment(SkeletonData sourceData, Skin skin, string slotName, string attachmentName) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown int num = FindSlotIndex(sourceData, slotName); skin.SetAttachment(num, attachmentName, (Attachment)new BoundingBoxAttachment("hidden." + attachmentName)); } private static int FindSlotIndex(SkeletonData sourceData, string slotName) { ExposedList slots = sourceData.Slots; for (int i = 0; i < slots.Count; i++) { if (slots.Items[i].Name == slotName) { return i; } } throw new InvalidOperationException("Shamura's Spine rig is missing slot '" + slotName + "'"); } private static void SuppressTransientEffectSlots(SkeletonAnimation spine) { if (!((Object)(object)spine == (Object)null) && ((SkeletonRenderer)spine).Skeleton != null) { ClearSlotAttachment(((SkeletonRenderer)spine).Skeleton, "Other/whiteball"); ClearSlotAttachment(((SkeletonRenderer)spine).Skeleton, "Other/ATTACK_EFFECT"); ClearSlotAttachment(((SkeletonRenderer)spine).Skeleton, "slam"); } } private static void ClearSlotAttachment(Skeleton skeleton, string slotName) { Slot val = skeleton.FindSlot(slotName); if (val != null) { val.Attachment = null; } } private void LogNativeRenderSettingsOnce(SkeletonAnimation spine) { if (!_nativeRenderSettingsLogged && !((Object)(object)spine == (Object)null)) { _nativeRenderSettingsLogged = true; MeshRenderer component = ((Component)spine).GetComponent(); string text = ""; string text2 = ""; int num = 0; if ((Object)(object)component != (Object)null && (Object)(object)((Renderer)component).sharedMaterial != (Object)null) { Material sharedMaterial = ((Renderer)component).sharedMaterial; text2 = ((Object)sharedMaterial).name; text = (((Object)(object)sharedMaterial.shader != (Object)null) ? ((Object)sharedMaterial.shader).name : ""); num = sharedMaterial.renderQueue; } PlayableBishopsPlugin.Log.LogInfo((object)("Native Shamura Spine render settings before playable overrides: material='" + text2 + "', shader='" + text + "', renderQueue=" + num + ", pmaVertexColors=" + ((SkeletonRenderer)spine).pmaVertexColors + ", useClipping=" + ((SkeletonRenderer)spine).useClipping + ", singleSubmesh=" + ((SkeletonRenderer)spine).singleSubmesh + ".")); } } private void LogActiveAttachmentsOnce(SkeletonAnimation spine) { if (_activeAttachmentInventoryLogged || (Object)(object)spine == (Object)null || ((SkeletonRenderer)spine).Skeleton == null) { return; } _activeAttachmentInventoryLogged = true; string text = string.Empty; ExposedList slots = ((SkeletonRenderer)spine).Skeleton.Slots; for (int i = 0; i < slots.Count; i++) { Slot val = slots.Items[i]; if (val != null && val.Attachment != null) { if (text.Length > 0) { text += ", "; } text = text + i + ":" + val.Data.Name + "=" + val.Attachment.Name; } } PlayableBishopsPlugin.Log.LogInfo((object)("Playable Shamura active native attachment inventory: [" + text + "].")); } private SkeletonAnimation GetSpine() { if ((Object)(object)_boss == (Object)null || (Object)(object)_boss.simpleSpineAnimator == (Object)null) { return null; } return _boss.simpleSpineAnimator.anim; } private void PlayIdleAnimation() { PrepareSpineRendering(); SetAnimation("idle-boss", loop: true); } internal override void Follow(PlayerFarming player) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_boss == (Object)null) && !((Object)(object)player == (Object)null)) { SuppressAuxiliaryRenderers(); SuppressTransientEffectSlots(GetSpine()); RecoverExpiredActionLock(); Vector3 position = ((Component)player).transform.position; int num; if (_hasLastPlayerPosition) { Vector3 val = position - _lastPlayerPosition; num = ((((Vector3)(ref val)).sqrMagnitude > 2.5E-05f) ? 1 : 0); } else { num = 0; } bool flag = (Object)(object)player.playerController != (Object)null && (Mathf.Abs(player.playerController.xDir) > 0.05f || Mathf.Abs(player.playerController.yDir) > 0.05f); bool moving = (byte)((uint)num | (flag ? 1u : 0u)) != 0; _lastPlayerPosition = position; _hasLastPlayerPosition = true; ((Component)_boss).transform.position = position; if ((Object)(object)((UnitObject)_boss).rb != (Object)null) { ((UnitObject)_boss).rb.velocity = Vector2.zero; } if ((Object)(object)((UnitObject)_boss).state != (Object)null && (Object)(object)player.state != (Object)null) { ((UnitObject)_boss).state.facingAngle = player.state.facingAngle; ((UnitObject)_boss).state.LookAngle = player.state.facingAngle; } float num2 = (((Object)(object)player.playerController != (Object)null) ? player.playerController.xDir : 0f); if (Mathf.Abs(num2) < 0.05f && (Object)(object)player.state != (Object)null) { num2 = Mathf.Cos(player.state.facingAngle * ((float)Math.PI / 180f)); } ApplyHorizontalFacing(num2); UpdateLocomotion(moving); } } internal override void TryPrimary(PlayerFarming player) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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) if ((Object)(object)_boss == (Object)null || _actionInProgress || Time.time < _nextPrimaryTime) { return; } try { Vector3 direction = BishopAim.GetDirection(player); ApplyHorizontalFacing(direction.x); int sequence = BeginAction(); StartActionRoutine(SlashRoutine(direction, sequence)); _nextPrimaryTime = Time.time + BishopDamage.Cooldown(PlayableBishopsConfig.ShamuraSlashCooldown.Value, player); } catch (Exception exception) { ReportAttackFailure("slash", exception); } } private IEnumerator SlashRoutine(Vector3 direction, int sequence) { SetAnimation("attack", loop: false); PlayShamuraSound("event:/boss/spider/attack"); yield return WaitForSpineSeconds(0.32f); if (ActionIsCurrent(sequence)) { BishopDamage.DamageAndDestroyAtPosition(((Component)_boss).transform.position, PlayableBishopsConfig.ShamuraSlashRadius.Value, BishopDamage.Scale(PlayableBishopsConfig.ShamuraSlashBaseDamage.Value, PlayableBossIdentity.GetOwnerPlayer((Component)(object)_boss)), GetActiveOwnerObject()); yield return WaitForSpineSeconds(0.5f); FinishAction(sequence); } } internal override void TrySecondary(PlayerFarming player) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_boss == (Object)null || _actionInProgress || Time.time < _nextSecondaryTime) { return; } try { if ((Object)(object)_grenadePrefab == (Object)null) { throw new InvalidOperationException("Shamura grenade prefab was unavailable"); } Vector3 desired = ClampTarget(((Component)player).transform.position, BishopAim.GetAssistedPoint(player, 5.5f, 9f), 8f); desired = BishopAim.ClampToCurrentRoomFloor(((Component)player).transform.position, desired, 0.65f); ApplyHorizontalFacing(desired.x - ((Component)player).transform.position.x); int sequence = BeginAction(); StartActionRoutine(BombRoutine(desired, sequence)); _nextSecondaryTime = Time.time + BishopDamage.Cooldown(PlayableBishopsConfig.ShamuraBombCooldown.Value, player); } catch (Exception exception) { ReportAttackFailure("bomb volley", exception); } } private IEnumerator BombRoutine(Vector3 target, int sequence) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) SetAnimation("bombs", loop: false); PlayShamuraSound("event:/boss/spider/bomb_start"); yield return WaitForSpineSeconds(0.7f); if (!ActionIsCurrent(sequence)) { yield break; } PlayShamuraSound("event:/boss/spider/bomb_shoot"); GameObject val = (GameObject)((ShootBoneField != null) ? /*isinst with value type is only supported in some contexts*/: null); Vector3 val2 = (((Object)(object)val != (Object)null) ? val.transform.position : ((Component)_boss).transform.position); PlayerFarming ownerPlayer = PlayableBossIdentity.GetOwnerPlayer((Component)(object)_boss); Vector3 val3 = (((Object)(object)ownerPlayer != (Object)null) ? ((Component)ownerPlayer).transform.position : ((Component)_boss).transform.position); Vector3 direction = target - val3; direction.z = 0f; List targetsInSector = BishopAim.GetTargetsInSector(val3, direction, 12f, PlayableBishopsConfig.ProjectileAimAssistControllerCone.Value); int value = PlayableBishopsConfig.ShamuraBombCount.Value; int num = ((targetsInSector.Count > 0) ? Mathf.Clamp(PlayableBishopsConfig.ShamuraBombFocusedCount.Value, 0, value) : 0); for (int i = 0; i < value; i++) { GrenadeBullet component = ObjectPool.Spawn(_grenadePrefab, val2, Quaternion.identity).GetComponent(); if (!((Object)(object)component == (Object)null)) { component.SetOwner(GetActiveOwnerObject()); float damage = BishopDamage.Scale(PlayableBishopsConfig.ShamuraBombBaseDamage.Value, PlayableBossIdentity.GetOwnerPlayer((Component)(object)_boss)); component.Damage = damage; Vector3 desired; if (i < num) { Health obj = targetsInSector[i % Mathf.Min(6, targetsInSector.Count)]; Vector2 val4 = Random.insideUnitCircle * 0.5f; desired = ((Component)obj).transform.position + new Vector3(val4.x, val4.y, 0f); } else { Vector2 val5 = Random.insideUnitCircle * PlayableBishopsConfig.ShamuraBombSpreadRadius.Value; desired = target + new Vector3(val5.x, val5.y, 0f); } desired = BishopAim.ClampToCurrentRoomFloor(val3, desired, 0.55f); Vector3 val6 = desired - val2; val6.z = 0f; float num2 = Mathf.Atan2(val6.y, val6.x) * 57.29578f; float num3 = Random.Range(0.72f, 0.96f); float num4 = num3 * 4.44949f; float num5 = ((Vector3)(ref val6)).magnitude / num3; component.Play(-6f, num2, num5, num4, (Team)1, false, "", GetSpine()); } } PlayableBishopsLog.Debug("Shamura launched " + value + " room-safe bombs with " + num + " focused shots."); yield return WaitForSpineSeconds(0.8f); if (ActionIsCurrent(sequence)) { PlayShamuraSound("event:/boss/spider/bomb_end"); FinishAction(sequence); } } internal override void TrySignature(MonoBehaviour host, PlayerFarming player) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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) if ((Object)(object)_boss == (Object)null || _actionInProgress || Time.time < _nextSignatureTime) { return; } try { Vector3 direction = BishopAim.GetDirection(player); ApplyHorizontalFacing(direction.x); int sequence = BeginAction(); StartActionRoutine(JumpBarrageRoutine(player, direction, sequence)); _nextSignatureTime = Time.time + BishopDamage.Cooldown(PlayableBishopsConfig.ShamuraJumpCooldown.Value, player); } catch (Exception exception) { ReportAttackFailure("jump barrage", exception); } } private IEnumerator JumpBarrageRoutine(PlayerFarming player, Vector3 direction, int sequence) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player != (Object)null && (Object)(object)player.playerController != (Object)null) { player.playerController.MakeInvincible(2.7f); } SetAnimation("angry intro", loop: true); PlayShamuraSound("event:/boss/spider/angry"); yield return WaitForSpineSeconds(0.65f); if (!ActionIsCurrent(sequence)) { yield break; } for (int i = 0; i < 3; i++) { PlayShamuraSound("event:/boss/spider/jump_attack_jump"); SetAnimation("jump-attack", loop: false); yield return WaitForSpineSeconds(0.32f); if (!ActionIsCurrent(sequence)) { yield break; } BishopDamage.DamageAndDestroyAtPosition(((Component)_boss).transform.position, PlayableBishopsConfig.ShamuraJumpRadius.Value, BishopDamage.Scale(PlayableBishopsConfig.ShamuraJumpBaseDamage.Value, PlayableBossIdentity.GetOwnerPlayer((Component)(object)_boss)), GetActiveOwnerObject()); PlayShamuraSound("event:/boss/spider/jump_attack_land"); CameraManager.shakeCamera(0.3f, Utils.GetAngle(((Component)_boss).transform.position, ((Component)_boss).transform.position + ((Vector3)(ref direction)).normalized), true); yield return WaitForSpineSeconds(0.28f); } FinishAction(sequence); } internal override float BeginDeathPresentation() { if ((Object)(object)_boss == (Object)null) { return 0f; } _actionSequence++; _actionInProgress = true; _actionDeadline = 0f; _locomotionMoving = false; StopPuppetRoutines(); BishopPresentation.SetAlpha(GetSpine(), 1f); SetAnimation("die-noheart", loop: false); QueueAnimation("dead-noheart", loop: true); PlayShamuraSound("event:/boss/spider/death"); return 2.7f; } private int BeginAction() { _locomotionMoving = false; _actionInProgress = true; _actionDeadline = Time.time + 6f; return ++_actionSequence; } private void StartActionRoutine(IEnumerator routine) { if (routine != null && !((Object)(object)_routineHost == (Object)null)) { if (_actionRoutine != null) { ((MonoBehaviour)_routineHost).StopCoroutine(_actionRoutine); } _actionRoutine = ((MonoBehaviour)_routineHost).StartCoroutine(routine); } } private void StartPresentationRoutine(IEnumerator routine) { if (routine != null && !((Object)(object)_routineHost == (Object)null)) { if (_presentationRoutine != null) { ((MonoBehaviour)_routineHost).StopCoroutine(_presentationRoutine); } _presentationRoutine = ((MonoBehaviour)_routineHost).StartCoroutine(routine); } } private void StopPuppetRoutines() { if ((Object)(object)_routineHost != (Object)null) { if (_actionRoutine != null) { ((MonoBehaviour)_routineHost).StopCoroutine(_actionRoutine); } if (_presentationRoutine != null) { ((MonoBehaviour)_routineHost).StopCoroutine(_presentationRoutine); } } _actionRoutine = null; _presentationRoutine = null; if ((Object)(object)_boss != (Object)null) { ((MonoBehaviour)_boss).StopAllCoroutines(); } } private void FinishAction(int sequence) { if (ActionIsCurrent(sequence)) { _actionInProgress = false; _actionDeadline = 0f; PlayIdleAnimation(); } } private void RecoverExpiredActionLock() { if (_actionInProgress && !(_actionDeadline <= 0f) && !(Time.time < _actionDeadline) && !((Object)(object)_boss == (Object)null)) { PlayableBishopsPlugin.Log.LogWarning((object)"Recovered Shamura from an expired attack-state lock."); _actionSequence++; _actionInProgress = false; _actionDeadline = 0f; _locomotionMoving = false; StopPuppetRoutines(); PlayIdleAnimation(); } } private void UpdateLocomotion(bool moving) { if (_actionInProgress || (Object)(object)_boss == (Object)null) { _locomotionMoving = false; return; } SkeletonAnimation spine = GetSpine(); if (!moving) { if (_locomotionMoving || !IsCurrentAnimation(spine, "idle-boss")) { _locomotionMoving = false; PlayIdleAnimation(); } return; } bool flag = !string.IsNullOrEmpty(_locomotionAnimation) && _locomotionAnimation != "idle-boss"; bool flag2 = flag && !IsCurrentAnimation(spine, _locomotionAnimation); if (!_locomotionMoving || flag2) { if (flag) { SetAnimation(_locomotionAnimation, loop: true); } if (_locomotionMoving && flag2 && !_locomotionCorrectionLogged) { _locomotionCorrectionLogged = true; PlayableBishopsPlugin.Log.LogWarning((object)("Corrected Shamura's replaced locomotion track back to '" + _locomotionAnimation + "'.")); } _locomotionMoving = true; _nextLocomotionAnimationTime = Time.time; } if (Time.time >= _nextLocomotionAnimationTime) { PlayShamuraSound("event:/boss/spider/footstep"); _nextLocomotionAnimationTime = Time.time + GetLocomotionStepInterval(spine); } } private static bool IsCurrentAnimation(SkeletonAnimation spine, string animationName) { if ((Object)(object)spine == (Object)null || spine.AnimationState == null || string.IsNullOrEmpty(animationName)) { return false; } TrackEntry current = spine.AnimationState.GetCurrent(0); if (current != null && current.Animation != null) { return current.Animation.Name == animationName; } return false; } private bool ActionIsCurrent(int sequence) { if (_isActive && (Object)(object)_boss != (Object)null) { return sequence == _actionSequence; } return false; } private IEnumerator WaitForSpineSeconds(float duration) { float elapsed = 0f; SkeletonAnimation spine = GetSpine(); while ((Object)(object)_boss != (Object)null) { float num; elapsed = (num = elapsed + Time.deltaTime * (((Object)(object)spine != (Object)null) ? spine.timeScale : 1f)); if (num < duration) { yield return null; continue; } break; } } private void SetAnimation(string animationName, bool loop) { SkeletonAnimation spine = GetSpine(); if ((Object)(object)spine != (Object)null && ((SkeletonRenderer)spine).Skeleton != null && ((SkeletonRenderer)spine).Skeleton.Data.FindAnimation(animationName) != null) { spine.AnimationState.SetAnimation(0, animationName, loop); } } private void ResolveLocomotionAnimation() { _locomotionAnimation = "idle-boss"; SkeletonAnimation spine = GetSpine(); if ((Object)(object)spine == (Object)null || ((SkeletonRenderer)spine).Skeleton == null) { return; } if ((Object)(object)_boss.simpleSpineAnimator != (Object)null) { SpineChartacterAnimationData animationData = _boss.simpleSpineAnimator.GetAnimationData((State)1); if (animationData != null && (Object)(object)animationData.Animation != (Object)null && animationData.Animation.Animation != null && ((SkeletonRenderer)spine).Skeleton.Data.FindAnimation(animationData.Animation.Animation.Name) != null) { _locomotionAnimation = animationData.Animation.Animation.Name; } } string[] array = new string[8] { "run", "run2", "run3", "run4", "walk", "walking", "move", "moving" }; for (int i = 0; i < array.Length; i++) { if (_locomotionAnimation != "idle-boss") { break; } if (((SkeletonRenderer)spine).Skeleton.Data.FindAnimation(array[i]) != null) { _locomotionAnimation = array[i]; break; } } PlayableBishopsPlugin.Log.LogInfo((object)("Shamura locomotion animation: " + _locomotionAnimation + ".")); } private float GetLocomotionStepInterval(SkeletonAnimation spine) { if ((Object)(object)spine != (Object)null && ((SkeletonRenderer)spine).Skeleton != null && !string.IsNullOrEmpty(_locomotionAnimation)) { Animation val = ((SkeletonRenderer)spine).Skeleton.Data.FindAnimation(_locomotionAnimation); if (val != null) { return Mathf.Clamp(val.Duration, 0.28f, 0.65f); } } return 0.47f; } private void QueueAnimation(string animationName, bool loop) { SkeletonAnimation spine = GetSpine(); if ((Object)(object)spine != (Object)null && ((SkeletonRenderer)spine).Skeleton != null && ((SkeletonRenderer)spine).Skeleton.Data.FindAnimation(animationName) != null) { spine.AnimationState.AddAnimation(0, animationName, loop, 0f); } } private Vector2 GetVector2(FieldInfo field, Vector2 fallback) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) if (!(field != null) || !((Object)(object)_boss != (Object)null)) { return fallback; } return (Vector2)field.GetValue(_boss); } private static Vector3 ClampTarget(Vector3 origin, Vector3 target, float maxDistance) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //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_0037: 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_0020: 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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) Vector3 val = target - origin; val.z = 0f; if (((Vector3)(ref val)).sqrMagnitude > maxDistance * maxDistance) { target = origin + ((Vector3)(ref val)).normalized * maxDistance; } target.z = origin.z; return target; } private void CaptureFacingScale() { SkeletonAnimation spine = GetSpine(); if (!_facingScaleCaptured && !((Object)(object)spine == (Object)null) && ((SkeletonRenderer)spine).Skeleton != null) { _spineBaseScaleX = Mathf.Max(0.01f, Mathf.Abs(((SkeletonRenderer)spine).Skeleton.ScaleX)); _facingScaleCaptured = true; } } private void ApplyHorizontalFacing(float horizontal) { SkeletonAnimation spine = GetSpine(); if (!(Mathf.Abs(horizontal) < 0.15f) && !((Object)(object)spine == (Object)null) && ((SkeletonRenderer)spine).Skeleton != null) { CaptureFacingScale(); ((SkeletonRenderer)spine).Skeleton.ScaleX = _spineBaseScaleX * ((horizontal < 0f) ? 1f : (-1f)); } } private void PlayShamuraSound(string eventPath) { if ((Object)(object)_boss == (Object)null || string.IsNullOrEmpty(eventPath)) { return; } try { AudioManager.Instance.PlayOneShot(eventPath, GetActiveOwnerObject()); } catch (Exception ex) { PlayableBishopsLog.Debug("Shamura sound failed for " + eventPath + ": " + ex.GetBaseException().Message); } } private GameObject GetActiveOwnerObject() { if (!((Object)(object)_boss != (Object)null)) { return _root; } return ((Component)_boss).gameObject; } private void ReportAttackFailure(string attack, Exception exception) { PlayableBishopsPlugin.Log.LogError((object)("Shamura " + attack + " failed: " + exception.GetBaseException().Message)); ResetVisualState(); } internal override float BeginSpawnPresentation() { SkeletonAnimation spine = GetSpine(); if ((Object)(object)_boss == (Object)null || (Object)(object)spine == (Object)null) { return 0f; } _actionSequence++; _actionInProgress = true; _actionDeadline = 0f; _locomotionMoving = false; StopPuppetRoutines(); ConfigureFriendlyState(); RebuildMonsterPresentation(); PrepareSpineRendering(); SetAnimation("angry intro", loop: false); QueueAnimation("idle-boss", loop: true); PlayShamuraSound("event:/boss/spider/angry"); StartPresentationRoutine(BishopPresentation.Fade(spine, 0f, 1f, 0.7f)); return BishopPresentation.GetAnimationDuration(spine, "angry intro", 0.7f, 0.6f, 1.1f); } internal override void CompleteSpawnPresentation() { _actionInProgress = false; BishopPresentation.SetAlpha(GetSpine(), 1f); PlayIdleAnimation(); } internal override float BeginDespawnPresentation() { SkeletonAnimation spine = GetSpine(); if ((Object)(object)_boss == (Object)null || (Object)(object)spine == (Object)null) { return 0f; } _actionSequence++; _actionInProgress = true; _actionDeadline = 0f; _locomotionMoving = false; StopPuppetRoutines(); PrepareSpineRendering(); SetAnimation("jump-attack", loop: false); PlayShamuraSound("event:/boss/spider/jump_attack_jump"); StartPresentationRoutine(BishopPresentation.Fade(spine, 1f, 0f, 0.6f)); return BishopPresentation.GetAnimationDuration(spine, "jump-attack", 0.6f, 0.5f, 0.85f); } internal override void ResetVisualState() { if (!((Object)(object)_boss == (Object)null)) { _actionSequence++; _actionInProgress = false; _actionDeadline = 0f; _locomotionMoving = false; StopPuppetRoutines(); ConfigureFriendlyState(); RebuildMonsterPresentation(); PrepareSpineRendering(); BishopPresentation.SetAlpha(GetSpine(), 1f); PlayIdleAnimation(); PlayableBishopsPlugin.Log.LogInfo((object)"Shamura visual and attack state reset."); } } internal override void Deactivate() { _isActive = false; _actionSequence++; _actionInProgress = false; _actionDeadline = 0f; _locomotionMoving = false; _hasLastPlayerPosition = false; if ((Object)(object)_boss != (Object)null) { StopPuppetRoutines(); SkeletonAnimation spine = GetSpine(); if ((Object)(object)spine != (Object)null) { ((Component)spine).gameObject.SetActive(false); } if ((Object)(object)((UnitObject)_boss).health != (Object)null) { ((UnitObject)_boss).health.SetTeam((Team)0); } } ResetCooldowns(); PlayableBishopsPlugin.Log.LogInfo((object)"Shamura aspect disabled; initialized puppet retained for reuse."); } private void ResetCooldowns() { _nextPrimaryTime = 0f; _nextSecondaryTime = 0f; _nextSignatureTime = 0f; _nextLocomotionAnimationTime = 0f; _actionDeadline = 0f; } internal override void Dispose() { //IL_00bf: Unknown result type (might be due to invalid IL or missing references) StopPuppetRoutines(); PlayableShamuraMeshGuardPatch.Unregister((SkeletonRenderer)(object)GetSpine()); if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)_root); _root = null; _boss = null; _grenadePrefab = null; } _isActive = false; _actionInProgress = false; _locomotionMoving = false; _facingScaleCaptured = false; _skinInventoryLogged = false; _activeAttachmentInventoryLogged = false; _nativeRenderSettingsLogged = false; _nativeSkinLogged = false; _spineUpdaterOwnershipLogged = false; _locomotionCorrectionLogged = false; _rendererIsolationLogged = false; _sanitizedPlayableSkin = null; _sanitizedPlayableSkinData = null; _sanitizedPlayableBaseSkin = null; _suppressedAuxiliaryRenderers = null; _routineHost = null; _nativeBossBrainDetached = false; if (_hasPrefabHandle) { Addressables.Release(_prefabHandle); _hasPrefabHandle = false; } } } internal sealed class PlayableBossMarker : MonoBehaviour { internal BishopAspectController Controller; } internal static class PlayableBossIdentity { internal static bool IsPlayable(Component component) { if ((Object)(object)component != (Object)null) { return (Object)(object)component.GetComponentInParent() != (Object)null; } return false; } internal static bool IsPlayable(GameObject gameObject) { if ((Object)(object)gameObject != (Object)null) { return (Object)(object)gameObject.GetComponentInParent() != (Object)null; } return false; } internal static PlayerFarming GetOwnerPlayer(Component component) { PlayableBossMarker playableBossMarker = (((Object)(object)component != (Object)null) ? component.GetComponentInParent() : null); if (!((Object)(object)playableBossMarker != (Object)null) || !((Object)(object)playableBossMarker.Controller != (Object)null)) { return null; } return playableBossMarker.Controller.CurrentPlayer; } internal static PlayerFarming GetOwnerPlayer(GameObject gameObject) { PlayableBossMarker playableBossMarker = (((Object)(object)gameObject != (Object)null) ? gameObject.GetComponentInParent() : null); if (!((Object)(object)playableBossMarker != (Object)null) || !((Object)(object)playableBossMarker.Controller != (Object)null)) { return null; } return playableBossMarker.Controller.CurrentPlayer; } } internal sealed class ShamuraStraightAlphaMaterialFix : MonoBehaviour { private static readonly int StraightAlphaInputProperty = Shader.PropertyToID("_StraightAlphaInput"); private const string StraightAlphaInputKeyword = "_STRAIGHT_ALPHA_INPUT"; private EnemySpiderMonster _owner; private SkeletonAnimation _spine; private Material _sourceMaterial; private Material _runtimeMaterial; internal static void Attach(EnemySpiderMonster owner) { if (!((Object)(object)owner == (Object)null) && !((Object)(object)((Component)owner).gameObject == (Object)null)) { ShamuraStraightAlphaMaterialFix shamuraStraightAlphaMaterialFix = ((Component)owner).GetComponent(); if ((Object)(object)shamuraStraightAlphaMaterialFix == (Object)null) { shamuraStraightAlphaMaterialFix = ((Component)owner).gameObject.AddComponent(); } shamuraStraightAlphaMaterialFix._owner = owner; shamuraStraightAlphaMaterialFix.EnsureApplied(); } } private void OnEnable() { if ((Object)(object)_owner == (Object)null) { _owner = ((Component)this).GetComponent(); } EnsureApplied(); } private void EnsureApplied() { //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Expected O, but got Unknown if ((Object)(object)_owner == (Object)null || (Object)(object)_owner.simpleSpineAnimator == (Object)null || (Object)(object)_owner.simpleSpineAnimator.anim == (Object)null) { return; } SkeletonAnimation anim = _owner.simpleSpineAnimator.anim; if ((Object)(object)_runtimeMaterial != (Object)null && (Object)(object)_spine == (Object)(object)anim && (Object)(object)_sourceMaterial != (Object)null) { ApplyStraightAlphaSettings(_runtimeMaterial, anim); ((SkeletonRenderer)anim).CustomMaterialOverride[_sourceMaterial] = _runtimeMaterial; return; } ReleaseMaterial(); Renderer component = ((Component)anim).GetComponent(); Material val = (((Object)(object)component != (Object)null) ? component.sharedMaterial : null); if (!((Object)(object)val == (Object)null)) { _spine = anim; _sourceMaterial = val; _runtimeMaterial = new Material(val); ((Object)_runtimeMaterial).name = ((Object)val).name + " (PlayableBishops Straight Alpha)"; ((Object)_runtimeMaterial).hideFlags = (HideFlags)52; ApplyStraightAlphaSettings(_runtimeMaterial, anim); ((SkeletonRenderer)anim).CustomMaterialOverride[val] = _runtimeMaterial; } } private static void ApplyStraightAlphaSettings(Material material, SkeletonAnimation spine) { material.EnableKeyword("_STRAIGHT_ALPHA_INPUT"); if (material.HasProperty(StraightAlphaInputProperty)) { material.SetFloat(StraightAlphaInputProperty, 1f); } ((SkeletonRenderer)spine).pmaVertexColors = true; } private void OnDestroy() { ReleaseMaterial(); } private void ReleaseMaterial() { if ((Object)(object)_spine != (Object)null && (Object)(object)_sourceMaterial != (Object)null && ((SkeletonRenderer)_spine).CustomMaterialOverride.TryGetValue(_sourceMaterial, out var value) && (Object)(object)value == (Object)(object)_runtimeMaterial) { ((SkeletonRenderer)_spine).CustomMaterialOverride.Remove(_sourceMaterial); } if ((Object)(object)_runtimeMaterial != (Object)null) { Object.Destroy((Object)(object)_runtimeMaterial); } _spine = null; _sourceMaterial = null; _runtimeMaterial = null; } } internal static class PlayableLeshyTunnelDamageImmunityPatch { internal static bool Prefix(HealthPlayer __instance, ref bool __result) { for (int i = 0; i < PlayableBishopsPlugin.Controllers.Length; i++) { BishopAspectController bishopAspectController = PlayableBishopsPlugin.Controllers[i]; if ((Object)(object)bishopAspectController != (Object)null && bishopAspectController.ProtectsWithLeshyTunnel((Health)(object)__instance)) { __result = false; return false; } } return true; } } internal static class EnemyWormBossStartPatch { internal static bool Prefix(EnemyWormBoss __instance) { return !PlayableBossIdentity.IsPlayable((Component)(object)__instance); } } internal static class EnemyWormBossUpdatePatch { internal static bool Prefix(EnemyWormBoss __instance) { return !PlayableBossIdentity.IsPlayable((Component)(object)__instance); } } internal static class EnemyWormBossOnDiePatch { internal static bool Prefix(EnemyWormBoss __instance) { if (!PlayableBossIdentity.IsPlayable((Component)(object)__instance)) { return true; } if ((Object)(object)((UnitObject)__instance).health != (Object)null) { ((UnitObject)__instance).health.HP = ((UnitObject)__instance).health.totalHP; } return false; } } internal static class EnemyFrogBossStartPatch { internal static bool Prefix(EnemyFrogBoss __instance) { return !PlayableBossIdentity.IsPlayable((Component)(object)__instance); } } internal static class EnemyFrogBossUpdatePatch { internal static bool Prefix(EnemyFrogBoss __instance) { return !PlayableBossIdentity.IsPlayable((Component)(object)__instance); } } internal static class EnemyFrogBossOnDiePatch { internal static bool Prefix(EnemyFrogBoss __instance) { if (!PlayableBossIdentity.IsPlayable((Component)(object)__instance)) { return true; } if ((Object)(object)((UnitObject)__instance).health != (Object)null) { ((UnitObject)__instance).health.HP = ((UnitObject)__instance).health.totalHP; } return false; } } internal static class EnemyFrogBossOnDestroyPatch { internal static bool Prefix(EnemyFrogBoss __instance) { return !PlayableBossIdentity.IsPlayable((Component)(object)__instance); } } internal static class GrenadeBulletPlayPatch { internal static void Prefix(GrenadeBullet __instance, ref Team team) { GameObject owner = __instance.GetOwner(); if (PlayableBossIdentity.IsPlayable(owner)) { team = (Team)1; if ((Object)(object)owner.GetComponentInParent() != (Object)null) { float damage = BishopDamage.Scale(PlayableBishopsConfig.VolleyProjectileBaseDamage.Value, PlayableBossIdentity.GetOwnerPlayer(owner)); __instance.Damage = damage; } } } } internal static class GrenadeBulletDamagePatch { internal static bool Prefix(GrenadeBullet __instance, Collider2D collider) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Invalid comparison between Unknown and I4 //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) GameObject gameObject = (((Object)(object)__instance != (Object)null) ? __instance.GetOwner() : null); if (!PlayableBossIdentity.IsPlayable(gameObject)) { return true; } Health val = (((Object)(object)collider != (Object)null) ? ((Component)collider).GetComponent() : null); if ((Object)(object)val != (Object)null && (int)val.team != 1) { float damage = __instance.Damage; AttackFlags tarotAttackFlags = BishopDamage.GetTarotAttackFlags(PlayableBossIdentity.GetOwnerPlayer(gameObject), ref damage); val.DealDamage(damage, ((Component)__instance).gameObject, Vector3.Lerp(((Component)__instance).transform.position, ((Component)val).transform.position, 0.7f), false, (AttackTypes)0, false, tarotAttackFlags); } return false; } } internal static class PlayableLeshyDamagePatch { internal static bool Prefix(EnemyWormBoss __instance, Collider2D collider) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) if (!PlayableBossIdentity.IsPlayable((Component)(object)__instance)) { return true; } Health val = (((Object)(object)collider != (Object)null) ? ((Component)collider).GetComponent() : null); if ((Object)(object)val != (Object)null && (Object)(object)((UnitObject)__instance).health != (Object)null && val.team != ((UnitObject)__instance).health.team) { BishopDamage.DamageTarget(val, PlayableBishopsConfig.SpikeBaseDamage.Value, ((Component)__instance).gameObject, (AttackTypes)0); } return false; } } internal static class GrenadeBulletDoCollisionPatch { internal static void Postfix(GrenadeBullet __instance) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) GameObject val = (((Object)(object)__instance != (Object)null) ? __instance.GetOwner() : null); if (PlayableBossIdentity.IsPlayable(val)) { BishopDamage.DestroyPropsAtPosition(((Object)(object)__instance.t != (Object)null) ? __instance.t.position : ((Component)__instance).transform.position, 1.75f, val); } } } internal static class PlayableHeketTongueDamagePatch { internal static bool Prefix(FrogBossTongue __instance, Collider2D collider) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) if (!PlayableBossIdentity.IsPlayable((Component)(object)__instance)) { return true; } Health val = (((Object)(object)collider != (Object)null) ? ((Component)collider).GetComponent() : null); if ((Object)(object)val != (Object)null && (Object)(object)((UnitObject)__instance).health != (Object)null && val.team != ((UnitObject)__instance).health.team) { BishopDamage.DamageTarget(val, PlayableBishopsConfig.HeketTongueBaseDamage.Value, ((Component)__instance).gameObject, (AttackTypes)0); } return false; } } internal static class PlayableHeketExplosionDamagePatch { internal static void Prefix(Vector3 position, Health Origin, float Size, ref float Team2Damage, ref AttackFlags attackFlags) { //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: Expected I4, but got Unknown //IL_004a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Origin == (Object)null)) { EnemyFrogBoss componentInParent = ((Component)Origin).GetComponentInParent(); if (!((Object)(object)componentInParent == (Object)null) && PlayableBossIdentity.IsPlayable((Component)(object)componentInParent)) { PlayerFarming ownerPlayer = PlayableBossIdentity.GetOwnerPlayer((Component)(object)componentInParent); Team2Damage = BishopDamage.Scale(PlayableBishopsConfig.HeketMortarBaseDamage.Value, ownerPlayer); attackFlags |= BishopDamage.GetTarotAttackFlags(ownerPlayer, ref Team2Damage); BishopDamage.DestroyPropsAtPosition(position, Mathf.Max(1f, Size), ((Component)Origin).gameObject); } } } } internal static class EnemyTentacleMonsterStartPatch { internal static bool Prefix(EnemyTentacleMonster __instance) { return !PlayableBossIdentity.IsPlayable((Component)(object)__instance); } } internal static class EnemyTentacleMonsterOnEnablePatch { internal static bool Prefix(EnemyTentacleMonster __instance) { return !PlayableBossIdentity.IsPlayable((Component)(object)__instance); } } internal static class EnemyTentacleMonsterUpdatePatch { internal static bool Prefix(EnemyTentacleMonster __instance) { return !PlayableBossIdentity.IsPlayable((Component)(object)__instance); } } internal static class EnemyTentacleMonsterOnDiePatch { internal static bool Prefix(EnemyTentacleMonster __instance) { if (!PlayableBossIdentity.IsPlayable((Component)(object)__instance)) { return true; } if ((Object)(object)((UnitObject)__instance).health != (Object)null) { ((UnitObject)__instance).health.HP = ((UnitObject)__instance).health.totalHP; } return false; } } internal static class EnemyTentacleMonsterOnDestroyPatch { internal static bool Prefix(EnemyTentacleMonster __instance) { return !PlayableBossIdentity.IsPlayable((Component)(object)__instance); } } internal static class EnemySpiderMonsterAwakePatch { internal static void Prefix(EnemySpiderMonster __instance) { if (PlayableBossIdentity.IsPlayable((Component)(object)__instance)) { __instance.numberOfShotsToFire = 8f; } } } internal static class EnemySpiderMonsterAwakePostPatch { private static readonly FieldInfo SpiderNestsField = AccessTools.Field(typeof(EnemySpiderMonster), "spiderNests"); internal static void Postfix(EnemySpiderMonster __instance) { ShamuraStraightAlphaMaterialFix.Attach(__instance); if (!PlayableBossIdentity.IsPlayable((Component)(object)__instance) || SpiderNestsField == null || !(SpiderNestsField.GetValue(__instance) is IList list)) { return; } for (int i = 0; i < list.Count; i++) { object? obj = list[i]; SpiderNest val = (SpiderNest)((obj is SpiderNest) ? obj : null); if ((Object)(object)val != (Object)null) { val.Droppable = true; } } } } internal static class EnemySpiderMonsterStartPatch { internal static bool Prefix(EnemySpiderMonster __instance) { return !PlayableBossIdentity.IsPlayable((Component)(object)__instance); } } internal static class EnemySpiderMonsterOnEnablePatch { internal static bool Prefix(EnemySpiderMonster __instance) { return !PlayableBossIdentity.IsPlayable((Component)(object)__instance); } internal static void Postfix(EnemySpiderMonster __instance) { ShamuraStraightAlphaMaterialFix.Attach(__instance); } } internal static class EnemySpiderMonsterOnDiePatch { internal static bool Prefix(EnemySpiderMonster __instance) { if (!PlayableBossIdentity.IsPlayable((Component)(object)__instance)) { return true; } if ((Object)(object)((UnitObject)__instance).health != (Object)null) { ((UnitObject)__instance).health.HP = ((UnitObject)__instance).health.totalHP; } return false; } } internal static class PlayableShamuraMeshGuardPatch { private static readonly Dictionary GuardedSlots = new Dictionary(); internal static void Register(SkeletonRenderer renderer) { if (!((Object)(object)renderer == (Object)null) && renderer.Skeleton != null) { GuardedSlots[renderer] = (Slot[])(object)new Slot[3] { renderer.Skeleton.FindSlot("Other/whiteball"), renderer.Skeleton.FindSlot("Other/ATTACK_EFFECT"), renderer.Skeleton.FindSlot("slam") }; } } internal static void Unregister(SkeletonRenderer renderer) { if ((Object)(object)renderer != (Object)null) { GuardedSlots.Remove(renderer); } } internal static void Prefix(SkeletonRenderer __instance) { if ((Object)(object)__instance == (Object)null || !GuardedSlots.TryGetValue(__instance, out var value) || value == null) { return; } for (int i = 0; i < value.Length; i++) { if (value[i] != null) { value[i].Attachment = null; } } } } internal static class PlayableBishopBasicAttackDownPatch { internal static void Postfix(PlayerFarming playerFarming, ref bool __result) { BishopAspectController controller = PlayableBishopsPlugin.GetController(playerFarming); if (!((Object)(object)controller == (Object)null) && controller.BlocksBasicAttack(playerFarming)) { bool num = __result; __result = false; if (num) { controller.CaptureBasicAttack(playerFarming); } } } } internal static class PlayableBishopBasicAttackHeldPatch { internal static bool Prefix(PlayerFarming playerFarming, ref bool __result) { BishopAspectController controller = PlayableBishopsPlugin.GetController(playerFarming); if ((Object)(object)controller == (Object)null || !controller.BlocksBasicAttack(playerFarming)) { return true; } __result = false; return false; } } internal static class PlayableBishopSecondaryAttackDownPatch { internal static void Postfix(PlayerFarming playerFarming, ref bool __result) { BishopAspectController controller = PlayableBishopsPlugin.GetController(playerFarming); if (!((Object)(object)controller == (Object)null) && controller.BlocksCombatInput(playerFarming)) { bool num = __result; __result = false; if (num) { controller.CaptureSecondaryAttack(playerFarming); } } } } internal static class PlayableBishopSignatureAttackDownPatch { internal static void Postfix(PlayerFarming playerFarming, ref bool __result) { BishopAspectController controller = PlayableBishopsPlugin.GetController(playerFarming); if (!((Object)(object)controller == (Object)null) && controller.BlocksCombatInput(playerFarming)) { bool num = __result; __result = false; if (num) { controller.CaptureSignatureAttack(playerFarming); } } } } internal static class PlayableBishopCombatInputHeldPatch { internal static bool Prefix(PlayerFarming playerFarming, ref bool __result) { BishopAspectController controller = PlayableBishopsPlugin.GetController(playerFarming); if ((Object)(object)controller == (Object)null || !controller.BlocksCombatInput(playerFarming)) { return true; } __result = false; return false; } } internal static class PlayableBishopCombatInputUpPatch { internal static bool Prefix(PlayerFarming playerFarming, ref bool __result) { BishopAspectController controller = PlayableBishopsPlugin.GetController(playerFarming); if ((Object)(object)controller == (Object)null || !controller.BlocksCombatInput(playerFarming)) { return true; } __result = false; return false; } } internal static class PlayableBishopDodgeDownPatch { internal static void Postfix(PlayerFarming playerFarming, ref bool __result) { BishopAspectController controller = PlayableBishopsPlugin.GetController(playerFarming); if (!((Object)(object)controller == (Object)null) && controller.BlocksDodgeInput(playerFarming)) { bool num = __result; __result = false; if (num) { controller.CaptureDodge(playerFarming); } } } } internal static class PlayableBishopDodgeHeldPatch { internal static bool Prefix(PlayerFarming playerFarming, ref bool __result) { BishopAspectController controller = PlayableBishopsPlugin.GetController(playerFarming); if ((Object)(object)controller == (Object)null || !controller.BlocksDodgeInput(playerFarming)) { return true; } __result = false; return false; } } internal static class UIPlayerUpgradesMenuStartPatch { internal static void Postfix(UIPlayerUpgradesMenuController __instance) { BishopAspectAltarUi.Attach(__instance); } } }