using NUnit.Framework; using BaseGames.AI; using BaseGames.Enemies; namespace BaseGames.Tests.EditMode.AI { public class RushEngagementTests { const string Rest = "Rest"; // 单独跑交战模块:手搓一个最小 rest 态,直接以交战入口为图入口。 static AiRuntime RunAlone(RushEngagement m, FakeAiContext ctx) { var b = new BrainBuilder(); AiStateFragments.Locomotion(b, Rest, LocomotionMode.Patrol); m.Build(b, Rest); b.Entry(m.EntryState); return new AiRuntime(b.Build(), ctx); } [Test] public void OnLostTarget_CanEngage_IsChaseZoneOnly() { var m = new RushEngagement("rush", RushExit.OnLostTarget); var ctx = new FakeAiContext(); ctx.C.CanUse = false; // 冷却中 ctx.S.Chase = true; Assert.IsTrue(m.CanEngage(ctx)); // 不看冷却 Assert.AreEqual("InChaseZone", m.EngageLabel); } [Test] public void Committed_CanEngage_AlsoRequiresOffCooldown() { var m = new RushEngagement("rush", RushExit.Committed); var ctx = new FakeAiContext(); ctx.S.Chase = true; ctx.C.CanUse = false; Assert.IsFalse(m.CanEngage(ctx)); // CD 中不进 ctx.C.CanUse = true; Assert.IsTrue(m.CanEngage(ctx)); Assert.AreEqual("InChaseZone+offCD", m.EngageLabel); } [Test] public void OnLostTarget_ExitsWhenAllZonesLost() { var ctx = new FakeAiContext { }; ctx.S.Chase = true; var rt = RunAlone(new RushEngagement("rush", RushExit.OnLostTarget), ctx); Assert.AreEqual(RushEngagement.Rush, rt.CurrentStateName); rt.Tick(0.1f); Assert.AreEqual(RushEngagement.Rush, rt.CurrentStateName); // 还在追逐区 ctx.S.Chase = false; ctx.S.Vision = false; rt.Tick(0.1f); Assert.AreEqual(Rest, rt.CurrentStateName); } [Test] public void Committed_NotInterruptedByLosingTarget() { var ctx = new FakeAiContext(); ctx.S.Chase = true; var rt = RunAlone(new RushEngagement("rush", RushExit.Committed), ctx); Assert.AreEqual(RushEngagement.Rush, rt.CurrentStateName); ctx.S.Chase = false; ctx.S.Vision = false; // 中途丢失感知 rt.Tick(0.1f); Assert.AreEqual(RushEngagement.Rush, rt.CurrentStateName); // 冲锋不被打断 ctx.C.Running = null; // 冲锋跑完 rt.Tick(0.1f); Assert.AreEqual(Rest, rt.CurrentStateName); } [Test] public void Build_Throws_WhenAbilityMissing() { var b = new BrainBuilder(); AiStateFragments.Locomotion(b, Rest, LocomotionMode.Patrol); var m = new RushEngagement(); // 未配能力 Assert.Throws(() => m.Build(b, Rest)); } } }