123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540 |
- using CommonAI.Zone;
- using CommonAI.Zone.Helper;
- using CommonAI.Zone.Instance;
- using CommonLang;
- using CommonLang.Vector;
- using System;
- using static CommonAI.Zone.Instance.InstanceUnit;
- namespace XmdsCommonServer.Plugin.Units
- {
- public class XmdsInstanceUnitStateMachine
- {
- abstract public class XmdsStateFollow : InstanceUnit.State
- {
- public enum MoveState
- {
- Hold,
- Move,
- }
- // 被追目标
- private IPositionObject target;
- // 如果被单位碰撞,则向左或右挪动//
- private MoveAI moveAI;
- // 检测切换走停的间隔时间 //
- readonly private State<MoveState> state = new State<MoveState>(MoveState.Move);
- readonly private bool begin_in_min_range;
- // 检测切换走停的间隔时间 //
- private TimeInterval<int> start_move_hold_time;
- public abstract bool IsActive { get; }
- public bool IsNoWay { get { if (moveAI != null) { return moveAI.IsNoWay; } return false; } }
- public IPositionObject Target { get { return target; } }
- public MoveState FollowState { get { return state.Value; } }
- /// <summary>
- /// Hold到Move之间的检测间隔
- /// </summary>
- public int StartMoveHoldTimeMS
- {
- get { return (start_move_hold_time != null) ? start_move_hold_time.IntervalTimeMS : 0; }
- set
- {
- if (value > 0 && value != StartMoveHoldTimeMS)
- {
- start_move_hold_time = new TimeInterval<int>(value);
- }
- }
- }
- public virtual void MarkCannotArriveToAttack() { }
- public XmdsStateFollow(InstanceUnit unit, InstanceZoneObject target, bool beginInMinRange = true) : base(unit)
- {
- this.begin_in_min_range = beginInMinRange;
- this.target = target;
- this.moveAI = new MoveAI(unit);
- }
- public void ChangeMoveTarget(IPositionObject target)
- {
- if (moveAI.Target != target)
- {
- this.target = target;
- this.moveAI = new MoveAI(unit);
- }
- }
- public override bool onBlock(InstanceUnit.State new_state)
- {
- return true;
- }
- protected override void onStart()
- {
- if (cheekBeginInRange())
- {
- state.ChangeState(MoveState.Hold);
- unit.SetActionStatus(UnitActionStatus.Idle);
- }
- else
- {
- state.ChangeState(MoveState.Move);
- unit.SetActionStatus(UnitActionStatus.Move);
- moveAI.FindPath(target);
- }
- }
- protected override void onUpdate()
- {
- if (!IsActive)
- {
- unit.doSomething();
- }
- else
- {
- switch (FollowState)
- {
- case MoveState.Move:
- // 进入最小追踪距离 //
- if (CheckTargetInMinRange() == true)
- {
- changeToHold();
- }
- else
- {
- if (!this.unit.IsCannotMove)
- {
- if (moveAI.Target == null)
- {
- moveAI.FindPath(target);
- }
- moveAI.Update();
- }
- if (moveAI.IsNoWay)
- {
- if (CheckTargetInMaxRange() == true)
- {
- changeToHold();
- }
- else
- {
- //System.Console.WriteLine("标记不可攻击:" + this.unit.Name);
- this.MarkCannotArriveToAttack();
- unit.doSomething();
- }
- }
- }
- break;
- case MoveState.Hold:
- // 超过最大追踪范围 //
- if ((start_move_hold_time == null || start_move_hold_time.Update(zone.UpdateIntervalMS)) && (CheckTargetInMaxRange() == false))
- {
- changeToMove();
- }
- else
- {
- onUpdateFollowed(target);
- }
- break;
- }
- }
- }
- protected override void onStop() { }
- private bool cheekBeginInRange()
- {
- if (begin_in_min_range)
- {
- return CheckTargetInMinRange();
- }
- else
- {
- return CheckTargetInMaxRange();
- }
- }
- private void changeToMove()
- {
- state.ChangeState(MoveState.Move);
- unit.SetActionStatus(UnitActionStatus.Move);
- moveAI.FindPath(target);
- onInRangeChanged();
- onChangedToMove(target);
- }
- private void changeToHold()
- {
- state.ChangeState(MoveState.Hold);
- unit.SetActionStatus(UnitActionStatus.Idle);
- moveAI.Pause();
- onInRangeChanged();
- onChangedToHold(target);
- }
- /// <summary>
- /// 检查目标是否在跟随范围内。
- /// 检测为True,停止移动。
- /// </summary>
- protected abstract bool CheckTargetInMinRange();
- /// <summary>
- /// 检查目标是否在跟随范围内。
- /// 检测为False,开始移动。
- /// </summary>
- protected abstract bool CheckTargetInMaxRange();
- /// <summary>
- /// 行为改变
- /// </summary>
- protected virtual void onInRangeChanged()
- {
- }
- /// <summary>
- /// 目标已经被追踪到
- /// </summary>
- /// <param name="target"></param>
- protected virtual void onUpdateFollowed(IPositionObject target)
- {
- }
- /// <summary>
- /// 开始移动
- /// </summary>
- /// <param name="target"></param>
- protected virtual void onChangedToMove(IPositionObject target)
- {
- }
- /// <summary>
- /// changeToHold
- /// </summary>
- /// <param name="target"></param>
- protected virtual void onChangedToHold(IPositionObject target)
- {
- }
- }
- public class XmdsStateFollowAndAttack : XmdsStateFollow
- {
- /*readonly private*/
- InstanceUnit targetUnit;
- private SkillTemplate.CastTarget expectTarget;
- private TimeInterval<int> checkAdjustLaunchSkillTime;
- private InstanceUnit.SkillState launchSkill;
- private bool can_auto_focus_near_target;
- private bool can_random_skill = true;
- private bool can_attack = true;
- private float min_distance;
- private float max_distance;
- /// <summary>
- /// 是否追踪
- /// </summary>
- /// <returns></returns>
- override public bool IsActive
- {
- get { return can_attack && targetUnit.IsActive; }
- }
- public InstanceUnit.SkillState ExpectSkillState
- {
- get { return launchSkill; }
- set
- {
- launchSkill = value;
- expectTarget = value.Data.ExpectTarget;
- }
- }
- /** 标记不能达到目的,并攻击目标 */
- public override void MarkCannotArriveToAttack()
- {
- this.can_attack = false;
- }
- public SkillTemplate ExpectSkill
- {
- get { return (launchSkill != null) ? launchSkill.Data : unit.DefaultSkill; }
- }
- public InstanceUnit TargetUnit
- {
- get { return targetUnit; }
- set { targetUnit = value; }
- }
- public SkillTemplate.CastTarget ExpectTarget
- {
- get { return expectTarget; }
- }
- public bool IsLaunchRandomSkill
- {
- get { return can_random_skill; }
- set { can_random_skill = value; }
- }
- public bool IsAutoFocusNearTarget
- {
- get { return can_auto_focus_near_target; }
- set { can_auto_focus_near_target = value; }
- }
- public XmdsStateFollowAndAttack(
- InstanceUnit unit,
- InstanceUnit target,
- SkillTemplate.CastTarget expectTarget = SkillTemplate.CastTarget.Enemy,
- bool autoFocusNearTarget = false,
- InstanceUnit.SkillState lanuchSkill = null)
- : base(unit, target, false)
- {
- this.targetUnit = target;
- this.expectTarget = expectTarget;
- this.can_auto_focus_near_target = autoFocusNearTarget;
- this.StartMoveHoldTimeMS = zone.Templates.CFG.AI_FOLLOW_AND_ATTACK_HOLD_TIME_MS;
- this.launchSkill = lanuchSkill;
- }
- protected override void onStart()
- {
- this.resetMaxMinRange();
- this.checkAdjustLaunchSkillTime = new TimeInterval<int>(zone.Templates.CFG.AI_FOLLOW_AND_ATTACK_HOLD_TIME_MS);
- this.launchSkill = unit.getRandomLaunchableExpectSkill(expectTarget);
- base.onStart();
- }
- protected override void onUpdateFollowed(IPositionObject target)
- {
- this.can_attack = zone.IsAttackable(unit, targetUnit, expectTarget, AttackReason.Tracing, this.ExpectSkill);
- if (can_attack)
- {
- unit.faceTo(target.X, target.Y);
- if (TryLaunchSkill() == null)
- {
- SkillTemplate expect_skill = ExpectSkill;
- if (expect_skill != null && expect_skill.AttackKeepRange > 0)
- {
- if (checkAdjustLaunchSkillTime.IntervalTimeMS == 0 || checkAdjustLaunchSkillTime.Update(zone.UpdateIntervalMS))
- {
- if (CUtils.RandomPercent(zone.RandomN, zone.Templates.CFG.AI_FOLLOW_AND_ATTACK_ADJUST_ESCAPE_PCT))
- {
- unit.startAdjustLaunchSkill(expect_skill, targetUnit, this.OnEndAdjustKeepRange);
- }
- }
- }
- }
- }
- }
- protected override void onStop()
- {
- base.onStop();
- }
- protected override void onUpdate()
- {
- if (IsActive)
- {
- resetMaxMinRange();
- }
- base.onUpdate();
- }
- private void resetMaxMinRange()
- {
- var expect_skill = ExpectSkillState;
- min_distance = unit.BodyBlockSize + targetUnit.BodyBlockSize;
- max_distance = min_distance;//Math.Max(min_distance, unit.BodyBlockSize + targetUnit.BodyHitSize);
- bool needCheck = true;
- if (expect_skill == null)
- {
- var new_skill = unit.getRandomLaunchableExpectSkill(targetUnit, expectTarget, AttackReason.Tracing, true);
- if (new_skill != null)
- {
- ExpectSkillState = new_skill;
- expect_skill = new_skill;
- needCheck = false;
- }
- }
- if (expect_skill != null)
- {
- if (can_random_skill)
- {
- if (needCheck == true && !expect_skill.checkTargetRange(targetUnit))
- {
- var new_skill = unit.getRandomLaunchableExpectSkill(targetUnit, expectTarget, AttackReason.Tracing, true);
- if (new_skill != null)
- {
- ExpectSkillState = new_skill;
- expect_skill = new_skill;
- }
- }
- }
- float skill_distance = unit.GetSkillAttackRange(expect_skill.Data);
- float half = (skill_distance - min_distance) / 2;
- if (expect_skill.Data.AttackKeepRange > 0 && expect_skill.Data.AttackRange > expect_skill.Data.AttackKeepRange)
- {
- min_distance = Math.Max(min_distance, unit.GetSkillAttackRange(expect_skill.Data.AttackKeepRange) + targetUnit.BodyBlockSize);
- max_distance = Math.Max(max_distance, min_distance);
- }
- else if (half > 0)
- {
- min_distance = min_distance + half;
- max_distance = Math.Max(max_distance, min_distance);
- }
- else
- {
- min_distance = Math.Max(min_distance, skill_distance + targetUnit.BodyBlockSize);
- max_distance = Math.Max(max_distance, min_distance);
- }
- max_distance = Math.Max(max_distance, skill_distance + targetUnit.BodyHitSize);
- }
- }
- protected override bool CheckTargetInMaxRange()
- {
- return CMath.includeRoundPoint(unit.X, unit.Y, max_distance, targetUnit.X, targetUnit.Y);
- }
- protected override bool CheckTargetInMinRange()
- {
- return CMath.includeRoundPoint(unit.X, unit.Y, min_distance, targetUnit.X, targetUnit.Y);
- }
- protected virtual bool OnEndAdjustKeepRange(InstanceUnit.StateMove m)
- {
- unit.faceTo(Target.X, Target.Y);
- unit.changeState(this);
- return true;
- }
- protected virtual SkillTemplate TryLaunchSkill()
- {
- if (launchSkill == null)
- {
- this.launchSkill = unit.getRandomLaunchableExpectSkill(expectTarget);
- }
- InstanceUnit.StateSkill ret = null;
- Vector2 targetPos = targetUnit == null ? null : new Vector2(targetUnit.X, targetUnit.Y);
- if (launchSkill != null)
- {
- ret = unit.launchSkill(launchSkill.ID, new InstanceUnit.LaunchSkillParam(targetUnit.ID, targetPos, can_auto_focus_near_target, false, 0, true, true));
- if (ret != null)
- {
- return ret.SkillData;
- }
- }
- if (can_random_skill)
- {
- ret = unit.launchRandomSkill(expectTarget, new InstanceUnit.LaunchSkillParam(targetUnit.ID, targetPos, can_auto_focus_near_target, false, 0, true, true));
- if (ret != null)
- {
- return ret.SkillData;
- }
- }
- return null;
- }
- public void ChangeAttackTarget(InstanceUnit.SkillState expectSkill, InstanceUnit target)
- {
- TargetUnit = target;
- ExpectSkillState = expectSkill;
- ChangeMoveTarget(target);
- }
- }
- /// <summary>
- /// 嘲讽状态
- /// </summary>
- public class XmdsInstanceUnitStateMock : XmdsStateFollow, IStateNoneControllable
- {
- private InstanceUnit targetUnit;
- // 是否能攻击
- private bool can_attack = true;
- //标记失效
- public bool mMarkRemove = false;
- private float max_distance;
- public override bool IsActive
- {
- get
- {
- return targetUnit.IsActive && !mMarkRemove;
- }
- }
- public XmdsInstanceUnitStateMock(InstanceUnit unit, InstanceUnit targetUnit)
- : base(unit, targetUnit, false)
- {
- this.targetUnit = targetUnit;
- this.StartMoveHoldTimeMS = zone.Templates.CFG.AI_FOLLOW_AND_ATTACK_HOLD_TIME_MS;
- this.max_distance = unit.DefaultSkill.AttackRange - targetUnit.BodyBlockSize;
- }
- public InstanceUnit GetTargetUnit() { return this.targetUnit; }
- protected override void onStart()
- {
- unit.SetActionStatus(UnitActionStatus.ServerSyncMove);
- //unit.SendForceSync();
- base.onStart();
- }
- protected override void onStop()
- {
- unit.doSomething();
- base.onStop();
- }
- public override bool onBlock(InstanceUnit.State new_state)
- {
- if (!IsActive || (unit.IsDead() && new_state is StateDead))
- {
- return true;
- }
- if (new_state is XmdsInstanceUnitStateMock)
- {
- return true;
- }
- else if (new_state is StateSkill)
- {
- StateSkill ss = new_state as StateSkill;
- // 反击或者状态解除//
- if (ss.Skill.GetSkillType() == XmdsSkillType.normalAtk)
- {
- return true;
- }
- }
- return false;
- }
- protected override void onUpdateFollowed(IPositionObject target)
- {
- this.can_attack = zone.IsAttackable(unit, targetUnit, SkillTemplate.CastTarget.Enemy, AttackReason.Tracing, this.unit.DefaultSkill);
- if (can_attack)
- {
- unit.faceTo(targetUnit.X, targetUnit.Y);
- unit.launchSkill(this.unit.DefaultSkillStatus(), new InstanceUnit.LaunchSkillParam(targetUnit.ID));
- }
- }
- protected override bool CheckTargetInMinRange()
- {
- return CMath.includeRoundPoint(unit.X, unit.Y, max_distance, targetUnit.X, targetUnit.Y);
- }
- protected override bool CheckTargetInMaxRange()
- {
- return CMath.includeRoundPoint(unit.X, unit.Y, max_distance, targetUnit.X, targetUnit.Y);
- }
- public State AsState()
- {
- return this;
- }
- }
- }
- }
|