123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733 |
- using System;
- using System.Collections.Generic;
- using System.Text;
- using CommonAI.RTS.Manhattan;
- using CommonAI.RTS;
- using CommonLang.Vector;
- using CommonLang;
- using CommonAI.ZoneClient;
- using CommonAI.Zone.Helper;
- using CommonAI.Zone.Formula;
- using CommonAI.Zone.Attributes;
- namespace CommonAI.Zone.Instance
- {
- //--------------------------------------------------------------------------------------------------------
- /// <summary>
- /// 所有自动电脑AI
- /// </summary>
- public class InstanceGuard : InstanceUnit, IGuardUnit, ViewTrigger.ViewTriggerListener
- {
- protected ViewTrigger mViewTrigger;
- protected HateSystem mHateSystem;
- protected StateAttackTo mRunningPath;
- protected StateFollowAndAttack mTracingTarget;
- protected StateFollowAndGuard mGuardTarget;
- protected StateBackToPosition mBackToPosition;
- protected Vector2 mOrginPosition;
- //protected TimeInterval<int> mCheckInGuardLimit;
- protected SimpleTrigger mNextCheckGuardLimit;
- public InstanceUnit TracingTarget
- {
- get
- {
- if (mTracingTarget != null) return mTracingTarget.TargetUnit;
- return null;
- }
- }
- public InstanceGuard(InstanceZone zone, UnitInfo info, string name, int force, int level)
- : base(zone, info, name, force, level)
- {
- //this.mCheckInGuardLimit = new TimeInterval<int>(Templates.CFG.AI_NPC_CHECK_IN_GUARD_LIMIT_TIME_MS);
- this.mNextCheckGuardLimit = new SimpleTrigger(Templates.CFG.AI_NPC_CHECK_IN_GUARD_LIMIT_TIME_MS);
- this.OnActivated += this.onUnitActivated;
- }
- protected override void onAdded(bool pointLv)
- {
- base.onAdded(pointLv);
- this.mHateSystem = TemplateManager.Factory.CreateHateSystem(this);
- this.mOrginPosition = new Vector2(X, Y);
- }
- protected override void Disposing()
- {
- base.Disposing();
- if (mViewTrigger != null) mViewTrigger.Dispose();
- mHateSystem.Clear();
- mRunningPath = null;
- mTracingTarget = null;
- mGuardTarget = null;
- mBackToPosition = null;
- mOrginPosition = null;
- this.mNextCheckGuardLimit = null;
- this.OnActivated -= this.onUnitActivated;
- }
- override protected void onResetAI()
- {
- mTracingTarget = null;
- mHateSystem.Clear();
- doSomething();
- }
- protected override void onDead(InstanceUnit killer)
- {
- base.onDead(killer);
- SetEnableView(false);
- }
- //--------------------------------------------------------------------------------------------------------
- #region View
- public void SetEnableView(bool view)
- {
- if (mViewTrigger != null)
- {
- this.mViewTrigger.Enable = view && !IsNature && !IsNoneSkill;
- }
- }
- private void initViewTrigger()
- {
- this.mViewTrigger = CreateViewTrigger(Parent);
- if (mViewTrigger != null)
- {
- this.mViewTrigger.setListener(this);
- }
- }
- protected virtual ViewTrigger CreateViewTrigger(InstanceZone zone)
- {
- if (Info.GuardRange > 0)
- {
- return new ViewTriggerRoundBody(zone, Info.GuardRange);
- }
- else
- {
- return new ViewTriggerBlind(zone);
- }
- }
- void ViewTrigger.ViewTriggerListener.onObjectEnterView(ViewTrigger src, InstanceZoneObject obj)
- {
- onAddEnemy(obj as InstanceUnit, true, AttackReason.Look);
- }
- void ViewTrigger.ViewTriggerListener.onObjectLeaveView(ViewTrigger src, InstanceZoneObject obj)
- {
- }
- bool ViewTrigger.ViewTriggerListener.select(ViewTrigger src, InstanceZoneObject obj)
- {
- if (obj == this)
- {
- return false;
- }
- else if ((obj is InstanceUnit))
- {
- InstanceUnit u = obj as InstanceUnit;
- if (!u.IsNature && !this.IsNature && Parent.IsAttackable(this, u, SkillTemplate.CastTarget.Enemy, AttackReason.Look, Info))
- {
- return true;
- }
- }
- return false;
- }
- #endregion
- //--------------------------------------------------------------------------------------------------------
- #region Action
- void IGuardUnit.AttackTo(ZoneWayPoint start, int peaceTime)
- {
- this.attackTo(start, peaceTime);
- }
- void IGuardUnit.SetOrginPosition(float x, float y)
- {
- this.setOrginPosition(x, y);
- }
- void IGuardUnit.PatrolWith(ZoneWayPoint start, int holdMinTimeMS, int holdMaxTimeMS, int peaceTime)
- {
- this.patrolWith(start, holdMinTimeMS, holdMaxTimeMS, peaceTime);
- }
- bool IGuardUnit.FollowAndAttack(InstanceUnit target, AttackReason reason)
- {
- return this.followAndAttack(target, reason);
- }
- void IGuardUnit.GuardUnit(InstanceUnit vip)
- {
- this.guardUnit(vip);
- }
- public override void doSomething()
- {
- if (CurrentState is StateSkill)
- {
- var target = TracingTarget;
- if (target != null)
- {
- if (tryMoveScatterTarget(target)) { return; }
- }
- }
- guard();
- }
- /// <summary>
- /// 设置警戒地点,如果在寻路或保护单位,则无效
- /// </summary>
- /// <param name="x"></param>
- /// <param name="y"></param>
- public virtual void setOrginPosition(float x, float y)
- {
- this.mOrginPosition.SetX(x);
- this.mOrginPosition.SetY(y);
- }
- public virtual Vector2 GetOrginPosition()
- {
- return mOrginPosition;
- }
- /// <summary>
- /// 寻路攻击目标
- /// </summary>
- /// <param name="src"></param>
- /// <param name="reason"></param>
- public virtual bool followAndAttack(InstanceUnit src, AttackReason reason)
- {
- if (IsNoneSkill) return false;
- if ((src != null))
- {
- if (Parent.IsAttackable(this, src, SkillTemplate.CastTarget.Enemy, reason, Info))
- {
- this.SetEnableView(false);
- mHateSystem.Add(src);
- if (TracingTarget != src)
- {
- //Console.WriteLine(" - - BBBBBB - - " + ((TracingTarget == null) ? "null" : TracingTarget.Name) + ", " + src.Name);
- mTracingTarget = new StateFollowAndAttack(this, src);
- }
- changeState(mTracingTarget);
- return true;
- }
- else
- {
- mHateSystem.Remove(src);
- }
- }
- return false;
- }
- /// <summary>
- /// 寻路并一路警戒
- /// </summary>
- /// <param name="path"></param>
- public virtual void attackTo(ZoneWayPoint path, int peaceTime = 0)
- {
- this.mRunningPath = new StateAttackToZoneWayPoint(this, path, peaceTime);
- changeState(this.mRunningPath);
- }
- /// <summary>
- /// 在路点范围内警戒
- /// </summary>
- /// <param name="wp"></param>
- /// <param name="holdMinTimeMS"></param>
- /// <param name="holdMaxTimeMS"></param>
- public virtual void patrolWith(ZoneWayPoint wp, int holdMinTimeMS, int holdMaxTimeMS, int peaceTime = 0)
- {
- this.mRunningPath = new StatePatrolWayPoint(this, wp, holdMinTimeMS, holdMaxTimeMS, peaceTime);
- changeState(this.mRunningPath);
- }
- /// <summary>
- /// 保护单位
- /// </summary>
- /// <param name="vip"></param>
- public virtual void guardUnit(InstanceUnit vip)
- {
- if (mGuardTarget == null || !mGuardTarget.IsActive || mGuardTarget.TargetUnit != vip)
- {
- mGuardTarget = new StateFollowAndGuard(this, vip, this.BodyBlockSize * 2 + vip.BodyBlockSize, Info.GuardRange);
- }
- changeState(mGuardTarget);
- }
- /// <summary>
- /// 待机
- /// </summary>
- public virtual void guard()
- {
- if(mHateSystem != null && mHateSystem.Count > 0)
- {
- if (followAndAttack(mHateSystem.GetHated(), AttackReason.Tracing))
- {
- return;
- }
- }
- mTracingTarget = null;
- SetEnableView(true);
- if (mGuardTarget != null && mGuardTarget.IsActive)
- {
- changeState(this.mGuardTarget);
- return;
- }
- if (mRunningPath != null && !mRunningPath.IsDone)
- {
- changeState(this.mRunningPath);
- return;
- }
- if (Moveable && MoveSpeedSEC > 0)
- {
- guardInPosition(mOrginPosition);
- return;
- }
- base.startIdle();
- }
- public virtual void guardInPosition(Vector2 pos)
- {
- changeState(new StateGuardInPosition(this, pos));
- }
- /// <summary>
- /// 立刻开始返回原点
- /// </summary>
- public virtual void backToOrgin()
- {
- mHateSystem.Clear();
- mTracingTarget = null;
- if (mGuardTarget != null && mGuardTarget.IsActive)
- {
- changeState(this.mGuardTarget);
- }
- else
- {
- mBackToPosition = new StateBackToPosition(this, mOrginPosition);
- changeState(mBackToPosition);
- }
- OnBackToOrgin();
- }
- /// <summary>
- /// 在一定范围内浪
- /// </summary>
- /// <param name="timeMS">浪多久</param>
- /// <param name="range">浪多远</param>
- public virtual void idleMove(int timeMS, int range)
- {
- changeState(new StateIdleMove(this, mOrginPosition, timeMS, range));
- }
- #endregion
- //--------------------------------------------------------------------------------------------------------
- #region Update
- protected override void onUpdateRecover()
- {
- if (mTracingTarget == null)
- {
- base.onUpdateRecover();
- }
- }
- override protected void onUpdate(bool slowRefresh)
- {
- base.onUpdate(slowRefresh);
- updateTracingTarget();
- updateRunningPath();
- updateGuardTarget();
- updateBackToOrgin();
- //updateHate();
- updateView();
- }
- protected virtual void updateTracingTarget()
- {
- if (mTracingTarget != null)
- {
- if (Parent.IsAttackable(this, mTracingTarget.TargetUnit, SkillTemplate.CastTarget.Enemy, AttackReason.Tracing, Info))
- {
- //有攻击目标//
- if ((CurrentState is StateSkill))
- {
- tryLaunchRandomSkillAndCancelCurrentSkill(TracingTarget, false);
- }
- else if (CurrentState is StateIdle)
- {
- tryMoveScatterTarget(TracingTarget);
- }
- }
- else
- {
- mHateSystem.Remove(mTracingTarget.TargetUnit);
- if (mTracingTarget == CurrentState)
- {
- doSomething();
- }
- mTracingTarget = null;
- }
- }
- }
- protected virtual void updateRunningPath()
- {
- if (mRunningPath != null)
- {
- if (CurrentState == mRunningPath)
- {
- if (mRunningPath.IsDone)
- {
- mRunningPath = null;
- }
- else if (mRunningPath.Target != null)
- {
- mOrginPosition.SetX(this.X);
- mOrginPosition.SetY(this.Y);
- }
- }
- else if (CurrentState is StateIdle)
- {
- changeState(this.mRunningPath);
- }
- }
- }
- protected virtual void updateGuardTarget()
- {
- //如果在寻路或保护,则实时更新OrginPosition//
- if (mGuardTarget != null)
- {
- if (!mGuardTarget.IsActive)
- {
- mGuardTarget = null;
- }
- else
- {
- mOrginPosition.SetX(mGuardTarget.TargetUnit.X);
- mOrginPosition.SetY(mGuardTarget.TargetUnit.Y);
- }
- }
- }
- protected virtual void updateBackToOrgin()
- {
- if (mBackToPosition != null)
- {
- if (mBackToPosition.IsDone)
- {
- mBackToPosition = null;
- }
- }
- if (Info.GuardRangeLimit > Info.GuardRange)
- {
- //if (mCheckInGuardLimit.Update(Parent.UpdateIntervalMS))
- if(mNextCheckGuardLimit != null && mNextCheckGuardLimit.IsTrigger())
- {
- if (!CMath.includeRoundPoint(X, Y, Info.GuardRangeLimit, mOrginPosition.X, mOrginPosition.Y))
- {
- backToOrgin();
- }
- else if (mTracingTarget != null)
- {
- if (!mTracingTarget.IsActive || !CMath.intersectRound(
- X, Y, Info.GuardRangeLimit,
- mTracingTarget.TargetUnit.X,
- mTracingTarget.TargetUnit.Y,
- mTracingTarget.TargetUnit.BodyHitSize))
- {
- backToOrgin();
- return;
- }
- }
- }
- }
- }
- protected virtual void updateView()
- {
- if (mViewTrigger != null)
- {
- mViewTrigger.onLookUpdate(X, Y);
- }
- }
- //protected virtual void updateHate(bool slowRefresh, int intervalMS)
- //{
- // if(slowRefresh && mHateSystem != null)
- // {
- // mHateSystem.Update(intervalMS);
- // }
- //}
- /// <summary>
- /// 攻击间歇,尝试换个位置,避免怪物堆在一个点
- /// </summary>
- protected virtual bool tryMoveScatterTarget(InstanceUnit target)
- {
- //只有单位为非碰撞时,才有这个需求//
- if (!this.IntersectObj)
- {
- if (CommonLang.CUtils.localTimeMS > mCheckAttackSpread && CUtils.RandomPercent(Parent.RandomN, Templates.CFG.AI_NPC_ATTACK_IDLE_SCATTER_PCT))
- {
- mCheckAttackSpread = CommonLang.CUtils.localTimeMS + Templates.CFG.AI_NPC_ATTACK_IDLE_INTERVAL;
- InstanceUnit block = null;
- Parent.ForEachNearObjects(X, Y, (InstanceZoneObject o, ref bool cancel) =>
- {
- if ((o != this) && (o is InstanceUnit) && Parent.TouchObject2(this, o))
- {
- block = o as InstanceUnit;
- cancel = true;
- }
- });
- if (block != null)
- {
- float degree = MathVector.getDegree(X, Y, target.X, target.Y);
- float distance = this.BodyBlockSize + block.BodyBlockSize;
- Vector2 turnL = new Vector2(X, Y);
- Vector2 turnR = new Vector2(X, Y);
- MathVector.movePolar(turnL, degree + CMath.PI_DIV_2, distance);
- MathVector.movePolar(turnR, degree - CMath.PI_DIV_2, distance);
- float dl = MathVector.getDistanceSquare(turnL.X, turnL.Y, target.X, target.Y);
- float dr = MathVector.getDistanceSquare(turnR.X, turnR.Y, target.X, target.Y);
- if (dl < dr)
- {
- this.startMoveTo(turnL.X, turnL.Y);
- }
- else
- {
- this.startMoveTo(turnR.X, turnR.Y);
- }
- return true;
- }
- }
- }
- return false;
- }
- #endregion
- //--------------------------------------------------------------------------------------------------------
- #region InternalEvents
- protected virtual void onUnitActivated(InstanceUnit unit)
- {
- initViewTrigger();
- }
- protected override void onStateChanged(State old_state, State state)
- {
- if (state is StateIdle)
- {
- followAndAttack(mHateSystem.GetHated(), AttackReason.Tracing);
- }
- if (old_state != null)
- {
- if (old_state == mBackToPosition)
- {
- mBackToPosition = null;
- }
- if (old_state == mTracingTarget)
- {
- if (mTracingTarget.IsNoWay)
- {
- mHateSystem.Remove(mTracingTarget.TargetUnit);
- mTracingTarget = null;
- }
- }
- }
- }
- protected override void onMoveBlockWithObject(InstanceZoneObject obj)
- {
- if (IsNoneSkill)
- {
- return;
- }
- if (obj is InstanceUnit)
- {
- followAndAttack(obj as InstanceUnit, AttackReason.MoveBlocked);
- }
- }
- protected override bool onBlockOther(InstanceZoneObject obj)
- {
- if (CurrentActionStatus == UnitActionStatus.Move)
- {
- return true;
- }
- if (CurrentActionStatus == UnitActionStatus.Idle)
- {
- //给自己友军让路//
- if (obj is InstanceUnit)
- {
- InstanceUnit u = obj as InstanceUnit;
- if (u.Force == this.Force)
- {
- return changeState(new StateMoveAway(this, u));
- }
- }
- }
- return false;
- }
- protected override void onDamaged(InstanceUnit attacker, AttackSource attack, int reduceHP)
- {
- if (IsNoneSkill)
- {
- return;
- }
- if(attacker.IsPet)
- {
- InstanceUnit master = attacker.Virtual.GetMasterUnit();
- if(master == null)
- {
- log.Warn("onDamaged: 找不到宠物主人:" + attacker.Info.ID + ", " + attacker.Parent.GetSceneID());
- }
- else
- {
- attacker = master;
- }
- }
- // 被攻击转火
- mHateSystem.OnHitted(attacker, attack, reduceHP);
- onAddEnemy(attacker, true, AttackReason.Damaged);
- }
- protected virtual void onAddEnemy(InstanceUnit target, bool group, AttackReason reason)
- {
- if (onAddEnemyInternal(target, group, reason))
- {
- if (group && Info.GuardRangeGroup > 0)
- {
- Parent.ForEachNearObjects(X, Y, Info.GuardRangeGroup, (InstanceZoneObject o, ref bool cancel) =>
- {
- if ((o != this) && (o is InstanceGuard))
- {
- InstanceGuard g = o as InstanceGuard;
- if (g.Force == this.Force && Parent.IsAttackable(g, target, SkillTemplate.CastTarget.Enemy, AttackReason.Look, Info))
- {
- if (CMath.includeRoundPoint(g.X, g.Y, g.Info.GuardRangeLimit, target.X, target.Y))
- {
- g.onAddEnemyInternal(target, true, reason);
- }
- }
- }
- });
- }
- }
- }
- protected bool onAddEnemyInternal(InstanceUnit target, bool group, AttackReason reason)
- {
- bool attack = true;
- if (mOnEnemyAdded != null)
- {
- mOnEnemyAdded.Invoke(this, target, ref attack);
- }
- if (attack)
- {
- if (!mHateSystem.Contains(target))
- {
- mHateSystem.Add(target);
- }
- followAndAttack(mHateSystem.GetHated(), reason);
- }
- return attack;
- }
- protected virtual void OnBackToOrgin()
- {
- }
- #endregion
- //--------------------------------------------------------------------------------------------------------
- #region Events
- protected override void clearEvents()
- {
- base.clearEvents();
- mOnEnemyAdded = null;
- }
- public delegate void EnemyAdded(InstanceUnit unit, InstanceUnit enemy, ref bool attack);
- private EnemyAdded mOnEnemyAdded;
- [EventTriggerDescAttribute("Add敌人")]
- public event EnemyAdded OnEnemyAdded { add { mOnEnemyAdded += value; } remove { mOnEnemyAdded -= value; } }
- #endregion
- //--------------------------------------------------------------------------------------------------------
- /// <summary>
- /// 移动状态
- /// </summary>
- public class StateMoveAway : State
- {
- private Vector2 target;
- private InstanceUnit other;
- public StateMoveAway(InstanceGuard unit, InstanceUnit other)
- : base(unit)
- {
- this.other = other;
- this.target = new Vector2(unit.X, unit.Y);
- float angle = MathVector.getDegree(other.X, other.Y, unit.X, unit.Y);
- angle = (float)(-CMath.PI_DIV_2 + unit.RandomN.NextDouble() * CMath.PI_F);
- MathVector.movePolar(target, angle, (unit.BodyBlockSize));
- }
- override public bool onBlock(State new_state)
- {
- return true;
- }
- override protected void onStart()
- {
- unit.SetActionStatus(UnitActionStatus.Move);
- }
- override protected void onUpdate()
- {
- unit.SetActionStatus(UnitActionStatus.Move);
- unit.faceTo(target.X, target.Y);
- MoveBlockResult result = unit.moveBlockTo(target.X, target.Y, unit.MoveSpeedSEC, zone.UpdateIntervalMS);
- if ((result.result & MoveResult.RESULTS_MOVE_END) != 0)
- {
- InstanceGuard guard = (unit as InstanceGuard);
- guard.doSomething();
- }
- }
- override protected void onStop()
- {
- }
- }
- //----------------------------------------------------------------------------------------------------------
- }
- //--------------------------------------------------------------------------------------------------------
- public class InstanceSummon : InstanceGuard, ISummonedUnit
- {
- public InstanceUnit SummonerUnit { get; set; }
- public InstanceSummon(InstanceZone zone, UnitInfo info, string name, int force, int level)
- : base(zone, info, name, force, level)
- {
- }
- override protected void onUpdate(bool slowRefresh)
- {
- base.onUpdate(slowRefresh);
- if ((PassTimeMS >= Info.LifeTimeMS) || (SummonerUnit != null && SummonerUnit.IsDead()))
- {
- kill();
- }
- }
- }
- //--------------------------------------------------------------------------------------------------------
- }
|