using System; using BaseGames.AI; namespace BaseGames.Enemies { /// /// 交战层:发现玩家之后怎么打。骨架只认这四件事——从哪个态进、什么条件进、 /// 边标签是什么、内部怎么打。新增一种打法 = 新增一个实现,骨架与其他模块不受影响。 /// /// CanEngage 归本模块所有是关键:像"冲锋冷却门"这种只对某一种打法有意义的条件, /// 若留在骨架上就会变成骨架的开关字段,并与其他开关互相耦合。 /// /// 实现注意:模块会经 [SerializeReference] 反序列化,构造函数不保证被调用。 /// 不要在构造函数里预计算缓存或做参数校验——缓存用惰性属性,校验放 Build()。 /// /// 为何本层只需单阶段 Build(而未发现层要拆 Declare/Link):骨架只把边**指向** /// EntryState,从不在本模块自己的状态上挂边,所以 Build 内声明的边不会被外部抢占。 /// 将来若修改骨架、使其向交战态挂边,必须先回来重新审视本契约。 /// public interface IEngagementModule { /// 声明交战态与脱战边。 /// 脱战后回到的未发现态,由骨架传入。 void Build(BrainBuilder b, string rest); /// 骨架从未发现态 / 警觉态连过来的目标。 string EntryState { get; } /// 进入交战的条件。惰性构建并缓存。 Func CanEngage { get; } /// CanEngage 的可读标签(trace / 图导出用)。 string EngageLabel { get; } } }