|
using System;
|
using vnxbqy.UI;
|
|
using UnityEngine;
|
|
public abstract class HeroAI_Auto : HeroAI_Base
|
{
|
private float m_LastUseSkillTime;
|
private float m_PauseStartTime;
|
|
/// <summary>
|
/// 定点挂机的坐标
|
/// </summary>
|
|
protected uint m_LockTargetSID;
|
protected int m_LockTargetNpcID;
|
private int m_UserClickSkillID;
|
|
private Skill m_DecideSkill = null;
|
|
#region 配置相关
|
private float m_PauseResumeTime;
|
protected float m_HandupRange;
|
protected int[] m_HandUpSkill;
|
#endregion
|
|
private bool m_IsDungeon;
|
private byte m_State;
|
|
DungeonModel m_DungeonModel;
|
DungeonModel dungeonModel
|
{
|
get
|
{
|
return m_DungeonModel ?? (m_DungeonModel = ModelCenter.Instance.GetModel<DungeonModel>());
|
}
|
}
|
|
public bool IsPause()
|
{
|
return m_State == 1;
|
}
|
|
public override bool Condition()
|
{
|
return false;
|
}
|
|
public sealed override void Enter()
|
{
|
m_LastUseSkillTime = 0;
|
m_PauseStartTime = 0;
|
m_LockTargetSID = 0;
|
m_UserClickSkillID = -1;
|
m_NeedMoveToPos = false;
|
m_HandUpSkill = null;
|
m_State = 0;
|
|
// 初始化配置
|
if (m_PauseResumeTime == 0)
|
{
|
FuncConfigConfig _func = FuncConfigConfig.Get("HandupResumeTime");
|
m_PauseResumeTime = float.Parse(_func.Numerical1) * Constants.F_GAMMA;
|
|
}
|
|
FuncConfigConfig _funcConfig = FuncConfigConfig.Get("XpSkillID");
|
xpSkillID = ConfigParse.GetDic<int, int>(_funcConfig.Numerical1)[PlayerDatas.Instance.baseData.Job];//获取各个职业的XP技能
|
xpSkillID = SkillHelper.Instance.GetSkillID(xpSkillID);
|
|
var _skillModel = ModelCenter.Instance.GetModel<SkillModel>();
|
var _skillList = _skillModel.GetSkillMatchs();
|
if (_skillList != null)
|
{
|
m_HandUpSkill = new int[_skillList.Count];
|
for (int i = 0; i < _skillList.Count; ++i)
|
{
|
m_HandUpSkill[i] = _skillList[i];
|
}
|
}
|
|
var _mapConfig = MapConfig.Get(PlayerDatas.Instance.baseData.MapID);
|
m_IsDungeon = _mapConfig.MapFBType != (int)MapType.OpenCountry;
|
|
if (m_IsDungeon)
|
{
|
int _dgDataID = dungeonModel.GetDataMapIdByMapId(PlayerDatas.Instance.baseData.MapID);
|
var dungeonOpen = DungeonOpenTimeConfig.Get(_dgDataID);
|
|
if (dungeonOpen != null)
|
{
|
if (dungeonOpen.DoFight == 1)
|
{
|
GA_Hero.forceAutoFight = true;
|
}
|
}
|
}
|
|
UserInputHandler.OnCirclePanelTouched += OnActiveInterrupt;
|
UserInputHandler.OnClickedFloor += OnClickFloor;
|
GA_Hero.OnLockTargetChanged += OnLockTargetChanged;
|
HeroBehaviour.OnUserClickSkill += OnUserClickSkill;
|
_skillModel.onSkillMatchPageUpdate += OnSkillMatchPageUpdate;
|
|
OnEnter();
|
}
|
|
private void OnSkillMatchPageUpdate()
|
{
|
var _skillModel = ModelCenter.Instance.GetModel<SkillModel>();
|
var _skillList = _skillModel.GetSkillMatchs();
|
if (_skillList != null)
|
{
|
m_HandUpSkill = new int[_skillList.Count];
|
for (int i = 0; i < _skillList.Count; ++i)
|
{
|
m_HandUpSkill[i] = _skillList[i];
|
}
|
}
|
}
|
|
public sealed override void Update()
|
{
|
if (!DTC0403_tagPlayerLoginLoadOK.finishedLogin)
|
{
|
Debug.LogWarning("登陆流程尚未完成");
|
stopReason = 1;
|
return;
|
}
|
|
GA_Hero _hero = PlayerDatas.Instance.hero;
|
|
if (_hero.IsPolyMorph)
|
{
|
stopReason = 2;
|
return;
|
}
|
|
if (GA_Hero.s_MapSwitching
|
|| AdventureStage.Instance.IsInAdventureStage)
|
{
|
stopReason = 21;
|
return;
|
}
|
|
if (_hero.SelectTarget == _hero)
|
{
|
_hero.SelectTarget = null;
|
}
|
|
if (_hero.LockTarget == _hero)
|
{
|
_hero.LockTarget = null;
|
}
|
|
if (_hero == null || _hero.ActorInfo.serverDie)
|
{
|
stopReason = 3;
|
return;
|
}
|
|
// 处理仙魔之争
|
if (PlayerDatas.Instance.baseData.MapID == 31010)
|
{
|
if (_hero.heavenBattleModel.IsBattlePrepare)
|
{
|
stopReason = 4;
|
return;
|
}
|
}
|
|
if (_hero.IsCollect() && m_UserClickSkillID <= 0 && _hero.SelectTarget is GActorNpcNoFight)
|
{
|
stopReason = 5;
|
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;
|
}
|
}
|
stopReason = 6;
|
return;
|
}
|
}
|
|
// 释放处于释放需要预备的技能状态下
|
if (_hero.SkillMgr.DoingPrepareSkill)
|
{
|
stopReason = 7;
|
return;
|
}
|
|
_skill = null;
|
|
switch (m_State)
|
{
|
case 0:// 正常状态
|
|
// 挂机状态下等待拾取装备
|
if (WaitForPickup())
|
{
|
stopReason = 8;
|
return;
|
}
|
|
if (m_IsDungeon)
|
{
|
if (ClientCrossServerOneVsOne.isClientCrossServerOneVsOne || ArenaManager.isArenaClient)
|
{
|
if (dungeonModel.dungeonFightStage == DungeonFightStage.Prepare)
|
{
|
return;
|
}
|
}
|
|
if (dungeonModel.dungeonFightStage == DungeonFightStage.Normal
|
|| PlayerDatas.Instance.baseData.MapID == 31010)
|
{
|
// 子类有自己需要在技能释放前处理的逻辑
|
if (OnUpdate())
|
{
|
stopReason = 9;
|
return;
|
}
|
}
|
// else if (dungeonModel.dungeonFightStage == DungeonFightStage.Prepare
|
// || dungeonModel.dungeonFightStage == DungeonFightStage.ExitPrepare)
|
// {
|
// return;
|
// }
|
}
|
else
|
{
|
// 子类有自己需要在技能释放前处理的逻辑
|
if (OnUpdate())
|
{
|
stopReason = 10;
|
return;
|
}
|
}
|
|
break;
|
case 1:// 暂停状态
|
|
if (m_NeedMoveToPos)
|
{
|
if (StatusMgr.Instance.CanMove(PlayerDatas.Instance.PlayerId))
|
{
|
if (MathUtility.DistanceSqrtXZ(_hero.Pos, m_TargetPos) > 0.25f)
|
{
|
_hero.MoveToPosition(m_TargetPos);
|
stopReason = 11;
|
return;
|
}
|
}
|
m_NeedMoveToPos = false;
|
}
|
|
if (Time.realtimeSinceStartup - m_PauseStartTime > m_PauseResumeTime)
|
{
|
m_State = 0;
|
}
|
|
break;
|
}
|
|
// 是否处于攻击间隔
|
if (Time.realtimeSinceStartup - m_LastUseSkillTime < (1f / _hero.ActorInfo.atkSpeed))
|
{
|
stopReason = 12;
|
return;
|
}
|
|
if (m_UserClickSkillID == 0)
|
{
|
int _index = _hero.nextComAtkIndex;
|
if (_index == -1)
|
{
|
_index = 0;
|
}
|
m_UserClickSkillID = _hero.GetCommonSkillID(_index);
|
if(ArenaManager.IsArenaClientNotMirrorFight)
|
{
|
for(int i=0;i < GeneralDefine.WorkNotSkills.Length;i++)
|
{
|
if (m_UserClickSkillID == GeneralDefine.WorkNotSkills[i])
|
m_UserClickSkillID = -1;
|
}
|
}
|
}
|
|
if (m_State == 0 || m_UserClickSkillID != -1)
|
{
|
// 决策此次要使用的技能
|
_skill = DecideUserSkill(m_HandUpSkill, m_UserClickSkillID);
|
}
|
|
if (_skill == null)
|
{
|
stopReason = 13;
|
return;
|
}
|
|
// 判断周围是否有可攻击目标
|
GActorFight _atkTarget = null;
|
|
// 处理玩家主动切换攻击目标行为
|
if (_hero.LockTarget != null
|
&& _hero.LockTarget is GActorFight
|
&& (_hero.LockTarget as GActorFight).CanAtked())
|
{
|
_atkTarget = _hero.LockTarget as GActorFight;
|
}
|
else if (_hero.aiHandler.PriorityNpcID > 0)
|
{
|
_atkTarget = DecideAttackTarget(_hero.Pos, m_HandupRange, _hero.aiHandler.PriorityNpcID);
|
}
|
else if (m_LockTargetNpcID > 0)
|
{
|
_atkTarget = DecideAttackTarget(_hero.Pos, m_HandupRange, m_LockTargetNpcID);
|
}
|
else if (m_LockTargetSID != 0)
|
{
|
_atkTarget = GAMgr.Instance.GetBySID(m_LockTargetSID) as GActorFight;
|
|
if (_atkTarget == null
|
|| _atkTarget.ActorInfo.serverDie
|
|| !_atkTarget.CanAtked())
|
{
|
m_LockTargetSID = 0;
|
_atkTarget = null;
|
}
|
}
|
else
|
{
|
_atkTarget = SelectTarget();
|
}
|
|
bool _forceMove = _skill.skillInfo.soFile != null && _skill.skillInfo.soFile.forceMove;
|
if (((_atkTarget == null
|
|| _atkTarget.ActorInfo.serverDie) && m_UserClickSkillID != -1)
|
|| (!_forceMove && !IsSkillNeedMove(_skill.skillInfo.config.Tag, (E_SkillType)_skill.skillInfo.config.SkillType)))
|
{
|
_hero.Behaviour.DoAttack(_skill);
|
m_DecideSkill = null;
|
m_UserClickSkillID = -1;
|
stopReason = 14;
|
return;
|
}
|
|
if (_atkTarget == null || !_atkTarget.CanAtked())
|
{
|
_hero.StopRush();
|
stopReason = 15;
|
return;
|
}
|
|
#if UNITY_EDITOR
|
var _prev = _hero.SelectTarget;
|
if (_prev is GActorPlayerBase && _atkTarget is GA_NpcFightBoss)
|
{
|
if (_hero.LockTarget != null)
|
{
|
Debug.LogFormat("当前的锁定目标为: {0}-{1}", _hero.LockTarget.GetType(), _hero.LockTarget.ServerInstID);
|
}
|
Debug.LogFormat("<color=yellow>在当前选择目标是玩家的时候切换到了Boss: {0} => {1} </color>", _prev.ServerInstID, _atkTarget.ServerInstID);
|
Debug.LogFormat("<color=yellow>m_LockTargetSID: {0} </color>", m_LockTargetSID);
|
}
|
#endif
|
_hero.SelectTarget = _atkTarget;
|
|
// 判断技能范围, 不在可释放范围需要移动至目标
|
float _compareDist = _skill.skillInfo.config.AtkDist * .5f;
|
float _compareDistSqrt = _compareDist * _compareDist;
|
|
// 计算当前和目标的距离
|
float _currentDistSqrt = MathUtility.DistanceSqrtXZ(_hero.Pos, _atkTarget.Pos);
|
// 比较距离
|
if (_currentDistSqrt > _compareDistSqrt)
|
{
|
if ((StatusMgr.IsValid()
|
&& !StatusMgr.Instance.CanMove(_hero.ServerInstID)))
|
{
|
stopReason = 16;
|
return;
|
}
|
|
// 移动至目标
|
_hero.MoveToTarget(_atkTarget, _compareDist, CrossServerUtility.IsCrossServerOneVsOne() || ClientDungeonStageUtility.isClientDungeon);
|
|
// 判断是否需要冲锋
|
if (_hero.IsNeedRush(_currentDistSqrt))
|
{
|
_hero.StartRush();
|
}
|
|
stopReason = 17;
|
return;
|
}
|
|
// 停止冲锋逻辑
|
_hero.StopRush();
|
|
if (IsSkillNeedMove(_skill.skillInfo.config.Tag, (E_SkillType)_skill.skillInfo.config.SkillType))
|
{
|
Vector3 _forward = MathUtility.ForwardXZ(_atkTarget.Pos, _hero.Pos);
|
_hero.destForward = _hero.Forward = _forward;
|
}
|
|
// 判断是否普通, 调用不同的接口
|
if (_hero.Behaviour.IsComAtk(_skill.id))
|
{
|
_hero.Behaviour.DoCommonAttack();
|
if (m_DecideSkill != null && m_DecideSkill.id == _skill.id)
|
{
|
m_DecideSkill = null;
|
}
|
if (_skill.id == m_UserClickSkillID)
|
{
|
m_UserClickSkillID = -1;
|
}
|
}
|
else
|
{
|
_hero.Behaviour.DoAttack(_skill);
|
if (m_DecideSkill != null && m_DecideSkill.id == _skill.id)
|
{
|
m_DecideSkill = null;
|
}
|
if (_skill.id == m_UserClickSkillID)
|
{
|
m_UserClickSkillID = -1;
|
}
|
}
|
|
stopReason = 255;
|
|
m_LastUseSkillTime = Time.realtimeSinceStartup;
|
}
|
|
public sealed override void Exit()
|
{
|
GA_Hero _hero = PlayerDatas.Instance.hero;
|
if (_hero != null)
|
{
|
_hero.StopRush();
|
}
|
UserInputHandler.OnCirclePanelTouched -= OnActiveInterrupt;
|
UserInputHandler.OnClickedFloor -= OnClickFloor;
|
HeroBehaviour.OnUserClickSkill -= OnUserClickSkill;
|
GA_Hero.OnLockTargetChanged -= OnLockTargetChanged;
|
var _skillModel = ModelCenter.Instance.GetModel<SkillModel>();
|
_skillModel.onSkillMatchPageUpdate -= OnSkillMatchPageUpdate;
|
OnExit();
|
}
|
|
public override bool IsOver()
|
{
|
GA_Hero _hero = PlayerDatas.Instance.hero;
|
|
return _hero == null
|
|| _hero.ActorInfo.serverDie
|
|| MapArea.IsInMapArea(_hero.CurMapArea, MapArea.E_Type.Safe)
|
|| MapArea.IsInMapArea(_hero.CurMapArea, MapArea.E_Type.RebornSafe);
|
}
|
|
protected virtual void OnActiveInterrupt()
|
{
|
GA_Hero _hero = PlayerDatas.Instance.hero;
|
if (_hero == null)
|
{
|
return;
|
}
|
//if (Time.realtimeSinceStartup - m_PauseStartTime > m_PauseResumeTime)
|
//{
|
// // 弹出挂机暂停提示
|
// SysNotifyMgr.Instance.ShowTip("HookPrompt_Manual");
|
//}
|
m_PauseStartTime = Time.realtimeSinceStartup;
|
m_State = 1;
|
m_NeedMoveToPos = false;
|
_hero.StopRush();
|
_hero.StopPathFind();
|
|
Skill _skill = _hero.SkillMgr.CurCastSkill;
|
if (_skill != null)
|
{
|
if (!_skill.SkillCompelete)
|
{
|
m_UserClickSkillID = -1;
|
}
|
}
|
}
|
|
private Vector3 m_TargetPos;
|
private bool m_NeedMoveToPos;
|
|
protected virtual void OnClickFloor(Vector3 dest)
|
{
|
if (!StatusMgr.Instance.CanMove(PlayerDatas.Instance.PlayerId))
|
{
|
return;
|
}
|
|
GA_Hero _hero = PlayerDatas.Instance.hero;
|
|
if (_hero == null || _hero.IsDaZuo())
|
{
|
return;
|
}
|
|
m_PauseStartTime = Time.realtimeSinceStartup;
|
m_State = 1;
|
m_UserClickSkillID = -1;
|
_hero.StopAll();
|
|
m_TargetPos = dest;
|
m_NeedMoveToPos = true;
|
}
|
|
protected virtual void OnUserClickSkill(int skillID)
|
{
|
m_UserClickSkillID = skillID;
|
|
//if (Time.realtimeSinceStartup - m_PauseStartTime > m_PauseResumeTime)
|
//{
|
// // 弹出挂机暂停提示
|
// SysNotifyMgr.Instance.ShowTip("HookPrompt_Manual");
|
//}
|
m_NeedMoveToPos = false;
|
}
|
|
private void OnLockTargetChanged(uint sid)
|
{
|
m_LockTargetSID = sid;
|
}
|
|
protected abstract void OnEnter();
|
protected abstract void OnExit();
|
protected abstract bool OnUpdate();
|
protected abstract GActorFight SelectTarget();
|
}
|