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));
}
}
}
}