using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using EnemySyncing.Boss; using EnemySyncing.Components; using EnemySyncing.Networking; using EnemySyncing.Patches; using GlobalEnums; using HarmonyLib; using HutongGames.PlayMaker; using HutongGames.PlayMaker.Actions; using InControl; using Microsoft.CodeAnalysis; using SSMP.Api.Client; using SSMP.Api.Client.Networking; using SSMP.Api.Server; using SSMP.Api.Server.Networking; using SSMP.Math; using SSMP.Networking.Packet; using SSMP.Networking.Packet.Data; using SSMP.Util; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("EnemySyncing")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyInformationalVersion("1.0.1+3adc5a0dabcb1c712242ef3fc185501d2728423b")] [assembly: AssemblyProduct("EnemySyncing")] [assembly: AssemblyTitle("EnemySyncing")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace EnemySyncing { public class ClientAddon : ClientAddon { public class RemoteCocoonResponder : MonoBehaviour, IHitResponder { public ushort OwnerPlayerId; public HitResponse Hit(HitInstance hitInstance) { //IL_0000: 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_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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_0062: 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) if (!hitInstance.IsHeroDamage) { return default(HitResponse); } CocoonDamagePacket packet = new CocoonDamagePacket { TargetPlayerId = OwnerPlayerId, DamageDealt = hitInstance.DamageDealt }; Instance?.SendPacket(EnemySyncPacketId.CocoonDamage, (IPacketData)(object)packet); EnemyHitEffectsRegular component = ((Component)this).GetComponent(); if ((Object)(object)component != (Object)null) { component.ReceiveHitEffect(hitInstance); } return default(HitResponse); } } private IClientApi? _clientApi; private IClientAddonNetworkSender? _clientSender; private ushort _localPlayerId = ushort.MaxValue; public ushort SceneOwnerId = ushort.MaxValue; public readonly Dictionary LastKnownPositions = new Dictionary(); public readonly Dictionary LastKnownScales = new Dictionary(); public readonly Dictionary LastKnownActiveStates = new Dictionary(); public readonly Dictionary LastKnownControllers = new Dictionary(); public readonly Dictionary LastKnownTargets = new Dictionary(); public readonly Dictionary PrefabCache = new Dictionary(); public static readonly HashSet FailedPrefabSearches = new HashSet(); public static readonly HashSet DeadEnemies = new HashSet(); public static readonly Dictionary> SceneDeadEnemies = new Dictionary>(); public static bool IsApplyingRemoteDeath = false; public static bool IsLocalPlayerCocooned = false; public static int LocalPlayerCocoonHp = 25; public static bool IsSuiciding = false; public static Vector3 LocalCocoonSafePosition = Vector3.zero; public readonly HashSet CocoonedPlayers = new HashSet(); public static int originalHeroLayer = 0; public static int originalHeroBoxLayer = 0; public static readonly HashSet originalEnabledRenderers = new HashSet(); private GameObject? localCocoonVisual; private static Sprite? _cachedCocoonSprite; private static readonly Dictionary> RemotePlayerOriginalRenderers = new Dictionary>(); public static ClientAddon? Instance { get; private set; } public IClientApi? Api => _clientApi; protected override string Name => "EnemySyncingAddon"; protected override string Version => "1.0.1"; public override bool NeedsNetwork => true; public override uint ApiVersion => 1u; public ushort LocalPlayerId => _localPlayerId; public bool IsLocalSceneOwner { get { if (SceneOwnerId != _localPlayerId && SceneOwnerId != ushort.MaxValue) { return GetPlayersInSceneCount() <= 1; } return true; } } public bool IsSceneOwner => IsLocalSceneOwner; public int GetPlayersInSceneCount() { int num = 1; foreach (IClientPlayer item in GetPlayersInScene()) { _ = item; num++; } return num; } public override void Initialize(IClientApi clientApi) { //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Expected O, but got Unknown Instance = this; _clientApi = clientApi; IClientAddonNetworkReceiver networkReceiver = clientApi.NetClient.GetNetworkReceiver((ClientAddon)(object)this, (Func)InstantiatePacket); _clientSender = clientApi.NetClient.GetNetworkSender((ClientAddon)(object)this); networkReceiver.RegisterPacketHandler(EnemySyncPacketId.EnemyPosition, (GenericClientPacketHandler)HandleEnemyPosition); networkReceiver.RegisterPacketHandler(EnemySyncPacketId.EnemyAnimation, (GenericClientPacketHandler)HandleEnemyAnimation); networkReceiver.RegisterPacketHandler(EnemySyncPacketId.EnemyTarget, (GenericClientPacketHandler)HandleEnemyTarget); networkReceiver.RegisterPacketHandler(EnemySyncPacketId.EnemyTakeDamage, (GenericClientPacketHandler)HandleEnemyTakeDamage); networkReceiver.RegisterPacketHandler(EnemySyncPacketId.EnemyHp, (GenericClientPacketHandler)HandleEnemyHp); networkReceiver.RegisterPacketHandler(EnemySyncPacketId.EnemyDie, (GenericClientPacketHandler)HandleEnemyDie); networkReceiver.RegisterPacketHandler(EnemySyncPacketId.SpawnProjectile, (GenericClientPacketHandler)HandleSpawnProjectile); networkReceiver.RegisterPacketHandler(EnemySyncPacketId.PlayerIdNotify, (GenericClientPacketHandler)HandlePlayerIdNotify); networkReceiver.RegisterPacketHandler(EnemySyncPacketId.EnemyFsmState, (GenericClientPacketHandler)HandleEnemyFsmState); networkReceiver.RegisterPacketHandler(EnemySyncPacketId.BossSyncRequest, (GenericClientPacketHandler)HandleBossSyncRequest); networkReceiver.RegisterPacketHandler(EnemySyncPacketId.PlayerCocoon, (GenericClientPacketHandler)HandlePlayerCocoon); networkReceiver.RegisterPacketHandler(EnemySyncPacketId.CocoonDamage, (GenericClientPacketHandler)HandleCocoonDamage); networkReceiver.RegisterPacketHandler(EnemySyncPacketId.SceneOwnerNotify, (GenericClientPacketHandler)HandleSceneOwnerNotify); networkReceiver.RegisterPacketHandler(EnemySyncPacketId.VerifyEnemyDieRequest, (GenericClientPacketHandler)HandleVerifyEnemyDieRequest); clientApi.ClientManager.ConnectEvent += OnClientConnect; clientApi.ClientManager.DisconnectEvent += OnClientDisconnect; SceneManager.activeSceneChanged += OnSceneChanged; GameObject val = new GameObject("EnemySyncManager"); Object.DontDestroyOnLoad((Object)val); val.AddComponent(); ApplyHarmonyPatches(); } private void ApplyHarmonyPatches() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) try { new Harmony("com.ssmp.enemysyncing").PatchAll(typeof(ClientAddon).Assembly); Debug.Log((object)"[EnemySync] Harmony patches applied successfully."); } catch (Exception arg) { Debug.LogError((object)$"[EnemySync] Failed to apply Harmony patches: {arg}"); } } public void UnsubscribeFromAllBosses() { foreach (EnemyAvatar value in EnemyAvatar.ActiveAvatars.Values) { if ((Object)(object)value != (Object)null && value.isBoss) { BossSyncRequestPacket packet = new BossSyncRequestPacket { EnemyName = value.enemyName, Subscribe = false }; SendPacket(EnemySyncPacketId.BossSyncRequest, (IPacketData)(object)packet); value.isController = false; value.controllerId = ushort.MaxValue; value.TargetPlayerId = ushort.MaxValue; } } } private void OnSceneChanged(Scene current, Scene next) { UnsubscribeFromAllBosses(); LastKnownControllers.Clear(); LastKnownTargets.Clear(); LastKnownPositions.Clear(); LastKnownScales.Clear(); LastKnownActiveStates.Clear(); EnemyAvatar.ActiveAvatars.Clear(); DeadEnemies.Clear(); PrefabCache.Clear(); FailedPrefabSearches.Clear(); SceneOwnerId = ushort.MaxValue; Debug.Log((object)("[EnemySync] Scene changed to '" + ((Scene)(ref next)).name + "'. Cleared state cache.")); } private void OnClientConnect() { _localPlayerId = ushort.MaxValue; SendPacket(EnemySyncPacketId.RequestPlayerId, (IPacketData)(object)new RequestPlayerIdPacket()); Debug.Log((object)"[EnemySync] Connected to server. Requested player ID."); } private void OnClientDisconnect() { _localPlayerId = ushort.MaxValue; CocoonedPlayers.Clear(); DeadEnemies.Clear(); PrefabCache.Clear(); Debug.Log((object)"[EnemySync] Disconnected from server."); } private void HandlePlayerIdNotify(PlayerIdNotifyPacket packet) { _localPlayerId = packet.AssignedPlayerId; Debug.Log((object)$"[EnemySync] Assigned local player ID: {_localPlayerId}"); } private IPacketData InstantiatePacket(EnemySyncPacketId id) { return (IPacketData)(id switch { EnemySyncPacketId.EnemyPosition => new PacketDataCollection(), EnemySyncPacketId.EnemyAnimation => new EnemyAnimationPacket(), EnemySyncPacketId.EnemyTarget => new EnemyTargetPacket(), EnemySyncPacketId.EnemyTakeDamage => new EnemyTakeDamagePacket(), EnemySyncPacketId.EnemyHp => new EnemyHpPacket(), EnemySyncPacketId.EnemyDie => new EnemyDiePacket(), EnemySyncPacketId.SpawnProjectile => new SpawnProjectilePacket(), EnemySyncPacketId.RequestPlayerId => new RequestPlayerIdPacket(), EnemySyncPacketId.PlayerIdNotify => new PlayerIdNotifyPacket(), EnemySyncPacketId.EnemyFsmState => new EnemyFsmStatePacket(), EnemySyncPacketId.BossSyncRequest => new BossSyncRequestPacket(), EnemySyncPacketId.PlayerCocoon => new PlayerCocoonPacket(), EnemySyncPacketId.CocoonDamage => new CocoonDamagePacket(), EnemySyncPacketId.SceneOwnerNotify => new SceneOwnerNotifyPacket(), EnemySyncPacketId.VerifyEnemyDieRequest => new VerifyEnemyDieRequestPacket(), _ => throw new ArgumentException("Unknown packet ID"), }); } private void HandleSceneOwnerNotify(SceneOwnerNotifyPacket packet) { SceneOwnerId = packet.SceneOwnerId; Debug.Log((object)$"[EnemySync] Scene Owner updated: {SceneOwnerId} (isLocalOwner: {IsLocalSceneOwner})"); } private void HandleVerifyEnemyDieRequest(VerifyEnemyDieRequestPacket packet) { //IL_0083: 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) if (!IsLocalSceneOwner || string.IsNullOrEmpty(packet.EnemyName)) { return; } Debug.Log((object)$"[EnemySync] Scene Owner verifying death request for '{packet.EnemyName}' from player {packet.RequesterPlayerId}"); EnemyAvatar enemyAvatar = FindEnemyAvatar(packet.EnemyName); if ((Object)(object)enemyAvatar != (Object)null) { HealthManager component = ((Component)enemyAvatar).GetComponent(); if ((Object)(object)component != (Object)null) { component.hp = 0; } } DeadEnemies.Add(packet.EnemyName); Scene activeScene = SceneManager.GetActiveScene(); string name = ((Scene)(ref activeScene)).name; if (!string.IsNullOrEmpty(name)) { if (!SceneDeadEnemies.TryGetValue(name, out HashSet value)) { value = new HashSet(); SceneDeadEnemies[name] = value; } value.Add(packet.EnemyName); } EnemyDiePacket packet2 = new EnemyDiePacket { EnemyName = packet.EnemyName, AttackDirection = packet.AttackDirection, AttackType = packet.AttackType }; SendPacket(EnemySyncPacketId.EnemyDie, (IPacketData)(object)packet2); } public void SendPacket(EnemySyncPacketId packetId, IPacketData packet) { if (_clientSender != null && ((ClientAddon)this).ClientApi != null && ((ClientAddon)this).ClientApi.NetClient != null && ((ClientAddon)this).ClientApi.NetClient.IsConnected) { if (packetId == EnemySyncPacketId.EnemyPosition) { _clientSender.SendCollectionData(packetId, (EnemyPositionPacket)(object)packet); } else { _clientSender.SendSingleData(packetId, packet); } } } public IClientPlayer? GetPlayer(ushort id) { if (((ClientAddon)this).ClientApi == null) { return null; } foreach (IClientPlayer player in ((ClientAddon)this).ClientApi.ClientManager.Players) { if (player.Id == id) { return player; } } return null; } public IEnumerable GetPlayersInScene() { if (((ClientAddon)this).ClientApi == null) { return Array.Empty(); } List list = new List(); foreach (IClientPlayer player in ((ClientAddon)this).ClientApi.ClientManager.Players) { if (player.IsInLocalScene) { list.Add(player); } } return list; } public static string GetPrefabNameFromName(string name) { if (string.IsNullOrEmpty(name)) { return ""; } string text = name.Replace("(Clone)", "").Trim(); int num = text.IndexOf("_fs_", StringComparison.OrdinalIgnoreCase); if (num >= 0) { text = text.Substring(0, num); } int num2 = text.IndexOf(" ("); if (num2 >= 0) { text = text.Substring(0, num2); } while (text.Length > 0 && (char.IsDigit(text[text.Length - 1]) || char.IsWhiteSpace(text[text.Length - 1]))) { text = text.Substring(0, text.Length - 1); } return text.Trim(); } public EnemyAvatar? GetActiveBoss() { return BossSyncManager.GetActiveBoss(); } public GameObject? FindPrefab(string name) { //IL_0044: 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_00c9: 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_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(name)) { return null; } string prefabNameFromName = GetPrefabNameFromName(name); if (string.IsNullOrEmpty(prefabNameFromName)) { return null; } if (FailedPrefabSearches.Contains(prefabNameFromName)) { return null; } Scene scene; if (PrefabCache.TryGetValue(prefabNameFromName, out GameObject value) && (Object)(object)value != (Object)null) { scene = value.scene; if (!((Scene)(ref scene)).IsValid()) { return value; } EnemyAvatar enemyAvatar = default(EnemyAvatar); if (!value.TryGetComponent(ref enemyAvatar) || !enemyAvatar.isBoss) { return value; } PrefabCache.Remove(prefabNameFromName); } GameObject val = null; GameObject val2 = null; HealthManager[] array = Resources.FindObjectsOfTypeAll(); EnemyAvatar enemyAvatar2 = default(EnemyAvatar); foreach (HealthManager val3 in array) { if ((Object)(object)val3 == (Object)null || (Object)(object)((Component)val3).gameObject == (Object)null) { continue; } GameObject gameObject = ((Component)val3).gameObject; string prefabNameFromName2 = GetPrefabNameFromName(((Object)gameObject).name); scene = gameObject.scene; bool flag = !((Scene)(ref scene)).IsValid(); if (((Object)gameObject).name == prefabNameFromName || prefabNameFromName2 == prefabNameFromName) { if (flag) { val = gameObject; break; } if ((Object)(object)val2 == (Object)null && (!gameObject.TryGetComponent(ref enemyAvatar2) || !enemyAvatar2.isBoss) && val3.hp <= 100) { val2 = gameObject; } } } GameObject val4 = val ?? val2; if ((Object)(object)val4 == (Object)null) { val = null; val2 = null; string text = prefabNameFromName.ToLower(); GameObject[] array2 = Resources.FindObjectsOfTypeAll(); EnemyAvatar enemyAvatar3 = default(EnemyAvatar); foreach (GameObject val5 in array2) { if ((Object)(object)val5 == (Object)null) { continue; } string text2 = ((Object)val5).name.ToLower(); string text3 = GetPrefabNameFromName(((Object)val5).name).ToLower(); scene = val5.scene; bool flag2 = !((Scene)(ref scene)).IsValid(); if (((Object)val5).name == prefabNameFromName || text3 == text || text2.Contains(text) || text.Contains(text3)) { if (flag2) { val = val5; break; } if ((Object)(object)val2 == (Object)null && (!val5.TryGetComponent(ref enemyAvatar3) || !enemyAvatar3.isBoss)) { val2 = val5; } } } val4 = val ?? val2; } if ((Object)(object)val4 != (Object)null) { PrefabCache[prefabNameFromName] = val4; FailedPrefabSearches.Remove(prefabNameFromName); } else { FailedPrefabSearches.Add(prefabNameFromName); } return val4; } public EnemyAvatar? FindEnemyAvatar(string name, bool autoSpawn = false, Vector3? spawnPos = null, bool excludeBosses = false) { //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_0367: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(name)) { return null; } if (EnemyAvatar.ActiveAvatars.TryGetValue(name, out EnemyAvatar value) && (Object)(object)value != (Object)null && (!excludeBosses || !value.isBoss)) { return value; } string text = BossSyncManager.NormalizePath(name); foreach (EnemyAvatar value2 in EnemyAvatar.ActiveAvatars.Values) { if ((Object)(object)value2 != (Object)null && (Object)(object)((Component)value2).gameObject != (Object)null && (!excludeBosses || !value2.isBoss)) { if (value2.enemyName == name || ((Object)((Component)value2).gameObject).name == name) { return value2; } if (!string.IsNullOrEmpty(text) && BossSyncManager.NormalizePath(value2.enemyName) == text) { return value2; } } } Scene activeScene = SceneManager.GetActiveScene(); if (((Scene)(ref activeScene)).IsValid()) { GameObject[] rootGameObjects = ((Scene)(ref activeScene)).GetRootGameObjects(); foreach (GameObject val in rootGameObjects) { if ((Object)(object)val == (Object)null) { continue; } EnemyAvatar[] componentsInChildren = val.GetComponentsInChildren(true); foreach (EnemyAvatar enemyAvatar in componentsInChildren) { if ((Object)(object)enemyAvatar != (Object)null && (Object)(object)((Component)enemyAvatar).gameObject != (Object)null && (!excludeBosses || !enemyAvatar.isBoss) && (enemyAvatar.enemyName == name || ((Object)((Component)enemyAvatar).gameObject).name == name || (!string.IsNullOrEmpty(text) && BossSyncManager.NormalizePath(enemyAvatar.enemyName) == text))) { EnemyAvatar.ActiveAvatars[name] = enemyAvatar; return enemyAvatar; } } } } if (DeadEnemies.Contains(name)) { return null; } if (autoSpawn) { if ((Object)(object)HeroController.instance == (Object)null || HeroController.instance.cState.dead) { return null; } if (!name.Contains("_fs_")) { return null; } string prefabNameFromName = GetPrefabNameFromName(name); GameObject val2 = FindPrefab(prefabNameFromName); if ((Object)(object)val2 != (Object)null) { Vector3 val3 = (Vector3)(((??)spawnPos) ?? Vector3.zero); GameObject val4 = Object.Instantiate(val2, val3, Quaternion.identity); ((Object)val4).name = name; val4.SetActive(true); if ((Object)(object)val4.GetComponent() == (Object)null) { val4.AddComponent(); } EnemyAvatar enemyAvatar2 = val4.GetComponent() ?? val4.AddComponent(); enemyAvatar2.enemyName = name; enemyAvatar2.targetPosition = val3; ((Component)enemyAvatar2).transform.position = val3; ushort num = ushort.MaxValue; if (name.Contains("_fs_")) { string[] array = name.Split(new string[1] { "_fs_" }, StringSplitOptions.None); if (array.Length >= 2) { string[] array2 = array[1].Split('_'); if (array2.Length >= 1 && ushort.TryParse(array2[0], out var result)) { num = result; } } } if (num != ushort.MaxValue) { enemyAvatar2.controllerId = num; enemyAvatar2.TargetPlayerId = num; enemyAvatar2.isController = num == LocalPlayerId; } enemyAvatar2.ReEnableFSMs(); EnemyAvatar.ActiveAvatars[name] = enemyAvatar2; Debug.Log((object)$"[EnemySync] Auto-spawned missing enemy '{name}' from prefab '{prefabNameFromName}' at {val3} (controller: {enemyAvatar2.controllerId})"); return enemyAvatar2; } } return null; } private void HandleBossSyncRequest(BossSyncRequestPacket packet) { if (string.IsNullOrEmpty(packet.EnemyName) || !packet.Subscribe) { return; } if (DeadEnemies.Contains(packet.EnemyName)) { EnemyDiePacket packet2 = new EnemyDiePacket { EnemyName = packet.EnemyName }; SendPacket(EnemySyncPacketId.EnemyDie, (IPacketData)(object)packet2); return; } EnemyAvatar enemyAvatar = FindEnemyAvatar(packet.EnemyName); if ((Object)(object)enemyAvatar != (Object)null && enemyAvatar.isBoss && enemyAvatar.isController) { Debug.Log((object)("[EnemySync] Received BossSyncRequest for '" + packet.EnemyName + "'. Sending FSM states.")); enemyAvatar.SendAllFsmStates(); } } public static void EnterCocoonState() { //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) if (IsLocalPlayerCocooned) { return; } IsLocalPlayerCocooned = true; LocalCocoonSafePosition = Vector3.zero; LocalPlayerCocoonHp = 25; Debug.Log((object)"[EnemySync] Local player entered cocoon state!"); SetCocoonInputsEnabled(enabled: false); originalEnabledRenderers.Clear(); if ((Object)(object)HeroController.instance != (Object)null) { HeroController instance = HeroController.instance; instance.RelinquishControl(); instance.acceptingInput = false; Rigidbody2D val = default(Rigidbody2D); if (((Component)instance).TryGetComponent(ref val)) { val.bodyType = (RigidbodyType2D)0; } if (instance.cState != null) { instance.cState.jumping = false; instance.cState.doubleJumping = false; instance.cState.dashing = false; instance.cState.backDashing = false; instance.cState.superDashing = false; instance.cState.recoiling = false; instance.cState.recoilFrozen = false; instance.cState.wallSliding = false; instance.cState.touchingWall = false; } originalHeroLayer = ((Component)instance).gameObject.layer; Transform obj = instance.transform.Find("HeroBox"); GameObject val2 = ((obj != null) ? ((Component)obj).gameObject : null); if ((Object)(object)val2 != (Object)null) { originalHeroBoxLayer = val2.layer; } Renderer[] componentsInChildren = ((Component)instance).GetComponentsInChildren(false); foreach (Renderer val3 in componentsInChildren) { if ((Object)(object)val3 != (Object)null && val3.enabled && ((Object)((Component)val3).gameObject).name != "LocalCocoonVisual") { originalEnabledRenderers.Add(val3); } } } PlayerCocoonPacket packet = new PlayerCocoonPacket { PlayerId = (Instance?.LocalPlayerId ?? ushort.MaxValue), IsCocooned = true }; Instance?.SendPacket(EnemySyncPacketId.PlayerCocoon, (IPacketData)(object)packet); Instance?.StartCocoonSettling(); } public static void ExitCocoonState(bool heal) { //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) if (!IsLocalPlayerCocooned) { return; } IsLocalPlayerCocooned = false; LocalCocoonSafePosition = Vector3.zero; SyncManager? instance = SyncManager.Instance; if (instance != null) { ((MonoBehaviour)instance).StopAllCoroutines(); } Debug.Log((object)$"[EnemySync] Local player exited cocoon state (heal={heal})!"); SetCocoonInputsEnabled(enabled: true); if ((Object)(object)HeroController.instance != (Object)null) { HeroController instance2 = HeroController.instance; instance2.acceptingInput = true; ((Component)instance2).gameObject.layer = ((originalHeroLayer > 0 && originalHeroLayer != 11) ? originalHeroLayer : 9); Transform obj = instance2.transform.Find("HeroBox"); GameObject val = ((obj != null) ? ((Component)obj).gameObject : null); if ((Object)(object)val != (Object)null) { val.layer = ((originalHeroBoxLayer > 0 && originalHeroBoxLayer != 11) ? originalHeroBoxLayer : 17); } if (originalEnabledRenderers.Count > 0) { foreach (Renderer originalEnabledRenderer in originalEnabledRenderers) { if ((Object)(object)originalEnabledRenderer != (Object)null && ((Object)((Component)originalEnabledRenderer).gameObject).name != "LocalCocoonVisual") { originalEnabledRenderer.enabled = true; } } } else { Renderer component = ((Component)instance2).GetComponent(); if ((Object)(object)component != (Object)null) { component.enabled = true; } tk2dSpriteAnimator val2 = ((Component)instance2).GetComponent() ?? ((Component)instance2).GetComponentInChildren(); Renderer val3 = default(Renderer); if ((Object)(object)val2 != (Object)null && ((Component)val2).TryGetComponent(ref val3)) { val3.enabled = true; } Transform val4 = instance2.transform.Find("Username"); if ((Object)(object)val4 != (Object)null) { Renderer[] componentsInChildren = ((Component)val4).GetComponentsInChildren(true); foreach (Renderer val5 in componentsInChildren) { if ((Object)(object)val5 != (Object)null) { val5.enabled = true; } } } } originalEnabledRenderers.Clear(); Rigidbody2D val6 = default(Rigidbody2D); if (((Component)instance2).TryGetComponent(ref val6)) { val6.bodyType = (RigidbodyType2D)0; } Collider2D component2 = ((Component)instance2).GetComponent(); if ((Object)(object)component2 != (Object)null) { ((Behaviour)component2).enabled = true; } Transform obj2 = instance2.transform.Find("HeroBox"); Collider2D val7 = ((obj2 != null) ? ((Component)obj2).GetComponent() : null); if ((Object)(object)val7 != (Object)null) { ((Behaviour)val7).enabled = true; } try { FieldInfo field = typeof(HeroController).GetField("damageMode", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { field.SetValue(instance2, 0); } } catch { } instance2.cState.invulnerable = false; instance2.cState.hazardDeath = false; instance2.cState.hazardRespawning = false; instance2.cState.recoiling = false; instance2.cState.transitioning = false; instance2.cState.onGround = true; instance2.RegainControl(); ResetHeroSpriteFlash(); if (heal) { instance2.playerData.health = 1; try { EventRegister.SendEvent("HP CHANGED", (GameObject)null); PlayMakerFSM.BroadcastEvent("HP CHANGED"); } catch { } } } PlayerCocoonPacket packet = new PlayerCocoonPacket { PlayerId = (Instance?.LocalPlayerId ?? ushort.MaxValue), IsCocooned = false }; Instance?.SendPacket(EnemySyncPacketId.PlayerCocoon, (IPacketData)(object)packet); Instance?.DestroyLocalCocoonVisual(); } public static void SetCocoonInputsEnabled(bool enabled) { if ((Object)(object)ManagerSingleton.Instance == (Object)null || ManagerSingleton.Instance.inputActions == null) { return; } try { HeroActions inputActions = ManagerSingleton.Instance.inputActions; ((OneAxisInputControl)inputActions.Jump).Enabled = enabled; ((OneAxisInputControl)inputActions.Evade).Enabled = enabled; ((OneAxisInputControl)inputActions.Dash).Enabled = enabled; ((OneAxisInputControl)inputActions.SuperDash).Enabled = enabled; ((OneAxisInputControl)inputActions.Attack).Enabled = enabled; ((OneAxisInputControl)inputActions.Cast).Enabled = enabled; ((OneAxisInputControl)inputActions.QuickCast).Enabled = enabled; ((OneAxisInputControl)inputActions.Taunt).Enabled = enabled; ((OneAxisInputControl)inputActions.Left).Enabled = enabled; ((OneAxisInputControl)inputActions.Right).Enabled = enabled; ((OneAxisInputControl)inputActions.Up).Enabled = enabled; ((OneAxisInputControl)inputActions.Down).Enabled = enabled; ((OneAxisInputControl)inputActions.OpenInventory).Enabled = enabled; ((OneAxisInputControl)inputActions.OpenInventoryMap).Enabled = enabled; ((OneAxisInputControl)inputActions.OpenInventoryJournal).Enabled = enabled; ((OneAxisInputControl)inputActions.OpenInventoryTools).Enabled = enabled; ((OneAxisInputControl)inputActions.OpenInventoryQuests).Enabled = enabled; ((OneAxisInputControl)inputActions.SwipeInventoryMap).Enabled = enabled; ((OneAxisInputControl)inputActions.SwipeInventoryJournal).Enabled = enabled; ((OneAxisInputControl)inputActions.SwipeInventoryTools).Enabled = enabled; } catch (Exception arg) { Debug.LogError((object)$"[EnemySync] Failed to modify input actions state: {arg}"); } } public static void ResetHeroSpriteFlash() { if ((Object)(object)HeroController.instance == (Object)null) { return; } try { SpriteFlash component = ((Component)HeroController.instance).GetComponent(); if (!((Object)(object)component != (Object)null)) { return; } MethodInfo method = ((object)component).GetType().GetMethod("CancelFlash", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method != null) { method.Invoke(component, null); } else { MethodInfo method2 = ((object)component).GetType().GetMethod("removeFromList", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method2 != null) { method2.Invoke(component, null); } } ((Behaviour)component).enabled = false; ((Behaviour)component).enabled = true; } catch { } } public static PlayerAction? GetAction(string name) { if ((Object)(object)ManagerSingleton.Instance == (Object)null || ManagerSingleton.Instance.inputActions == null) { return null; } HeroActions inputActions = ManagerSingleton.Instance.inputActions; FieldInfo field = ((object)inputActions).GetType().GetField(name, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public); if (field != null) { object? value = field.GetValue(inputActions); return (PlayerAction?)((value is PlayerAction) ? value : null); } PropertyInfo property = ((object)inputActions).GetType().GetProperty(name, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public); if (property != null) { object? value2 = property.GetValue(inputActions); return (PlayerAction?)((value2 is PlayerAction) ? value2 : null); } return null; } public static PlayerAction? GetQuickMapAction() { return GetAction("quickMap") ?? GetAction("map"); } public unsafe static string GetQuickMapButtonName() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Invalid comparison between Unknown and I4 //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_0034: 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_0077: Invalid comparison between Unknown and I4 //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Invalid comparison between Unknown and I4 //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Invalid comparison between Unknown and I4 PlayerAction quickMapAction = GetQuickMapAction(); if (quickMapAction != null) { try { bool flag = (Object)(object)ManagerSingleton.Instance != (Object)null && (int)ManagerSingleton.Instance.lastActiveController == 1; if (flag) { InputControlType controllerButtonBinding = KeybindUtil.GetControllerButtonBinding(quickMapAction); if ((int)controllerButtonBinding != 0) { return ((object)(*(InputControlType*)(&controllerButtonBinding))/*cast due to .constrained prefix*/).ToString(); } } foreach (BindingSource binding in quickMapAction.Bindings) { if (!(binding == (BindingSource)null)) { if (flag && (int)binding.BindingSourceType == 1) { return binding.Name; } if (!flag && ((int)binding.BindingSourceType == 2 || (int)binding.BindingSourceType == 3)) { return binding.Name; } } } foreach (BindingSource binding2 in quickMapAction.Bindings) { if (binding2 != (BindingSource)null && !string.IsNullOrEmpty(binding2.Name)) { return binding2.Name; } } } catch { } } return "TAB"; } private void HandlePlayerCocoon(PlayerCocoonPacket packet) { if (packet.PlayerId == LocalPlayerId) { return; } if (packet.IsCocooned) { CocoonedPlayers.Add(packet.PlayerId); IClientPlayer player = GetPlayer(packet.PlayerId); if (player != null && (Object)(object)player.PlayerObject != (Object)null) { SpawnRemoteCocoon(player.PlayerObject, player.Id); } } else { CocoonedPlayers.Remove(packet.PlayerId); IClientPlayer player2 = GetPlayer(packet.PlayerId); if (player2 != null && (Object)(object)player2.PlayerObject != (Object)null) { DestroyRemoteCocoon(player2.PlayerObject); } } if (AreAllPlayersCocooned()) { TriggerNativeDeath(); } } private void HandleCocoonDamage(CocoonDamagePacket packet) { if (packet.TargetPlayerId == LocalPlayerId && IsLocalPlayerCocooned) { LocalPlayerCocoonHp -= packet.DamageDealt; Debug.Log((object)$"[EnemySync] Local cocoon took damage! HP remaining: {LocalPlayerCocoonHp}"); if (LocalPlayerCocoonHp <= 0) { ExitCocoonState(heal: true); } } } public void StartCocoonSettling() { SyncManager? instance = SyncManager.Instance; if (instance != null) { ((MonoBehaviour)instance).StopAllCoroutines(); } SyncManager? instance2 = SyncManager.Instance; if (instance2 != null) { ((MonoBehaviour)instance2).StartCoroutine(SettleCocoonRoutine()); } } private IEnumerator SettleCocoonRoutine() { HeroController hc = HeroController.instance; Rigidbody2D val = default(Rigidbody2D); if ((Object)(object)hc != (Object)null && ((Component)hc).TryGetComponent(ref val)) { val.bodyType = (RigidbodyType2D)0; } int maxAttempts = 10; Rigidbody2D val2 = default(Rigidbody2D); for (int attempt = 0; attempt < maxAttempts; attempt++) { yield return (object)new WaitForSeconds(2f); if ((Object)(object)hc == (Object)null || !IsLocalPlayerCocooned) { yield break; } bool num = hc.cState != null && (hc.cState.hazardDeath || hc.cState.hazardRespawning); bool flag = false; if (((Component)hc).TryGetComponent(ref val2)) { Vector2 linearVelocity = val2.linearVelocity; if (((Vector2)(ref linearVelocity)).magnitude > 0.05f) { flag = true; } } bool flag2 = hc.cState != null && hc.cState.onGround; if (!num && (!flag || flag2)) { break; } } if (!((Object)(object)hc != (Object)null) || !IsLocalPlayerCocooned) { yield break; } Vector3 val3 = hc.transform.position; try { if (hc.playerData != null) { Vector3 vector = hc.playerData.GetVector3("hazardRespawnLocation"); if (vector != Vector3.zero && hc.cState != null && (hc.cState.hazardDeath || hc.cState.hazardRespawning)) { val3 = vector; hc.transform.position = val3; } } } catch { } LocalCocoonSafePosition = val3; Rigidbody2D val4 = default(Rigidbody2D); if (((Component)hc).TryGetComponent(ref val4)) { val4.bodyType = (RigidbodyType2D)1; val4.linearVelocity = Vector2.zero; val4.angularVelocity = 0f; } ResetHeroSpriteFlash(); foreach (Renderer originalEnabledRenderer in originalEnabledRenderers) { if ((Object)(object)originalEnabledRenderer != (Object)null && ((Object)((Component)originalEnabledRenderer).gameObject).name != "LocalCocoonVisual" && !((Object)((Component)originalEnabledRenderer).gameObject).name.Contains("Username") && !((Object)((Component)originalEnabledRenderer).gameObject).name.Contains("Name")) { originalEnabledRenderer.enabled = false; } } SpawnLocalCocoonVisual(); } public static Sprite? GetCocoonSprite() { //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Expected O, but got Unknown //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: 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: Expected O, but got Unknown //IL_00ae: 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_015b: 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) if ((Object)(object)_cachedCocoonSprite != (Object)null) { return _cachedCocoonSprite; } try { Assembly assembly = typeof(ClientAddon).Assembly; string text = Array.Find(assembly.GetManifestResourceNames(), (string name) => name.EndsWith("Hornet_death.png")); if (text != null) { using Stream stream = assembly.GetManifestResourceStream(text); if (stream != null) { byte[] array = new byte[stream.Length]; stream.Read(array, 0, (int)stream.Length); Texture2D val = new Texture2D(2, 2); ImageConversion.LoadImage(val, array); _cachedCocoonSprite = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); return _cachedCocoonSprite; } } } catch { } Texture2D val2 = new Texture2D(32, 48); for (int num = 0; num < 48; num++) { for (int num2 = 0; num2 < 32; num2++) { float num3 = ((float)num2 - 16f) / 14f; float num4 = ((float)num - 24f) / 22f; if (num3 * num3 + num4 * num4 <= 1f) { val2.SetPixel(num2, num, new Color(0.9f, 0.95f, 1f, 0.85f)); } else { val2.SetPixel(num2, num, Color.clear); } } } val2.Apply(); _cachedCocoonSprite = Sprite.Create(val2, new Rect(0f, 0f, 32f, 48f), new Vector2(0.5f, 0.5f), 100f); return _cachedCocoonSprite; } public void SpawnLocalCocoonVisual() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_0070: 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) if (!((Object)(object)localCocoonVisual != (Object)null) && !((Object)(object)HeroController.instance == (Object)null)) { Sprite cocoonSprite = GetCocoonSprite(); if (!((Object)(object)cocoonSprite == (Object)null)) { localCocoonVisual = new GameObject("LocalCocoonVisual"); localCocoonVisual.transform.SetParent(HeroController.instance.transform); localCocoonVisual.transform.localPosition = new Vector3(0f, 0.5f, -0.05f); localCocoonVisual.transform.localScale = new Vector3(1.5f, 1.5f, 1f); SpriteRenderer obj = localCocoonVisual.AddComponent(); obj.sprite = cocoonSprite; ((Renderer)obj).sortingOrder = 30; } } } public void DestroyLocalCocoonVisual() { if ((Object)(object)localCocoonVisual != (Object)null) { Object.Destroy((Object)(object)localCocoonVisual); localCocoonVisual = null; } } public void SpawnRemoteCocoon(GameObject remotePlayerGo, ushort ownerId) { //IL_00b4: 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_00ca: 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_00e9: 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_0108: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) DestroyRemoteCocoon(remotePlayerGo); Sprite cocoonSprite = GetCocoonSprite(); if ((Object)(object)cocoonSprite == (Object)null) { return; } List list = new List(); Renderer[] componentsInChildren = remotePlayerGo.GetComponentsInChildren(false); foreach (Renderer val in componentsInChildren) { if ((Object)(object)val != (Object)null && val.enabled && ((Object)((Component)val).gameObject).name != "RemoteCocoonVisual" && !((Object)((Component)val).gameObject).name.Contains("Username") && !((Object)((Component)val).gameObject).name.Contains("Name")) { list.Add(val); val.enabled = false; } } RemotePlayerOriginalRenderers[remotePlayerGo] = list; GameObject val2 = new GameObject("RemoteCocoonVisual"); val2.transform.SetParent(remotePlayerGo.transform); val2.transform.localPosition = new Vector3(0f, 0.5f, -0.05f); val2.transform.localScale = new Vector3(1.5f, 1.5f, 1f); SpriteRenderer obj = val2.AddComponent(); obj.sprite = cocoonSprite; ((Renderer)obj).sortingOrder = 30; BoxCollider2D obj2 = val2.AddComponent(); obj2.size = new Vector2(1.2f, 2f); ((Collider2D)obj2).isTrigger = true; val2.layer = 11; val2.AddComponent().OwnerPlayerId = ownerId; } public void DestroyRemoteCocoon(GameObject remotePlayerGo) { Transform val = remotePlayerGo.transform.Find("RemoteCocoonVisual"); if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); } if (RemotePlayerOriginalRenderers.TryGetValue(remotePlayerGo, out List value)) { foreach (Renderer item in value) { if ((Object)(object)item != (Object)null) { item.enabled = true; } } RemotePlayerOriginalRenderers.Remove(remotePlayerGo); return; } Renderer component = remotePlayerGo.GetComponent(); if ((Object)(object)component != (Object)null) { component.enabled = true; } tk2dSpriteAnimator val2 = remotePlayerGo.GetComponent() ?? remotePlayerGo.GetComponentInChildren(); Renderer val3 = default(Renderer); if ((Object)(object)val2 != (Object)null && ((Component)val2).TryGetComponent(ref val3)) { val3.enabled = true; } Transform val4 = remotePlayerGo.transform.Find("Username"); if (!((Object)(object)val4 != (Object)null)) { return; } Renderer[] componentsInChildren = ((Component)val4).GetComponentsInChildren(true); foreach (Renderer val5 in componentsInChildren) { if ((Object)(object)val5 != (Object)null) { val5.enabled = true; } } } public static bool AreAllPlayersCocooned() { if (Instance == null || !IsLocalPlayerCocooned) { return false; } IEnumerable playersInScene = Instance.GetPlayersInScene(); if (!playersInScene.Any()) { return true; } foreach (IClientPlayer item in playersInScene) { if (!Instance.CocoonedPlayers.Contains(item.Id)) { return false; } } return true; } public static void TriggerNativeDeath() { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown if (!((Object)(object)HeroController.instance == (Object)null) && !HeroController.instance.cState.dead) { Debug.Log((object)"[EnemySync] Triggering native team death."); Instance?.UnsubscribeFromAllBosses(); if (IsLocalPlayerCocooned) { ExitCocoonState(heal: false); } IsSuiciding = true; HeroController.instance.TakeDamage(new GameObject("AllCocoonedDeath"), (CollisionSide)4, 9999, (HazardType)1, (DamagePropertyFlags)0); IsSuiciding = false; } } private void HandleEnemyPosition(EnemyPositionPacket packet) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(packet.Position.X, packet.Position.Y, 0f); LastKnownPositions[packet.EnemyName] = val; LastKnownScales[packet.EnemyName] = packet.ScaleX; LastKnownActiveStates[packet.EnemyName] = packet.Active; LastKnownControllers[packet.EnemyName] = packet.ControllerId; EnemyAvatar enemyAvatar = FindEnemyAvatar(packet.EnemyName); if (!((Object)(object)enemyAvatar != (Object)null)) { return; } if (enemyAvatar.isBoss || enemyAvatar.enemyName.Contains("_fs_") || enemyAvatar.IsHazardOrSummonOrProjectile()) { if (!enemyAvatar.isController && (enemyAvatar.controllerId != LocalPlayerId || LocalPlayerId == ushort.MaxValue) && enemyAvatar.controllerId != packet.ControllerId) { enemyAvatar.SetTargetAndControllerLocal(packet.ControllerId, packet.ControllerId); } } else if (enemyAvatar.controllerId == ushort.MaxValue && packet.ControllerId != ushort.MaxValue) { enemyAvatar.SetTargetAndControllerLocal(packet.ControllerId, packet.ControllerId); } else if (enemyAvatar.TargetPlayerId != ushort.MaxValue) { if (enemyAvatar.controllerId != enemyAvatar.TargetPlayerId) { enemyAvatar.SetTargetAndControllerLocal(enemyAvatar.TargetPlayerId, enemyAvatar.TargetPlayerId); } } else if (enemyAvatar.isController && LocalPlayerId != ushort.MaxValue && packet.ControllerId != LocalPlayerId) { float num = (((Object)(object)HeroController.instance != (Object)null) ? Vector3.Distance(((Component)enemyAvatar).transform.position, HeroController.instance.transform.position) : 999f); IClientPlayer player = GetPlayer(packet.ControllerId); if (((player != null && (Object)(object)player.PlayerObject != (Object)null) ? Vector3.Distance(((Component)enemyAvatar).transform.position, player.PlayerObject.transform.position) : 999f) < num - 5f) { Debug.Log((object)$"[EnemySync] Yielding FOV position control of '{packet.EnemyName}' to closer player {packet.ControllerId}"); enemyAvatar.SetTargetAndControllerLocal(ushort.MaxValue, packet.ControllerId); } } else if (!enemyAvatar.isController && enemyAvatar.controllerId != packet.ControllerId) { enemyAvatar.SetTargetAndControllerLocal(ushort.MaxValue, packet.ControllerId); } if ((!enemyAvatar.isBoss || ((!((Object)(object)HeroController.instance != (Object)null) || !HeroController.instance.cState.dead) && !(enemyAvatar.spawnDelayTimer > 0f))) && !enemyAvatar.isController) { enemyAvatar.UpdatePosition(val); enemyAvatar.targetScaleX = packet.ScaleX; enemyAvatar.targetActive = packet.Active; if (((Component)enemyAvatar).gameObject.activeSelf != packet.Active) { ((Component)enemyAvatar).gameObject.SetActive(packet.Active); } if (!packet.Active && packet.EnemyName.Contains("_fs_")) { Object.Destroy((Object)(object)((Component)enemyAvatar).gameObject, 0.5f); } } } private void HandleEnemyAnimation(EnemyAnimationPacket packet) { //IL_0083: 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_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) EnemyAvatar enemyAvatar = FindEnemyAvatar(packet.EnemyName); if (!((Object)(object)enemyAvatar != (Object)null) || enemyAvatar.isController) { return; } if (enemyAvatar.isBoss || enemyAvatar.IsHazardOrSummonOrProjectile()) { if (((Object)(object)HeroController.instance != (Object)null && HeroController.instance.cState.dead) || enemyAvatar.spawnDelayTimer > 0f) { return; } } else if ((Object)(object)HeroController.instance != (Object)null && Vector2.Distance(Vector2.op_Implicit(HeroController.instance.transform.position), Vector2.op_Implicit(((Component)enemyAvatar).transform.position)) > 35f) { return; } tk2dSpriteAnimator val = ((Component)enemyAvatar).GetComponent() ?? ((Component)enemyAvatar).GetComponentInChildren(true); if ((Object)(object)val != (Object)null && (Object)(object)val.Library != (Object)null) { tk2dSpriteAnimationClip clipByName = val.Library.GetClipByName(packet.ClipName); if (clipByName != null) { val.Play(clipByName); } else { val.Play(packet.ClipName); } } } private void HandleEnemyTarget(EnemyTargetPacket packet) { LastKnownControllers[packet.EnemyName] = packet.ControllerId; LastKnownTargets[packet.EnemyName] = packet.TargetPlayerId; EnemyAvatar enemyAvatar = FindEnemyAvatar(packet.EnemyName); if (!((Object)(object)enemyAvatar != (Object)null)) { return; } if (enemyAvatar.IsHazardOrSummonOrProjectile() && !enemyAvatar.isBoss) { enemyAvatar.SetTargetAndControllerLocal(packet.TargetPlayerId, packet.ControllerId); return; } if (enemyAvatar.isBoss && enemyAvatar.isController && enemyAvatar.controllerId == LocalPlayerId && packet.ControllerId != LocalPlayerId) { ushort num = Math.Min(LocalPlayerId, packet.ControllerId); if (LocalPlayerId == num) { Debug.Log((object)$"[EnemySync] Local player {LocalPlayerId} won boss claim tie-break for '{packet.EnemyName}'. Retaining control."); EnemyTargetPacket packet2 = new EnemyTargetPacket { EnemyName = packet.EnemyName, TargetPlayerId = enemyAvatar.TargetPlayerId, ControllerId = LocalPlayerId }; SendPacket(EnemySyncPacketId.EnemyTarget, (IPacketData)(object)packet2); } else { Debug.Log((object)$"[EnemySync] Local player {LocalPlayerId} lost boss claim tie-break for '{packet.EnemyName}' to player {packet.ControllerId}. Yielding control."); enemyAvatar.SetTargetAndControllerLocal(packet.TargetPlayerId, packet.ControllerId); } return; } if (!enemyAvatar.isBoss && !enemyAvatar.IsHazardOrSummonOrProjectile()) { if (enemyAvatar.TargetPlayerId == LocalPlayerId && LocalPlayerId != ushort.MaxValue && packet.TargetPlayerId != LocalPlayerId && (Object)(object)HeroController.instance != (Object)null && !enemyAvatar.IsPlayerDeadOrCocooned(((Component)HeroController.instance).gameObject)) { if (packet.ControllerId != LocalPlayerId && Time.time - enemyAvatar.lastTargetConfirmTime > 2f) { enemyAvatar.lastTargetConfirmTime = Time.time; EnemyTargetPacket packet3 = new EnemyTargetPacket { EnemyName = packet.EnemyName, TargetPlayerId = LocalPlayerId, ControllerId = LocalPlayerId }; SendPacket(EnemySyncPacketId.EnemyTarget, (IPacketData)(object)packet3); } return; } if (enemyAvatar.isController && enemyAvatar.controllerId == LocalPlayerId && packet.ControllerId != LocalPlayerId) { Debug.Log((object)$"[EnemySync] Yielding control of '{packet.EnemyName}' to new controller {packet.ControllerId}"); } } enemyAvatar.SetTargetAndControllerLocal(packet.TargetPlayerId, packet.ControllerId); } private void HandleEnemyFsmState(EnemyFsmStatePacket packet) { //IL_00bd: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(packet.EnemyName) || string.IsNullOrEmpty(packet.FsmName) || DeadEnemies.Contains(packet.EnemyName)) { return; } EnemyAvatar enemyAvatar = FindEnemyAvatar(packet.EnemyName); if (!((Object)(object)enemyAvatar != (Object)null)) { return; } if (enemyAvatar.isBoss) { if ((Object)(object)HeroController.instance != (Object)null && HeroController.instance.cState.dead) { return; } enemyAvatar.spawnDelayTimer = 0f; enemyAvatar.hasStartedMovingNatively = true; if (enemyAvatar.isController) { return; } } Vector2 value = default(Vector2); ((Vector2)(ref value))..ctor(packet.Position.X, packet.Position.Y); enemyAvatar.SetFsmState(packet.FsmName, packet.StateName, value, packet.ScaleX); } private void HandleEnemyTakeDamage(EnemyTakeDamagePacket packet) { //IL_0061: 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_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0106: 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_0189: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) EnemyAvatar enemyAvatar = FindEnemyAvatar(packet.EnemyName); if (!((Object)(object)enemyAvatar != (Object)null) || (enemyAvatar.isBoss && enemyAvatar.spawnDelayTimer > 0f)) { return; } GameObject gameObject = ((Component)enemyAvatar).gameObject; if (enemyAvatar.isController) { HealthManager component = gameObject.GetComponent(); if (!((Object)(object)component != (Object)null)) { return; } HitInstance val = new HitInstance { Source = gameObject, DamageDealt = packet.DamageDealt, Direction = packet.Direction, AttackType = (AttackTypes)packet.AttackType, Multiplier = packet.Multiplier, MagnitudeMultiplier = packet.MagnitudeMultiplier, NailElement = (NailElements)packet.NailElement, NonLethal = packet.NonLethal, CriticalHit = packet.CriticalHit, CanWeakHit = packet.CanWeakHit, DamageScalingLevel = packet.DamageScalingLevel, SpecialType = (SpecialTypes)packet.SpecialType, IsHeroDamage = false }; EnemyHitHandler enemyHitHandler = default(EnemyHitHandler); if (gameObject.TryGetComponent(ref enemyHitHandler)) { enemyHitHandler.SuppressNextHpSync = true; } HealthPatches.IsApplyingRemoteDamage = true; try { component.TakeDamage(val); } catch { } finally { HealthPatches.IsApplyingRemoteDamage = false; } EnemyHpPacket packet2 = new EnemyHpPacket { EnemyName = ((!string.IsNullOrEmpty(enemyAvatar.enemyName)) ? enemyAvatar.enemyName : ((Object)gameObject).name), Hp = component.hp }; SendPacket(EnemySyncPacketId.EnemyHp, (IPacketData)(object)packet2); return; } try { EnemyHitEffectsRegular component2 = gameObject.GetComponent(); if ((Object)(object)component2 != (Object)null) { HitInstance val2 = new HitInstance { Source = gameObject, DamageDealt = 0, Direction = packet.Direction, AttackType = (AttackTypes)packet.AttackType, IsHeroDamage = true }; component2.ReceiveHitEffect(val2); } SpriteFlash val3 = gameObject.GetComponent() ?? gameObject.GetComponentInChildren(true); if ((Object)(object)val3 != (Object)null) { MethodInfo methodInfo = ((object)val3).GetType().GetMethod("flashWhiteQuick", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? ((object)val3).GetType().GetMethod("flashArmoured", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (methodInfo != null) { methodInfo.Invoke(val3, null); } else { val3.flashInfected(); } } } catch { } } private void HandleEnemyHp(EnemyHpPacket packet) { EnemyAvatar enemyAvatar = FindEnemyAvatar(packet.EnemyName); if (!((Object)(object)enemyAvatar != (Object)null) || (!enemyAvatar.isBoss && enemyAvatar.isController) || (enemyAvatar.isBoss && enemyAvatar.spawnDelayTimer > 0f)) { return; } HealthManager component = ((Component)enemyAvatar).GetComponent(); if ((Object)(object)component != (Object)null) { component.hp = packet.Hp; if (packet.Hp <= 0) { HandleEnemyDie(new EnemyDiePacket { EnemyName = packet.EnemyName }); } } } private void HandleEnemyDie(EnemyDiePacket packet) { //IL_0366: Unknown result type (might be due to invalid IL or missing references) //IL_039d: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Unknown result type (might be due to invalid IL or missing references) //IL_02df: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(packet.EnemyName)) { return; } Debug.Log((object)("[EnemySync] Received Die update for '" + packet.EnemyName + "'")); EnemyAvatar enemyAvatar = FindEnemyAvatar(packet.EnemyName); if ((Object)(object)enemyAvatar == (Object)null) { string text = BossSyncManager.NormalizePath(packet.EnemyName); HealthManager[] array = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (HealthManager val in array) { if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).gameObject != (Object)null && ((Component)val).gameObject.activeInHierarchy) { string fullScenePath = BossSyncManager.GetFullScenePath(((Component)val).transform); string text2 = BossSyncManager.NormalizePath(fullScenePath); if (((Object)((Component)val).gameObject).name == packet.EnemyName || fullScenePath == packet.EnemyName || (!string.IsNullOrEmpty(text) && text2 == text)) { enemyAvatar = ((Component)val).gameObject.GetComponent() ?? ((Component)val).gameObject.AddComponent(); enemyAvatar.enemyName = packet.EnemyName; break; } } } } if ((Object)(object)enemyAvatar != (Object)null && !((Component)enemyAvatar).gameObject.activeInHierarchy) { Debug.Log((object)("[EnemySync] Ignored Die update for '" + packet.EnemyName + "' because matching scene object is inactive (dormant / future wave enemy).")); return; } bool num = ((Object)(object)enemyAvatar != (Object)null && (enemyAvatar.isBoss || enemyAvatar.IsHazardOrSummonOrProjectile())) || packet.EnemyName.Contains("_fs_"); bool flag = packet.EnemyName.StartsWith("scene:") || ((Object)(object)enemyAvatar != (Object)null && (enemyAvatar.enemyName.StartsWith("scene:") || enemyAvatar.enemyName.ToLower().Contains("battle") || enemyAvatar.enemyName.ToLower().Contains("wave"))); if (!num && !flag) { DeadEnemies.Add(packet.EnemyName); Scene activeScene = SceneManager.GetActiveScene(); string name = ((Scene)(ref activeScene)).name; if (!string.IsNullOrEmpty(name)) { if (!SceneDeadEnemies.TryGetValue(name, out HashSet value)) { value = new HashSet(); SceneDeadEnemies[name] = value; } value.Add(packet.EnemyName); } } if (!((Object)(object)enemyAvatar != (Object)null) || enemyAvatar.isController) { return; } IsApplyingRemoteDeath = true; try { enemyAvatar.noRespondCounter = -1f; enemyAvatar.ReEnableFSMs(restoreLastState: false); HealthManager component = ((Component)enemyAvatar).GetComponent(); if ((Object)(object)component != (Object)null) { component.hp = 0; float? num2 = ((packet.AttackDirection != 0f) ? new float?(packet.AttackDirection) : ((float?)null)); AttackTypes val2 = (AttackTypes)((packet.AttackType < 0 || packet.AttackType > 10) ? 1 : packet.AttackType); try { component.Die(num2, val2, (NailElements)0, (GameObject)null, true, 1f, false, false); } catch (Exception ex) { Debug.LogWarning((object)("[EnemySync] Exception in remote hm.Die for '" + packet.EnemyName + "': " + ex.Message)); } if (packet.HasCorpseSnapshot) { Rigidbody2D val3 = ((Component)enemyAvatar).GetComponent() ?? ((Component)enemyAvatar).GetComponentInChildren(); if ((Object)(object)val3 != (Object)null) { val3.simulated = true; val3.bodyType = (RigidbodyType2D)1; val3.position = new Vector2(packet.CorpsePosition.X, packet.CorpsePosition.Y); val3.rotation = packet.CorpseRotation; val3.bodyType = (RigidbodyType2D)0; val3.linearVelocity = new Vector2(packet.CorpseVelocity.X, packet.CorpseVelocity.Y); } } } else { ((Component)enemyAvatar).gameObject.SetActive(false); } } finally { IsApplyingRemoteDeath = false; } } private void HandleSpawnProjectile(SpawnProjectilePacket packet) { //IL_034d: Unknown result type (might be due to invalid IL or missing references) //IL_035b: Unknown result type (might be due to invalid IL or missing references) //IL_03a2: Unknown result type (might be due to invalid IL or missing references) //IL_03a7: Unknown result type (might be due to invalid IL or missing references) //IL_03b6: Unknown result type (might be due to invalid IL or missing references) //IL_03bd: Unknown result type (might be due to invalid IL or missing references) //IL_03c4: Unknown result type (might be due to invalid IL or missing references) //IL_024a: 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_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0718: Unknown result type (might be due to invalid IL or missing references) //IL_017b: 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_0323: Unknown result type (might be due to invalid IL or missing references) //IL_0328: Unknown result type (might be due to invalid IL or missing references) //IL_032d: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_0330: Unknown result type (might be due to invalid IL or missing references) //IL_0332: Unknown result type (might be due to invalid IL or missing references) //IL_04a4: Unknown result type (might be due to invalid IL or missing references) //IL_050e: Unknown result type (might be due to invalid IL or missing references) //IL_0510: Unknown result type (might be due to invalid IL or missing references) //IL_051c: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(packet.PrefabName) || string.IsNullOrEmpty(packet.UniqueName) || DeadEnemies.Contains(packet.UniqueName)) { return; } ushort num = ushort.MaxValue; if (packet.UniqueName.Contains("_fs_")) { string[] array = packet.UniqueName.Split(new string[1] { "_fs_" }, StringSplitOptions.None); if (array.Length >= 2) { string[] array2 = array[1].Split('_'); if (array2.Length >= 1 && ushort.TryParse(array2[0], out var result)) { num = result; } } } EnemyAvatar enemyAvatar = FindEnemyAvatar(packet.UniqueName, autoSpawn: false, null, excludeBosses: true); if ((Object)(object)enemyAvatar != (Object)null && !enemyAvatar.isBoss) { Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(packet.Position.X, packet.Position.Y, ((Component)enemyAvatar).transform.position.z); enemyAvatar.targetPosition = val; ((Component)enemyAvatar).transform.position = val; ((Component)enemyAvatar).transform.rotation = Quaternion.Euler(new Vector3(packet.Rotation.X, packet.Rotation.Y, packet.Rotation.Z)); Vector3 localScale = ((Component)enemyAvatar).transform.localScale; ((Component)enemyAvatar).transform.localScale = new Vector3(packet.ScaleX, localScale.y, localScale.z); ((Component)enemyAvatar).gameObject.SetActive(true); Rigidbody2D val2 = default(Rigidbody2D); if (((Component)enemyAvatar).TryGetComponent(ref val2)) { val2.position = Vector2.op_Implicit(val); if (packet.Velocity != (Vector2)null) { val2.linearVelocity = new Vector2(packet.Velocity.X, packet.Velocity.Y); } } if (string.IsNullOrEmpty(packet.ClipName)) { return; } tk2dSpriteAnimator val3 = ((Component)enemyAvatar).GetComponent() ?? ((Component)enemyAvatar).GetComponentInChildren(true); if ((Object)(object)val3 != (Object)null) { tk2dSpriteAnimationClip val4 = (((Object)(object)val3.Library != (Object)null) ? val3.Library.GetClipByName(packet.ClipName) : null); if (val4 != null) { val3.Play(val4); } else { val3.Play(packet.ClipName); } } return; } LastKnownPositions[packet.UniqueName] = new Vector3(packet.Position.X, packet.Position.Y, 0f); LastKnownActiveStates[packet.UniqueName] = true; if (num != ushort.MaxValue) { LastKnownControllers[packet.UniqueName] = num; LastKnownTargets[packet.UniqueName] = num; } GameObject val5 = FindPrefab(packet.PrefabName); if ((Object)(object)val5 == (Object)null) { EnemyAvatar enemyAvatar2 = FindEnemyAvatar(packet.PrefabName, autoSpawn: false, null, excludeBosses: true); if ((Object)(object)enemyAvatar2 != (Object)null) { val5 = ((Component)enemyAvatar2).gameObject; } } if (!((Object)(object)val5 != (Object)null)) { return; } Vector3 val6 = default(Vector3); ((Vector3)(ref val6))..ctor(packet.Position.X, packet.Position.Y, 0f); Quaternion val7 = Quaternion.Euler(new Vector3(packet.Rotation.X, packet.Rotation.Y, packet.Rotation.Z)); GameObject val8; try { val8 = Object.Instantiate(val5, val6, val7); } catch { try { val8 = Object.Instantiate(val5); val8.transform.position = val6; val8.transform.rotation = val7; } catch (Exception ex) { Debug.LogWarning((object)("[EnemySync] Failed to instantiate projectile prefab '" + packet.PrefabName + "': " + ex.Message)); return; } } ((Object)val8).name = packet.UniqueName; Vector3 localScale2 = val8.transform.localScale; val8.transform.localScale = new Vector3(packet.ScaleX, localScale2.y, localScale2.z); val8.SetActive(true); Transform[] componentsInChildren = val8.GetComponentsInChildren(true); foreach (Transform val9 in componentsInChildren) { if ((Object)(object)val9 != (Object)null) { ((Component)val9).gameObject.SetActive(true); } } Renderer[] componentsInChildren2 = val8.GetComponentsInChildren(true); foreach (Renderer val10 in componentsInChildren2) { if ((Object)(object)val10 != (Object)null) { val10.enabled = true; } } Rigidbody2D component = val8.GetComponent(); if ((Object)(object)component != (Object)null) { if (packet.Velocity != (Vector2)null && (packet.Velocity.X != 0f || packet.Velocity.Y != 0f)) { component.linearVelocity = new Vector2(packet.Velocity.X, packet.Velocity.Y); } else { component.bodyType = (RigidbodyType2D)1; } } EnemyAvatar enemyAvatar3 = val8.GetComponent() ?? val8.AddComponent(); enemyAvatar3.enemyName = packet.UniqueName; enemyAvatar3.controllerId = num; enemyAvatar3.TargetPlayerId = num; enemyAvatar3.isController = num != ushort.MaxValue && num == LocalPlayerId; enemyAvatar3.isBoss = false; enemyAvatar3.targetPosition = val6; ((Component)enemyAvatar3).transform.position = val6; enemyAvatar3.targetActive = true; enemyAvatar3.hasStartedMovingNatively = true; val8.SetActive(true); if (!enemyAvatar3.isController) { DamageHero[] componentsInChildren3 = val8.GetComponentsInChildren(true); foreach (DamageHero val11 in componentsInChildren3) { if ((Object)(object)val11 != (Object)null) { ((Behaviour)val11).enabled = false; } } Collider2D[] componentsInChildren4 = val8.GetComponentsInChildren(true); foreach (Collider2D val12 in componentsInChildren4) { if ((Object)(object)val12 != (Object)null && val12.isTrigger) { ((Behaviour)val12).enabled = false; } } } if ((Object)(object)val8.GetComponentInChildren(true) != (Object)null && (Object)(object)val8.GetComponent() == (Object)null) { val8.AddComponent(); } EnemyAvatar.ActiveAvatars[packet.UniqueName] = enemyAvatar3; PlayMakerFSM[] componentsInChildren5 = val8.GetComponentsInChildren(true); foreach (PlayMakerFSM val13 in componentsInChildren5) { if (!((Object)(object)val13 != (Object)null) || val13.Fsm == null) { continue; } if (enemyAvatar3.isController) { ((Behaviour)val13).enabled = true; try { val13.Fsm.Start(); } catch { } } else { ((Behaviour)val13).enabled = false; } } if (!string.IsNullOrEmpty(packet.ClipName)) { tk2dSpriteAnimator val14 = val8.GetComponent() ?? val8.GetComponentInChildren(true); if ((Object)(object)val14 != (Object)null) { tk2dSpriteAnimationClip val15 = (((Object)(object)val14.Library != (Object)null) ? val14.Library.GetClipByName(packet.ClipName) : null); if (val15 != null) { val14.Play(val15); } else { val14.Play(packet.ClipName); } } } if (enemyAvatar3.isController) { enemyAvatar3.ReEnableFSMs(); } if (!enemyAvatar3.isController && packet.UniqueName.Contains("_fs_")) { Object.Destroy((Object)(object)val8, 12f); } Debug.Log((object)$"[EnemySync] Instantiated summon/projectile '{packet.UniqueName}' from prefab '{packet.PrefabName}' at {val6} (ScaleX: {packet.ScaleX}, Clip: '{packet.ClipName}')"); } } [BepInPlugin("bg52.enemysync.ssmp", "BasicEnemySync", "1.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class EnemySyncingPlugin : BaseUnityPlugin { private void Awake() { try { ClientAddon.RegisterAddon((ClientAddon)(object)new ClientAddon()); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[EnemySync] ClientAddon registered successfully."); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[EnemySync] ClientAddon registration warning: " + ex.Message)); } try { ServerAddon.RegisterAddon((ServerAddon)(object)new ServerAddon()); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[EnemySync] ServerAddon registered successfully."); } catch (Exception ex2) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[EnemySync] ServerAddon registration warning: " + ex2.Message)); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"[EnemySync] Plugin loaded. Client and Server addons registered with SSMP."); } } public class ServerAddon : ServerAddon { private IServerApi? _serverApi; private IServerAddonNetworkSender? _serverSender; private readonly HashSet _knownBosses = new HashSet(); private readonly Dictionary> _bossSubscriptions = new Dictionary>(); private readonly Dictionary _sceneOwners = new Dictionary(); public static ServerAddon? Instance { get; private set; } protected override string Name => "EnemySyncingAddon"; protected override string Version => "1.0.1"; public override bool NeedsNetwork => true; public override uint ApiVersion => 1u; public override void Initialize(IServerApi serverApi) { Instance = this; _serverApi = serverApi; IServerAddonNetworkReceiver networkReceiver = serverApi.NetServer.GetNetworkReceiver((ServerAddon)(object)this, (Func)InstantiatePacket); _serverSender = serverApi.NetServer.GetNetworkSender((ServerAddon)(object)this); networkReceiver.RegisterPacketHandler(EnemySyncPacketId.EnemyPosition, (GenericServerPacketHandler)delegate(ushort id, EnemyPositionPacket p) { ForwardToScene(id, EnemySyncPacketId.EnemyPosition, p); }); networkReceiver.RegisterPacketHandler(EnemySyncPacketId.EnemyAnimation, (GenericServerPacketHandler)delegate(ushort id, EnemyAnimationPacket p) { ForwardToScene(id, EnemySyncPacketId.EnemyAnimation, p); }); networkReceiver.RegisterPacketHandler(EnemySyncPacketId.EnemyTarget, (GenericServerPacketHandler)delegate(ushort id, EnemyTargetPacket p) { ForwardToScene(id, EnemySyncPacketId.EnemyTarget, p); }); networkReceiver.RegisterPacketHandler(EnemySyncPacketId.EnemyTakeDamage, (GenericServerPacketHandler)delegate(ushort id, EnemyTakeDamagePacket p) { ForwardToScene(id, EnemySyncPacketId.EnemyTakeDamage, p); }); networkReceiver.RegisterPacketHandler(EnemySyncPacketId.EnemyHp, (GenericServerPacketHandler)delegate(ushort id, EnemyHpPacket p) { ForwardToScene(id, EnemySyncPacketId.EnemyHp, p); }); networkReceiver.RegisterPacketHandler(EnemySyncPacketId.EnemyDie, (GenericServerPacketHandler)delegate(ushort id, EnemyDiePacket p) { ForwardToScene(id, EnemySyncPacketId.EnemyDie, p); }); networkReceiver.RegisterPacketHandler(EnemySyncPacketId.SpawnProjectile, (GenericServerPacketHandler)delegate(ushort id, SpawnProjectilePacket p) { ForwardToScene(id, EnemySyncPacketId.SpawnProjectile, p); }); networkReceiver.RegisterPacketHandler(EnemySyncPacketId.EnemyFsmState, (GenericServerPacketHandler)delegate(ushort id, EnemyFsmStatePacket p) { ForwardToScene(id, EnemySyncPacketId.EnemyFsmState, p); }); networkReceiver.RegisterPacketHandler(EnemySyncPacketId.RequestPlayerId, (GenericServerPacketHandler)HandleRequestPlayerId); networkReceiver.RegisterPacketHandler(EnemySyncPacketId.BossSyncRequest, (GenericServerPacketHandler)HandleBossSyncRequest); networkReceiver.RegisterPacketHandler(EnemySyncPacketId.PlayerCocoon, (GenericServerPacketHandler)delegate(ushort id, PlayerCocoonPacket p) { ForwardToScene(id, EnemySyncPacketId.PlayerCocoon, p); }); networkReceiver.RegisterPacketHandler(EnemySyncPacketId.CocoonDamage, (GenericServerPacketHandler)delegate(ushort id, CocoonDamagePacket p) { ForwardToScene(id, EnemySyncPacketId.CocoonDamage, p); }); networkReceiver.RegisterPacketHandler(EnemySyncPacketId.VerifyEnemyDieRequest, (GenericServerPacketHandler)HandleVerifyEnemyDieRequest); serverApi.ServerManager.PlayerEnterSceneEvent += OnPlayerEnterScene; serverApi.ServerManager.PlayerLeaveSceneEvent += OnPlayerLeaveScene; } private void OnPlayerEnterScene(IServerPlayer player) { if (player != null && !string.IsNullOrEmpty(player.CurrentScene)) { UpdateSceneOwner(player.CurrentScene); } } private void OnPlayerLeaveScene(IServerPlayer player) { if (player != null && !string.IsNullOrEmpty(player.CurrentScene)) { UpdateSceneOwner(player.CurrentScene); } } public ushort GetSceneOwner(string sceneName) { if (string.IsNullOrEmpty(sceneName) || _serverApi == null) { return ushort.MaxValue; } List list = new List(); foreach (IServerPlayer player in _serverApi.ServerManager.Players) { if (player.CurrentScene == sceneName) { list.Add(player); } } if (list.Count == 0) { _sceneOwners.Remove(sceneName); return ushort.MaxValue; } if (_sceneOwners.TryGetValue(sceneName, out var currentOwner) && list.Exists((IServerPlayer p) => p.Id == currentOwner)) { return currentOwner; } list.Sort((IServerPlayer a, IServerPlayer b) => a.Id.CompareTo(b.Id)); ushort id = list[0].Id; _sceneOwners[sceneName] = id; SceneOwnerNotifyPacket sceneOwnerNotifyPacket = new SceneOwnerNotifyPacket { SceneOwnerId = id }; ushort[] array = list.ConvertAll((IServerPlayer p) => p.Id).ToArray(); _serverSender?.SendSingleData(EnemySyncPacketId.SceneOwnerNotify, (IPacketData)(object)sceneOwnerNotifyPacket, array); ((ServerAddon)this).Logger.Info($"[EnemySync] Assigned player {id} as Scene Owner for '{sceneName}'"); return id; } private void UpdateSceneOwner(string sceneName) { GetSceneOwner(sceneName); } private void HandleVerifyEnemyDieRequest(ushort senderId, VerifyEnemyDieRequestPacket packet) { if (_serverApi == null || _serverSender == null) { return; } IServerPlayer player = _serverApi.ServerManager.GetPlayer(senderId); if (player != null) { ushort sceneOwner = GetSceneOwner(player.CurrentScene); packet.RequesterPlayerId = senderId; if (sceneOwner != ushort.MaxValue) { ((ServerAddon)this).Logger.Info($"[EnemySync] Forwarding death verification request for '{packet.EnemyName}' from player {senderId} to Scene Owner {sceneOwner}"); _serverSender.SendSingleData(EnemySyncPacketId.VerifyEnemyDieRequest, (IPacketData)(object)packet, sceneOwner); } } } private void HandleRequestPlayerId(ushort senderId, RequestPlayerIdPacket packet) { if (_serverSender != null && _serverApi != null) { PlayerIdNotifyPacket playerIdNotifyPacket = new PlayerIdNotifyPacket { AssignedPlayerId = senderId }; _serverSender.SendSingleData(EnemySyncPacketId.PlayerIdNotify, (IPacketData)(object)playerIdNotifyPacket, senderId); ((ServerAddon)this).Logger.Info($"[EnemySync] Sent player ID notification {senderId} to client"); IServerPlayer player = _serverApi.ServerManager.GetPlayer(senderId); if (player != null && !string.IsNullOrEmpty(player.CurrentScene)) { UpdateSceneOwner(player.CurrentScene); } } } private void HandleBossSyncRequest(ushort senderId, BossSyncRequestPacket packet) { if (string.IsNullOrEmpty(packet.EnemyName)) { return; } lock (_knownBosses) { _knownBosses.Add(packet.EnemyName); } lock (_bossSubscriptions) { HashSet value2; if (packet.Subscribe) { if (!_bossSubscriptions.TryGetValue(packet.EnemyName, out HashSet value)) { value = new HashSet(); _bossSubscriptions[packet.EnemyName] = value; } value.Add(senderId); ((ServerAddon)this).Logger.Info($"[EnemySync] Player {senderId} subscribed to boss sync for '{packet.EnemyName}'"); } else if (_bossSubscriptions.TryGetValue(packet.EnemyName, out value2)) { value2.Remove(senderId); ((ServerAddon)this).Logger.Info($"[EnemySync] Player {senderId} unsubscribed from boss sync for '{packet.EnemyName}'"); } } ForwardToScene(senderId, EnemySyncPacketId.BossSyncRequest, packet); } private IPacketData InstantiatePacket(EnemySyncPacketId id) { return (IPacketData)(id switch { EnemySyncPacketId.EnemyPosition => new PacketDataCollection(), EnemySyncPacketId.EnemyAnimation => new EnemyAnimationPacket(), EnemySyncPacketId.EnemyTarget => new EnemyTargetPacket(), EnemySyncPacketId.EnemyTakeDamage => new EnemyTakeDamagePacket(), EnemySyncPacketId.EnemyHp => new EnemyHpPacket(), EnemySyncPacketId.EnemyDie => new EnemyDiePacket(), EnemySyncPacketId.SpawnProjectile => new SpawnProjectilePacket(), EnemySyncPacketId.RequestPlayerId => new RequestPlayerIdPacket(), EnemySyncPacketId.PlayerIdNotify => new PlayerIdNotifyPacket(), EnemySyncPacketId.EnemyFsmState => new EnemyFsmStatePacket(), EnemySyncPacketId.BossSyncRequest => new BossSyncRequestPacket(), EnemySyncPacketId.PlayerCocoon => new PlayerCocoonPacket(), EnemySyncPacketId.CocoonDamage => new CocoonDamagePacket(), EnemySyncPacketId.SceneOwnerNotify => new SceneOwnerNotifyPacket(), EnemySyncPacketId.VerifyEnemyDieRequest => new VerifyEnemyDieRequestPacket(), _ => throw new ArgumentException("Unknown packet ID"), }); } private void ForwardToScene(ushort senderId, EnemySyncPacketId packetId, TPacketData packet) where TPacketData : IPacketData, new() { if (_serverApi == null || _serverSender == null) { return; } IServerPlayer player = _serverApi.ServerManager.GetPlayer(senderId); if (player == null) { return; } string currentScene = player.CurrentScene; string text = string.Empty; PropertyInfo property = ((object)packet/*cast due to .constrained prefix*/).GetType().GetProperty("EnemyName"); if (property != null) { text = (property.GetValue(packet) as string) ?? string.Empty; } else { PropertyInfo property2 = ((object)packet/*cast due to .constrained prefix*/).GetType().GetProperty("UniqueName"); if (property2 != null) { text = (property2.GetValue(packet) as string) ?? string.Empty; } } bool flag = false; if (!string.IsNullOrEmpty(text)) { lock (_knownBosses) { flag = _knownBosses.Contains(text); } } List list = new List(); foreach (IServerPlayer player2 in _serverApi.ServerManager.Players) { if (player2.Id == senderId || !(player2.CurrentScene == currentScene)) { continue; } if (flag) { bool flag2 = false; lock (_bossSubscriptions) { if (_bossSubscriptions.TryGetValue(text, out HashSet value)) { flag2 = value.Contains(player2.Id); } } if (!flag2) { continue; } } list.Add(player2.Id); } if (list.Count > 0) { if (packetId == EnemySyncPacketId.EnemyPosition) { _serverSender.SendCollectionData(packetId, packet, list.ToArray()); } else { _serverSender.SendSingleData(packetId, (IPacketData)(object)packet, list.ToArray()); } } } } public class SyncManager : MonoBehaviour { public static float SuicideHoldTimer = 0f; private GameObject? suicideUiGo; private Text? cocoonUiText; private Text? suicideHintText; private static Font? _defaultFont; private float hazardScanTimer; private float restorationTimer; private static readonly Dictionary OriginalTextColors = new Dictionary(); public static SyncManager? Instance { get; private set; } private void Awake() { if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this) { Object.Destroy((Object)(object)((Component)this).gameObject); return; } Instance = this; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); } public static Font GetDefaultFont() { if ((Object)(object)_defaultFont != (Object)null) { return _defaultFont; } try { _defaultFont = Font.CreateDynamicFontFromOSFont("Arial", 28); } catch { } if ((Object)(object)_defaultFont == (Object)null) { Font[] array = Resources.FindObjectsOfTypeAll(); foreach (Font val in array) { if ((Object)(object)val != (Object)null) { _defaultFont = val; break; } } } return _defaultFont ?? Resources.GetBuiltinResource("Arial.ttf"); } private void Update() { //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) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) if (ClientAddon.Instance == null || ClientAddon.Instance.Api == null || !ClientAddon.Instance.Api.NetClient.IsConnected) { return; } if (ClientAddon.IsLocalPlayerCocooned && (Object)(object)HeroController.instance != (Object)null) { if (ClientAddon.AreAllPlayersCocooned()) { Debug.Log((object)"[EnemySync] All players in scene are cocooned or no survivors left. Triggering team wipe."); ClientAddon.TriggerNativeDeath(); return; } HeroController instance = HeroController.instance; instance.acceptingInput = false; if (ClientAddon.LocalCocoonSafePosition != Vector3.zero) { instance.transform.position = ClientAddon.LocalCocoonSafePosition; Rigidbody2D val = default(Rigidbody2D); if (((Component)instance).TryGetComponent(ref val)) { val.bodyType = (RigidbodyType2D)1; val.linearVelocity = Vector2.zero; val.angularVelocity = 0f; } } if (Input.GetKeyDown((KeyCode)27)) { instance.acceptingInput = true; } } if (ClientAddon.IsLocalPlayerCocooned) { bool flag = false; if (Input.GetKey((KeyCode)9) || Input.GetKey((KeyCode)109) || Input.GetKey((KeyCode)27)) { flag = true; } if ((Object)(object)ManagerSingleton.Instance != (Object)null && ManagerSingleton.Instance.inputActions != null) { PlayerAction openInventoryMap = ManagerSingleton.Instance.inputActions.OpenInventoryMap; PlayerAction quickMap = ManagerSingleton.Instance.inputActions.QuickMap; if ((openInventoryMap != null && (((OneAxisInputControl)openInventoryMap).WasPressed || ((OneAxisInputControl)openInventoryMap).IsPressed)) || (quickMap != null && (((OneAxisInputControl)quickMap).WasPressed || ((OneAxisInputControl)quickMap).IsPressed))) { flag = true; } } if (flag) { SuicideHoldTimer += Time.deltaTime; if (SuicideHoldTimer >= 1.5f) { SuicideHoldTimer = 0f; Debug.Log((object)"[EnemySync] Respawn hold threshold met. Triggering suicide respawn."); ClientAddon.TriggerNativeDeath(); } } else { SuicideHoldTimer = 0f; } UpdateSuicideUi(); } else { SuicideHoldTimer = 0f; HideSuicideUi(); } HealthManager[] array = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (HealthManager val2 in array) { if ((Object)(object)val2 != (Object)null && (Object)(object)((Component)val2).gameObject != (Object)null && ((Component)val2).gameObject.activeInHierarchy) { if ((Object)(object)((Component)val2).gameObject.GetComponent() == (Object)null) { ((Component)val2).gameObject.AddComponent(); } if ((Object)(object)((Component)val2).gameObject.GetComponent() == (Object)null) { EnemyAvatar enemyAvatar = ((Component)val2).gameObject.AddComponent(); string enemyName = ((((Object)((Component)val2).gameObject).name.Contains("_fs_") || ((Object)((Component)val2).gameObject).name.StartsWith("scene:")) ? ((Object)((Component)val2).gameObject).name : BossSyncManager.GetFullScenePath(((Component)val2).transform)); enemyAvatar.enemyName = enemyName; } } } ScanAndSyncSceneHazards(); CheckAndRestoreMissingEnemies(); UpdateBossTargetUsernameTags(); } private void ScanAndSyncSceneHazards() { //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) hazardScanTimer += Time.deltaTime; if (hazardScanTimer < 1f) { return; } hazardScanTimer = 0f; if (ClientAddon.Instance == null || !ClientAddon.Instance.IsSceneOwner) { return; } Scene activeScene = SceneManager.GetActiveScene(); if (!((Scene)(ref activeScene)).IsValid()) { return; } GameObject[] rootGameObjects = ((Scene)(ref activeScene)).GetRootGameObjects(); foreach (GameObject val in rootGameObjects) { if ((Object)(object)val == (Object)null || !val.activeInHierarchy) { continue; } Transform[] componentsInChildren = val.GetComponentsInChildren(true); foreach (Transform val2 in componentsInChildren) { if ((Object)(object)val2 == (Object)null || (Object)(object)((Component)val2).gameObject == (Object)null) { continue; } GameObject gameObject = ((Component)val2).gameObject; if ((Object)(object)gameObject.GetComponent() != (Object)null && !EnemyAvatar.IsBackgroundOrAmbientObject(gameObject) && (!((Object)(object)gameObject.transform.parent != (Object)null) || (!((Object)(object)gameObject.GetComponentInParent() != (Object)null) && !((Object)(object)((Component)gameObject.transform.parent).GetComponentInParent() != (Object)null)))) { string text = ((Object)gameObject).name.ToLower(); if (!text.Contains("hit") && !text.Contains("stab") && !text.Contains("slash") && !text.Contains("attack") && !text.Contains("bite") && !text.Contains("punch") && !text.Contains("range") && !text.Contains("detector") && !text.Contains("trigger") && !text.Contains("alert") && !text.Contains("helper") && !text.Contains("parry") && !text.Contains("patrol") && !text.Contains("turn") && !text.Contains("sight") && (Object)(object)gameObject.GetComponent() == (Object)null) { EnemyAvatar enemyAvatar = gameObject.AddComponent(); enemyAvatar.enemyName = ((Object)gameObject).name; enemyAvatar.controllerId = ClientAddon.Instance.LocalPlayerId; enemyAvatar.TargetPlayerId = ClientAddon.Instance.LocalPlayerId; enemyAvatar.isController = true; } } } } } private void CheckAndRestoreMissingEnemies() { //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_0069: Unknown result type (might be due to invalid IL or missing references) restorationTimer += Time.deltaTime; if (restorationTimer < 3f) { return; } restorationTimer = 0f; if (ClientAddon.Instance == null) { return; } Scene activeScene = SceneManager.GetActiveScene(); string name = ((Scene)(ref activeScene)).name; foreach (KeyValuePair lastKnownPosition in ClientAddon.Instance.LastKnownPositions) { string key = lastKnownPosition.Key; _ = lastKnownPosition.Value; if (key.Contains("_fs_") || ClientAddon.DeadEnemies.Contains(key) || (!string.IsNullOrEmpty(name) && ClientAddon.SceneDeadEnemies.TryGetValue(name, out HashSet value) && value.Contains(key))) { continue; } string text = key.ToLower(); if (!text.Contains("fader") && !text.Contains("fade") && !text.Contains("canvas") && !text.Contains("hud") && !text.Contains("camera")) { EnemyAvatar enemyAvatar = ClientAddon.Instance.FindEnemyAvatar(key); if ((Object)(object)enemyAvatar != (Object)null && (Object)(object)((Component)enemyAvatar).gameObject != (Object)null && !((Component)enemyAvatar).gameObject.activeSelf) { Debug.Log((object)("[EnemySync] Background routine restored missing enemy '" + key + "'")); ((Component)enemyAvatar).gameObject.SetActive(true); enemyAvatar.ReEnableFSMs(); } } } } private void UpdateBossTargetUsernameTags() { //IL_062d: Unknown result type (might be due to invalid IL or missing references) //IL_0626: Unknown result type (might be due to invalid IL or missing references) //IL_05e9: Unknown result type (might be due to invalid IL or missing references) //IL_05e0: Unknown result type (might be due to invalid IL or missing references) //IL_05e5: Unknown result type (might be due to invalid IL or missing references) //IL_05f2: Unknown result type (might be due to invalid IL or missing references) //IL_05fb: Unknown result type (might be due to invalid IL or missing references) //IL_05fd: Unknown result type (might be due to invalid IL or missing references) //IL_05f0: Unknown result type (might be due to invalid IL or missing references) //IL_060d: Unknown result type (might be due to invalid IL or missing references) //IL_0609: Unknown result type (might be due to invalid IL or missing references) //IL_04e3: Unknown result type (might be due to invalid IL or missing references) //IL_04e8: Unknown result type (might be due to invalid IL or missing references) //IL_04f1: Unknown result type (might be due to invalid IL or missing references) //IL_04f3: Unknown result type (might be due to invalid IL or missing references) //IL_0521: Unknown result type (might be due to invalid IL or missing references) //IL_051a: Unknown result type (might be due to invalid IL or missing references) //IL_0503: Unknown result type (might be due to invalid IL or missing references) //IL_04ff: Unknown result type (might be due to invalid IL or missing references) //IL_03e1: Unknown result type (might be due to invalid IL or missing references) //IL_03e6: Unknown result type (might be due to invalid IL or missing references) //IL_03ef: Unknown result type (might be due to invalid IL or missing references) //IL_03f1: Unknown result type (might be due to invalid IL or missing references) //IL_041f: Unknown result type (might be due to invalid IL or missing references) //IL_0418: Unknown result type (might be due to invalid IL or missing references) //IL_0401: Unknown result type (might be due to invalid IL or missing references) //IL_03fd: Unknown result type (might be due to invalid IL or missing references) if (ClientAddon.Instance == null || ClientAddon.Instance.Api == null || !ClientAddon.Instance.Api.NetClient.IsConnected) { return; } EnemyAvatar activeBoss = BossSyncManager.GetActiveBoss(); ushort num = (((Object)(object)activeBoss != (Object)null && activeBoss.isBoss && (Object)(object)((Component)activeBoss).gameObject != (Object)null && ((Component)activeBoss).gameObject.activeInHierarchy && activeBoss.controllerId != ushort.MaxValue && activeBoss.hasStartedMovingNatively && activeBoss.TargetPlayerId != ushort.MaxValue) ? activeBoss.TargetPlayerId : ushort.MaxValue); List<(ushort, string, GameObject)> list = new List<(ushort, string, GameObject)>(); ushort localPlayerId = ClientAddon.Instance.LocalPlayerId; string item = ClientAddon.Instance.Api.ClientManager.Username ?? ""; if ((Object)(object)HeroController.instance != (Object)null && (Object)(object)((Component)HeroController.instance).gameObject != (Object)null) { list.Add((localPlayerId, item, ((Component)HeroController.instance).gameObject)); } foreach (IClientPlayer item5 in ClientAddon.Instance.GetPlayersInScene()) { GameObject val = item5.PlayerObject; if ((Object)(object)val == (Object)null) { try { PropertyInfo property = ((object)item5).GetType().GetProperty("PlayerContainer"); if (property != null) { object? value = property.GetValue(item5); val = (GameObject)((value is GameObject) ? value : null); } } catch { } } if ((Object)(object)val != (Object)null) { list.Add((item5.Id, item5.Username ?? "", val)); } } foreach (var item6 in list) { ushort item2 = item6.Item1; string item3 = item6.Item2; GameObject item4 = item6.Item3; bool flag = num != ushort.MaxValue && item2 == num; Transform transform = item4.transform; List list2 = new List { transform }; if ((Object)(object)transform.parent != (Object)null && !((Object)transform.parent).name.Contains("Scene") && !((Object)transform.parent).name.Contains("Root")) { list2.Add(transform.parent); } foreach (Transform item7 in list2) { bool num2; if (item2 != localPlayerId) { if (ClientAddon.Instance == null) { goto IL_0282; } num2 = ClientAddon.Instance.CocoonedPlayers.Contains(item2); } else { num2 = ClientAddon.IsLocalPlayerCocooned; } if (!num2) { goto IL_0282; } goto IL_02f4; IL_02f4: Text[] componentsInChildren = ((Component)item7).GetComponentsInChildren(true); foreach (Text val2 in componentsInChildren) { if ((Object)(object)val2 == (Object)null) { continue; } string text = ((Object)((Component)val2).gameObject).name.ToLower(); if (!text.Contains("suicide") && !text.Contains("cocoon") && !text.Contains("hud") && !text.Contains("health") && (text.Contains("name") || text.Contains("tag") || text.Contains("label") || text.Contains("username") || (!string.IsNullOrEmpty(item3) && val2.text != null && val2.text.Contains(item3)))) { if (!OriginalTextColors.ContainsKey((Component)(object)val2)) { Color color = ((Graphic)val2).color; OriginalTextColors[(Component)(object)val2] = ((color == Color.red) ? Color.white : color); } ((Graphic)val2).color = (flag ? Color.red : OriginalTextColors[(Component)(object)val2]); } } TextMesh[] componentsInChildren2 = ((Component)item7).GetComponentsInChildren(true); foreach (TextMesh val3 in componentsInChildren2) { if ((Object)(object)val3 == (Object)null) { continue; } string text2 = ((Object)((Component)val3).gameObject).name.ToLower(); if (text2.Contains("name") || text2.Contains("tag") || text2.Contains("label") || text2.Contains("username") || (!string.IsNullOrEmpty(item3) && val3.text != null && val3.text.Contains(item3))) { if (!OriginalTextColors.ContainsKey((Component)(object)val3)) { Color color2 = val3.color; OriginalTextColors[(Component)(object)val3] = ((color2 == Color.red) ? Color.white : color2); } val3.color = (flag ? Color.red : OriginalTextColors[(Component)(object)val3]); } } Component[] componentsInChildren3 = ((Component)item7).GetComponentsInChildren(true); foreach (Component val4 in componentsInChildren3) { if ((Object)(object)val4 == (Object)null) { continue; } string name = ((object)val4).GetType().Name; if (!name.Contains("TextMeshPro") && !name.Contains("TMP_Text")) { continue; } try { PropertyInfo property2 = ((object)val4).GetType().GetProperty("color"); if (property2 != null && property2.CanWrite) { if (!OriginalTextColors.ContainsKey(val4)) { Color val5 = ((property2.GetValue(val4) is Color val6) ? val6 : Color.white); OriginalTextColors[val4] = ((val5 == Color.red) ? Color.white : val5); } property2.SetValue(val4, flag ? Color.red : OriginalTextColors[val4]); } } catch { } } continue; IL_0282: Transform val7 = item7.Find("Username"); if ((Object)(object)val7 != (Object)null) { if (!((Component)val7).gameObject.activeSelf) { ((Component)val7).gameObject.SetActive(true); } Renderer[] componentsInChildren4 = ((Component)val7).GetComponentsInChildren(true); foreach (Renderer val8 in componentsInChildren4) { if ((Object)(object)val8 != (Object)null && !val8.enabled) { val8.enabled = true; } } } goto IL_02f4; } } } private void UpdateSuicideUi() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_005a: 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_0085: Expected O, but got Unknown //IL_00b9: 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_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Expected O, but got Unknown //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_025b: 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) if ((Object)(object)suicideUiGo == (Object)null) { suicideUiGo = new GameObject("SuicideUiPrompt"); Canvas obj = suicideUiGo.AddComponent(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 10000; CanvasScaler obj2 = suicideUiGo.AddComponent(); obj2.uiScaleMode = (ScaleMode)1; obj2.referenceResolution = new Vector2(1920f, 1080f); obj2.matchWidthOrHeight = 0.5f; suicideUiGo.AddComponent(); GameObject val = new GameObject("CenterText"); val.transform.SetParent(suicideUiGo.transform, false); cocoonUiText = val.AddComponent(); RectTransform component = val.GetComponent(); component.anchorMin = new Vector2(0f, 0f); component.anchorMax = new Vector2(1f, 1f); component.offsetMin = new Vector2(0f, 60f); component.offsetMax = new Vector2(0f, -60f); cocoonUiText.font = GetDefaultFont(); cocoonUiText.fontSize = 34; cocoonUiText.alignment = (TextAnchor)7; cocoonUiText.supportRichText = true; Shadow obj3 = val.AddComponent(); obj3.effectColor = new Color(0f, 0f, 0f, 0.95f); obj3.effectDistance = new Vector2(2f, -2f); GameObject val2 = new GameObject("SuicideHintText"); val2.transform.SetParent(suicideUiGo.transform, false); suicideHintText = val2.AddComponent(); RectTransform component2 = val2.GetComponent(); component2.anchorMin = new Vector2(1f, 0f); component2.anchorMax = new Vector2(1f, 0f); component2.pivot = new Vector2(1f, 0f); component2.anchoredPosition = new Vector2(-60f, 60f); component2.sizeDelta = new Vector2(600f, 80f); suicideHintText.font = GetDefaultFont(); suicideHintText.fontSize = 28; suicideHintText.alignment = (TextAnchor)8; suicideHintText.supportRichText = true; Shadow obj4 = val2.AddComponent(); obj4.effectColor = new Color(0f, 0f, 0f, 0.95f); obj4.effectDistance = new Vector2(2f, -2f); } if ((Object)(object)cocoonUiText != (Object)null) { cocoonUiText.text = $"COCOONED! (HP: {ClientAddon.LocalPlayerCocoonHp}/25)\nAwaiting revive from teammates..."; } if ((Object)(object)suicideHintText != (Object)null) { string quickMapButtonName = ClientAddon.GetQuickMapButtonName(); if (SuicideHoldTimer > 0f) { int num = Mathf.Clamp(Mathf.RoundToInt(SuicideHoldTimer / 1.5f * 100f), 0, 100); suicideHintText.text = $"HOLD [{quickMapButtonName.ToUpper()}] TO SUICIDE ({num}%)"; } else { suicideHintText.text = "HOLD [" + quickMapButtonName.ToUpper() + "] TO SUICIDE"; } } } private void HideSuicideUi() { if ((Object)(object)suicideUiGo != (Object)null) { Object.Destroy((Object)(object)suicideUiGo); suicideUiGo = null; cocoonUiText = null; suicideHintText = null; } } } } namespace EnemySyncing.Patches { [HarmonyPatch(typeof(tk2dSpriteAnimator))] [HarmonyPatch("Play", new Type[] { typeof(tk2dSpriteAnimationClip), typeof(float), typeof(float) })] internal static class Patch_EnemyAnimatorPlay1 { private static void Prefix(tk2dSpriteAnimationClip clip, tk2dSpriteAnimator __instance) { EnemyAvatar enemyAvatar = default(EnemyAvatar); if (clip != null && ((Component)__instance).gameObject.TryGetComponent(ref enemyAvatar) && enemyAvatar.isController) { enemyAvatar.SendAnimation(clip.name); } } } [HarmonyPatch(typeof(tk2dSpriteAnimator))] [HarmonyPatch("Play", new Type[] { typeof(tk2dSpriteAnimationClip) })] internal static class Patch_EnemyAnimatorPlay2 { private static void Prefix(tk2dSpriteAnimationClip clip, tk2dSpriteAnimator __instance) { EnemyAvatar enemyAvatar = default(EnemyAvatar); if (clip != null && ((Component)__instance).gameObject.TryGetComponent(ref enemyAvatar) && enemyAvatar.isController) { enemyAvatar.SendAnimation(clip.name); } } } [HarmonyPatch(typeof(tk2dSpriteAnimator))] [HarmonyPatch("Play", new Type[] { typeof(string) })] internal static class Patch_EnemyAnimatorPlay3 { private static void Prefix(string name, tk2dSpriteAnimator __instance) { EnemyAvatar enemyAvatar = default(EnemyAvatar); if (!string.IsNullOrEmpty(name) && ((Component)__instance).gameObject.TryGetComponent(ref enemyAvatar) && enemyAvatar.isController) { enemyAvatar.SendAnimation(name); } } } [HarmonyPatch(typeof(HealthManager), "Awake")] internal class Patch_HealthManager_Awake { private static void Postfix(HealthManager __instance) { //IL_001d: 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_0038: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || (Object)(object)((Component)__instance).gameObject == (Object)null) { return; } Scene scene = ((Component)__instance).gameObject.scene; if (!((Scene)(ref scene)).IsValid() || ((Component)__instance).gameObject.transform.position.x < -80f || !((Object)(object)((Component)__instance).gameObject.GetComponent() == (Object)null)) { return; } ((Component)__instance).gameObject.AddComponent(); EnemyAvatar enemyAvatar = ((Component)__instance).gameObject.AddComponent(); string enemyName = ((((Object)((Component)__instance).gameObject).name.Contains("_fs_") || ((Object)((Component)__instance).gameObject).name.StartsWith("scene:")) ? ((Object)((Component)__instance).gameObject).name : BossSyncManager.GetFullScenePath(((Component)__instance).transform)); enemyAvatar.enemyName = enemyName; bool flag = enemyAvatar.IsHazardOrSummonOrProjectile(); bool flag2 = false; Transform val = ((Component)__instance).transform; while ((Object)(object)val != (Object)null) { string text = ((Object)val).name.ToLower(); if (text.Contains("battle") || text.Contains("wave") || text.Contains("colosseum") || text.Contains("arena") || (Object)(object)((Component)val).GetComponent("BattleScene") != (Object)null) { flag2 = true; break; } val = val.parent; } if (!enemyAvatar.isBoss && !flag && !flag2 && !enemyAvatar.enemyName.Contains("_fs_") && !enemyAvatar.enemyName.StartsWith("scene:") && ClientAddon.DeadEnemies.Contains(enemyAvatar.enemyName)) { Debug.Log((object)("[EnemySync] Enemy '" + enemyAvatar.enemyName + "' was previously killed in this scene. Hiding on Awake.")); __instance.hp = 0; ((Component)__instance).gameObject.SetActive(false); } } } [HarmonyPatch(typeof(Recoil))] [HarmonyPatch("RecoilByDirection")] internal class Patch_Recoil_RecoilByDirection { private static bool Prefix(Recoil __instance) { if ((Object)(object)__instance == (Object)null || (Object)(object)((Component)__instance).gameObject == (Object)null) { return true; } EnemyAvatar enemyAvatar = ((Component)__instance).GetComponent() ?? ((Component)__instance).GetComponentInParent(); if ((Object)(object)enemyAvatar != (Object)null && enemyAvatar.controllerId != ushort.MaxValue && !enemyAvatar.isController) { return false; } return true; } } [HarmonyPatch] public static class Patch_AddSilk { [HarmonyTargetMethods] private static IEnumerable TargetMethods() { List list = new List(); MethodInfo[] methods = typeof(HeroController).GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name.Equals("AddSilk", StringComparison.OrdinalIgnoreCase) || methodInfo.Name.Equals("GainSilk", StringComparison.OrdinalIgnoreCase) || methodInfo.Name.Equals("AddMPCharge", StringComparison.OrdinalIgnoreCase) || methodInfo.Name.Equals("AddSoul", StringComparison.OrdinalIgnoreCase)) { list.Add(methodInfo); } } return list; } private static bool Prefix() { if (HealthPatches.IsApplyingRemoteDamage) { return false; } return true; } } [HarmonyPatch] internal class Patch_TinkEffect_Hit { private static IEnumerable TargetMethods() { List list = new List(); try { Type type = Type.GetType("TinkEffect, Assembly-CSharp"); if (type != null) { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name == "Hit") { list.Add(methodInfo); } } } } catch { } return list; } private static Exception? Finalizer(Exception? __exception) { return null; } } [HarmonyPatch] internal class Patch_NailSlashTerrainThunk_HandleCollision { private static IEnumerable TargetMethods() { List list = new List(); try { Type type = Type.GetType("NailSlashTerrainThunk, Assembly-CSharp"); if (type != null) { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name == "HandleCollision") { list.Add(methodInfo); } } } } catch { } return list; } private static Exception? Finalizer(Exception? __exception) { return null; } } [HarmonyPatch] internal class Patch_AudioPlayerOneShot { private static IEnumerable TargetMethods() { List list = new List(); try { Type type = Type.GetType("HutongGames.PlayMaker.Actions.AudioPlayerOneShot, PlayMaker") ?? Type.GetType("HutongGames.PlayMaker.Actions.AudioPlayerOneShot, Assembly-CSharp"); if (type != null) { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name == "DoPlayRandomClip" || methodInfo.Name == "OnEnter") { list.Add(methodInfo); } } } } catch { } return list; } private static Exception? Finalizer(Exception? __exception) { return null; } } [HarmonyPatch] internal class Patch_AudioPlayerOneShotSingle { private static IEnumerable TargetMethods() { List list = new List(); try { Type type = Type.GetType("HutongGames.PlayMaker.Actions.AudioPlayerOneShotSingle, PlayMaker") ?? Type.GetType("HutongGames.PlayMaker.Actions.AudioPlayerOneShotSingle, Assembly-CSharp"); if (type != null) { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name == "DoPlayRandomClip" || methodInfo.Name == "OnEnter") { list.Add(methodInfo); } } } } catch { } return list; } private static Exception? Finalizer(Exception? __exception) { return null; } } [HarmonyPatch] internal class Patch_BloodSpawner { private static IEnumerable TargetMethods() { List list = new List(); try { Type type = Type.GetType("BloodSpawner, Assembly-CSharp"); if (type != null) { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name == "SpawnBlood") { list.Add(methodInfo); } } } } catch { } return list; } private static Exception? Finalizer(Exception? __exception) { return null; } } [HarmonyPatch(typeof(HealthManager), "TakeDamage")] public class HealthPatches { public static bool IsApplyingRemoteDamage; public static bool IsLocalHitSource(GameObject? source) { if ((Object)(object)source == (Object)null) { return true; } if ((Object)(object)HeroController.instance != (Object)null) { GameObject gameObject = ((Component)HeroController.instance).gameObject; if ((Object)(object)source == (Object)(object)gameObject) { return true; } Transform val = source.transform; while ((Object)(object)val != (Object)null) { if ((Object)(object)((Component)val).gameObject == (Object)(object)gameObject) { return true; } if (((Object)val).name == "Knight") { return true; } if (((Component)val).CompareTag("Player")) { return true; } val = val.parent; } } if (PatchUtil.IsPlayerObject(source)) { return false; } _ = (Object)(object)source.GetComponent() != (Object)null; return true; } private static bool Prefix(HealthManager __instance, ref HitInstance hitInstance) { //IL_00fe: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || (Object)(object)((Component)__instance).gameObject == (Object)null) { return true; } if ((Object)(object)hitInstance.Source != (Object)null && PatchUtil.IsPlayerObject(hitInstance.Source) && (Object)(object)hitInstance.Source != (Object)(object)(((Object)(object)HeroController.instance != (Object)null) ? ((Component)HeroController.instance).gameObject : null)) { return false; } if (IsApplyingRemoteDamage) { return true; } if (!IsLocalHitSource(hitInstance.Source)) { return false; } EnemyHitHandler enemyHitHandler = default(EnemyHitHandler); if (((Component)__instance).gameObject.TryGetComponent(ref enemyHitHandler)) { EnemyAvatar enemyAvatar = default(EnemyAvatar); if (((Component)__instance).gameObject.TryGetComponent(ref enemyAvatar) && enemyAvatar.isController) { int num = 1; if (ClientAddon.Instance != null) { foreach (IClientPlayer item in ClientAddon.Instance.GetPlayersInScene()) { _ = item; num++; } } int num2 = Mathf.FloorToInt((float)hitInstance.DamageDealt / (float)num); hitInstance.DamageDealt = Mathf.Max(1, num2); } enemyHitHandler.ProcessHit(hitInstance); } EnemyAvatar enemyAvatar2 = default(EnemyAvatar); if (((Component)__instance).gameObject.TryGetComponent(ref enemyAvatar2)) { if (enemyAvatar2.isBoss && enemyAvatar2.controllerId == ushort.MaxValue) { ushort num3 = ClientAddon.Instance?.LocalPlayerId ?? ushort.MaxValue; if (num3 != ushort.MaxValue) { enemyAvatar2.hasStartedMovingNatively = true; enemyAvatar2.SetTargetAndController(num3, num3); enemyAvatar2.TriggerBossClaim(); } } if (!enemyAvatar2.isBoss && !enemyAvatar2.IsHazardOrSummonOrProjectile()) { ushort num4 = ClientAddon.Instance?.LocalPlayerId ?? ushort.MaxValue; if (num4 != ushort.MaxValue) { if (enemyAvatar2.controllerId == ushort.MaxValue || enemyAvatar2.IsControllerDeadOrInvalid()) { Debug.Log((object)$"[EnemySync] Local player hit unclaimed enemy '{enemyAvatar2.enemyName}'. Claiming combat target & controller for local player {num4}."); enemyAvatar2.SetTargetAndController(num4, num4); } else if (enemyAvatar2.isController && enemyAvatar2.TargetPlayerId != num4) { enemyAvatar2.SetTargetAndController(num4, num4); } } } } return true; } private static void Postfix(HealthManager __instance) { EnemyAvatar enemyAvatar = default(EnemyAvatar); if (!((Object)(object)__instance == (Object)null) && !((Object)(object)((Component)__instance).gameObject == (Object)null) && ((Component)__instance).gameObject.TryGetComponent(ref enemyAvatar) && !enemyAvatar.isController && !enemyAvatar.IsControllerDeadOrInvalid() && __instance.hp <= 0) { __instance.hp = 1; } } private static Exception? Finalizer(Exception? __exception) { return null; } public static bool IsHeroInvincible(HeroController hc) { if ((Object)(object)hc == (Object)null) { return false; } try { if (hc.cState != null && (hc.cState.invulnerable || hc.cState.hazardDeath || hc.cState.hazardRespawning || hc.cState.recoiling || hc.cState.transitioning || hc.cState.recoilFrozen || hc.cState.parrying)) { return true; } } catch { } try { MethodInfo method = ((object)hc).GetType().GetMethod("CanTakeDamage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method != null && !(bool)method.Invoke(hc, null)) { return true; } } catch { } try { if (hc.playerData != null) { FieldInfo fieldInfo = ((object)hc.playerData).GetType().GetField("isInvincible", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? ((object)hc.playerData).GetType().GetField("invincible", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); bool flag = default(bool); int num; if (fieldInfo != null) { object value = fieldInfo.GetValue(hc.playerData); if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } } else { num = 0; } if (((uint)num & (flag ? 1u : 0u)) != 0) { return true; } } } catch { } return false; } public static int GetBlueHealth(PlayerData pd) { if (pd == null) { return 0; } try { FieldInfo fieldInfo = ((object)pd).GetType().GetField("healthBlue", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? ((object)pd).GetType().GetField("blueHealth", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (fieldInfo != null) { return (int)fieldInfo.GetValue(pd); } PropertyInfo propertyInfo = ((object)pd).GetType().GetProperty("healthBlue", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? ((object)pd).GetType().GetProperty("blueHealth", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (propertyInfo != null) { return (int)propertyInfo.GetValue(pd); } MethodInfo method = ((object)pd).GetType().GetMethod("GetInt", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method != null) { try { int num = (int)method.Invoke(pd, new object[1] { "healthBlue" }); if (num > 0) { return num; } } catch { } try { int num2 = (int)method.Invoke(pd, new object[1] { "blueHealth" }); if (num2 > 0) { return num2; } } catch { } } } catch { } return 0; } public static void ClearBlueHealth(PlayerData pd) { if (pd == null) { return; } try { FieldInfo fieldInfo = ((object)pd).GetType().GetField("healthBlue", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? ((object)pd).GetType().GetField("blueHealth", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (fieldInfo != null) { fieldInfo.SetValue(pd, 0); return; } PropertyInfo propertyInfo = ((object)pd).GetType().GetProperty("healthBlue", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? ((object)pd).GetType().GetProperty("blueHealth", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (propertyInfo != null && propertyInfo.CanWrite) { propertyInfo.SetValue(pd, 0); return; } MethodInfo method = ((object)pd).GetType().GetMethod("SetInt", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(method != null)) { return; } try { method.Invoke(pd, new object[2] { "healthBlue", 0 }); } catch { } try { method.Invoke(pd, new object[2] { "blueHealth", 0 }); } catch { } } catch { } } } [HarmonyPatch(typeof(HealthManager))] [HarmonyPatch("Die")] [HarmonyPatch(new Type[] { typeof(float?), typeof(AttackTypes), typeof(NailElements), typeof(GameObject), typeof(bool), typeof(float), typeof(bool), typeof(bool) })] public class Patch_HealthManager_Die { private static bool Prefix(HealthManager __instance, float? attackDirection, AttackTypes attackType) { //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected I4, but got Unknown //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected I4, but got Unknown //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Expected O, but got Unknown //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Expected O, but got Unknown if ((Object)(object)__instance == (Object)null || (Object)(object)((Component)__instance).gameObject == (Object)null) { return true; } if (ClientAddon.IsApplyingRemoteDeath) { return true; } if (ClientAddon.Instance != null && ClientAddon.Instance.Api != null && ClientAddon.Instance.Api.NetClient.IsConnected) { EnemyAvatar enemyAvatar = default(EnemyAvatar); string text = ((((Component)__instance).gameObject.TryGetComponent(ref enemyAvatar) && !string.IsNullOrEmpty(enemyAvatar.enemyName)) ? enemyAvatar.enemyName : ((Object)((Component)__instance).gameObject).name); if (!ClientAddon.Instance.IsLocalSceneOwner) { Debug.Log((object)("[EnemySync] Non-owner client requesting enemy death verification for '" + text + "' from Scene Owner")); VerifyEnemyDieRequestPacket packet = new VerifyEnemyDieRequestPacket { EnemyName = text, AttackDirection = attackDirection.GetValueOrDefault(), AttackType = (int)attackType, RequesterPlayerId = ClientAddon.Instance.LocalPlayerId }; ClientAddon.Instance.SendPacket(EnemySyncPacketId.VerifyEnemyDieRequest, (IPacketData)(object)packet); return false; } EnemyDiePacket enemyDiePacket = new EnemyDiePacket { EnemyName = text, AttackDirection = attackDirection.GetValueOrDefault(), AttackType = (int)attackType }; Rigidbody2D val = ((Component)__instance).GetComponent() ?? ((Component)__instance).GetComponentInChildren(); if ((Object)(object)val != (Object)null) { enemyDiePacket.HasCorpseSnapshot = true; enemyDiePacket.CorpsePosition = new Vector2(val.position.x, val.position.y); enemyDiePacket.CorpseRotation = val.rotation; enemyDiePacket.CorpseVelocity = new Vector2(val.linearVelocity.x, val.linearVelocity.y); } ClientAddon.Instance.SendPacket(EnemySyncPacketId.EnemyDie, (IPacketData)(object)enemyDiePacket); } return true; } } [HarmonyPatch(typeof(PlayerData), "TakeHealth")] internal class Patch_PlayerData_TakeHealth { private static bool Prefix(PlayerData __instance, int amount) { if (ClientAddon.Instance == null || ClientAddon.Instance.Api == null || !ClientAddon.Instance.Api.NetClient.IsConnected) { return true; } if (ClientAddon.IsSuiciding) { return true; } if ((Object)(object)HeroController.instance != (Object)null && HealthPatches.IsHeroInvincible(HeroController.instance)) { return false; } int num = 1; foreach (IClientPlayer item in ClientAddon.Instance.GetPlayersInScene()) { _ = item; num++; } if (num <= 1) { return true; } int blueHealth = HealthPatches.GetBlueHealth(__instance); if (__instance.health + blueHealth - amount <= 0) { __instance.health = 1; if (blueHealth > 0) { HealthPatches.ClearBlueHealth(__instance); } if (!ClientAddon.IsLocalPlayerCocooned) { ClientAddon.EnterCocoonState(); } return false; } return true; } } [HarmonyPatch(typeof(HeroController), "TakeDamage")] internal class Patch_HeroController_TakeDamage { private static bool Prefix(HeroController __instance, GameObject go, CollisionSide damageSide, int damageAmount, HazardType hazardType) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) if (ClientAddon.Instance == null || ClientAddon.Instance.Api == null || !ClientAddon.Instance.Api.NetClient.IsConnected) { return true; } if (ClientAddon.IsLocalPlayerCocooned) { if (ClientAddon.IsSuiciding) { return true; } if ((int)hazardType != 0 || ((Object)(object)go != (Object)null && (((Object)go).name.ToLower().Contains("hazard") || ((Object)go).name.ToLower().Contains("spike") || ((Object)go).name.ToLower().Contains("acid") || ((Object)go).name.ToLower().Contains("pit") || ((Object)go).name.ToLower().Contains("lava")))) { return true; } return false; } if (HealthPatches.IsHeroInvincible(__instance)) { return true; } int blueHealth = HealthPatches.GetBlueHealth(__instance.playerData); if (__instance.playerData.health + blueHealth - damageAmount <= 0 && !ClientAddon.IsSuiciding) { int num = 1; foreach (IClientPlayer item in ClientAddon.Instance.GetPlayersInScene()) { _ = item; num++; } if (num > 1) { __instance.playerData.health = 1; if (blueHealth > 0) { HealthPatches.ClearBlueHealth(__instance.playerData); } if (!ClientAddon.IsLocalPlayerCocooned) { ClientAddon.EnterCocoonState(); } return false; } } return true; } } internal static class PatchUtil { public static bool IsRemotePlayerObject(GameObject go) { if ((Object)(object)go == (Object)null) { return false; } if ((Object)(object)HeroController.instance != (Object)null) { GameObject gameObject = ((Component)HeroController.instance).gameObject; if ((Object)(object)go == (Object)(object)gameObject || go.transform.IsChildOf(gameObject.transform)) { return false; } } if (ClientAddon.Instance != null) { foreach (IClientPlayer item in ClientAddon.Instance.GetPlayersInScene()) { if (item.Id == ClientAddon.Instance.LocalPlayerId) { continue; } GameObject val = item.PlayerObject; if ((Object)(object)val == (Object)null) { try { PropertyInfo property = ((object)item).GetType().GetProperty("PlayerContainer"); if (property != null) { object? value = property.GetValue(item); val = (GameObject)((value is GameObject) ? value : null); } } catch { } } if ((Object)(object)val != (Object)null && ((Object)(object)go == (Object)(object)val || go.transform.IsChildOf(val.transform))) { return true; } } } string text = ((Object)go).name.ToLower(); if (text.Contains("player prefab") || text.Contains("player container") || text.Contains("player_clone") || text.Contains("remoteplayer")) { return true; } return false; } public static bool IsPlayerObject(GameObject go) { if ((Object)(object)go == (Object)null) { return false; } if ((Object)(object)HeroController.instance != (Object)null && (Object)(object)go == (Object)(object)((Component)HeroController.instance).gameObject) { return true; } return IsRemotePlayerObject(go); } public static void RedirectFsmGameObject(FsmGameObject fsmVar, EnemyAvatar ea) { //IL_0148: 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_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) if (fsmVar == null || (Object)(object)ea == (Object)null) { return; } if ((Object)(object)ea.TargetPlayer != (Object)null) { fsmVar.Value = ea.TargetPlayer; return; } if (ea.TargetPlayerId != ushort.MaxValue && ClientAddon.Instance != null && ea.TargetPlayerId != ClientAddon.Instance.LocalPlayerId) { IClientPlayer player = ClientAddon.Instance.GetPlayer(ea.TargetPlayerId); if (player != null) { GameObject val = player.PlayerObject; if ((Object)(object)val == (Object)null) { try { PropertyInfo property = ((object)player).GetType().GetProperty("PlayerContainer"); if (property != null) { object? value = property.GetValue(player); val = (GameObject)((value is GameObject) ? value : null); } } catch { } } if ((Object)(object)val != (Object)null) { ea.TargetPlayer = val; fsmVar.Value = val; return; } } } if (ea.isBoss || ea.IsHazardOrSummonOrProjectile() || (ea.TargetPlayerId != ushort.MaxValue && !ea.isController)) { return; } ushort num = ClientAddon.Instance?.LocalPlayerId ?? ushort.MaxValue; if (num == ushort.MaxValue || Patch_FsmEnterState.IsRemoteExecuting || ea.TargetPlayerId != ushort.MaxValue || !((Object)(object)HeroController.instance != (Object)null) || ea.IsPlayerDeadOrCocooned(((Component)HeroController.instance).gameObject)) { return; } float num2 = Vector2.Distance(Vector2.op_Implicit(((Component)ea).transform.position), Vector2.op_Implicit(HeroController.instance.transform.position)); if (num2 <= 20f) { Debug.Log((object)$"[EnemySync] Enemy '{ea.enemyName}' natively aggroed local player {num} via FSM action ({num2:F1}u away). Setting combat target & control!"); ea.SetTargetAndController(num, num); if ((Object)(object)ea.TargetPlayer != (Object)null) { fsmVar.Value = ea.TargetPlayer; } } } } public static class TargetPatches { public static void RedirectAllFsmTargetVariables(GameObject go, GameObject target) { if ((Object)(object)go == (Object)null || (Object)(object)target == (Object)null) { return; } PlayMakerFSM[] components = go.GetComponents(); foreach (PlayMakerFSM val in components) { if ((Object)(object)val == (Object)null || val.Fsm == null) { continue; } FsmGameObject[] gameObjectVariables = val.FsmVariables.GameObjectVariables; foreach (FsmGameObject val2 in gameObjectVariables) { if (val2 != null) { string text = ((NamedVariable)val2).Name.ToLower(); bool num = text.Contains("hero") || text.Contains("player") || text == "targetplayer" || text == "herotarget" || text == "playertarget"; bool flag = (Object)(object)val2.Value != (Object)null && PatchUtil.IsPlayerObject(val2.Value); if (num || flag) { val2.Value = target; } } } } } } [HarmonyPatch(typeof(ChaseObject), "DoBuzz")] internal class Patch_ChaseObject { private static void Prefix(ChaseObject __instance) { EnemyAvatar ea = default(EnemyAvatar); if ((Object)(object)((FsmStateAction)__instance).Fsm.GameObject != (Object)null && ((FsmStateAction)__instance).Fsm.GameObject.TryGetComponent(ref ea)) { PatchUtil.RedirectFsmGameObject(__instance.target, ea); } } } [HarmonyPatch(typeof(ChaseObjectGround), "DoChase")] internal class Patch_ChaseObjectGround { private static void Prefix(ChaseObjectGround __instance) { EnemyAvatar ea = default(EnemyAvatar); if ((Object)(object)((FsmStateAction)__instance).Fsm.GameObject != (Object)null && ((FsmStateAction)__instance).Fsm.GameObject.TryGetComponent(ref ea)) { PatchUtil.RedirectFsmGameObject(__instance.target, ea); } } } [HarmonyPatch(typeof(ChaseObjectV2), "DoChase")] internal class Patch_ChaseObjectV2 { private static void Prefix(ChaseObjectV2 __instance) { EnemyAvatar ea = default(EnemyAvatar); if ((Object)(object)((FsmStateAction)__instance).Fsm.GameObject != (Object)null && ((FsmStateAction)__instance).Fsm.GameObject.TryGetComponent(ref ea)) { PatchUtil.RedirectFsmGameObject(__instance.target, ea); } } } [HarmonyPatch(typeof(ChaseObjectV3), "DoChase")] internal class Patch_ChaseObjectV3 { private static void Prefix(ChaseObjectV3 __instance) { EnemyAvatar ea = default(EnemyAvatar); if ((Object)(object)((FsmStateAction)__instance).Fsm.GameObject != (Object)null && ((FsmStateAction)__instance).Fsm.GameObject.TryGetComponent(ref ea)) { PatchUtil.RedirectFsmGameObject(__instance.target, ea); } } } [HarmonyPatch(typeof(ChaseObjectVertical), "DoChase")] internal class Patch_ChaseObjectVertical { private static void Prefix(ChaseObjectVertical __instance) { EnemyAvatar ea = default(EnemyAvatar); if ((Object)(object)((FsmStateAction)__instance).Fsm.GameObject != (Object)null && ((FsmStateAction)__instance).Fsm.GameObject.TryGetComponent(ref ea)) { PatchUtil.RedirectFsmGameObject(__instance.target, ea); } } } [HarmonyPatch(typeof(FaceObject), "DoFace")] internal class Patch_FaceObject { private static void Prefix(FaceObject __instance) { EnemyAvatar ea = default(EnemyAvatar); if ((Object)(object)((FsmStateAction)__instance).Fsm.GameObject != (Object)null && ((FsmStateAction)__instance).Fsm.GameObject.TryGetComponent(ref ea)) { PatchUtil.RedirectFsmGameObject(__instance.objectB, ea); } } } [HarmonyPatch(typeof(FaceObjectV2), "DoFace")] internal class Patch_FaceObjectV2 { private static void Prefix(FaceObjectV2 __instance) { EnemyAvatar ea = default(EnemyAvatar); if ((Object)(object)((FsmStateAction)__instance).Fsm.GameObject != (Object)null && ((FsmStateAction)__instance).Fsm.GameObject.TryGetComponent(ref ea)) { PatchUtil.RedirectFsmGameObject(__instance.objectB, ea); } } } [HarmonyPatch(typeof(FaceObjectV3), "DoFace")] internal class Patch_FaceObjectV3 { private static void Prefix(FaceObjectV3 __instance) { EnemyAvatar ea = default(EnemyAvatar); if ((Object)(object)((FsmStateAction)__instance).Fsm.GameObject != (Object)null && ((FsmStateAction)__instance).Fsm.GameObject.TryGetComponent(ref ea)) { PatchUtil.RedirectFsmGameObject(__instance.ObjectB, ea); } } } [HarmonyPatch(typeof(FaceObjectV4), "DoFace")] internal class Patch_FaceObjectV4 { private static void Prefix(FaceObjectV4 __instance) { EnemyAvatar ea = default(EnemyAvatar); if ((Object)(object)((FsmStateAction)__instance).Fsm.GameObject != (Object)null && ((FsmStateAction)__instance).Fsm.GameObject.TryGetComponent(ref ea)) { PatchUtil.RedirectFsmGameObject(__instance.ObjectB, ea); } } } [HarmonyPatch(typeof(CheckTargetDirection), "DoCheckDirection")] internal class Patch_CheckTargetDirection { private static void Prefix(CheckTargetDirection __instance) { EnemyAvatar ea = default(EnemyAvatar); if ((Object)(object)((FsmStateAction)__instance).Fsm.GameObject != (Object)null && ((FsmStateAction)__instance).Fsm.GameObject.TryGetComponent(ref ea)) { PatchUtil.RedirectFsmGameObject(__instance.target, ea); } } } [HarmonyPatch(typeof(GetDistance), "DoGetDistance")] internal class Patch_GetDistance { private static bool Prefix(GetDistance __instance) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Invalid comparison between Unknown and I4 //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) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) EnemyAvatar enemyAvatar = default(EnemyAvatar); if ((Object)(object)((FsmStateAction)__instance).Fsm.GameObject != (Object)null && ((FsmStateAction)__instance).Fsm.GameObject.TryGetComponent(ref enemyAvatar) && (Object)(object)enemyAvatar.TargetPlayer != (Object)null && __instance.gameObject != null && (int)__instance.gameObject.OwnerOption == 1 && (Object)(object)__instance.gameObject.GameObject.Value != (Object)null && PatchUtil.IsPlayerObject(__instance.gameObject.GameObject.Value)) { Vector3 position = enemyAvatar.TargetPlayer.transform.position; float value = Vector3.Distance(((FsmStateAction)__instance).Fsm.GameObject.transform.position, position); if (__instance.storeResult != null) { __instance.storeResult.Value = value; } return false; } return true; } } [HarmonyPatch(typeof(GetXDistance), "DoGetDistance")] internal class Patch_GetXDistance { private static bool Prefix(GetXDistance __instance) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Invalid comparison between Unknown and I4 //IL_0091: 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) EnemyAvatar enemyAvatar = default(EnemyAvatar); if ((Object)(object)((FsmStateAction)__instance).Fsm.GameObject != (Object)null && ((FsmStateAction)__instance).Fsm.GameObject.TryGetComponent(ref enemyAvatar) && (Object)(object)enemyAvatar.TargetPlayer != (Object)null && __instance.gameObject != null && (int)__instance.gameObject.OwnerOption == 1 && (Object)(object)__instance.gameObject.GameObject.Value != (Object)null && PatchUtil.IsPlayerObject(__instance.gameObject.GameObject.Value)) { float x = enemyAvatar.TargetPlayer.transform.position.x; float x2 = ((FsmStateAction)__instance).Fsm.GameObject.transform.position.x; float value = Mathf.Abs(x - x2); if (__instance.storeResult != null) { __instance.storeResult.Value = value; } return false; } return true; } } [HarmonyPatch(typeof(GetYDistance), "DoGetDistance")] internal class Patch_GetYDistance { private static bool Prefix(GetYDistance __instance) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Invalid comparison between Unknown and I4 //IL_0091: 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) EnemyAvatar enemyAvatar = default(EnemyAvatar); if ((Object)(object)((FsmStateAction)__instance).Fsm.GameObject != (Object)null && ((FsmStateAction)__instance).Fsm.GameObject.TryGetComponent(ref enemyAvatar) && (Object)(object)enemyAvatar.TargetPlayer != (Object)null && __instance.gameObject != null && (int)__instance.gameObject.OwnerOption == 1 && (Object)(object)__instance.gameObject.GameObject.Value != (Object)null && PatchUtil.IsPlayerObject(__instance.gameObject.GameObject.Value)) { float y = enemyAvatar.TargetPlayer.transform.position.y; float y2 = ((FsmStateAction)__instance).Fsm.GameObject.transform.position.y; float value = Mathf.Abs(y - y2); if (__instance.storeResult != null) { __instance.storeResult.Value = value; } return false; } return true; } } [HarmonyPatch(typeof(GetPosition), "DoGetPosition")] internal class Patch_GetPosition { private static bool Prefix(GetPosition __instance) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Invalid comparison between Unknown and I4 //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: 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_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: 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_010e: Unknown result type (might be due to invalid IL or missing references) EnemyAvatar enemyAvatar = default(EnemyAvatar); if ((Object)(object)((FsmStateAction)__instance).Fsm.GameObject != (Object)null && ((FsmStateAction)__instance).Fsm.GameObject.TryGetComponent(ref enemyAvatar) && (Object)(object)enemyAvatar.TargetPlayer != (Object)null && __instance.gameObject != null && (int)__instance.gameObject.OwnerOption == 1 && (Object)(object)__instance.gameObject.GameObject.Value != (Object)null && PatchUtil.IsPlayerObject(__instance.gameObject.GameObject.Value)) { Vector3 val = (((int)__instance.space == 0) ? enemyAvatar.TargetPlayer.transform.position : enemyAvatar.TargetPlayer.transform.localPosition); if (__instance.vector != null) { __instance.vector.Value = val; } if (__instance.x != null) { __instance.x.Value = val.x; } if (__instance.y != null) { __instance.y.Value = val.y; } if (__instance.z != null) { __instance.z.Value = val.z; } return false; } return true; } } } namespace EnemySyncing.Networking { public enum EnemySyncPacketId : byte { EnemyPosition = 0, EnemyAnimation = 1, EnemyTarget = 2, EnemyTakeDamage = 3, EnemyHp = 4, EnemyDie = 5, RequestPlayerId = 6, PlayerIdNotify = 7, SpawnProjectile = 8, EnemyFsmState = 9, BossSyncRequest = 11, PlayerCocoon = 12, CocoonDamage = 13, SceneOwnerNotify = 14, VerifyEnemyDieRequest = 15 } public class EnemyPositionPacket : IPacketData { public bool IsReliable => false; public bool DropReliableDataIfNewerExists => false; public string EnemyName { get; set; } = string.Empty; public Vector2 Position { get; set; } = Vector2.Zero; public float ScaleX { get; set; } public bool Active { get; set; } public ushort ControllerId { get; set; } = ushort.MaxValue; public void WriteData(IPacket packet) { packet.Write(EnemyName ?? string.Empty); packet.Write(Position); packet.Write(ScaleX); packet.Write(Active); packet.Write(ControllerId); } public void ReadData(IPacket packet) { EnemyName = packet.ReadString() ?? string.Empty; Position = packet.ReadVector2(); ScaleX = packet.ReadFloat(); Active = packet.ReadBool(); ControllerId = packet.ReadUShort(); } } public class EnemyAnimationPacket : IPacketData { public bool IsReliable => true; public bool DropReliableDataIfNewerExists => false; public string EnemyName { get; set; } = string.Empty; public string ClipName { get; set; } = string.Empty; public void WriteData(IPacket packet) { packet.Write(EnemyName ?? string.Empty); packet.Write(ClipName ?? string.Empty); } public void ReadData(IPacket packet) { EnemyName = packet.ReadString() ?? string.Empty; ClipName = packet.ReadString() ?? string.Empty; } } public class EnemyTargetPacket : IPacketData { public bool IsReliable => true; public bool DropReliableDataIfNewerExists => false; public string EnemyName { get; set; } = string.Empty; public ushort TargetPlayerId { get; set; } public ushort ControllerId { get; set; } public void WriteData(IPacket packet) { packet.Write(EnemyName ?? string.Empty); packet.Write(TargetPlayerId); packet.Write(ControllerId); } public void ReadData(IPacket packet) { EnemyName = packet.ReadString() ?? string.Empty; TargetPlayerId = packet.ReadUShort(); ControllerId = packet.ReadUShort(); } } public class EnemyTakeDamagePacket : IPacketData { public bool IsReliable => true; public bool DropReliableDataIfNewerExists => false; public string EnemyName { get; set; } = string.Empty; public ushort AttackerPlayerId { get; set; } = ushort.MaxValue; public int DamageDealt { get; set; } public float Direction { get; set; } public int AttackType { get; set; } public float Multiplier { get; set; } public float MagnitudeMultiplier { get; set; } public int NailElement { get; set; } public bool NonLethal { get; set; } public bool CriticalHit { get; set; } public bool CanWeakHit { get; set; } public int DamageScalingLevel { get; set; } public int SpecialType { get; set; } public void WriteData(IPacket packet) { packet.Write(EnemyName ?? string.Empty); packet.Write(AttackerPlayerId); packet.Write(DamageDealt); packet.Write(Direction); packet.Write(AttackType); packet.Write(Multiplier); packet.Write(MagnitudeMultiplier); packet.Write(NailElement); packet.Write(NonLethal); packet.Write(CriticalHit); packet.Write(CanWeakHit); packet.Write(DamageScalingLevel); packet.Write(SpecialType); } public void ReadData(IPacket packet) { EnemyName = packet.ReadString() ?? string.Empty; AttackerPlayerId = packet.ReadUShort(); DamageDealt = packet.ReadInt(); Direction = packet.ReadFloat(); AttackType = packet.ReadInt(); Multiplier = packet.ReadFloat(); MagnitudeMultiplier = packet.ReadFloat(); NailElement = packet.ReadInt(); NonLethal = packet.ReadBool(); CriticalHit = packet.ReadBool(); CanWeakHit = packet.ReadBool(); DamageScalingLevel = packet.ReadInt(); SpecialType = packet.ReadInt(); } } public class EnemyHpPacket : IPacketData { public bool IsReliable => true; public bool DropReliableDataIfNewerExists => false; public string EnemyName { get; set; } = string.Empty; public int Hp { get; set; } public void WriteData(IPacket packet) { packet.Write(EnemyName ?? string.Empty); packet.Write(Hp); } public void ReadData(IPacket packet) { EnemyName = packet.ReadString() ?? string.Empty; Hp = packet.ReadInt(); } } public class EnemyDiePacket : IPacketData { public bool IsReliable => true; public bool DropReliableDataIfNewerExists => false; public string EnemyName { get; set; } = string.Empty; public float AttackDirection { get; set; } public int AttackType { get; set; } public bool HasCorpseSnapshot { get; set; } public Vector2 CorpsePosition { get; set; } = Vector2.Zero; public float CorpseRotation { get; set; } public Vector2 CorpseVelocity { get; set; } = Vector2.Zero; public void WriteData(IPacket packet) { packet.Write(EnemyName ?? string.Empty); packet.Write(AttackDirection); packet.Write(AttackType); packet.Write(HasCorpseSnapshot); if (HasCorpseSnapshot) { packet.Write(CorpsePosition); packet.Write(CorpseRotation); packet.Write(CorpseVelocity); } } public void ReadData(IPacket packet) { EnemyName = packet.ReadString() ?? string.Empty; AttackDirection = packet.ReadFloat(); AttackType = packet.ReadInt(); HasCorpseSnapshot = packet.ReadBool(); if (HasCorpseSnapshot) { CorpsePosition = packet.ReadVector2(); CorpseRotation = packet.ReadFloat(); CorpseVelocity = packet.ReadVector2(); } } } public class SpawnProjectilePacket : IPacketData { public bool IsReliable => true; public bool DropReliableDataIfNewerExists => false; public string PrefabName { get; set; } = string.Empty; public string UniqueName { get; set; } = string.Empty; public Vector2 Position { get; set; } = Vector2.Zero; public Vector3 Rotation { get; set; } = new Vector3(0f, 0f, 0f); public Vector2 Velocity { get; set; } = Vector2.Zero; public float ScaleX { get; set; } = 1f; public string ClipName { get; set; } = string.Empty; public void WriteData(IPacket packet) { packet.Write(PrefabName ?? string.Empty); packet.Write(UniqueName ?? string.Empty); packet.Write(Position); packet.Write(Rotation); packet.Write(Velocity); packet.Write(ScaleX); packet.Write(ClipName ?? string.Empty); } public void ReadData(IPacket packet) { PrefabName = packet.ReadString() ?? string.Empty; UniqueName = packet.ReadString() ?? string.Empty; Position = packet.ReadVector2(); Rotation = packet.ReadVector3(); Velocity = packet.ReadVector2(); ScaleX = packet.ReadFloat(); ClipName = packet.ReadString() ?? string.Empty; } } public class RequestPlayerIdPacket : IPacketData { public bool IsReliable => true; public bool DropReliableDataIfNewerExists => false; public void WriteData(IPacket packet) { } public void ReadData(IPacket packet) { } } public class PlayerIdNotifyPacket : IPacketData { public bool IsReliable => true; public bool DropReliableDataIfNewerExists => false; public ushort AssignedPlayerId { get; set; } public void WriteData(IPacket packet) { packet.Write(AssignedPlayerId); } public void ReadData(IPacket packet) { AssignedPlayerId = packet.ReadUShort(); } } public class EnemyFsmStatePacket : IPacketData { public bool IsReliable => true; public bool DropReliableDataIfNewerExists => false; public string EnemyName { get; set; } = string.Empty; public string FsmName { get; set; } = string.Empty; public string StateName { get; set; } = string.Empty; public Vector2 Position { get; set; } = Vector2.Zero; public float ScaleX { get; set; } = 1f; public void WriteData(IPacket packet) { packet.Write(EnemyName ?? string.Empty); packet.Write(FsmName ?? string.Empty); packet.Write(StateName ?? string.Empty); packet.Write(Position); packet.Write(ScaleX); } public void ReadData(IPacket packet) { EnemyName = packet.ReadString() ?? string.Empty; FsmName = packet.ReadString() ?? string.Empty; StateName = packet.ReadString() ?? string.Empty; Position = packet.ReadVector2(); ScaleX = packet.ReadFloat(); } } public class BossSyncRequestPacket : IPacketData { public bool IsReliable => true; public bool DropReliableDataIfNewerExists => false; public string EnemyName { get; set; } = string.Empty; public bool Subscribe { get; set; } public void WriteData(IPacket packet) { packet.Write(EnemyName ?? string.Empty); packet.Write(Subscribe); } public void ReadData(IPacket packet) { EnemyName = packet.ReadString() ?? string.Empty; Subscribe = packet.ReadBool(); } } public class PlayerCocoonPacket : IPacketData { public bool IsReliable => true; public bool DropReliableDataIfNewerExists => false; public ushort PlayerId { get; set; } public bool IsCocooned { get; set; } public void WriteData(IPacket packet) { packet.Write(PlayerId); packet.Write(IsCocooned); } public void ReadData(IPacket packet) { PlayerId = packet.ReadUShort(); IsCocooned = packet.ReadBool(); } } public class CocoonDamagePacket : IPacketData { public bool IsReliable => true; public bool DropReliableDataIfNewerExists => false; public ushort TargetPlayerId { get; set; } public int DamageDealt { get; set; } public void WriteData(IPacket packet) { packet.Write(TargetPlayerId); packet.Write(DamageDealt); } public void ReadData(IPacket packet) { TargetPlayerId = packet.ReadUShort(); DamageDealt = packet.ReadInt(); } } public class SceneOwnerNotifyPacket : IPacketData { public bool IsReliable => true; public bool DropReliableDataIfNewerExists => false; public ushort SceneOwnerId { get; set; } = ushort.MaxValue; public void WriteData(IPacket packet) { packet.Write(SceneOwnerId); } public void ReadData(IPacket packet) { SceneOwnerId = packet.ReadUShort(); } } public class VerifyEnemyDieRequestPacket : IPacketData { public bool IsReliable => true; public bool DropReliableDataIfNewerExists => false; public string EnemyName { get; set; } = string.Empty; public float AttackDirection { get; set; } public int AttackType { get; set; } public ushort RequesterPlayerId { get; set; } = ushort.MaxValue; public void WriteData(IPacket packet) { packet.Write(EnemyName ?? string.Empty); packet.Write(AttackDirection); packet.Write(AttackType); packet.Write(RequesterPlayerId); } public void ReadData(IPacket packet) { EnemyName = packet.ReadString() ?? string.Empty; AttackDirection = packet.ReadFloat(); AttackType = packet.ReadInt(); RequesterPlayerId = packet.ReadUShort(); } } } namespace EnemySyncing.Components { public class EnemyAvatar : MonoBehaviour { public static readonly Dictionary ActiveAvatars = new Dictionary(); public bool isController; public bool isBoss; private string _enemyName = string.Empty; public ushort controllerId = ushort.MaxValue; public GameObject? TargetPlayer; public ushort TargetPlayerId = ushort.MaxValue; public Vector3 targetPosition; public float targetScaleX = 1f; public bool targetActive = true; public float lerpSpeed = 10f; public float noRespondCounter; public float spawnDelayTimer; private readonly Dictionary lastSentFsmStates = new Dictionary(); private bool fsmDisabledForPuppet; private bool wasController; private bool hasSentSyncRequest; private Vector3 spawnPosition; private bool isSpawnPositionCaptured; public Vector3 originalScenePosition; public bool hasOriginalScenePosition; public float lastPosUpdateReceivedTime; private float settleTimer = 0.5f; private string puppetControlFsmState = ""; public float puppetSpawnTime; private float migrationCooldown; private const float MigrationCooldownDuration = 5f; public bool hasStartedMovingNatively; private const float MaxTimerStep = 0.1f; private HealthManager? hm; private Rigidbody2D? rb; private RigidbodyType2D originalBodyType; private bool hasCachedBodyType; private float syncTimer; private const float SyncInterval = 0.05f; private Vector2? lastSentPosition; private bool? lastSentActiveState; private float bossTargetTimer; private int lastKnownPlayerCount; private PlayMakerFSM[] fsms = (PlayMakerFSM[])(object)new PlayMakerFSM[0]; private bool fsmsCached; public float lastTargetConfirmTime; private float lastSentPositionTime; public static readonly int TerrainLayerMask = 256; private static int projectileCounter = 0; public string enemyName { get { return _enemyName; } set { if (_enemyName != value) { if (!string.IsNullOrEmpty(_enemyName) && ActiveAvatars.TryGetValue(_enemyName, out EnemyAvatar value2) && (Object)(object)value2 == (Object)(object)this) { ActiveAvatars.Remove(_enemyName); } _enemyName = value; if (!string.IsNullOrEmpty(_enemyName)) { ActiveAvatars[_enemyName] = this; } } } } private void OnDestroy() { //IL_0040: 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_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) if (isController && (enemyName.Contains("_fs_") || IsHazardOrSummonOrProjectile())) { EnemyPositionPacket packet = new EnemyPositionPacket { EnemyName = enemyName, Position = new Vector2(((Component)this).transform.position.x, ((Component)this).transform.position.y), ScaleX = ((Component)this).transform.localScale.x, Active = false, ControllerId = controllerId }; ClientAddon.Instance?.SendPacket(EnemySyncPacketId.EnemyPosition, (IPacketData)(object)packet); EnemyDiePacket packet2 = new EnemyDiePacket { EnemyName = enemyName }; ClientAddon.Instance?.SendPacket(EnemySyncPacketId.EnemyDie, (IPacketData)(object)packet2); } if (!string.IsNullOrEmpty(_enemyName)) { if (ActiveAvatars.TryGetValue(_enemyName, out EnemyAvatar value) && (Object)(object)value == (Object)(object)this) { ActiveAvatars.Remove(_enemyName); } if (ClientAddon.Instance != null) { ClientAddon.Instance.LastKnownPositions.Remove(_enemyName); ClientAddon.Instance.LastKnownScales.Remove(_enemyName); ClientAddon.Instance.LastKnownActiveStates.Remove(_enemyName); ClientAddon.Instance.LastKnownControllers.Remove(_enemyName); ClientAddon.Instance.LastKnownTargets.Remove(_enemyName); } } } private void OnEnable() { lastSentActiveState = null; lastSentPosition = null; puppetSpawnTime = Time.time; } private void OnDisable() { //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_0047: Expected O, but got Unknown //IL_004e: Unknown result type (might be due to invalid IL or missing references) if (isController) { EnemyPositionPacket packet = new EnemyPositionPacket { EnemyName = enemyName, Position = new Vector2(((Component)this).transform.position.x, ((Component)this).transform.position.y), ScaleX = ((Component)this).transform.localScale.x, Active = false, ControllerId = controllerId }; ClientAddon.Instance?.SendPacket(EnemySyncPacketId.EnemyPosition, (IPacketData)(object)packet); lastSentActiveState = false; } } private void CacheFSMs() { fsms = ((Component)this).GetComponentsInChildren(true); fsmsCached = true; } public void ReEnableFSMs(bool restoreLastState = true) { if (!fsmsCached) { CacheFSMs(); } PlayMakerFSM[] array = fsms; foreach (PlayMakerFSM val in array) { if (!((Object)(object)val != (Object)null)) { continue; } ((Behaviour)val).enabled = true; if (!restoreLastState || val.Fsm == null) { continue; } string key = GetRelativePath(((Component)val).transform, ((Component)this).transform) + ":" + val.FsmName; if (!lastSentFsmStates.TryGetValue(key, out string value) || string.IsNullOrEmpty(value)) { continue; } Patch_FsmEnterState.IsRemoteExecuting = true; try { val.Fsm.SetState(value); } catch { } finally { Patch_FsmEnterState.IsRemoteExecuting = false; } } } public static bool IsGameplayOrDamageLayer(GameObject go) { if ((Object)(object)go == (Object)null) { return false; } switch (go.layer) { case 5: case 18: case 20: case 23: case 24: case 25: case 27: return false; case 11: case 13: case 14: case 17: case 22: case 26: return true; default: { Collider2D componentInChildren = go.GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null) { int layer = ((Component)componentInChildren).gameObject.layer; if (layer == 11 || layer == 13 || layer == 14 || layer == 17 || layer == 22 || layer == 26) { return true; } } if ((Object)(object)go.GetComponentInChildren(true) != (Object)null || (Object)(object)go.GetComponentInChildren(true) != (Object)null) { return true; } return false; } } } public static bool IsBackgroundOrAmbientObject(GameObject go) { if ((Object)(object)go == (Object)null) { return true; } if (!IsGameplayOrDamageLayer(go)) { return true; } string text = ((Object)go).name.ToLower(); if (text.Contains("door") || text.Contains("gate") || text.Contains("lock") || text.Contains("barrier") || text.Contains("fence") || text.Contains("portcullis")) { return true; } if (text.Contains("indicator") || text.Contains("warning") || text.Contains("telegraph") || text.Contains("hazard") || text.Contains("spike") || text.Contains("stalactite") || text.Contains("rock") || text.Contains("boulder") || text.Contains("damage")) { return false; } if (text.Contains("dragonfly") || text.Contains("butterfly") || text.Contains("moth") || text.Contains("beetle") || text.Contains("bird") || text.Contains("ambient_bug") || text.Contains("decor_bug") || text.Contains("bg_bug")) { return true; } if (text.Contains("background") || text.StartsWith("bg_") || text.Contains("decor") || text.Contains("foliage") || text.Contains("curtain") || text.Contains("statue") || text.Contains("banner") || text.Contains("chain_decor") || text.Contains("leaf_bg") || text.Contains("grass_bg")) { return true; } if (text.Contains("camera") || text.Contains("canvas") || text.Contains("hud") || text.Contains("ui_") || text.Contains("menu") || text.Contains("fader") || text.Contains("audio") || text.Contains("music") || text.Contains("sound") || text.Contains("jingle") || text.Contains("light_beam_bg")) { return true; } return false; } public static bool IsHazardOrDamageOrTelegraph(GameObject go) { if ((Object)(object)go == (Object)null) { return false; } if (!IsGameplayOrDamageLayer(go)) { return false; } if (IsBackgroundOrAmbientObject(go)) { return false; } if ((Object)(object)go.transform.parent != (Object)null && ((Object)(object)go.GetComponentInParent() != (Object)null || (Object)(object)((Component)go.transform.parent).GetComponentInParent() != (Object)null)) { return false; } string text = ((Object)go).name.ToLower(); if (text.Contains("hit") || text.Contains("stab") || text.Contains("slash") || text.Contains("attack") || text.Contains("bite") || text.Contains("punch") || text.Contains("range") || text.Contains("detector") || text.Contains("trigger") || text.Contains("alert") || text.Contains("helper") || text.Contains("parry") || text.Contains("patrol") || text.Contains("turn") || text.Contains("sight")) { return false; } if (text.Contains("indicator") || text.Contains("warning") || text.Contains("telegraph") || text.Contains("reticle") || text.Contains("target_marker") || text.Contains("danger_zone") || text.Contains("anticipation") || text.Contains("threat") || text.Contains("alert") || text.Contains("falling_indicator") || text.Contains("rock_indicator") || text.Contains("drop_indicator") || text.Contains("ground_effect") || text.Contains("floor_warning") || text.Contains("aim")) { return true; } if (text.Contains("hazard") || text.Contains("spike") || text.Contains("stalactite") || text.Contains("rock") || text.Contains("boulder") || text.Contains("bomb") || text.Contains("mine") || text.Contains("saw") || text.Contains("blade") || text.Contains("trap") || text.Contains("lava") || text.Contains("acid") || text.Contains("fire") || text.Contains("flame") || text.Contains("laser") || text.Contains("beam") || text.Contains("shockwave") || text.Contains("thorn") || text.Contains("spear") || text.Contains("claw") || text.Contains("drip") || text.Contains("pit") || text.Contains("icicle") || text.Contains("spit") || text.Contains("shot") || text.Contains("bullet") || text.Contains("blast") || text.Contains("lightning") || text.Contains("zap") || text.Contains("electric") || text.Contains("rubble") || text.Contains("debris") || text.Contains("damage")) { return true; } if ((Object)(object)go.GetComponentInChildren(true) != (Object)null) { return true; } if ((Object)(object)go.GetComponentInChildren(true) != (Object)null) { return true; } MonoBehaviour[] componentsInChildren = go.GetComponentsInChildren(true); foreach (MonoBehaviour val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { string text2 = ((object)val).GetType().Name.ToLower(); if (text2.Contains("damage") || text2.Contains("hazard") || text2.Contains("telegraph") || text2.Contains("indicator")) { return true; } } } return false; } public bool IsHazardOrSummonOrProjectile() { if (isBoss) { return true; } if (enemyName.Contains("_fs_")) { return true; } string text = enemyName.ToLower(); if (text.Contains("summon") || text.Contains("minion") || text.Contains("stalactite") || text.Contains("rock") || text.Contains("spike") || text.Contains("hazard") || text.Contains("blob") || text.Contains("beam") || text.Contains("laser") || text.Contains("fire") || text.Contains("flame") || text.Contains("acid") || text.Contains("pillar") || text.Contains("crystal") || text.Contains("orb") || text.Contains("projectile") || text.Contains("wave") || text.Contains("thorn") || text.Contains("drip") || text.Contains("spear") || text.Contains("claw") || text.Contains("indicator") || text.Contains("warning") || text.Contains("telegraph") || text.Contains("sign") || text.Contains("target") || text.Contains("crosshair") || text.Contains("ray") || text.Contains("mark") || text.Contains("ground_effect") || text.Contains("floor_warning")) { return true; } return false; } private void HandlePuppetFsms() { if (spawnDelayTimer > 0f || isBoss || IsHazardOrSummonOrProjectile()) { return; } if (TargetPlayerId == ushort.MaxValue) { if (fsmDisabledForPuppet) { fsmDisabledForPuppet = false; ReEnableFSMs(); } } else { if (fsmDisabledForPuppet) { return; } fsmDisabledForPuppet = true; if (!fsmsCached) { CacheFSMs(); } PlayMakerFSM[] array = fsms; foreach (PlayMakerFSM val in array) { if ((Object)(object)val != (Object)null) { ((Behaviour)val).enabled = false; } } Debug.Log((object)$"[EnemySync] Disabled FSMs on puppet enemy '{enemyName}' during active combat (controller = {controllerId}, target = {TargetPlayerId})"); } } private void Awake() { if (string.IsNullOrEmpty(_enemyName)) { if (((Object)((Component)this).gameObject).name.Contains("_fs_") || ((Object)((Component)this).gameObject).name.StartsWith("scene:")) { enemyName = ((Object)((Component)this).gameObject).name; } else { enemyName = BossSyncManager.GetFullScenePath(((Component)this).transform); } } } private void Start() { //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_009a: 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) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_0346: Unknown result type (might be due to invalid IL or missing references) //IL_034b: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrEmpty(enemyName) && !ActiveAvatars.ContainsKey(enemyName)) { ActiveAvatars[enemyName] = this; } hm = ((Component)this).GetComponent(); isBoss = (Object)(object)hm != (Object)null && hm.hp > 100; if (!hasOriginalScenePosition) { originalScenePosition = ((Component)this).transform.position; hasOriginalScenePosition = true; } targetPosition = ((Component)this).transform.position; targetScaleX = ((Component)this).transform.localScale.x; targetActive = ((Component)this).gameObject.activeSelf; if (enemyName.Contains("_fs_")) { string[] array = enemyName.Split(new string[1] { "_fs_" }, StringSplitOptions.None); if (array.Length >= 2) { string[] array2 = array[1].Split('_'); if (array2.Length >= 1 && ushort.TryParse(array2[0], out var result)) { controllerId = result; TargetPlayerId = result; } } } if (ClientAddon.Instance != null) { bool flag = false; if (ClientAddon.Instance.LastKnownControllers.TryGetValue(enemyName, out var value)) { controllerId = value; flag = true; } if (ClientAddon.Instance.LastKnownTargets.TryGetValue(enemyName, out var value2)) { TargetPlayerId = value2; flag = true; } bool num = !isBoss; if (num && ClientAddon.Instance.LastKnownPositions.TryGetValue(enemyName, out var value3)) { targetPosition = value3; ((Component)this).transform.position = value3; flag = true; } if (num && ClientAddon.Instance.LastKnownScales.TryGetValue(enemyName, out var value4)) { targetScaleX = value4; Vector3 localScale = ((Component)this).transform.localScale; ((Component)this).transform.localScale = new Vector3(value4, localScale.y, localScale.z); flag = true; } if (num && ClientAddon.Instance.LastKnownActiveStates.TryGetValue(enemyName, out var value5)) { targetActive = value5; ((Component)this).gameObject.SetActive(value5); flag = true; } if (flag) { Debug.Log((object)$"[EnemySync] Enemy '{enemyName}' restored state from cache: Controller = {controllerId}, Target = {TargetPlayerId}, Position = {targetPosition}"); } } if (controllerId != ushort.MaxValue && ClientAddon.Instance != null) { isController = controllerId == ClientAddon.Instance.LocalPlayerId; } if (isController) { hasStartedMovingNatively = true; fsmDisabledForPuppet = false; } Debug.Log((object)$"[EnemySync] Enemy '{enemyName}' spawned locally (isBoss: {isBoss}, HP: {(((Object)(object)hm != (Object)null) ? hm.hp : (-1))}, isController: {isController}, controller: {controllerId})"); rb = ((Component)this).GetComponent(); if ((Object)(object)rb != (Object)null) { originalBodyType = rb.bodyType; hasCachedBodyType = true; } if (!isBoss) { return; } bossTargetTimer = Random.Range(15f, 20f); spawnDelayTimer = 5f; lastKnownPlayerCount = 0; if (ClientAddon.Instance != null) { foreach (IClientPlayer item in ClientAddon.Instance.GetPlayersInScene()) { _ = item; lastKnownPlayerCount++; } } isSpawnPositionCaptured = false; settleTimer = 0.5f; } private void Update() { //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Invalid comparison between Unknown and I4 //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_022d: 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_03f1: Unknown result type (might be due to invalid IL or missing references) //IL_03f7: Unknown result type (might be due to invalid IL or missing references) //IL_03de: Unknown result type (might be due to invalid IL or missing references) //IL_03e4: Unknown result type (might be due to invalid IL or missing references) //IL_0405: Unknown result type (might be due to invalid IL or missing references) //IL_0417: Unknown result type (might be due to invalid IL or missing references) //IL_041d: Invalid comparison between Unknown and I4 //IL_0431: Unknown result type (might be due to invalid IL or missing references) //IL_0556: Unknown result type (might be due to invalid IL or missing references) //IL_055b: Unknown result type (might be due to invalid IL or missing references) //IL_0566: Unknown result type (might be due to invalid IL or missing references) //IL_056b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)GameManager.instance == (Object)null || (Object)(object)HeroController.instance == (Object)null) { return; } if ((Object)(object)GameManager.instance != (Object)null && GameManager.instance.isPaused && isController) { ushort num = ushort.MaxValue; if (ClientAddon.Instance != null) { foreach (IClientPlayer item in ClientAddon.Instance.GetPlayersInScene()) { if (item.Id != ClientAddon.Instance.LocalPlayerId) { num = item.Id; break; } } } if (num != ushort.MaxValue) { SetTargetAndController((TargetPlayerId != ushort.MaxValue) ? TargetPlayerId : num, num); } else { ReleaseControl(); } } else { if ((Object)(object)GameManager.instance == (Object)null || (int)GameManager.instance.GameState != 4) { return; } if (migrationCooldown > 0f) { migrationCooldown -= Time.deltaTime; } if (!isBoss && IsHazardOrSummonOrProjectile()) { EnemyAvatar activeBoss = BossSyncManager.GetActiveBoss(); if ((Object)(object)activeBoss != (Object)null && activeBoss.controllerId != ushort.MaxValue && (controllerId != activeBoss.controllerId || TargetPlayerId != activeBoss.TargetPlayerId)) { SetTargetAndControllerLocal(activeBoss.TargetPlayerId, activeBoss.controllerId); } } if ((Object)(object)TargetPlayer == (Object)null && TargetPlayerId != ushort.MaxValue) { ResolveTargetPlayer(); } if (isBoss) { if (!isSpawnPositionCaptured) { settleTimer -= Time.deltaTime; if (settleTimer <= 0f) { spawnPosition = ((Component)this).transform.position; isSpawnPositionCaptured = true; Debug.Log((object)$"[EnemySync] Boss '{enemyName}' settled at spawn position {spawnPosition}"); } } if (isSpawnPositionCaptured && !hasStartedMovingNatively) { float num2; if (!((Object)(object)rb != (Object)null)) { num2 = 0f; } else { Vector2 linearVelocity = rb.linearVelocity; num2 = ((Vector2)(ref linearVelocity)).magnitude; } float num3 = num2; float num4 = Vector3.Distance(((Component)this).transform.position, spawnPosition); if (controllerId != ushort.MaxValue || num4 > 1f || num3 > 0.5f) { if (spawnDelayTimer > 0f) { spawnDelayTimer -= Mathf.Min(Time.deltaTime, 0.1f); } else { hasStartedMovingNatively = true; Debug.Log((object)("[EnemySync] Boss '" + enemyName + "' intro grace period elapsed. Starting sync.")); } } } if (hasStartedMovingNatively && !hasSentSyncRequest) { TriggerBossClaim(); } } if (ClientAddon.Instance == null || ClientAddon.Instance.Api == null || !ClientAddon.Instance.Api.NetClient.IsConnected) { isController = true; controllerId = ushort.MaxValue; return; } if (isBoss && (Object)(object)HeroController.instance != (Object)null && IsPlayerDead(((Component)HeroController.instance).gameObject)) { controllerId = ushort.MaxValue; TargetPlayerId = ushort.MaxValue; isController = false; wasController = false; if (fsmDisabledForPuppet) { fsmDisabledForPuppet = false; ReEnableFSMs(); } return; } isController = controllerId != ushort.MaxValue && ClientAddon.Instance != null && controllerId == ClientAddon.Instance.LocalPlayerId; if ((Object)(object)rb != (Object)null && hasCachedBodyType) { if (isController || controllerId == ushort.MaxValue || spawnDelayTimer > 0f) { if ((!wasController || rb.bodyType != originalBodyType) && rb.bodyType != originalBodyType) { rb.bodyType = originalBodyType; } } else if ((int)rb.bodyType != 1) { rb.bodyType = (RigidbodyType2D)1; rb.linearVelocity = Vector2.zero; } } wasController = isController; if (isController) { noRespondCounter = 0f; if (fsmDisabledForPuppet) { fsmDisabledForPuppet = false; ReEnableFSMs(); } if (!isBoss || hasStartedMovingNatively) { SyncAsController(); } return; } if (controllerId != ushort.MaxValue) { if (!isBoss || hasStartedMovingNatively) { HandlePuppetFsms(); SyncAsPuppet(); return; } if (fsmDisabledForPuppet) { fsmDisabledForPuppet = false; ReEnableFSMs(); } if (migrationCooldown > 0f) { migrationCooldown -= Time.deltaTime; } noRespondCounter = 0f; return; } noRespondCounter = 0f; if (fsmDisabledForPuppet) { fsmDisabledForPuppet = false; ReEnableFSMs(); } if (isBoss) { if (hasStartedMovingNatively) { TriggerBossClaim(); } } else if ((Object)(object)HeroController.instance != (Object)null && !IsPlayerDeadOrCocooned(((Component)HeroController.instance).gameObject) && Vector2.Distance(Vector2.op_Implicit(HeroController.instance.transform.position), Vector2.op_Implicit(((Component)this).transform.position)) <= 15f) { TryClaimEnemy(); } } } private void SyncAsController() { //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_013a: 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_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_02d2: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Unknown result type (might be due to invalid IL or missing references) //IL_02e3: Expected O, but got Unknown //IL_02ea: 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_00a9: Unknown result type (might be due to invalid IL or missing references) if (!isBoss && !IsHazardOrSummonOrProjectile() && TargetPlayerId == ushort.MaxValue && (((Object)(object)HeroController.instance != (Object)null) ? Vector3.Distance(((Component)this).transform.position, HeroController.instance.transform.position) : 999f) > 25f) { bool flag = false; if (ClientAddon.Instance != null) { foreach (IClientPlayer item in ClientAddon.Instance.GetPlayersInScene()) { if ((Object)(object)item.PlayerObject != (Object)null && Vector3.Distance(((Component)this).transform.position, item.PlayerObject.transform.position) <= 25f) { flag = true; break; } } } if (!flag) { Debug.Log((object)("[EnemySync] Local player walked away (>25u) from unclaimed FOV enemy '" + enemyName + "'. Auto-releasing control.")); ReleaseControl(); return; } } float num = 0.05f; if (!isBoss && ClientAddon.Instance != null) { float num2 = float.MaxValue; if ((Object)(object)HeroController.instance != (Object)null) { num2 = Vector3.Distance(((Component)this).transform.position, HeroController.instance.transform.position); } foreach (IClientPlayer item2 in ClientAddon.Instance.GetPlayersInScene()) { if ((Object)(object)item2.PlayerObject != (Object)null) { float num3 = Vector3.Distance(((Component)this).transform.position, item2.PlayerObject.transform.position); if (num3 < num2) { num2 = num3; } } } if (num2 > 30f) { num = 0.25f; } } syncTimer -= Time.deltaTime; if (syncTimer <= 0f) { syncTimer = num; Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(((Component)this).transform.position.x, ((Component)this).transform.position.y); bool activeInHierarchy = ((Component)this).gameObject.activeInHierarchy; bool num4 = !lastSentActiveState.HasValue || lastSentActiveState.Value != activeInHierarchy; bool flag2 = !lastSentPosition.HasValue || Vector2.Distance(lastSentPosition.Value, val) > 0.05f; bool flag3 = !isBoss && Time.time - lastSentPositionTime > 1.5f; if (num4 || flag2 || flag3) { lastSentPositionTime = Time.time; lastSentActiveState = activeInHierarchy; lastSentPosition = val; EnemyPositionPacket packet = new EnemyPositionPacket { EnemyName = enemyName, Position = new Vector2(val.x, val.y), ScaleX = ((Component)this).transform.localScale.x, Active = activeInHierarchy, ControllerId = controllerId }; ClientAddon.Instance?.SendPacket(EnemySyncPacketId.EnemyPosition, (IPacketData)(object)packet); } } if (isController || controllerId == ushort.MaxValue) { if (isBoss) { UpdateBossTargeting(); } else if (!IsHazardOrSummonOrProjectile()) { UpdateNormalTargeting(); } } } private void SyncAsPuppet() { //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0211: 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_013a: Unknown result type (might be due to invalid IL or missing references) //IL_02fe: 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_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_016c: 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_026d: Unknown result type (might be due to invalid IL or missing references) ResolveTargetPlayer(); bool flag = !IsControllerDeadOrInvalid(); if (flag) { noRespondCounter = 0f; } else { noRespondCounter += Time.deltaTime; } if (migrationCooldown > 0f) { migrationCooldown -= Time.deltaTime; } if (isBoss && migrationCooldown <= 0f && noRespondCounter > 5f && !flag && (Object)(object)HeroController.instance != (Object)null && !IsPlayerDead(((Component)HeroController.instance).gameObject)) { ushort num = ClientAddon.Instance?.LocalPlayerId ?? ushort.MaxValue; if (num != ushort.MaxValue) { Debug.Log((object)$"[EnemySync] Puppet client detected boss controller dead/disconnected. Transferring boss '{enemyName}' control to local player {num}!"); migrationCooldown = 5f; SetTargetAndController(num, num); } } if (!isBoss && IsHazardOrSummonOrProjectile() && !isController && lastPosUpdateReceivedTime > 0f && Time.time - lastPosUpdateReceivedTime > 2.5f && hasOriginalScenePosition && Vector3.Distance(targetPosition, originalScenePosition) > 0.1f) { targetPosition = originalScenePosition; if ((Object)(object)rb != (Object)null) { rb.position = Vector2.op_Implicit(originalScenePosition); } ((Component)this).transform.position = originalScenePosition; Debug.Log((object)$"[EnemySync] Resetting idle hazard '{enemyName}' back to original scene position {originalScenePosition}"); } if (isBoss || IsHazardOrSummonOrProjectile() || !IsControllerDeadOrInvalid()) { return; } if ((Object)(object)HeroController.instance != (Object)null && !IsPlayerDeadOrCocooned(((Component)HeroController.instance).gameObject) && Vector2.Distance(Vector2.op_Implicit(HeroController.instance.transform.position), Vector2.op_Implicit(((Component)this).transform.position)) <= 15f) { Debug.Log((object)$"[EnemySync] Puppet enemy '{enemyName}' has dead/inactive controller {controllerId}. Local player claiming authority & re-enabling FSMs."); fsmDisabledForPuppet = false; ReEnableFSMs(); if ((Object)(object)rb != (Object)null && hasCachedBodyType) { rb.bodyType = originalBodyType; } SetTargetAndController(ushort.MaxValue, ClientAddon.Instance?.LocalPlayerId ?? ushort.MaxValue); return; } Debug.Log((object)("[EnemySync] Controller for non-boss enemy '" + enemyName + "' no longer valid/active. Resetting to unclaimed & re-enabling FSMs.")); controllerId = ushort.MaxValue; TargetPlayerId = ushort.MaxValue; noRespondCounter = 0f; fsmDisabledForPuppet = false; ReEnableFSMs(); if ((Object)(object)rb != (Object)null && hasCachedBodyType) { rb.bodyType = originalBodyType; } } public bool IsControllerDeadOrInvalid() { if (controllerId == ushort.MaxValue) { return true; } if (ClientAddon.Instance == null) { return true; } if (controllerId == ClientAddon.Instance.LocalPlayerId) { if (!((Object)(object)HeroController.instance == (Object)null) && !IsPlayerDead(((Component)HeroController.instance).gameObject)) { return ClientAddon.IsLocalPlayerCocooned; } return true; } IClientPlayer player = ClientAddon.Instance.GetPlayer(controllerId); if (player == null || !player.IsInLocalScene) { return true; } if (ClientAddon.Instance.CocoonedPlayers.Contains(controllerId)) { return true; } return false; } private void LateUpdate() { //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: 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_00c7: 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_0232: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Invalid comparison between Unknown and I4 //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_029a: Unknown result type (might be due to invalid IL or missing references) //IL_029f: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Invalid comparison between Unknown and I4 //IL_02da: Unknown result type (might be due to invalid IL or missing references) //IL_02e0: Unknown result type (might be due to invalid IL or missing references) //IL_02ed: Unknown result type (might be due to invalid IL or missing references) //IL_02f2: Unknown result type (might be due to invalid IL or missing references) //IL_02fb: Unknown result type (might be due to invalid IL or missing references) //IL_0300: Unknown result type (might be due to invalid IL or missing references) //IL_0302: Unknown result type (might be due to invalid IL or missing references) //IL_0307: Unknown result type (might be due to invalid IL or missing references) //IL_02b9: Unknown result type (might be due to invalid IL or missing references) //IL_02bf: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_02c9: 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_033c: Unknown result type (might be due to invalid IL or missing references) //IL_031d: Unknown result type (might be due to invalid IL or missing references) //IL_032a: Unknown result type (might be due to invalid IL or missing references) //IL_032c: Unknown result type (might be due to invalid IL or missing references) if (ClientAddon.Instance == null || ClientAddon.Instance.Api == null || !ClientAddon.Instance.Api.NetClient.IsConnected || spawnDelayTimer > 0f || ((Object)(object)hm != (Object)null && hm.hp <= 0) || (isBoss && (Object)(object)HeroController.instance != (Object)null && IsPlayerDead(((Component)HeroController.instance).gameObject)) || (isBoss && !hasStartedMovingNatively) || isController || controllerId == ushort.MaxValue) { return; } Vector3 localScale = ((Component)this).transform.localScale; ((Component)this).transform.localScale = new Vector3(targetScaleX, localScale.y, localScale.z); if (((Component)this).gameObject.activeSelf != targetActive) { ((Component)this).gameObject.SetActive(targetActive); } bool flag = puppetControlFsmState == "Stunned" || puppetControlFsmState == "Stun Recover" || puppetControlFsmState == "In Combo" || puppetControlFsmState == "Stun Start" || puppetControlFsmState == "Stun Knockback" || puppetControlFsmState == "Stunned Airborne" || puppetControlFsmState == "Stun"; bool flag2 = enemyName.Contains("_fs_"); if ((Object)(object)rb != (Object)null && !flag2) { if ((int)rb.bodyType != 1) { rb.bodyType = (RigidbodyType2D)1; } rb.linearVelocity = Vector2.zero; rb.angularVelocity = 0f; } if (!flag2) { Rigidbody2D[] componentsInChildren = ((Component)this).GetComponentsInChildren(true); foreach (Rigidbody2D val in componentsInChildren) { if ((Object)(object)val != (Object)null) { if ((int)val.bodyType != 1) { val.bodyType = (RigidbodyType2D)1; } val.linearVelocity = Vector2.zero; val.angularVelocity = 0f; } } } Vector3 val2 = targetPosition - ((Component)this).transform.position; float num = (isBoss ? 15f : 25f); Vector3 val3; if (IsHazardOrSummonOrProjectile() || flag2) { float num2 = Mathf.Max(25f, ((Vector3)(ref val2)).magnitude * 15f); val3 = Vector3.Lerp(((Component)this).transform.position, targetPosition, Time.deltaTime * num2); } else if (((Vector3)(ref val2)).magnitude > num || flag) { val3 = ClampPositionToTerrain(((Component)this).transform.position, targetPosition); } else { float num3 = 25f; Vector3 targetPos = Vector3.Lerp(((Component)this).transform.position, targetPosition, Time.deltaTime * num3); val3 = ClampPositionToTerrain(((Component)this).transform.position, targetPos); } if ((Object)(object)rb != (Object)null && (int)rb.bodyType != 0) { rb.position = Vector2.op_Implicit(val3); } ((Component)this).transform.position = val3; } public Vector3 ClampPositionToTerrain(Vector3 currentPos, Vector3 targetPos) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: 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_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)((Component)this).gameObject == (Object)null) { return targetPos; } if (IsHazardOrSummonOrProjectile()) { return targetPos; } string text = puppetControlFsmState.ToLower(); string text2 = enemyName.ToLower(); if (text.Contains("dig") || text.Contains("burrow") || text.Contains("underground") || text.Contains("submerge") || text.Contains("wall") || text.Contains("ceiling") || text.Contains("phase") || text.Contains("teleport") || text.Contains("vanish") || text.Contains("hide") || text.Contains("disappear") || text.Contains("dive") || text2.Contains("wall") || text2.Contains("burrow")) { return targetPos; } Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(currentPos.x, currentPos.y); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(targetPos.x, targetPos.y); Vector2 val3 = val2 - val; if (((Vector2)(ref val3)).magnitude > 0.05f) { RaycastHit2D val4 = Physics2D.Linecast(val, val2, TerrainLayerMask); if ((Object)(object)((RaycastHit2D)(ref val4)).collider != (Object)null && (Object)(object)((Component)((RaycastHit2D)(ref val4)).collider).gameObject != (Object)(object)((Component)this).gameObject && !((Component)((RaycastHit2D)(ref val4)).collider).transform.IsChildOf(((Component)this).transform) && ((RaycastHit2D)(ref val4)).fraction > 0f && !((RaycastHit2D)(ref val4)).collider.isTrigger) { Vector2 val5 = ((RaycastHit2D)(ref val4)).point + ((RaycastHit2D)(ref val4)).normal * 0.2f; return new Vector3(val5.x, val5.y, targetPos.z); } } return targetPos; } private void ResolveTargetPlayer() { if (TargetPlayerId == ushort.MaxValue) { TargetPlayer = null; return; } if (ClientAddon.Instance != null) { if (TargetPlayerId == ClientAddon.Instance.LocalPlayerId) { HeroController instance = HeroController.instance; TargetPlayer = ((instance != null) ? ((Component)instance).gameObject : null); } else { IClientPlayer player = ClientAddon.Instance.GetPlayer(TargetPlayerId); if (player != null && player.IsInLocalScene) { TargetPlayer = player.PlayerObject; if ((Object)(object)TargetPlayer == (Object)null) { try { PropertyInfo property = ((object)player).GetType().GetProperty("PlayerContainer"); if (property != null) { ref GameObject? targetPlayer = ref TargetPlayer; object? value = property.GetValue(player); targetPlayer = (GameObject?)((value is GameObject) ? value : null); } } catch { } } } else { TargetPlayer = null; } } } if ((Object)(object)TargetPlayer != (Object)null) { TargetPatches.RedirectAllFsmTargetVariables(((Component)this).gameObject, TargetPlayer); } } public void TriggerBossClaim() { if (!isBoss) { return; } if (!hasSentSyncRequest) { hasSentSyncRequest = true; hasStartedMovingNatively = true; spawnDelayTimer = 0f; Debug.Log((object)("[EnemySync] Boss '" + enemyName + "' trigger sequence initiated. Requesting sync subscription.")); BossSyncRequestPacket packet = new BossSyncRequestPacket { EnemyName = enemyName, Subscribe = true }; ClientAddon.Instance?.SendPacket(EnemySyncPacketId.BossSyncRequest, (IPacketData)(object)packet); } if (controllerId == ushort.MaxValue) { ushort num = ClientAddon.Instance?.LocalPlayerId ?? ushort.MaxValue; if (num != ushort.MaxValue && (Object)(object)HeroController.instance != (Object)null && !IsPlayerDeadOrCocooned(((Component)HeroController.instance).gameObject)) { Debug.Log((object)$"[EnemySync] Local player {num} triggered boss '{enemyName}' first! Claiming control."); SetTargetAndController(num, num); } } } private void UpdateBossTargeting() { if (ClientAddon.Instance == null || !isController) { return; } ResolveTargetPlayer(); bool flag = false; if ((Object)(object)TargetPlayer == (Object)null && TargetPlayerId != ushort.MaxValue) { IClientPlayer player = ClientAddon.Instance.GetPlayer(TargetPlayerId); if (TargetPlayerId != ClientAddon.Instance.LocalPlayerId && (player == null || !player.IsInLocalScene)) { flag = true; } } else if ((Object)(object)TargetPlayer != (Object)null) { if (TargetPlayerId == ClientAddon.Instance.LocalPlayerId) { if (IsPlayerDeadOrCocooned(((Component)HeroController.instance).gameObject)) { flag = true; } } else { IClientPlayer player2 = ClientAddon.Instance.GetPlayer(TargetPlayerId); if (player2 == null || !player2.IsInLocalScene || (Object)(object)player2.PlayerObject == (Object)null || IsPlayerDeadOrCocooned(player2.PlayerObject)) { flag = true; } } } if (flag) { SelectBossTarget(); return; } if ((Object)(object)TargetPlayer != (Object)null) { TargetPatches.RedirectAllFsmTargetVariables(((Component)this).gameObject, TargetPlayer); } bossTargetTimer -= Time.deltaTime; if (bossTargetTimer <= 0f) { bossTargetTimer = 15f; SelectBossTarget(); } } private void SelectBossTarget() { if (ClientAddon.Instance == null || !isController) { return; } List list = new List(); if ((Object)(object)HeroController.instance != (Object)null && !IsPlayerDeadOrCocooned(((Component)HeroController.instance).gameObject)) { list.Add(ClientAddon.Instance.LocalPlayerId); } foreach (IClientPlayer item in ClientAddon.Instance.GetPlayersInScene()) { if ((Object)(object)item.PlayerObject != (Object)null && !IsPlayerDeadOrCocooned(item.PlayerObject)) { list.Add(item.Id); } } if (list.Count > 1) { List list2 = list.FindAll((ushort id) => id != TargetPlayerId); if (list2.Count > 0) { list = list2; } } if (list.Count > 0) { list.Sort(); ushort num = list[Random.Range(0, list.Count)]; bossTargetTimer = 15f; Debug.Log((object)$"[EnemySync] Boss '{enemyName}' selected target: Target = {num}, Controller = {controllerId}"); SetTargetAndController(num, controllerId); } } public void TryClaimEnemy() { //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) //IL_00ba: 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_0187: Unknown result type (might be due to invalid IL or missing references) if (spawnDelayTimer > 0f || isBoss || IsHazardOrSummonOrProjectile() || enemyName.Contains("_fs_") || enemyName.Contains("Summon") || enemyName.Contains("Stalactite") || ClientAddon.Instance == null || ClientAddon.Instance.Api == null || !ClientAddon.Instance.Api.NetClient.IsConnected || (Object)(object)HeroController.instance == (Object)null || IsPlayerDeadOrCocooned(((Component)HeroController.instance).gameObject)) { return; } float num = Vector2.Distance(Vector2.op_Implicit(((Component)this).transform.position), Vector2.op_Implicit(HeroController.instance.transform.position)); if (num > 15f) { return; } ushort localPlayerId = ClientAddon.Instance.LocalPlayerId; if (localPlayerId == ushort.MaxValue) { return; } bool flag = false; if (controllerId == ushort.MaxValue) { flag = true; } else if (controllerId != localPlayerId) { bool num2 = IsControllerDeadOrInvalid(); bool flag2 = lastPosUpdateReceivedTime > 0f && Time.time - lastPosUpdateReceivedTime > 4f; if (num2 || flag2) { flag = true; Debug.Log((object)$"[EnemySync] Local player is close ({num:F1}u) to '{enemyName}' while current controller {controllerId} is dead/unresponsive. Taking over authority."); } } if (flag) { fsmDisabledForPuppet = false; ReEnableFSMs(); if ((Object)(object)rb != (Object)null && hasCachedBodyType) { rb.bodyType = originalBodyType; } SetTargetAndController(ushort.MaxValue, localPlayerId); } } public void SetTargetAndControllerLocal(ushort targetId, ushort ctrlId) { //IL_0006: 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_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)this).transform.position; TargetPlayerId = targetId; controllerId = ctrlId; bool flag = isController; isController = ctrlId == (ClientAddon.Instance?.LocalPlayerId ?? ushort.MaxValue); ResolveTargetPlayer(); noRespondCounter = 0f; migrationCooldown = 4f; if (isBoss) { bossTargetTimer = 15f; if (ctrlId != ushort.MaxValue) { spawnDelayTimer = 0f; hasStartedMovingNatively = true; if (!isController && !hasSentSyncRequest) { hasSentSyncRequest = true; BossSyncRequestPacket packet = new BossSyncRequestPacket { EnemyName = enemyName, Subscribe = true }; ClientAddon.Instance?.SendPacket(EnemySyncPacketId.BossSyncRequest, (IPacketData)(object)packet); } } } if ((Object)(object)TargetPlayer != (Object)null) { TargetPatches.RedirectAllFsmTargetVariables(((Component)this).gameObject, TargetPlayer); } if (!isController || flag) { return; } fsmDisabledForPuppet = false; ReEnableFSMs(); ((Component)this).transform.position = position; targetPosition = position; if ((Object)(object)rb != (Object)null) { rb.position = Vector2.op_Implicit(position); if (hasCachedBodyType && rb.bodyType != originalBodyType) { rb.bodyType = originalBodyType; } } } public void SetTargetAndController(ushort targetId, ushort ctrlId) { if (TargetPlayerId != targetId || controllerId != ctrlId) { Debug.Log((object)$"[EnemySync] SetTargetAndController on '{enemyName}': Target = {targetId}, Controller = {ctrlId}"); SetTargetAndControllerLocal(targetId, ctrlId); if (!IsHazardOrSummonOrProjectile() || isBoss) { EnemyTargetPacket packet = new EnemyTargetPacket { EnemyName = enemyName, TargetPlayerId = targetId, ControllerId = ctrlId }; ClientAddon.Instance?.SendPacket(EnemySyncPacketId.EnemyTarget, (IPacketData)(object)packet); } } } public void ReleaseControl() { //IL_0065: Unknown result type (might be due to invalid IL or missing references) if (controllerId != ushort.MaxValue || isController) { TargetPlayerId = ushort.MaxValue; controllerId = ushort.MaxValue; isController = false; TargetPlayer = null; fsmDisabledForPuppet = false; ReEnableFSMs(); if ((Object)(object)rb != (Object)null && hasCachedBodyType) { rb.bodyType = originalBodyType; } Debug.Log((object)("[EnemySync] Released control of enemy '" + enemyName + "'")); EnemyTargetPacket packet = new EnemyTargetPacket { EnemyName = enemyName, TargetPlayerId = ushort.MaxValue, ControllerId = ushort.MaxValue }; ClientAddon.Instance?.SendPacket(EnemySyncPacketId.EnemyTarget, (IPacketData)(object)packet); } } public void UpdatePosition(Vector3 pos) { //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) targetPosition = pos; noRespondCounter = 0f; lastPosUpdateReceivedTime = Time.time; } public void SendAnimation(string clipName) { if (TargetPlayerId != ushort.MaxValue || isBoss || IsHazardOrSummonOrProjectile()) { EnemyAnimationPacket packet = new EnemyAnimationPacket { EnemyName = enemyName, ClipName = clipName }; ClientAddon.Instance?.SendPacket(EnemySyncPacketId.EnemyAnimation, (IPacketData)(object)packet); } } public static bool IsProjectileOrSpawn(GameObject projectile, bool isBossContext = false) { if ((Object)(object)projectile == (Object)null) { return false; } if (IsBackgroundOrAmbientObject(projectile)) { return false; } if (IsHazardOrDamageOrTelegraph(projectile)) { return true; } string text = ((Object)projectile).name.ToLower(); if (text.Contains("particle") || text.Contains("hit effect") || text.Contains("spatter") || text.Contains("dust") || text.Contains("thunk") || text.Contains("audio") || text.Contains("sound") || text.Contains("impact") || text.Contains("smoke") || text.Contains("puff") || text.Contains("spark") || text.Contains("shatter")) { return false; } string prefabNameFromName = ClientAddon.GetPrefabNameFromName(((Object)projectile).name); EnemyAvatar enemyAvatar = ClientAddon.Instance?.GetActiveBoss(); if ((Object)(object)enemyAvatar != (Object)null && (prefabNameFromName == enemyAvatar.enemyName || prefabNameFromName == ClientAddon.GetPrefabNameFromName(enemyAvatar.enemyName))) { return false; } if (isBossContext) { return true; } if ((Object)(object)projectile.GetComponentInChildren(true) != (Object)null) { return true; } return false; } public void OnProjectileSpawned(GameObject projectile) { //IL_003a: 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_003f: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Expected O, but got Unknown //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_026b: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_0285: Unknown result type (might be due to invalid IL or missing references) //IL_028f: Expected O, but got Unknown //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_0296: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: Expected O, but got Unknown //IL_02ad: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)projectile == (Object)null) && isController && IsProjectileOrSpawn(projectile, isBoss)) { Rigidbody2D component = projectile.GetComponent(); Vector2 val = (((Object)(object)component != (Object)null) ? component.linearVelocity : Vector2.zero); ushort num = ((controllerId != ushort.MaxValue) ? controllerId : ((ClientAddon.Instance != null && ClientAddon.Instance.LocalPlayerId != ushort.MaxValue) ? ClientAddon.Instance.LocalPlayerId : ushort.MaxValue)); ushort targetPlayerId = ((TargetPlayerId != ushort.MaxValue) ? TargetPlayerId : num); projectileCounter++; string text = ClientAddon.GetPrefabNameFromName(((Object)projectile).name); if (string.IsNullOrEmpty(text)) { text = ((Object)projectile).name.Replace("(Clone)", "").Trim(); } if (ClientAddon.Instance != null && !ClientAddon.Instance.PrefabCache.ContainsKey(text)) { ClientAddon.Instance.PrefabCache[text] = projectile; } string text2 = $"{text}_fs_{num}_{projectileCounter}"; if (ActiveAvatars.TryGetValue(((Object)projectile).name, out EnemyAvatar value) && (Object)(object)((Component)value).gameObject == (Object)(object)projectile) { ActiveAvatars.Remove(((Object)projectile).name); } ((Object)projectile).name = text2; EnemyAvatar enemyAvatar = projectile.GetComponent() ?? projectile.AddComponent(); enemyAvatar.enemyName = text2; ActiveAvatars[text2] = enemyAvatar; enemyAvatar.controllerId = num; enemyAvatar.TargetPlayerId = targetPlayerId; enemyAvatar.isController = num == (ClientAddon.Instance?.LocalPlayerId ?? ushort.MaxValue); Debug.Log((object)$"[EnemySync] Spawner enemy '{enemyName}' spawned projectile/minion '{text2}' at {projectile.transform.position}"); tk2dSpriteAnimator val2 = projectile.GetComponent() ?? projectile.GetComponentInChildren(true); string clipName = (((Object)(object)val2 != (Object)null && val2.CurrentClip != null) ? val2.CurrentClip.name : string.Empty); SpawnProjectilePacket packet = new SpawnProjectilePacket { PrefabName = text, UniqueName = text2, Position = new Vector2(projectile.transform.position.x, projectile.transform.position.y), Rotation = new Vector3(projectile.transform.eulerAngles.x, projectile.transform.eulerAngles.y, projectile.transform.eulerAngles.z), Velocity = new Vector2(val.x, val.y), ScaleX = projectile.transform.localScale.x, ClipName = clipName }; ClientAddon.Instance?.SendPacket(EnemySyncPacketId.SpawnProjectile, (IPacketData)(object)packet); } } public string GetRelativePath(Transform child, Transform parent) { if ((Object)(object)child == (Object)(object)parent) { return ""; } string text = ((Object)child).name; Transform parent2 = child.parent; while ((Object)(object)parent2 != (Object)null && (Object)(object)parent2 != (Object)(object)parent) { text = ((Object)parent2).name + "/" + text; parent2 = parent2.parent; } return text; } public void SetFsmState(string fsmKey, string stateName, Vector2? pos = null, float? scaleX = null) { //IL_0050: 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_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008d: 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_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_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0121: 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_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) if (!isController && pos.HasValue && IsHazardOrSummonOrProjectile()) { Vector3 position = default(Vector3); ((Vector3)(ref position))..ctor(pos.Value.x, pos.Value.y, ((Component)this).transform.position.z); ((Component)this).transform.position = position; targetPosition = position; Rigidbody2D val = default(Rigidbody2D); if (((Component)this).TryGetComponent(ref val)) { val.position = new Vector2(pos.Value.x, pos.Value.y); } if (!((Component)this).gameObject.activeSelf) { ((Component)this).gameObject.SetActive(true); } } if (!isController && scaleX.HasValue && scaleX.Value != 0f) { Vector3 localScale = ((Component)this).transform.localScale; ((Component)this).transform.localScale = new Vector3(scaleX.Value, localScale.y, localScale.z); } if (!fsmsCached || fsms == null || fsms.Length == 0) { CacheFSMs(); } bool applied = false; PlayMakerFSM[] array; if (fsms != null) { array = fsms; foreach (PlayMakerFSM fsm in array) { TryApplyState(fsm); if (applied) { return; } } } if (applied) { return; } CacheFSMs(); if (fsms == null) { return; } array = fsms; foreach (PlayMakerFSM fsm2 in array) { TryApplyState(fsm2); if (applied) { break; } } void TryApplyState(PlayMakerFSM val2) { //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)val2 == (Object)null) && val2.Fsm != null) { string text = GetRelativePath(((Component)val2).transform, ((Component)this).transform) + ":" + val2.FsmName; if (text == fsmKey || val2.FsmName == fsmKey || (fsmKey.StartsWith(":") && fsmKey.Substring(1) == val2.FsmName) || (fsmKey.Contains(":") && fsmKey.EndsWith(":" + val2.FsmName))) { lastSentFsmStates[text] = stateName; string activeStateName = val2.Fsm.ActiveStateName; if (fsmKey == ":Control" || fsmKey.EndsWith(":Control")) { puppetControlFsmState = stateName; } if (pos.HasValue && (Object)(object)((Component)val2).transform != (Object)(object)((Component)this).transform) { Vector3 position2 = default(Vector3); ((Vector3)(ref position2))..ctor(pos.Value.x, pos.Value.y, ((Component)val2).transform.position.z); ((Component)val2).transform.position = position2; Rigidbody2D val3 = default(Rigidbody2D); if (((Component)val2).TryGetComponent(ref val3)) { val3.position = new Vector2(pos.Value.x, pos.Value.y); } } if (!isBoss && !IsHazardOrSummonOrProjectile()) { string text2 = stateName.ToLower(); if (!text2.Contains("stun") && !text2.Contains("stagger") && !text2.Contains("die") && !text2.Contains("death") && !text2.Contains("daze") && !text2.Contains("knockback") && ((Behaviour)val2).enabled && !string.IsNullOrEmpty(activeStateName)) { applied = true; return; } } Patch_FsmEnterState.IsRemoteExecuting = true; try { ((Behaviour)val2).enabled = true; val2.Fsm.SetState(stateName); applied = true; } catch (Exception ex) { Debug.LogWarning((object)("[EnemySync] Ignored exception forcing FSM '" + fsmKey + "' on '" + enemyName + "' to state '" + stateName + "': " + ex.Message)); } finally { Patch_FsmEnterState.IsRemoteExecuting = false; } } } } } public void SendAllFsmStates() { //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_010e: 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_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Expected O, but got Unknown //IL_0132: Unknown result type (might be due to invalid IL or missing references) if (!isController || ClientAddon.Instance == null) { return; } EnemyTargetPacket packet = new EnemyTargetPacket { EnemyName = enemyName, TargetPlayerId = TargetPlayerId, ControllerId = controllerId }; ClientAddon.Instance.SendPacket(EnemySyncPacketId.EnemyTarget, (IPacketData)(object)packet); if (!fsmsCached) { CacheFSMs(); } PlayMakerFSM[] array = fsms; foreach (PlayMakerFSM val in array) { if (!((Object)(object)val == (Object)null) && val.Fsm != null && !((Object)(object)((Component)val).gameObject == (Object)null)) { string activeStateName = val.Fsm.ActiveStateName; if (!string.IsNullOrEmpty(activeStateName)) { string text = GetRelativePath(((Component)val).transform, ((Component)this).transform) + ":" + val.FsmName; lastSentFsmStates[text] = activeStateName; Vector3 position = ((Component)val).gameObject.transform.position; EnemyFsmStatePacket packet2 = new EnemyFsmStatePacket { EnemyName = enemyName, FsmName = text, StateName = activeStateName, Position = new Vector2(position.x, position.y), ScaleX = ((Component)val).gameObject.transform.localScale.x }; ClientAddon.Instance.SendPacket(EnemySyncPacketId.EnemyFsmState, (IPacketData)(object)packet2); } } } } private void UpdateNormalTargeting() { //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_007b: 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) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: 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_0103: 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) if (ClientAddon.Instance == null || IsHazardOrSummonOrProjectile() || isBoss || !isController) { return; } ushort localPlayerId = ClientAddon.Instance.LocalPlayerId; bool num = (Object)(object)HeroController.instance == (Object)null || IsPlayerDeadOrCocooned(((Component)HeroController.instance).gameObject); bool flag = (((Object)(object)HeroController.instance != (Object)null) ? Vector2.Distance(Vector2.op_Implicit(((Component)this).transform.position), Vector2.op_Implicit(HeroController.instance.transform.position)) : float.MaxValue) > 25f; if (num) { ushort num2 = ushort.MaxValue; float num3 = 20f; foreach (IClientPlayer item in ClientAddon.Instance.GetPlayersInScene()) { if (item.Id != localPlayerId && (Object)(object)item.PlayerObject != (Object)null && !IsPlayerDeadOrCocooned(item.PlayerObject)) { float num4 = Vector2.Distance(Vector2.op_Implicit(((Component)this).transform.position), Vector2.op_Implicit(item.PlayerObject.transform.position)); if (num4 <= num3) { num3 = num4; num2 = item.Id; } } } if (num2 != ushort.MaxValue) { Debug.Log((object)$"[EnemySync] Controller became cocooned/dead. Transferring '{enemyName}' control to nearby player {num2}"); SetTargetAndController(num2, num2); } else { Debug.Log((object)("[EnemySync] Controller became cocooned/dead with no nearby players. Releasing '" + enemyName + "' control")); ReleaseControl(); } } else { if (!flag || TargetPlayerId != ushort.MaxValue) { return; } bool flag2 = false; foreach (IClientPlayer item2 in ClientAddon.Instance.GetPlayersInScene()) { if ((Object)(object)item2.PlayerObject != (Object)null && Vector3.Distance(((Component)this).transform.position, item2.PlayerObject.transform.position) <= 25f) { flag2 = true; break; } } if (!flag2) { ReleaseControl(); } } } public bool IsPlayerDead(GameObject playerGo) { if ((Object)(object)playerGo == (Object)null) { return true; } if ((Object)(object)HeroController.instance != (Object)null && (Object)(object)playerGo == (Object)(object)((Component)HeroController.instance).gameObject) { HeroController instance = HeroController.instance; if (!((Object)(object)instance == (Object)null)) { return instance.cState.dead; } return true; } tk2dSpriteAnimator component = playerGo.GetComponent(); if ((Object)(object)component != (Object)null && component.CurrentClip != null) { string text = component.CurrentClip.name.ToLower(); if (text.Contains("death") || text.Contains("defeat") || text.Contains("dead")) { return true; } } return !playerGo.activeInHierarchy; } public bool IsPlayerDeadOrCocooned(GameObject playerGo) { if ((Object)(object)playerGo == (Object)null) { return true; } if (IsPlayerDead(playerGo)) { return true; } if ((Object)(object)HeroController.instance != (Object)null && (Object)(object)playerGo == (Object)(object)((Component)HeroController.instance).gameObject) { return ClientAddon.IsLocalPlayerCocooned; } if (ClientAddon.Instance != null) { foreach (IClientPlayer item in ClientAddon.Instance.GetPlayersInScene()) { if ((Object)(object)item.PlayerObject == (Object)(object)playerGo) { return ClientAddon.Instance.CocoonedPlayers.Contains(item.Id); } } } return false; } } public class EnemyHitHandler : MonoBehaviour { private HealthManager? hm; public bool DoNotSend; public bool SuppressNextHpSync; private EnemyAvatar? ea; private int lastHp; public float damageMultiplier = 1f; private void Start() { hm = ((Component)this).GetComponent(); ea = ((Component)this).GetComponent(); if ((Object)(object)hm != (Object)null) { lastHp = hm.hp; } } private void Update() { if ((Object)(object)hm == (Object)null || (Object)(object)ea == (Object)null || ClientAddon.Instance == null || ClientAddon.Instance.Api == null || !ClientAddon.Instance.Api.NetClient.IsConnected) { return; } int num = 1; if (ClientAddon.Instance != null) { int num2 = 0; foreach (IClientPlayer item in ClientAddon.Instance.GetPlayersInScene()) { _ = item; num2++; } num += num2; } damageMultiplier = 1f / (float)num; if ((Object)(object)ea != (Object)null && ea.isController && hm.hp != lastHp) { lastHp = hm.hp; if (SuppressNextHpSync) { SuppressNextHpSync = false; return; } string enemyName = (((Object)(object)ea != (Object)null && !string.IsNullOrEmpty(ea.enemyName)) ? ea.enemyName : BossSyncManager.GetFullScenePath(((Component)this).transform)); EnemyHpPacket packet = new EnemyHpPacket { EnemyName = enemyName, Hp = hm.hp }; ClientAddon.Instance?.SendPacket(EnemySyncPacketId.EnemyHp, (IPacketData)(object)packet); } } public void ProcessHit(HitInstance hitInstance) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected I4, but got Unknown //IL_009f: 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) //IL_00b7: 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_00c2: Expected I4, but got Unknown //IL_00c3: 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_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: 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_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Expected I4, but got Unknown if (!((Object)(object)hm == (Object)null)) { if (!DoNotSend) { string enemyName = (((Object)(object)ea != (Object)null && !string.IsNullOrEmpty(ea.enemyName)) ? ea.enemyName : BossSyncManager.GetFullScenePath(((Component)this).transform)); EnemyTakeDamagePacket packet = new EnemyTakeDamagePacket { EnemyName = enemyName, AttackerPlayerId = (ClientAddon.Instance?.LocalPlayerId ?? ushort.MaxValue), DamageDealt = hitInstance.DamageDealt, Direction = hitInstance.Direction, AttackType = (int)hitInstance.AttackType, Multiplier = hitInstance.Multiplier, MagnitudeMultiplier = hitInstance.MagnitudeMultiplier, NailElement = (int)hitInstance.NailElement, NonLethal = hitInstance.NonLethal, CriticalHit = hitInstance.CriticalHit, CanWeakHit = hitInstance.CanWeakHit, DamageScalingLevel = hitInstance.DamageScalingLevel, SpecialType = (int)hitInstance.SpecialType }; ClientAddon.Instance?.SendPacket(EnemySyncPacketId.EnemyTakeDamage, (IPacketData)(object)packet); } else { DoNotSend = false; } } } } } namespace EnemySyncing.Boss { [HarmonyPatch(typeof(CreateObject), "OnEnter")] internal class Patch_CreateObject { private static bool Prefix(CreateObject __instance) { if (__instance == null || ((FsmStateAction)__instance).Fsm == null || (Object)(object)((FsmStateAction)__instance).Fsm.GameObject == (Object)null) { return true; } if (Patch_FsmEnterState.IsRemoteExecuting) { ((FsmStateAction)__instance).Finish(); return false; } EnemyAvatar enemyAvatar = SpawnerBossResolver.Resolve(((FsmStateAction)__instance).Fsm.GameObject); if ((Object)(object)enemyAvatar == (Object)null) { return true; } if (enemyAvatar.controllerId != ushort.MaxValue && !enemyAvatar.isController) { ((FsmStateAction)__instance).Finish(); return false; } return true; } private static void Postfix(CreateObject __instance) { if (__instance == null || ((FsmStateAction)__instance).Fsm == null || (Object)(object)((FsmStateAction)__instance).Fsm.GameObject == (Object)null) { return; } EnemyAvatar enemyAvatar = SpawnerBossResolver.Resolve(((FsmStateAction)__instance).Fsm.GameObject); if (!((Object)(object)enemyAvatar == (Object)null) && enemyAvatar.isController && __instance.storeObject != null && !((NamedVariable)__instance.storeObject).IsNone) { GameObject value = __instance.storeObject.Value; if ((Object)(object)value != (Object)null) { enemyAvatar.OnProjectileSpawned(value); } } } } [HarmonyPatch(typeof(SpawnObjectFromGlobalPool), "OnEnter")] internal class Patch_SpawnObjectFromGlobalPool { private static bool Prefix(SpawnObjectFromGlobalPool __instance) { if (__instance == null || ((FsmStateAction)__instance).Fsm == null || (Object)(object)((FsmStateAction)__instance).Fsm.GameObject == (Object)null) { return true; } if (Patch_FsmEnterState.IsRemoteExecuting) { ((FsmStateAction)__instance).Finish(); return false; } EnemyAvatar enemyAvatar = SpawnerBossResolver.Resolve(((FsmStateAction)__instance).Fsm.GameObject); if ((Object)(object)enemyAvatar == (Object)null) { return true; } if (enemyAvatar.controllerId != ushort.MaxValue && !enemyAvatar.isController) { ((FsmStateAction)__instance).Finish(); return false; } return true; } private static void Postfix(SpawnObjectFromGlobalPool __instance) { if (__instance == null || ((FsmStateAction)__instance).Fsm == null || (Object)(object)((FsmStateAction)__instance).Fsm.GameObject == (Object)null) { return; } EnemyAvatar enemyAvatar = SpawnerBossResolver.Resolve(((FsmStateAction)__instance).Fsm.GameObject); if (!((Object)(object)enemyAvatar == (Object)null) && enemyAvatar.isController && __instance.storeObject != null && !((NamedVariable)__instance.storeObject).IsNone) { GameObject value = __instance.storeObject.Value; if ((Object)(object)value != (Object)null) { enemyAvatar.OnProjectileSpawned(value); } } } } [HarmonyPatch(typeof(FlingObjectsFromGlobalPool), "OnEnter")] internal class Patch_FlingObjectsFromGlobalPool { private static bool Prefix(FlingObjectsFromGlobalPool __instance) { if (__instance == null || ((FsmStateAction)__instance).Fsm == null || (Object)(object)((FsmStateAction)__instance).Fsm.GameObject == (Object)null) { return true; } if (Patch_FsmEnterState.IsRemoteExecuting) { ((FsmStateAction)__instance).Finish(); return false; } EnemyAvatar enemyAvatar = SpawnerBossResolver.Resolve(((FsmStateAction)__instance).Fsm.GameObject); if ((Object)(object)enemyAvatar == (Object)null) { return true; } if (enemyAvatar.controllerId != ushort.MaxValue && !enemyAvatar.isController) { ((FsmStateAction)__instance).Finish(); return false; } Patch_BossSpawner_Helper.ActiveBossSpawner = enemyAvatar; return true; } private static void Postfix() { Patch_BossSpawner_Helper.ActiveBossSpawner = null; } } [HarmonyPatch(typeof(FlingObjectsFromGlobalPoolVel), "OnEnter")] internal class Patch_FlingObjectsFromGlobalPoolVel { private static bool Prefix(FlingObjectsFromGlobalPoolVel __instance) { if (__instance == null || ((FsmStateAction)__instance).Fsm == null || (Object)(object)((FsmStateAction)__instance).Fsm.GameObject == (Object)null) { return true; } if (Patch_FsmEnterState.IsRemoteExecuting) { ((FsmStateAction)__instance).Finish(); return false; } EnemyAvatar enemyAvatar = SpawnerBossResolver.Resolve(((FsmStateAction)__instance).Fsm.GameObject); if ((Object)(object)enemyAvatar == (Object)null) { return true; } if (enemyAvatar.controllerId != ushort.MaxValue && !enemyAvatar.isController) { ((FsmStateAction)__instance).Finish(); return false; } Patch_BossSpawner_Helper.ActiveBossSpawner = enemyAvatar; return true; } private static void Postfix() { Patch_BossSpawner_Helper.ActiveBossSpawner = null; } } [HarmonyPatch(typeof(FlingObjectsFromGlobalPoolTime), "OnUpdate")] internal class Patch_FlingObjectsFromGlobalPoolTime { private static bool Prefix(FlingObjectsFromGlobalPoolTime __instance) { if (__instance == null || ((FsmStateAction)__instance).Fsm == null || (Object)(object)((FsmStateAction)__instance).Fsm.GameObject == (Object)null) { return true; } if (Patch_FsmEnterState.IsRemoteExecuting) { ((FsmStateAction)__instance).Finish(); return false; } EnemyAvatar enemyAvatar = SpawnerBossResolver.Resolve(((FsmStateAction)__instance).Fsm.GameObject); if ((Object)(object)enemyAvatar == (Object)null) { return true; } if (enemyAvatar.controllerId != ushort.MaxValue && !enemyAvatar.isController) { ((FsmStateAction)__instance).Finish(); return false; } Patch_BossSpawner_Helper.ActiveBossSpawner = enemyAvatar; return true; } private static void Postfix() { Patch_BossSpawner_Helper.ActiveBossSpawner = null; } } [HarmonyPatch(typeof(SpawnObjectFromGlobalPoolOverTime), "OnEnter")] internal class Patch_SpawnObjectFromGlobalPoolOverTime { private static bool Prefix(SpawnObjectFromGlobalPoolOverTime __instance) { if (__instance == null || ((FsmStateAction)__instance).Fsm == null || (Object)(object)((FsmStateAction)__instance).Fsm.GameObject == (Object)null) { return true; } if (Patch_FsmEnterState.IsRemoteExecuting) { ((FsmStateAction)__instance).Finish(); return false; } EnemyAvatar enemyAvatar = SpawnerBossResolver.Resolve(((FsmStateAction)__instance).Fsm.GameObject); if ((Object)(object)enemyAvatar == (Object)null) { return true; } if (enemyAvatar.controllerId != ushort.MaxValue && !enemyAvatar.isController) { ((FsmStateAction)__instance).Finish(); return false; } Patch_BossSpawner_Helper.ActiveBossSpawner = enemyAvatar; return true; } private static void Postfix() { Patch_BossSpawner_Helper.ActiveBossSpawner = null; } } [HarmonyPatch(typeof(ObjectPoolExtensions))] [HarmonyPatch("Spawn", new Type[] { typeof(GameObject), typeof(Vector3), typeof(Quaternion) })] internal class Patch_ObjectPoolExtensions_Spawn1 { private static bool Prefix(GameObject prefab) { if (Patch_BossSpawner_Helper.IsNonControllerSpawn(prefab)) { return false; } return true; } private static void Postfix(GameObject __result) { Patch_BossSpawner_Helper.OnSpawned(__result); } } [HarmonyPatch(typeof(ObjectPoolExtensions))] [HarmonyPatch("Spawn", new Type[] { typeof(GameObject), typeof(Vector3) })] internal class Patch_ObjectPoolExtensions_Spawn2 { private static bool Prefix(GameObject prefab) { if (Patch_BossSpawner_Helper.IsNonControllerSpawn(prefab)) { return false; } return true; } private static void Postfix(GameObject __result) { Patch_BossSpawner_Helper.OnSpawned(__result); } } [HarmonyPatch(typeof(ObjectPoolExtensions))] [HarmonyPatch("Spawn", new Type[] { typeof(GameObject) })] internal class Patch_ObjectPoolExtensions_Spawn3 { private static bool Prefix(GameObject prefab) { if (Patch_BossSpawner_Helper.IsNonControllerSpawn(prefab)) { return false; } return true; } private static void Postfix(GameObject __result) { Patch_BossSpawner_Helper.OnSpawned(__result); } } [HarmonyPatch(typeof(ObjectPoolExtensions))] [HarmonyPatch("Spawn", new Type[] { typeof(GameObject), typeof(Transform), typeof(Vector3), typeof(Quaternion) })] internal class Patch_ObjectPoolExtensions_Spawn4 { private static bool Prefix(GameObject prefab) { if (Patch_BossSpawner_Helper.IsNonControllerSpawn(prefab)) { return false; } return true; } private static void Postfix(GameObject __result) { Patch_BossSpawner_Helper.OnSpawned(__result); } } [HarmonyPatch(typeof(ObjectPoolExtensions))] [HarmonyPatch("Spawn", new Type[] { typeof(GameObject), typeof(Transform) })] internal class Patch_ObjectPoolExtensions_Spawn5 { private static bool Prefix(GameObject prefab) { if (Patch_BossSpawner_Helper.IsNonControllerSpawn(prefab)) { return false; } return true; } private static void Postfix(GameObject __result) { Patch_BossSpawner_Helper.OnSpawned(__result); } } [HarmonyPatch(typeof(Fsm), "EnterState")] internal class Patch_FsmEnterState { public static bool IsRemoteExecuting; private static bool Prefix() { return true; } private static void Postfix(Fsm __instance, FsmState state) { //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: 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_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Expected O, but got Unknown if (!IsRemoteExecuting && __instance != null && state != null && !((Object)(object)__instance.GameObject == (Object)null) && !((Object)(object)__instance.Owner == (Object)null)) { EnemyAvatar enemyAvatar = SpawnerBossResolver.Resolve(__instance.GameObject); if (!((Object)(object)enemyAvatar == (Object)null) && enemyAvatar.isController && (!enemyAvatar.isBoss || (!(enemyAvatar.spawnDelayTimer > 0f) && enemyAvatar.controllerId != ushort.MaxValue))) { string fsmName = enemyAvatar.GetRelativePath(((Component)__instance.Owner).transform, ((Component)enemyAvatar).transform) + ":" + __instance.Name; string name = state.Name; Vector3 position = __instance.GameObject.transform.position; float x = __instance.GameObject.transform.localScale.x; EnemyFsmStatePacket packet = new EnemyFsmStatePacket { EnemyName = enemyAvatar.enemyName, FsmName = fsmName, StateName = name, Position = new Vector2(position.x, position.y), ScaleX = x }; ClientAddon.Instance?.SendPacket(EnemySyncPacketId.EnemyFsmState, (IPacketData)(object)packet); } } } } public static class BossSyncManager { private static readonly Dictionary ScenePathCache = new Dictionary(); private static readonly HashSet FailedScenePathSearches = new HashSet(); public static EnemyAvatar? GetActiveBoss() { foreach (EnemyAvatar value in EnemyAvatar.ActiveAvatars.Values) { if ((Object)(object)value != (Object)null && value.isBoss && (Object)(object)((Component)value).gameObject != (Object)null && ((Component)value).gameObject.activeInHierarchy) { return value; } } return null; } public static bool HasBossInScene() { return (Object)(object)GetActiveBoss() != (Object)null; } public static void ClearScenePathCache() { ScenePathCache.Clear(); FailedScenePathSearches.Clear(); } public static GameObject? FindGameObjectByScenePath(string path) { //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) if (string.IsNullOrEmpty(path)) { return null; } if (FailedScenePathSearches.Contains(path)) { return null; } if (ScenePathCache.TryGetValue(path, out GameObject value) && (Object)(object)value != (Object)null) { return value; } GameObject val = GameObject.Find(path); if ((Object)(object)val != (Object)null) { ScenePathCache[path] = val; return val; } Scene activeScene = SceneManager.GetActiveScene(); if (((Scene)(ref activeScene)).IsValid()) { string[] array = path.Split('/'); if (array.Length != 0) { GameObject[] rootGameObjects = ((Scene)(ref activeScene)).GetRootGameObjects(); foreach (GameObject val2 in rootGameObjects) { if ((Object)(object)val2 != (Object)null && ((Object)val2).name == array[0]) { if (array.Length == 1) { ScenePathCache[path] = val2; return val2; } string text = string.Join("/", array, 1, array.Length - 1); Transform val3 = val2.transform.Find(text); if ((Object)(object)val3 != (Object)null) { ScenePathCache[path] = ((Component)val3).gameObject; return ((Component)val3).gameObject; } } } } } FailedScenePathSearches.Add(path); return null; } public static string GetFullScenePath(Transform t) { string text = ((Object)t).name; Transform parent = t.parent; while ((Object)(object)parent != (Object)null) { text = ((Object)parent).name + "/" + text; parent = parent.parent; } return text; } public static string NormalizePath(string path) { if (string.IsNullOrEmpty(path)) { return ""; } string text = path.Trim(); if (text.StartsWith("scene:")) { text = text.Substring(6); } string[] array = text.Split(new char[1] { '/' }, StringSplitOptions.RemoveEmptyEntries); List list = new List(); string[] array2 = array; foreach (string text2 in array2) { string text3 = text2.ToLower(); if (!text3.Contains("scenemanager") && !(text3 == "_scenemanager") && !(text3 == "scene manager")) { list.Add(text2); } } return string.Join("/", list); } } internal static class SpawnerBossResolver { public static bool IsGarbageFsm(GameObject go) { if ((Object)(object)go == (Object)null) { return true; } Transform val = go.transform; while ((Object)(object)val != (Object)null) { string text = ((Object)val).name.ToLower(); if (text.Contains("camera") || text.Contains("hud") || text.Contains("title") || text.Contains("ui") || text.Contains("menu") || text.Contains("canvas") || text.Contains("screen") || text.Contains("fader") || text.Contains("fade") || text.Contains("overlay") || text.Contains("transition")) { return true; } if (text.Contains("audio") || text.Contains("music") || text.Contains("sound") || text.Contains("voice") || text.Contains("jingle")) { return true; } if (text.Contains("globalpool") || text.Contains("impact") || text.Contains("effect") || text.Contains("particle") || text.Contains("roar wave emitter")) { return true; } if (text.Contains("hero") || text.Contains("player") || text.Contains("knight")) { return true; } if (text.Contains("restbench") || text.Contains("bench") || text.Contains("door") || text.Contains("transition") || text.Contains("save")) { return true; } if (text.Contains("re-encounter") || text.Contains("scenemanager") || text.Contains("scene manager")) { return true; } val = val.parent; } return false; } public static EnemyAvatar? Resolve(GameObject? fsmOwner) { if ((Object)(object)fsmOwner == (Object)null) { return null; } EnemyAvatar componentInParent = fsmOwner.GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null) { return componentInParent; } if ((Object)(object)fsmOwner.GetComponentInParent() != (Object)null) { return null; } if (PatchUtil.IsPlayerObject(fsmOwner)) { return null; } if (IsGarbageFsm(fsmOwner)) { return null; } EnemyAvatar activeBoss = BossSyncManager.GetActiveBoss(); if ((Object)(object)activeBoss != (Object)null && (Object)(object)((Component)activeBoss).gameObject != (Object)null && fsmOwner.transform.IsChildOf(((Component)activeBoss).gameObject.transform)) { return activeBoss; } return null; } } internal static class Patch_BossSpawner_Helper { public static EnemyAvatar? ActiveBossSpawner; public static bool IsPuppetBossActiveAndClaimed(EnemyAvatar? ea) { if ((Object)(object)ea == (Object)null) { return false; } if (!ea.isBoss) { return false; } if (ea.spawnDelayTimer > 0f) { return false; } if (ea.controllerId == ushort.MaxValue) { return false; } if (ea.isController) { return false; } return true; } public static bool IsNonControllerSpawn(GameObject? prefab) { if ((Object)(object)prefab == (Object)null) { return false; } EnemyAvatar activeBossSpawner = ActiveBossSpawner; if ((Object)(object)activeBossSpawner == (Object)null) { return false; } if (!IsPuppetBossActiveAndClaimed(activeBossSpawner)) { return false; } if (Patch_FsmEnterState.IsRemoteExecuting) { return true; } string text = ((Object)prefab).name.ToLower(); if (text.Contains("particle") || text.Contains("effect") || text.Contains("impact") || text.Contains("flash") || text.Contains("dust") || text.Contains("smoke") || text.Contains("puff") || text.Contains("spark") || text.Contains("spatter") || text.Contains("slash") || text.Contains("silk") || text.Contains("chunk") || text.Contains("soul") || text.Contains("mp") || text.Contains("orb") || text.Contains("hit") || text.Contains("blood") || text.Contains("damage") || text.Contains("shatter")) { return false; } return true; } public static void OnSpawned(GameObject spawned) { if ((Object)(object)spawned == (Object)null || ((Object)spawned).name.Contains("_fs_") || (Object)(object)spawned.GetComponent() != (Object)null) { return; } string text = ((Object)spawned).name.ToLower(); if (text.Contains("alert") || text.Contains("range") || text.Contains("trigger") || text.Contains("detector") || text.Contains("bounds") || text.Contains("helper") || text.Contains("check") || text.Contains("state") || text.Contains("controller") || text.Contains("break") || text.Contains("debris") || text.Contains("currency") || text.Contains("dust") || text.Contains("particle") || text.Contains("spatter") || text.Contains("impact") || text.Contains("smoke") || text.Contains("puff") || text.Contains("spark") || text.Contains("shatter") || EnemyAvatar.IsBackgroundOrAmbientObject(spawned) || (!EnemyAvatar.IsHazardOrDamageOrTelegraph(spawned) && (Object)(object)ActiveBossSpawner == (Object)null)) { return; } EnemyAvatar enemyAvatar = ActiveBossSpawner; if ((Object)(object)enemyAvatar == (Object)null) { enemyAvatar = BossSyncManager.GetActiveBoss(); } if ((Object)(object)enemyAvatar != (Object)null && enemyAvatar.isController) { Debug.Log((object)("[EnemySync] Intercepted spawned hazard/projectile object '" + ((Object)spawned).name + "' under spawner '" + enemyAvatar.enemyName + "'. Broadcasting SpawnProjectilePacket.")); enemyAvatar.OnProjectileSpawned(spawned); } else if ((Object)(object)ActiveBossSpawner != (Object)null && ClientAddon.Instance != null && ClientAddon.Instance.IsSceneOwner) { ushort localPlayerId = ClientAddon.Instance.LocalPlayerId; if (localPlayerId != ushort.MaxValue) { EnemyAvatar enemyAvatar2 = spawned.AddComponent(); enemyAvatar2.enemyName = ((Object)spawned).name; enemyAvatar2.isController = true; enemyAvatar2.controllerId = localPlayerId; enemyAvatar2.TargetPlayerId = localPlayerId; enemyAvatar2.OnProjectileSpawned(spawned); } } } } }