using System;
using BaseGames.AI;
namespace BaseGames.Enemies
{
///
/// Boss 图的共享建态片段。与 同级——是静态建态原语,
/// 不是可插拔模块:Boss 图手写,重复的形状抽成片段即可,不需要 SO 下拉与多态序列化。
///
public static class BossFragments
{
///
/// 阶段过渡态:进入时发起过渡(无敌 + 演出由 BossBase 负责),过渡结束后由调用方挂出边。
/// 只发起一次——放 OnEnter 而非 Tick,因为 BossBase.BeginPhaseTransition 对重入会告警。
///
public static BrainBuilder.StateBuilder PhaseTransition(
BrainBuilder b, string state, int targetPhase, float invincibleDuration)
{
if (targetPhase < 0)
throw new ArgumentOutOfRangeException(nameof(targetPhase),
$"BossFragments.PhaseTransition: 状态 '{state}' 的目标阶段不能为负。");
if (invincibleDuration <= 0f)
throw new ArgumentOutOfRangeException(nameof(invincibleDuration),
$"BossFragments.PhaseTransition: 状态 '{state}' 的无敌时长必须 > 0——" +
"为 0 意味着过渡演出期间可被打断,这不是阶段过渡的语义。");
return b.DeclareState(state)
.OnEnter(x =>
{
x.Locomotion.Stop();
x.Combat.InterruptAbilities();
x.Boss.BeginPhaseTransition(targetPhase, invincibleDuration);
});
}
///
/// 一组「逼近 ↔ 到射程选招攻击」。转发到 ApproachAttackEngagement 的共享实现,
/// 使模块路径与 Boss 图路径永远是同一份行为。
/// 返回逼近态的 builder,调用方可继续挂阶段过渡等出边。
///
public static BrainBuilder.StateBuilder ApproachAttack(
BrainBuilder b, string approach, string attack, string rest)
=> ApproachAttackEngagement.Declare(b, approach, attack, rest);
///
/// 移动到第 index 个竞技场锚点(),到位后由调用方挂出边。
/// 坐标经 IBossControl 取得——声明层的 lambda 不得闭包捕获具体实例。
///
public static BrainBuilder.StateBuilder MoveToAnchor(BrainBuilder b, string state, int index)
{
if (index < 0)
throw new ArgumentOutOfRangeException(nameof(index),
$"BossFragments.MoveToAnchor: 状态 '{state}' 的锚点下标不能为负。");
return b.DeclareState(state)
.OnEnter(x => x.Locomotion.MoveTo(x.Boss.AnchorAt(index)))
.OnExit (x => x.Locomotion.Stop());
}
/// 共享条件:已到达第 index 个锚点(容差内)。
public static Func AtAnchor(int index, float tolerance = 0.2f)
=> x => x.Boss.DistanceToAnchor(index) <= tolerance;
}
}