using System; using System.Collections.Generic; using System.Collections.ObjectModel; using Cielonos.MainGame.Characters; using Sirenix.OdinInspector; using SLSUtilities.FunctionalAnimation; using UnityEngine; namespace Cielonos.MainGame { public partial class CombatManager { public partial class EnemySubmodule : SubmoduleBase { public enum SortingType { Nearest, Farthest } private readonly List _activeEnemiesList; private readonly ReadOnlyCollection _activeEnemies; public IReadOnlyList ActiveEnemies => _activeEnemies; public int ActiveEnemyCount => _activeEnemiesList.Count; private int TargetingVersion { get; set; } /// /// 敌人从活跃列表中移除时触发(即敌人死亡/离场)。 /// 参数为被移除的敌人实例。 /// public event Action OnEnemyRemoved; public EnemySubmodule(CombatManager owner) : base(owner) { _activeEnemiesList = new List(); _activeEnemies = _activeEnemiesList.AsReadOnly(); } /// /// 将敌人加入活跃列表。所有敌人注册都应经过这里,避免外部直接修改索敌源。 /// public void RegisterEnemy(Enemy enemy) { if (enemy == null || _activeEnemiesList.Contains(enemy)) return; _activeEnemiesList.Add(enemy); TargetingVersion++; } /// /// 将敌人从活跃列表中移除并触发 OnEnemyRemoved 事件。 /// 由 Automata.Die() 调用,替代直接操作活跃敌人列表。 /// public void RemoveEnemy(Enemy enemy) { if (!_activeEnemiesList.Remove(enemy)) return; TargetingVersion++; OnEnemyRemoved?.Invoke(enemy); } /// /// 清空活跃敌人列表(房间重置时调用)。不触发逐条 OnEnemyRemoved 事件。 /// public void Reset() { if (_activeEnemiesList.Count == 0) return; _activeEnemiesList.Clear(); TargetingVersion++; } private List CollectEnemiesInRadius(Vector3 origin, float radius, SortingType sortingType = SortingType.Nearest) { List enemiesInRadius = new List(); foreach (Enemy enemy in _activeEnemiesList) { if (IsEnemyInRadius(enemy, origin, radius)) { enemiesInRadius.Add(enemy); } } if (sortingType == SortingType.Nearest) { enemiesInRadius.Sort((a, b) => GetSurfaceDistance(origin, a).CompareTo(GetSurfaceDistance(origin, b))); } else if (sortingType == SortingType.Farthest) { enemiesInRadius.Sort((a, b) => GetSurfaceDistance(origin, b).CompareTo(GetSurfaceDistance(origin, a))); } return enemiesInRadius; } public bool IsEnemyInRadius(Enemy enemy, Vector3 origin, float radius) { if (enemy == null || enemy.statusSm.isDead) return false; return GetSurfaceDistance(origin, enemy) <= radius; } [Button("Debug: Force GetHit All Enemies", ButtonSizes.Medium)] [GUIColor(1f, 0.55f, 0.35f)] private void DebugForceGetHitAllEnemies() { for (int i = 0; i < _activeEnemiesList.Count; i++) { Enemy enemy = _activeEnemiesList[i]; if (enemy == null || enemy.statusSm.isDead) continue; Vector3 direction = Vector3.zero; Player player = MainGameManager.Player; if (player != null) { direction = enemy.transform.position - player.transform.position; } enemy.GetHit( Breakthrough.Type.Forced, out _, DisruptionType.ForcedExternal, direction); } } [Button("Debug: Force Deplete All Enemies", ButtonSizes.Medium)] [GUIColor(1f, 0.55f, 0.35f)] private void DebugForceDepleteAllEnemies() { for (int i = 0; i < _activeEnemiesList.Count; i++) { Enemy enemy = _activeEnemiesList[i]; if (enemy == null || enemy.statusSm.isDead) continue; Player player = MainGameManager.Player; enemy.TakeDepletion(player, 999999, false); } } private float GetSurfaceDistance(Vector3 origin, Enemy enemy) { if (enemy == null) return float.MaxValue; float colliderRadius = enemy.collisionSc != null ? enemy.collisionSc.colliderRadius : 0f; return Mathf.Max(0f, Vector3.Distance(origin, enemy.transform.position) - colliderRadius); } /// /// 获取所有可见敌人 /// public List GetVisibleEnemies(float radius = 50f) { return Query(radius).OnlyVisible().Candidates(); } /// /// 获取按屏幕X坐标从左到右排序的可见敌人列表 /// public List GetVisibleEnemiesSortedByScreenX(float radius = 50f) { List visibleEnemies = GetVisibleEnemies(radius); visibleEnemies.Sort((a, b) => { Vector3 screenA = MainGameManager.Player.viewSc.playerCamera.WorldToScreenPoint(a.CenterPoint.position); Vector3 screenB = MainGameManager.Player.viewSc.playerCamera.WorldToScreenPoint(b.CenterPoint.position); return screenA.x.CompareTo(screenB.x); }); return visibleEnemies; } } } }