using Snxxz.UI; using TableConfig; using UnityEngine; public abstract class HeroAI_Auto : HeroAI_Base { private float m_LastUseSkillTime; private float m_PauseStartTime; /// /// 定点挂机的坐标 /// 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()); } } 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 = Config.Instance.Get("HandupResumeTime"); m_PauseResumeTime = float.Parse(_func.Numerical1) * Constants.F_GAMMA; } if (xpSkillID == 0) { FuncConfigConfig _funcConfig = Config.Instance.Get("XpSkillID"); xpSkillID = ConfigParse.GetDic(_funcConfig.Numerical1)[PlayerDatas.Instance.baseData.Job];//获取各个职业的XP技能 } GA_Hero _hero = PlayerDatas.Instance.hero; if (_hero != null) { if (!string.IsNullOrEmpty(_hero.JobSetup.DungeonSkillList)) { var _json = LitJson.JsonMapper.ToObject(_hero.JobSetup.DungeonSkillList); var _key = PlayerDatas.Instance.baseData.MapID.ToString(); if (((System.Collections.IDictionary)_json).Contains(_key)) { _json = _json[_key]; m_HandUpSkill = new int[_json.Count]; for (int i = 0; i < _json.Count; ++i) { m_HandUpSkill[i] = (int)_json[i]; } } } } var _mapConfig = Config.Instance.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 = Config.Instance.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; OnEnter(); } public sealed override void Update() { if (!DTC0403_tagPlayerLoginLoadOK.finishedLogin) { Debug.LogWarning("登陆流程尚未完成"); return; } GA_Hero _hero = PlayerDatas.Instance.hero; if (_hero.IsPolyMorph) { return; } if (_hero.SelectTarget == _hero) { _hero.SelectTarget = null; } if (_hero.LockTarget == _hero) { _hero.LockTarget = null; } if (_hero == null || _hero.ActorInfo.serverDie) { return; } // 处理仙魔之争 if (PlayerDatas.Instance.baseData.MapID == 31010) { if (_hero.heavenBattleModel.IsBattlePrepare) { return; } } if (_hero.IsCollect()) { 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; } _skill = null; switch (m_State) { case 0:// 正常状态 // 挂机状态下等待拾取装备 if (WaitForPickup()) { return; } if (m_IsDungeon) { if (dungeonModel.dungeonFightStage == DungeonFightStage.None || dungeonModel.dungeonFightStage == DungeonFightStage.Normal || PlayerDatas.Instance.baseData.MapID == 31010) { // 子类有自己需要在技能释放前处理的逻辑 if (OnUpdate()) { return; } } } else { // 子类有自己需要在技能释放前处理的逻辑 if (OnUpdate()) { 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); return; } } m_NeedMoveToPos = false; } if (Time.realtimeSinceStartup - m_PauseStartTime > m_PauseResumeTime) { m_State = 0; } break; } // 是否处于攻击间隔 if (Time.realtimeSinceStartup - m_LastUseSkillTime < (1f / _hero.ActorInfo.atkSpeed)) { return; } if (m_UserClickSkillID == 0) { int _index = _hero.nextComAtkIndex; if (_index == -1) { _index = 0; } m_UserClickSkillID = _hero.GetCommonSkillID(_index); } if (m_State == 0 || m_UserClickSkillID != -1) { // 决策此次要使用的技能 _skill = DecideUserSkill(m_HandUpSkill, m_UserClickSkillID); } if (_skill == null) { return; } // 判断周围是否有可攻击目标 GActorFight _atkTarget = null; // 处理玩家主动切换攻击目标行为 if (m_LockTargetSID != 0) { _atkTarget = GAMgr.Instance.GetBySID(m_LockTargetSID) as GActorFight; if (_atkTarget == null || !_atkTarget.CanAtked()) { m_LockTargetSID = 0; _atkTarget = null; } } 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 { _atkTarget = SelectTarget(); } bool _forceMove = _skill.skillInfo.soFile != null && _skill.skillInfo.soFile.forceMove; if ((_atkTarget == null || _atkTarget.ActorInfo.serverDie || (!_forceMove && !IsSkillNeedMove(_skill.skillInfo.config.Tag, (E_SkillType)_skill.skillInfo.config.SkillType))) && m_UserClickSkillID != -1) { _hero.Behaviour.DoAttack(_skill); m_DecideSkill = null; return; } if (_atkTarget == null) { _hero.StopRush(); return; } _hero.LockTarget = _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))) { return; } // 移动至目标 _hero.MoveToTarget(_atkTarget, _compareDist); // 判断是否需要冲锋 if (_hero.IsNeedRush(_currentDistSqrt)) { _hero.StartRush(); } 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; } } 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; 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() { //if (Time.realtimeSinceStartup - m_PauseStartTime > m_PauseResumeTime) //{ // // 弹出挂机暂停提示 // SysNotifyMgr.Instance.ShowTip("HookPrompt_Manual"); //} m_PauseStartTime = Time.realtimeSinceStartup; m_State = 1; GA_Hero _hero = PlayerDatas.Instance.hero; m_NeedMoveToPos = false; if (_hero != null) { _hero.StopRush(); } 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; m_PauseStartTime = Time.realtimeSinceStartup; m_State = 1; m_UserClickSkillID = -1; if (_hero != null) { _hero.StopRush(); } 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(); }