feat(enemy): EnemyAbilityBase 实现 IAttackCandidate 契约(自管圆形射程)
This commit is contained in:
@@ -16,7 +16,7 @@ namespace BaseGames.Enemies.Abilities
|
|||||||
/// - 受击/死亡时由 <see cref="EnemyBase"/> 调用 <see cref="Interrupt"/>。
|
/// - 受击/死亡时由 <see cref="EnemyBase"/> 调用 <see cref="Interrupt"/>。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DisallowMultipleComponent]
|
[DisallowMultipleComponent]
|
||||||
public abstract class EnemyAbilityBase : MonoBehaviour
|
public abstract class EnemyAbilityBase : MonoBehaviour, IAttackCandidate
|
||||||
{
|
{
|
||||||
[Header("配置 SO")]
|
[Header("配置 SO")]
|
||||||
[SerializeField] protected EnemyAbilitySO _config;
|
[SerializeField] protected EnemyAbilitySO _config;
|
||||||
@@ -43,6 +43,24 @@ namespace BaseGames.Enemies.Abilities
|
|||||||
/// <summary>BD 任务统一查询入口:当前是否可用(冷却完毕且未执行中)。</summary>
|
/// <summary>BD 任务统一查询入口:当前是否可用(冷却完毕且未执行中)。</summary>
|
||||||
public virtual bool CanUse => !_isRunning && !IsOnCooldown && _enemy != null && _enemy.IsAlive;
|
public virtual bool CanUse => !_isRunning && !IsOnCooldown && _enemy != null && _enemy.IsAlive;
|
||||||
|
|
||||||
|
// ── IAttackCandidate(供 EnemyAttackSelector 选招)──────────────────
|
||||||
|
public bool RequiresLineOfSight => _config != null && _config.requiresLineOfSight;
|
||||||
|
public bool RequiresGrounded => _config != null && _config.requiresGrounded;
|
||||||
|
public float Weight => _config != null ? _config.weight : 0f;
|
||||||
|
public int Priority => _config != null ? _config.priority : 0;
|
||||||
|
|
||||||
|
/// <summary>本招圆形攻击范围内是否有玩家(招式自管其射程;LOS 复用敌人级 IsPlayerVisible)。</summary>
|
||||||
|
public virtual bool InAttackRange()
|
||||||
|
{
|
||||||
|
if (_config == null || _config.rangeRadius <= 0f
|
||||||
|
|| _enemy == null || _enemy.PlayerTransform == null) return false;
|
||||||
|
float sign = _transform.localScale.x < 0f ? -1f : 1f;
|
||||||
|
Vector2 origin = (Vector2)_transform.position
|
||||||
|
+ new Vector2(_config.rangeOffset.x * sign, _config.rangeOffset.y);
|
||||||
|
float r = _config.rangeRadius;
|
||||||
|
return ((Vector2)_enemy.PlayerTransform.position - origin).sqrMagnitude <= r * r;
|
||||||
|
}
|
||||||
|
|
||||||
protected virtual void Awake()
|
protected virtual void Awake()
|
||||||
{
|
{
|
||||||
_enemy = GetComponentInParent<EnemyBase>();
|
_enemy = GetComponentInParent<EnemyBase>();
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
namespace BaseGames.Enemies.Abilities
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 攻击选择器的候选契约。攻击类 <see cref="EnemyAbilityBase"/> 实现之;
|
||||||
|
/// 抽象出来使 <see cref="EnemyAttackSelector"/> 可脱离 MonoBehaviour 单测。
|
||||||
|
/// </summary>
|
||||||
|
public interface IAttackCandidate
|
||||||
|
{
|
||||||
|
bool CanUse { get; } // 未冷却 + 未运行 + 存活
|
||||||
|
bool RequiresLineOfSight { get; } // 是否需要视线(由敌人级 LOS 提供)
|
||||||
|
bool RequiresGrounded { get; } // 是否需要着地
|
||||||
|
float Weight { get; } // WeightedRandom 权重
|
||||||
|
int Priority { get; } // Priority 优先级
|
||||||
|
bool InAttackRange(); // 招式自管圆形射程内是否有玩家
|
||||||
|
bool Execute(); // 触发本招
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user