using CommonAI.RTS; using CommonLang.Vector; using CommonAI.Zone.Helper; using CommonLang; using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace CommonAI.Zone.Instance { /// /// 纯手动控制AI,完全没有自动成分 /// public class InstanceManual : InstanceUnit { private StateFollowAndAttack mAttackTargget; private TimeExpire mWaitCommand; public InstanceManual(InstanceZone zone, UnitInfo info, string name, int force, int level) : base(zone, info, name, force, level) { } public void queueDoAction(float timeSEC, string actionName, State.StateStopHandler over = null) { mAttackTargget = null; QueueStateActionTime state = new QueueStateActionTime(this, timeSEC, actionName); if (over != null) { state.AddStopOnce(over); } queueState(state); } public void queueIdle(float timeSEC, State.StateStopHandler over = null) { mAttackTargget = null; QueueStateIdleTime state = new QueueStateIdleTime(this, timeSEC); if (over != null) { state.AddStopOnce(over); } queueState(state); } public void queueMoveTo(float x, float y, State.StateStopHandler over = null) { mAttackTargget = null; QueueStateMoveTo state = new QueueStateMoveTo(this, x, y); if (over != null) { state.AddStopOnce(over); } queueState(state); } public void queueLaunchSkill(int skillID, bool random, State.StateStopHandler over = null) { mAttackTargget = null; QueueStateLaunchSkill state = new QueueStateLaunchSkill(this, skillID, random, over); queueState(state); } public void focuseAttack(InstanceUnit targget) { mAttackTargget = new StateFollowAndAttack(this, targget); changeState(mAttackTargget); } public void wait(float timeSEC, WaitTimeHandler over) { // 强制中断前一个等待指令 if (mWaitCommand != null) { mWaitCommand.Tag.Invoke(); } mWaitCommand = new TimeExpire(over, (int)(timeSEC * 1000)); } protected override void onUpdate(bool slowRefresh) { base.onUpdate(slowRefresh); if (mWaitCommand != null && mWaitCommand.Update(Parent.UpdateIntervalMS)) { mWaitCommand.Tag.Invoke(); mWaitCommand = null; } } protected override void onAction(ObjectAction act) { if (IsDead()) { return; } if (act is UnitStopMoveAction) { doSomething(); } else if (act is UnitMoveAction) { UnitMoveAction move = act as UnitMoveAction; startMoveTo(move.x, move.y); } else if (act is UnitAxisAction) { } else if (act is UnitLaunchSkillAction) { UnitLaunchSkillAction sk = act as UnitLaunchSkillAction; launchSkill(sk.SkillID, new InstanceUnit.LaunchSkillParam(sk.TargetObjID, sk.SpellTargetPos, sk.IsAutoFocusNearTarget)); } else if (act is UnitFaceToAction) { UnitFaceToAction ufa = act as UnitFaceToAction; this.faceTo(ufa.Direction); } else if (act is UnitSlipAction) { // do nothing } else if (act is UnitGuardAction) { // do nothing } else if (act is UnitFocuseTargetAction) { // do nothing } } public delegate void WaitTimeHandler(); class QueueStateMoveTo : State { private readonly float targetX; private readonly float targetY; private bool isEnd = false; private MoveAI moveAI; public QueueStateMoveTo(InstanceUnit unit, float x, float y) : base(unit) { this.targetX = x; this.targetY = y; } override public bool onBlock(State new_state) { if (unit.IsDead()) return true; return isEnd; } override protected void onStart() { unit.SetActionStatus(UnitActionStatus.Move); this.moveAI = new MoveAI(unit); this.moveAI.FindPath(targetX, targetY); } override protected void onUpdate() { if (!isEnd) { unit.faceTo(targetX, targetY); MoveBlockResult result = moveAI.Update(); if ((result.result & MoveResult.MOVE_RESULT_NO_WAY) != 0) { isEnd = true; unit.doSomething(); } else if ((result.result & MoveResult.RESULTS_MOVE_END) != 0) { float r = Math.Max(zone.MinStep, unit.BodyBlockSize); if (CMath.includeRoundPoint(unit.X, unit.Y, r, targetX, targetY)) { isEnd = true; unit.doSomething(); } } else { float r = Math.Max(zone.MinStep, unit.BodyBlockSize); if (CMath.includeRoundPoint(unit.X, unit.Y, r, targetX, targetY)) { isEnd = true; unit.doSomething(); } } } } override protected void onStop() { } } class QueueStateLaunchSkill : State { private readonly int SkillID; private readonly bool IsRandom; private readonly StateStopHandler SkillOver; private StateSkill mSkillState; public QueueStateLaunchSkill(InstanceUnit unit, int skillID, bool random, StateStopHandler over) : base(unit) { this.SkillID = skillID; this.IsRandom = random; this.SkillOver = over; } public override bool onBlock(State new_state) { if (unit.IsDead()) return true; if (new_state is StateSkill) { return true; } return mSkillState != null; } protected override void onStart() { } protected override void onUpdate() { if (IsRandom) { mSkillState = unit.launchRandomSkillForAll(new InstanceUnit.LaunchSkillParam()); } else { mSkillState = unit.launchSkill(SkillID, new InstanceUnit.LaunchSkillParam()); } if (mSkillState != null && SkillOver != null) { mSkillState.AddStopOnce(SkillOver); } } protected override void onStop() { if (mSkillState == null && SkillOver != null) { SkillOver.Invoke(unit, this); } } } class QueueStateIdleTime : State { private readonly TimeExpire mIdleTime; public QueueStateIdleTime(InstanceUnit unit, float timeSEC) : base(unit) { mIdleTime = new TimeExpire((int)(timeSEC * 1000)); } override public bool onBlock(State new_state) { if (unit.IsDead()) return true; return mIdleTime.IsEnd; } override protected void onStart() { unit.SetActionStatus(UnitActionStatus.Idle); } override protected void onUpdate() { if (mIdleTime.Update(zone.UpdateIntervalMS)) { unit.doSomething(); } } override protected void onStop() { } } class QueueStateActionTime : QueueStateIdleTime { private readonly string ActionName; public QueueStateActionTime(InstanceUnit unit, float timeSEC, string actionName) : base(unit, timeSEC) { this.ActionName = actionName; } override protected void onStart() { unit.queueEvent(new UnitDoActionEvent(unit.ID, ActionName)); } } } }