using System;
|
using UnityEngine;
|
|
public class KillUntilDieData : HeroAI_Data
|
{
|
public uint targetServerInstID;
|
public int defaultSkillID;
|
}
|
|
/// <summary>
|
/// 执行普攻攻击致死的AI逻辑
|
/// </summary>
|
public class HeroAI_KillUntilDie : HeroAI_Base
|
{
|
private uint m_TargetID;
|
private int m_FirstSkill;
|
private float m_LastUseSkillTime;
|
private bool m_LimitOnce;
|
private bool m_ActiveInterrupt;
|
private bool m_IsMovingToTarget;
|
|
public override bool Condition()
|
{
|
GA_Hero _hero = PlayerDatas.Instance.hero;
|
if (_hero == null)
|
{
|
return false;
|
}
|
|
if (_hero.aiHandler.currentType == E_HeroAIType.KillUntilDie)
|
{
|
return true;
|
}
|
|
return false;
|
}
|
|
public override void Enter()
|
{
|
m_IsMovingToTarget = false;
|
m_FirstSkill = -1;
|
m_TargetID = 0;
|
m_LimitOnce = false;
|
m_ActiveInterrupt = false;
|
|
GA_Hero _hero = PlayerDatas.Instance.hero;
|
|
if (_hero == null)
|
{
|
return;
|
}
|
|
byte _type = (byte)E_HeroAIType.KillUntilDie;
|
KillUntilDieData _data = _hero.aiHandler.aiData[_type] as KillUntilDieData;
|
m_TargetID = _data.targetServerInstID;
|
m_FirstSkill = _data.defaultSkillID;
|
|
UserInputHandler.OnCirclePanelTouched += OnActiveInterrupt;
|
UserInputHandler.OnClickedFloor += OnClickFloor;
|
HeroBehaviour.OnUserClickSkill += OnUserClickSkill;
|
GA_Hero.OnLockTargetChanged += OnLockTargetChanged;
|
HeroBehaviour.OnStartHandupAI += OnStartHandupAI;
|
MapTransferUtility.s_OnHeroStartMoveToNPC += OnStartMoveToNpc;
|
}
|
|
private void OnStartMoveToNpc()
|
{
|
GA_Hero _hero = PlayerDatas.Instance.hero;
|
if (_hero != null)
|
{
|
_hero.aiHandler.currentType = E_HeroAIType.None;
|
}
|
m_LimitOnce = true;
|
}
|
|
private void OnStartHandupAI()
|
{
|
m_LimitOnce = true;
|
}
|
|
private void OnLockTargetChanged(uint sid)
|
{
|
m_TargetID = sid;
|
}
|
|
private void OnUserClickSkill(int skillID)
|
{
|
GActor _target = GAMgr.Instance.GetBySID(m_TargetID);
|
if (_target != null && !_target.ActorInfo.serverDie)
|
{
|
m_FirstSkill = skillID;
|
}
|
}
|
|
public override void Update()
|
{
|
if (!DTC0403_tagPlayerLoginLoadOK.finishedLogin)
|
{
|
return;
|
}
|
|
GA_Hero _hero = PlayerDatas.Instance.hero;
|
if (_hero == null
|
|| _hero.ActorInfo.serverDie
|
|| !_hero.CanCastSkill())
|
{
|
return;
|
}
|
|
// 这里需要实时取对象, 因为视野可能导致对象回收
|
GActorFight _target = GAMgr.Instance.GetBySID(m_TargetID) as GActorFight;
|
|
// 对象是否还存在且为可攻击状态
|
if (_target == null)
|
{
|
m_TargetID = 0;
|
_hero.aiHandler.currentType = E_HeroAIType.None;
|
_hero.StopRush();
|
}
|
|
// 攻击间隔中
|
if (Time.time - m_LastUseSkillTime
|
< (1f / _hero.ActorInfo.atkSpeed) * .8f)
|
{
|
return;
|
}
|
|
Skill _skill = _hero.SkillMgr.CurCastSkill;
|
|
// 判断主角当前是否有技能尚未释放完毕
|
if (_skill != null)
|
{
|
// 如果是蓄力技能, 判断是否蓄力完毕
|
if (!_skill.SkillCompelete)
|
{
|
if (_skill.skillInfo.config.CastTime > 0)
|
{
|
if (_skill.CSkillPrepareEnd && _hero.SkillMgr.DoingPrepareSkill)
|
{
|
_hero.Behaviour.DoAttack(_skill);
|
_hero.SkillMgr.DoingPrepareSkill = false;
|
}
|
}
|
return;
|
}
|
|
if (_hero.SkillMgr.DoingPrepareSkill)
|
{
|
return;
|
}
|
}
|
|
// 确定要使用的技能
|
// 是否存在预设定的技能
|
if (m_FirstSkill > 0)
|
{
|
_skill = _hero.SkillMgr.Get(m_FirstSkill);
|
}
|
else
|
{
|
int _index = _hero.nextComAtkIndex;
|
if (_index == -1)
|
{
|
_index = 0;
|
}
|
int _comSkillID = _hero.GetCommonSkillID(_index);
|
_skill = _hero.SkillMgr.Get(_comSkillID);
|
}
|
|
if (_skill == null || !_skill.IsValid())
|
{
|
m_FirstSkill = -1;
|
_skill = null;
|
return;
|
}
|
|
if (_skill.skillInfo.config.FuncType == 8)
|
{
|
if (!_hero.CanCommonAtk())
|
{
|
return;
|
}
|
}
|
|
bool _forceMove = _skill.skillInfo.soFile != null && _skill.skillInfo.soFile.forceMove;
|
|
if (_target == null ||
|
(!_forceMove
|
&& !_hero.IsRushing // 不处于移动至目标
|
&& !IsSkillNeedMove(_skill.skillInfo.config.Tag,
|
(E_SkillType)_skill.skillInfo.config.SkillType)))
|
{
|
_hero.Behaviour.DoAttack(_skill);
|
m_LimitOnce = true;
|
}
|
else
|
{
|
// 判断技能范围, 不在可释放范围需要移动至目标
|
float _compareDist = _skill.skillInfo.config.AtkDist * .5f;
|
|
if (!PreFightMission.Instance.IsFinished())
|
{
|
_compareDist -= 1;
|
if (_compareDist < 0)
|
{
|
_compareDist = 0;
|
}
|
}
|
|
float _compareDistSqrt = _compareDist * _compareDist;
|
|
// 计算当前和目标的距离
|
Vector3 _dest = _target.Pos;
|
PathFinder.TryGetValidDest(_hero.Pos, _target.Pos, ref _dest);
|
float _currentDistSqrt = MathUtility.DistanceSqrtXZ(_hero.Pos, _dest);
|
// 比较距离
|
if (_currentDistSqrt >= _compareDistSqrt)
|
{
|
if (StatusMgr.IsValid()
|
&& !StatusMgr.Instance.CanMove(_hero.ServerInstID))
|
{
|
return;
|
}
|
|
// 移动至目标
|
_hero.MoveToTarget(_target, _compareDist);
|
|
// 判断是否需要冲锋
|
if (_hero.IsNeedRush(_currentDistSqrt))
|
{
|
_hero.StartRush();
|
}
|
|
m_IsMovingToTarget = true;
|
|
if (!_hero.IsRushing && UserInputHandler.isTouched)
|
{
|
m_LimitOnce = true;
|
_hero.StopPathFind();
|
}
|
|
return;
|
}
|
|
// 停止冲锋逻辑
|
_hero.StopRush();
|
|
Vector3 _forward = MathUtility.ForwardXZ(_target.Pos, _hero.Pos);
|
_hero.destForward = _hero.Forward = _forward;
|
|
if (m_FirstSkill != -1 && !_hero.Behaviour.IsComAtk(m_FirstSkill))
|
{
|
_hero.Behaviour.DoAttack(_skill);
|
m_LimitOnce = true;
|
}
|
else
|
{
|
_hero.Behaviour.DoCommonAttack();
|
m_LimitOnce = true;
|
}
|
}
|
|
// 置空技能
|
m_FirstSkill = -1;
|
|
#if UNITY_EDITOR
|
if (RuntimeLogUtility.s_PerpetualAttack == false)
|
{
|
_hero.aiHandler.currentType = E_HeroAIType.None;
|
}
|
#endif
|
}
|
|
public override void Exit()
|
{
|
UserInputHandler.OnCirclePanelTouched -= OnActiveInterrupt;
|
UserInputHandler.OnClickedFloor -= OnClickFloor;
|
HeroBehaviour.OnUserClickSkill -= OnUserClickSkill;
|
GA_Hero.OnLockTargetChanged -= OnLockTargetChanged;
|
HeroBehaviour.OnStartHandupAI -= OnStartHandupAI;
|
MapTransferUtility.s_OnHeroStartMoveToNPC -= OnStartMoveToNpc;
|
|
m_FirstSkill = -1;
|
m_TargetID = 0;
|
|
GA_Hero _hero = PlayerDatas.Instance.hero;
|
if (_hero != null)
|
{
|
_hero.StopRush();
|
}
|
}
|
|
public override bool IsOver()
|
{
|
GA_Hero _hero = PlayerDatas.Instance.hero;
|
GActorFight _target = GAMgr.Instance.GetBySID(m_TargetID) as GActorFight;
|
|
// if (_target == null || !_target.CanAtked())
|
// {
|
// Debug.Log("目标已死亡或者不可被攻击");
|
// }
|
|
// if (PlayerDatas.Instance.hero == null)
|
// {
|
// Debug.Log("主角被销毁");
|
// }
|
|
// if (m_ActiveInterrupt)
|
// {
|
// Debug.Log("行为被打断");
|
// }
|
|
// if (_hero.aiHandler.currentType != E_HeroAIType.KillUntilDie)
|
// {
|
// Debug.Log("已切换ai行为");
|
// }
|
|
// if (m_LimitOnce)
|
// {
|
// Debug.Log("释放过一次技能");
|
// }
|
|
return (_target == null
|
|| !_target.CanAtked()
|
|| m_ActiveInterrupt
|
|| _hero == null
|
|| _hero.aiHandler.currentType != E_HeroAIType.KillUntilDie)
|
&& (m_LimitOnce
|
|| MapArea.IsInMapArea(_hero.CurMapArea, MapArea.E_Type.Safe)
|
|| MapArea.IsInMapArea(_hero.CurMapArea, MapArea.E_Type.RebornSafe));
|
}
|
|
private void OnActiveInterrupt()
|
{
|
m_ActiveInterrupt = true;
|
|
GA_Hero _hero = PlayerDatas.Instance.hero;
|
if (_hero != null && m_FirstSkill < 0)
|
{
|
_hero.aiHandler.currentType = E_HeroAIType.None;
|
}
|
}
|
|
private void OnClickFloor(Vector3 dest)
|
{
|
m_ActiveInterrupt = true;
|
|
GA_Hero _hero = PlayerDatas.Instance.hero;
|
if (_hero != null)
|
{
|
_hero.aiHandler.currentType = E_HeroAIType.None;
|
}
|
}
|
}
|