using UnityEngine;
|
using System.Collections.Generic;
|
|
using vnxbqy.UI;
|
using UnityEngine.Events;
|
|
public class HeroBehaviour
|
{
|
TreasureSkillModel treasureSkillModel = null;
|
|
TreasureSkillModel tsModel
|
{
|
get
|
{
|
return treasureSkillModel ?? (treasureSkillModel = ModelCenter.Instance.GetModel<TreasureSkillModel>());
|
}
|
}
|
|
/// <summary>
|
/// 挂机开始
|
/// </summary>
|
public static event System.Action OnStopHandupAI;
|
/// <summary>
|
/// 挂机结束
|
/// </summary>
|
public static event System.Action OnStartHandupAI;
|
|
public static event UnityAction<int> onCastSkill;
|
|
/// <summary>
|
/// 当用户点击了技能按钮, 并切技能可以释放的时候调用
|
/// </summary>
|
public static event UnityAction<int> OnUserClickSkill;
|
|
public enum E_BehaviourState
|
{
|
None,
|
KillUntilDie,
|
Auto,
|
FixedPosition,
|
}
|
|
private int curComAtkIndex;
|
private float m_LastCommonAtkTime;
|
|
private bool m_ClientFightEnable = false;
|
private GA_Hero m_Hero;
|
private int m_WillUsedSkillID;
|
|
public HeroBehaviour(GA_Hero hero)
|
{
|
m_Hero = hero;
|
|
FuncConfigConfig _func = FuncConfigConfig.Get("ClientFightEnable");
|
int _enable = int.Parse(_func.Numerical1);
|
m_ClientFightEnable = (_enable == 1);
|
|
}
|
|
private List<CB405_tagCMSuperAtk.tagSkillPosHurtObj> _serverHurtList = new List<CB405_tagCMSuperAtk.tagSkillPosHurtObj>();
|
|
public void DoPrepareCast(int skillID)
|
{
|
Skill _skill = m_Hero.SkillMgr.Get(skillID);
|
|
if (_skill.SkillPreparing == false)
|
{
|
return;
|
}
|
if (_skill.skillInfo.config.CastTime == 0)
|
{
|
return;
|
}
|
|
_skill.CSkillPrepareEnd = true;
|
}
|
|
public void StartKillUntilDieAI(int skillID = -1)
|
{
|
if (!DTC0403_tagPlayerLoginLoadOK.finishedLogin)
|
{
|
Debug.LogWarning("登陆流程尚未完成");
|
return;
|
}
|
|
MapTransferUtility.Instance.Clear();
|
|
// 安全区直接退出
|
if (MapArea.IsInMapArea(m_Hero.CurMapArea, MapArea.E_Type.Safe)
|
|| MapArea.IsInMapArea(m_Hero.CurMapArea, MapArea.E_Type.RebornSafe))
|
{
|
SysNotifyMgr.Instance.ShowTip("NoFighting");
|
return;
|
}
|
|
if (m_Hero.IsPolyMorph)
|
{
|
return;
|
}
|
|
if (m_Hero.aiHandler.currentType == E_HeroAIType.KillUntilDie)
|
{
|
if (IsComAtk(skillID))
|
{
|
return;
|
}
|
}
|
|
if (skillID < 0)
|
{
|
int _index = Mathf.Clamp(m_Hero.nextComAtkIndex, 0, m_Hero.JobSetup.ComAtkIdList.Length - 1);
|
skillID = m_Hero.JobSetup.ComAtkIdList[_index];
|
if(ArenaManager.IsArenaClientNotMirrorFight)
|
{
|
for(int j = 0; j < m_Hero.JobSetup.ComAtkIdList.Length;j++)
|
{
|
_index = Mathf.Clamp(m_Hero.nextComAtkIndex, 0, m_Hero.JobSetup.ComAtkIdList.Length - 1);
|
skillID = m_Hero.JobSetup.ComAtkIdList[_index];
|
bool bWork = true;
|
for (int i = 0; i < GeneralDefine.WorkNotSkills.Length; i++)
|
{
|
skillID = m_Hero.JobSetup.ComAtkIdList[_index];
|
if (skillID != GeneralDefine.WorkNotSkills[i])
|
bWork = false;
|
}
|
if (bWork)
|
break;
|
}
|
|
}
|
}
|
|
Skill _skill = m_Hero.SkillMgr.Get(skillID);
|
|
bool _forceCast = false;
|
SkillHelper.EffectValue _effectValue;
|
if (SkillHelper.Instance.TryGetExpertSkillEvByMainSkillID(_skill.id, 4093, out _effectValue))
|
{
|
_forceCast = true;
|
}
|
|
if ((!StatusMgr.Instance.CanAttack(m_Hero.ServerInstID, _skill.skillInfo.config) || m_Hero.IsStun()) && !_forceCast)
|
{
|
return;
|
}
|
|
if (_skill.IsValid() == false)
|
{
|
return;
|
}
|
|
m_WillUsedSkillID = skillID;
|
|
if (_skill.skillInfo.config.CastTime > 0)
|
{
|
_skill.CSkillPrepareEnd = false;
|
}
|
|
GActorFight _fightTarget = m_Hero.LockTarget as GActorFight;
|
|
if (_fightTarget != null && _fightTarget.CanAtked())
|
{
|
m_Hero.SelectTarget = _fightTarget;
|
}
|
else
|
{
|
_fightTarget = m_Hero.SelectTarget as GActorFight;
|
|
if (_fightTarget == null || !_fightTarget.CanAtked())
|
{
|
float _range = m_Hero.JobSetup.SearchEnemyDist * Constants.F_DELTA;
|
m_Hero.SelectTarget = GAMgr.Instance.FindAtkTarget(m_Hero.Pos, _range, 360);
|
_fightTarget = m_Hero.SelectTarget as GActorFight;
|
}
|
}
|
|
if (m_Hero.aiHandler.currentType == E_HeroAIType.None
|
|| m_Hero.aiHandler.currentType == E_HeroAIType.KillUntilDie)
|
{
|
byte _type = (byte)E_HeroAIType.KillUntilDie;
|
KillUntilDieData _data = m_Hero.aiHandler.aiData[_type] as KillUntilDieData;
|
if (_fightTarget != null)
|
{
|
_data.targetServerInstID = _fightTarget.ServerInstID;
|
}
|
_data.defaultSkillID = m_WillUsedSkillID;
|
m_Hero.aiHandler.currentType = E_HeroAIType.KillUntilDie;
|
|
if (OnUserClickSkill != null)
|
{
|
OnUserClickSkill(m_WillUsedSkillID);
|
}
|
}
|
else
|
{
|
if (OnUserClickSkill != null)
|
{
|
OnUserClickSkill(m_WillUsedSkillID);
|
}
|
}
|
}
|
|
public void StopKillUntilDieAI()
|
{
|
if (m_Hero.aiHandler.currentType == E_HeroAIType.KillUntilDie)
|
{
|
m_Hero.aiHandler.currentType = E_HeroAIType.None;
|
}
|
}
|
|
public void StartHandupAI()
|
{
|
if (!DTC0403_tagPlayerLoginLoadOK.finishedLogin)
|
{
|
Debug.LogWarning("登陆流程尚未完成");
|
return;
|
}
|
|
MapTransferUtility.Instance.Clear();
|
|
// 安全区直接退出
|
if (MapArea.IsInMapArea(m_Hero.CurMapArea, MapArea.E_Type.Safe)
|
|| MapArea.IsInMapArea(m_Hero.CurMapArea, MapArea.E_Type.RebornSafe))
|
{
|
SysNotifyMgr.Instance.ShowTip("NoFighting");
|
//
|
return;
|
}
|
|
if (PreFightMission.Instance.IsFinished() == false)
|
{
|
return;
|
}
|
|
m_Hero.aiHandler.currentType = E_HeroAIType.NormalAuto;
|
|
// 判断是什么副本类型
|
DungeonModel _dgModel = ModelCenter.Instance.GetModel<DungeonModel>();
|
int _dataMapID = _dgModel.GetDataMapIdByMapId(PlayerDatas.Instance.baseData.MapID);
|
if (_dataMapID != 0)
|
{
|
int _configID = _dataMapID * 10 + _dgModel.mission.lineID;
|
DungeonConfig _dgConfig = DungeonConfig.Get(_configID);
|
|
if (_dgConfig != null && _dgConfig.AutomaticATK > 1)
|
{
|
m_Hero.aiHandler.currentType = (E_HeroAIType)_dgConfig.AutomaticATK;
|
}
|
}
|
//#if UNITY_EDITOR
|
// Debug.LogFormat("AI类型: {0}", m_Hero.aiHandler.currentType.ToString());
|
//#endif
|
if (OnStartHandupAI != null)
|
{
|
OnStartHandupAI();
|
}
|
}
|
|
public void StopHandupAI(bool force = false)
|
{
|
if (!force)
|
{
|
if (StageLoad.Instance.stageType == Stage.E_StageType.Dungeon)
|
{
|
if (DungeonStage.CurrentMapType != MapType.OpenCountry)
|
{
|
return;
|
}
|
}
|
}
|
|
if (!PreFightMission.Instance.IsFinished())
|
{
|
return;
|
}
|
|
if (m_Hero.aiHandler.IsAuto())
|
{
|
m_Hero.aiHandler.Stop();
|
}
|
|
if (OnStopHandupAI != null)
|
{
|
OnStopHandupAI();
|
}
|
|
m_Hero.forceAutoFightTime = Time.realtimeSinceStartup;
|
}
|
|
public bool IsComAtk(int skillID)
|
{
|
for (int i = 0; i < m_Hero.JobSetup.ComAtkIdList.Length; ++i)
|
{
|
if (skillID == m_Hero.JobSetup.ComAtkIdList[i])
|
{
|
return true;
|
}
|
}
|
return false;
|
}
|
|
public void ResetComAtkConnectTime()
|
{
|
m_LastCommonAtkTime = Time.realtimeSinceStartup;
|
}
|
|
public int DoCommonAttack()
|
{
|
if (Time.realtimeSinceStartup - m_LastCommonAtkTime > GeneralDefine.ResetComAtkTime)
|
{
|
m_Hero.nextComAtkIndex = 0;
|
}
|
|
if (m_Hero.State == E_ActorState.DaZuo
|
|| GA_Hero.s_MapSwitching
|
|| MapArea.IsInMapArea(m_Hero.CurMapArea, MapArea.E_Type.Safe)
|
|| MapArea.IsInMapArea(m_Hero.CurMapArea, MapArea.E_Type.RebornSafe))
|
{
|
return -1;
|
}
|
|
int skillId = 0;
|
Skill _skill = null;
|
|
if (m_Hero.nextComAtkIndex >= 0 && m_Hero.nextComAtkIndex < m_Hero.JobSetup.ComAtkIdList.Length)
|
{
|
curComAtkIndex = m_Hero.nextComAtkIndex;
|
}
|
else
|
{
|
curComAtkIndex = 0;
|
}
|
|
skillId = m_Hero.GetCommonSkillID(curComAtkIndex);
|
_skill = m_Hero.SkillMgr.Get(skillId);
|
|
if (!StatusMgr.Instance.CanAttack(m_Hero.ServerInstID, _skill.skillInfo.config))
|
{
|
return -1;
|
}
|
|
if (_skill.IsValid() == false)
|
{
|
return -1;
|
}
|
|
int _chkIndex = curComAtkIndex == 0 ? m_Hero.JobSetup.ComAtkIdList.Length - 1 : curComAtkIndex - 1;
|
|
skillId = m_Hero.GetCommonSkillID(_chkIndex);
|
_skill = m_Hero.SkillMgr.Get(skillId);
|
if (_skill != null)
|
{
|
//Debug.LogFormat("取得技能: {0} 是否完成: {1}", skillId, _skill.SkillCompelete);
|
if (_skill.SkillCompelete)
|
{
|
skillId = m_Hero.GetCommonSkillID(curComAtkIndex);
|
_skill = m_Hero.SkillMgr.Get(skillId);
|
if (_skill != null)
|
{
|
DoAttack(_skill);
|
m_Hero.nextComAtkIndex = curComAtkIndex + 1;
|
}
|
}
|
}
|
|
return skillId;
|
}
|
|
public void DoAttack(Skill skill)
|
{
|
if (PlayerDatas.Instance.extersion.Tick == 0 &&
|
PlayerDatas.Instance.crossServerTick == 0)
|
{
|
return;
|
}
|
|
if (skill == null || GA_Hero.s_MapSwitching)
|
{
|
return;
|
}
|
|
if (m_Hero.ActorInfo.serverDie)
|
{
|
return;
|
}
|
|
// 可能有残留之前的伤害列表, 只在进入前端伤害的时候进行清除
|
if (ClientSceneManager.Instance.IsClientFightMode)
|
{
|
skill.ClearServerHurtList();
|
}
|
|
skill.mainTarget = null;
|
skill.targetPosition = Vector3.zero;
|
|
skill.hitTargetList.Clear();
|
skill.hitClientBattleTargetList.Clear();
|
|
SoSkill _soSkill = ScriptableObjectLoader.LoadSoSkill(skill.skillInfo.config.SkillTypeID);
|
if (_soSkill == null)
|
{
|
DebugEx.LogWarningFormat("技能: {0} 没有配置SoSkill文件, 将没有范围检测能力.", skill.id);
|
return;
|
}
|
|
// 确定此次可检测的目标数量
|
int _hitTestLimit = 1;
|
SkillHelper.EffectValue _effectValue;
|
if (skill.skillInfo.effectValue.TryGetValue(1200, out _effectValue))
|
{
|
_hitTestLimit = _effectValue.value1;
|
}
|
var _spSkillInfo = SkillHelper.Instance.GetSpSkill(skill.id);
|
if (_spSkillInfo != null)
|
{
|
for (int i = 0; i < _spSkillInfo.Count; ++i)
|
{
|
if (_spSkillInfo[i].effectValue.TryGetValue(4036, out _effectValue))
|
{
|
_hitTestLimit += _effectValue.value1;
|
#if UNITY_EDITOR
|
if (RuntimeLogUtility.s_SkillEffectLog)
|
{
|
Debug.LogFormat("技能 {0} 触发了效果 {1} , _hitTestLimit 增加了 {2}", _spSkillInfo[i].config.SkillID, 4036, _effectValue.value1);
|
}
|
#endif
|
}
|
}
|
}
|
|
if (PlayerDatas.Instance.baseData.AttackMode == (byte)E_AttackMode.Contest)
|
{
|
_hitTestLimit = 1;
|
}
|
|
E_SkillCastType _castType = (E_SkillCastType)(skill.skillInfo.config.Tag % 10);
|
E_SkillCastTarget _targetType = (E_SkillCastTarget)(skill.skillInfo.config.Tag / 10);
|
|
if (UserInputHandler.isTouched)
|
{
|
m_Hero.Forward = m_Hero.destForward;
|
}
|
|
Vector3 _sourcePosition = m_Hero.Pos;
|
_sourcePosition.y = 0;
|
|
Vector3 _realDir = m_Hero.Forward;
|
if (skill.id == 190)
|
{
|
_realDir = m_Hero.destForward;
|
}
|
|
if (!UserInputHandler.isTouched)
|
{
|
if (m_Hero.aiHandler.IsAuto())
|
{
|
GActorFight _fight = m_Hero.LockTarget as GActorFight;
|
if (_fight != null && _fight.CanAtked())
|
{
|
_realDir = m_Hero.Forward = MathUtility.ForwardXZ(m_Hero.LockTarget.Pos, m_Hero.Pos);
|
}
|
else if (m_Hero.SelectTarget != null)
|
{
|
_realDir = m_Hero.Forward = MathUtility.ForwardXZ(m_Hero.SelectTarget.Pos, m_Hero.Pos);
|
}
|
}
|
}
|
|
if (_realDir == Vector3.zero)
|
{
|
_realDir = m_Hero.Root.forward;
|
}
|
|
Vector3 _targetPosition = m_Hero.Pos + _realDir * (skill.skillInfo.config.AtkDist * .5f);
|
_targetPosition.y = 0;
|
UnityEngine.AI.NavMeshHit _navMeshHit;
|
if (UnityEngine.AI.NavMesh.Raycast(_sourcePosition, _targetPosition, out _navMeshHit, LayerUtility.WalkbleMask))
|
{
|
_targetPosition = _navMeshHit.position;
|
}
|
_targetPosition.y = m_Hero.Pos.y;
|
skill.targetPosition = _targetPosition;
|
|
// 如果技能是对地的技能, 则基准点应该为目标
|
// 没有目标则基准点为技能的施法距离
|
if (_castType == E_SkillCastType.Ground)
|
{
|
if (skill.skillInfo.config.Skillactmark != GAStaticDefine.Act_Roll
|
&& skill.skillInfo.config.AtkType != (int)E_AtkType.FlashMove)
|
{
|
GActorFight _fight = m_Hero.LockTarget as GActorFight;
|
if (_fight != null && _fight.CanAtked())
|
{
|
skill.targetPosition = m_Hero.LockTarget.Pos;
|
}
|
else if (m_Hero.SelectTarget != null)
|
{
|
skill.targetPosition = m_Hero.SelectTarget.Pos;
|
}
|
}
|
}
|
else if (_castType == E_SkillCastType.NeedTarget)
|
{
|
Vector3 _dir;
|
float _radius = 0.5f;
|
GActorFight _fight = m_Hero.LockTarget as GActorFight;
|
if (_fight != null && _fight.CanAtked())
|
{
|
GActorNpcFight _npcFight = m_Hero.LockTarget as GActorNpcFight;
|
if (_npcFight != null)
|
{
|
_radius = _npcFight.NpcConfig.ModelRadius;
|
}
|
_dir = MathUtility.ForwardXZ(m_Hero.Pos, m_Hero.LockTarget.Pos);
|
skill.targetPosition = m_Hero.LockTarget.Pos + _dir * _radius;
|
skill.mainTarget = m_Hero.LockTarget as GActorFight;
|
}
|
else if (m_Hero.SelectTarget != null)
|
{
|
GActorNpcFight _npcFight = m_Hero.SelectTarget as GActorNpcFight;
|
if (_npcFight != null && _npcFight.CanAtked())
|
{
|
_radius = _npcFight.NpcConfig.ModelRadius;
|
}
|
_dir = MathUtility.ForwardXZ(m_Hero.Pos, m_Hero.SelectTarget.Pos);
|
skill.targetPosition = m_Hero.SelectTarget.Pos + _dir * _radius;
|
skill.mainTarget = m_Hero.SelectTarget as GActorFight;
|
}
|
}
|
else
|
{
|
if (skill.id != 190)
|
{
|
GActorNpcFight _npcFight = m_Hero.SelectTarget as GActorNpcFight;
|
if (m_Hero.SelectTarget != null
|
&& (m_Hero.SelectTarget.ActorType != GameObjType.gotNPC
|
|| (_npcFight != null && _npcFight.NpcConfig.IsBoss > 1)))
|
{
|
float _distSqrt2 = MathUtility.DistanceSqrtXZ(m_Hero.SelectTarget.Pos, skill.targetPosition);
|
|
float _chkDist = m_Hero.JobSetup.MoveLimitDist * Constants.F_DELTA;
|
float _chkDistSqrt = Mathf.Pow(_chkDist, 2);
|
|
if (_distSqrt2 > _chkDistSqrt)
|
{
|
Vector3 _dir = MathUtility.ForwardXZ(m_Hero.SelectTarget.Pos, m_Hero.Pos);
|
if (_dir == Vector3.zero)
|
{
|
_dir = m_Hero.Root.forward;
|
}
|
skill.targetPosition = m_Hero.SelectTarget.Pos + _dir * _chkDist;
|
}
|
}
|
}
|
}
|
|
if (m_Hero.SelectTarget != null)
|
{
|
// 检测复活buff是否存在
|
if (StatusMgr.Instance.IsInvincible(m_Hero.SelectTarget.ServerInstID))
|
{
|
SysNotifyMgr.Instance.ShowTip("PKFuHuo");
|
}
|
}
|
|
if (skill.targetPosition != Vector3.zero)
|
{
|
Vector3 _adjustPos = PathFinder.AdjustPosition(skill.targetPosition);
|
skill.targetPosition = new Vector3(_adjustPos.x, skill.targetPosition.y, _adjustPos.z);
|
}
|
|
if (!StatusMgr.Instance.CanMove(m_Hero.ServerInstID))
|
{
|
skill.targetPosition = m_Hero.Pos;
|
}
|
|
if (_targetType == E_SkillCastTarget.CanAttacked)
|
{
|
if (m_Hero.SelectTarget != null)
|
{
|
if (StatusMgr.Instance.IsInvincible(m_Hero.SelectTarget.ServerInstID))
|
{
|
GAStaticDefine.PopHp(m_Hero, m_Hero.SelectTarget, (int)HurtAttackType.Immune, 0);
|
}
|
}
|
}
|
|
// 判断当前目标是否可以加入可攻击列表中
|
if (m_Hero.SelectTarget is GA_NpcClientFightNorm)
|
{
|
if (CheckCanAttackTarget(m_Hero.SelectTarget as GActorFight, skill, _soSkill, skill.targetPosition))
|
{
|
if (PersonalEnemy.m_CBinSdDict.ContainsKey(m_Hero.SelectTarget.ServerInstID))
|
{
|
//绑定木桩的算服务端
|
AddToHitTargetList(skill, m_Hero.SelectTarget);
|
}
|
else
|
{
|
AddToHitClientBattleTargetList(skill, m_Hero.SelectTarget);
|
}
|
}
|
}
|
else
|
{
|
if (CheckCanAttackTarget(m_Hero.SelectTarget as GActorFight, skill, _soSkill, skill.targetPosition))
|
{
|
AddToHitTargetList(skill, m_Hero.SelectTarget);
|
}
|
}
|
|
// 判断范围内的目标是否可以接入可攻击列表中
|
List<GActor> _actorList = GAMgr.Instance.GetAll();
|
_actorList.Sort((GActor a1, GActor a2) =>
|
{
|
float _distA1 = MathUtility.DistanceSqrtXZ(a1.Pos, skill.targetPosition);
|
float _distA2 = MathUtility.DistanceSqrtXZ(a2.Pos, skill.targetPosition);
|
|
if (_distA1 < _distA2)
|
{
|
return -1;
|
}
|
else if (_distA1 > _distA2)
|
{
|
return 1;
|
}
|
return 0;
|
});
|
|
for (int i = 0; i < _actorList.Count && skill.hitTargetList.Count + skill.hitClientBattleTargetList.Count < _hitTestLimit; ++i)
|
{
|
#if UNITY_EDITOR
|
if (RuntimeLogUtility.s_ForceOneEnemy && i > 0)
|
{
|
continue;
|
}
|
#endif
|
|
if (_actorList[i] is GA_NpcClientFightNorm)
|
{
|
if (CheckCanAttackTarget(_actorList[i] as GActorFight, skill, _soSkill, skill.targetPosition))
|
{
|
var _sid = _actorList[i].ServerInstID;
|
if (PersonalEnemy.GetPersionEnemySID(_sid) != 0)
|
{
|
AddToHitTargetList(skill, _actorList[i]);
|
}
|
else
|
{
|
AddToHitClientBattleTargetList(skill, _actorList[i]);
|
}
|
}
|
}
|
else if (_actorList[i] is GA_NpcFightSgzcZZ)
|
{
|
if (CheckCanAttackTarget(_actorList[i] as GActorFight, skill, _soSkill, skill.targetPosition))
|
{
|
AddToHitClientBattleTargetList(skill, _actorList[i]);
|
}
|
}
|
else
|
{
|
if (CheckCanAttackTarget(_actorList[i] as GActorFight, skill, _soSkill, skill.targetPosition))
|
{
|
AddToHitTargetList(skill, _actorList[i]);
|
}
|
}
|
}
|
|
if (skill.hitTargetList.Count == 0 && skill.hitClientBattleTargetList.Count == 0)
|
{
|
if (_castType == E_SkillCastType.NeedTarget)
|
{
|
SysNotifyMgr.Instance.ShowTip("SkillSelectedTarget");
|
return;
|
}
|
}
|
|
m_Hero.OnHorse(0);
|
DTC0428_tagPlayerRideHorse.Send_tagPlayerRideHorse(false);
|
|
// 处理吟唱和蓄力类技能
|
if (skill.skillInfo.config.CastTime > 0)
|
{
|
if (m_Hero.SkillMgr.CurCastSkill != skill || m_Hero.SkillMgr.CurCastSkill.SkillCompelete)
|
{
|
// 带进度条技能只设置当前技能, 并不将其释放
|
m_Hero.SkillMgr.CastSkill(m_Hero.ServerInstID, skill.id);
|
skill.SkillPreparing = true;
|
m_Hero.NextAction = 200;
|
m_Hero.SkillMgr.DoingPrepareSkill = true;
|
}
|
}
|
else
|
{
|
if (skill.id == 190)
|
{
|
m_Hero.StopPathFind();
|
m_Hero.State = E_ActorState.Roll;
|
}
|
|
// 开始执行表现层技能逻辑
|
m_Hero.SkillMgr.CastSkill(m_Hero.ServerInstID, skill.id);
|
|
if (skill.skillInfo.config.Skillactmark > 0
|
&& skill.skillInfo.config.Skillactmark < 20)
|
{
|
switch (skill.skillInfo.config.Skillactmark)
|
{
|
case 10:
|
m_Hero.Play(GAStaticDefine.State_Attack1Hash, 0);
|
break;
|
case 11:
|
m_Hero.Play(GAStaticDefine.State_Attack2Hash, 0);
|
break;
|
case 12:
|
m_Hero.Play(GAStaticDefine.State_Attack3Hash, 0);
|
break;
|
case 13:
|
m_Hero.Play(GAStaticDefine.State_Attack4Hash, 0);
|
break;
|
}
|
|
m_LastCommonAtkTime = Time.realtimeSinceStartup;
|
}
|
else
|
{
|
m_Hero.NextAction = skill.skillInfo.config.Skillactmark;
|
switch (skill.skillInfo.config.Skillactmark)
|
{
|
case 21:
|
m_Hero.Play(GAStaticDefine.State_Skill21, 0);
|
break;
|
case 22:
|
m_Hero.Play(GAStaticDefine.State_Skill22, 0);
|
break;
|
case 23:
|
m_Hero.Play(GAStaticDefine.State_Skill23, 0);
|
break;
|
case 24:
|
m_Hero.Play(GAStaticDefine.State_Skill24, 0);
|
break;
|
case 25:
|
m_Hero.Play(GAStaticDefine.State_Skill25, 0);
|
break;
|
case 26:
|
m_Hero.Play(GAStaticDefine.State_Skill26, 0);
|
break;
|
case 27:
|
m_Hero.Play(GAStaticDefine.State_Skill27, 0);
|
break;
|
case 28:
|
m_Hero.Play(GAStaticDefine.State_Skill28, 0);
|
break;
|
case 29:
|
m_Hero.Play(GAStaticDefine.State_Skill29, 0);
|
break;
|
case 99:
|
m_Hero.Play(GAStaticDefine.State_RollHash, 0);
|
break;
|
}
|
}
|
}
|
|
ulong _hurtValue = 0;
|
byte _attackType = 0;
|
|
if (PreFightMission.Instance.IsFinished())
|
{
|
if (_castType != E_SkillCastType.NeedTarget || skill.hitTargetList.Count > 0
|
|| skill.skillInfo.config.Skillactmark == GAStaticDefine.Act_Roll)
|
{
|
GActorFight _target = null;
|
|
CB405_tagCMSuperAtk _b405 = null;
|
if (!AdventureStage.Instance.IsInAdventureStage
|
#if UNITY_EDITOR
|
&& !RuntimeLogUtility.TEST_CLIENT_PVP
|
#endif
|
)
|
{
|
// 创建发包协议
|
_b405 = new CB405_tagCMSuperAtk();
|
_b405.SkillID = (ushort)SkillHelper.Instance.GetSkillID(skill.skillInfo.config.SkillTypeID);
|
_b405.PosX = (ushort)(m_Hero.Pos.x * 2 + GA_Hero.MapOffset.x);
|
_b405.PosY = (ushort)(m_Hero.Pos.z * 2 + GA_Hero.MapOffset.z);
|
_b405.TagPosX = (ushort)(skill.targetPosition.x * 2 + GA_Hero.MapOffset.x);
|
_b405.TagPosY = (ushort)(skill.targetPosition.z * 2 + GA_Hero.MapOffset.z);
|
_b405.WorldTick = PlayerDatas.Instance.GetWorldTick();
|
}
|
|
_serverHurtList.Clear();
|
|
if (ClientDungeonStageUtility.isClientDungeon)
|
{
|
_b405.PosX = (ushort)(GA_Hero.recordServerPos.x + GA_Hero.MapOffset.x);
|
_b405.PosY = (ushort)(GA_Hero.recordServerPos.z + GA_Hero.MapOffset.z);
|
_b405.TagPosX = (ushort)(GA_Hero.recordServerPos.x + GA_Hero.MapOffset.x);
|
_b405.TagPosY = (ushort)(GA_Hero.recordServerPos.z + GA_Hero.MapOffset.z);
|
}
|
|
// Debug.LogFormat("释放了技能: {0},当前位置: {1} 目标位置: {2}", _b405.SkillID, new Vector2(_b405.PosX, _b405.PosY), new Vector2(_b405.TagPosX, _b405.TagPosY));
|
uint _bindID = 0;
|
// 创建出攻击客户端攻击对象和服务端攻击对象
|
for (int i = 0; i < skill.hitTargetList.Count; ++i)
|
{
|
_target = GAMgr.Instance.GetByCID(skill.hitTargetList[i]) as GActorFight;
|
|
if (_target == null)
|
{
|
Debug.LogFormat("<color=red>找到的目标对象: C:{0} 为空....</color>", skill.hitTargetList[i]);
|
continue;
|
}
|
_bindID = 0;
|
|
ClientSceneManager.Instance.lastDeadPos = _target.Pos;
|
|
if (_target is GA_NpcClientFightNorm || _target is GA_PVPClientPlayer)
|
{
|
_bindID = PersonalEnemy.GetPersionEnemySID(_target.ServerInstID);
|
}
|
|
// 选中对象都要生成服务端对象
|
CB405_tagCMSuperAtk.tagSkillPosHurtObj _hurtObj = new CB405_tagCMSuperAtk.tagSkillPosHurtObj();
|
_hurtObj.ObjID = _bindID == 0 ? _target.ServerInstID : _bindID;
|
|
if (_target is GA_PlayerXMZZ
|
|| _target is GA_PVPClientPlayer || _target is GA_ILClientPlayer)
|
{
|
_hurtObj.ObjType = (byte)GameObjType.gotNPC;
|
}
|
else
|
{
|
_hurtObj.ObjType = (byte)_target.ActorType;
|
}
|
|
_serverHurtList.Add(_hurtObj);
|
|
if (m_ClientFightEnable == false)
|
{
|
continue;
|
}
|
|
// 人物, 非小怪不计算伤害,不生成客户端数据
|
if (_target.ActorType == GameObjType.gotPlayer
|
&& !(_target is GA_PVPClientPlayer || _target is GA_ILClientPlayer))
|
{
|
GA_Player _player = _target as GA_Player;
|
if (_player != null)
|
{
|
if (_player.MovingState == E_MovingState.Ride)
|
{
|
_player.SwitchHorse(0);
|
}
|
}
|
continue;
|
}
|
|
if (_target.ActorType == GameObjType.gotNPC
|
&& !(_target is GA_NpcFightSgzcZZ))
|
{
|
GActorNpcFight _npc = _target as GActorNpcFight;
|
if (_npc.NpcConfig.IsBoss != (int)E_MonsterType.Normal)
|
{
|
continue;
|
}
|
}
|
|
if (_bindID != 0)
|
{
|
continue;
|
}
|
|
// 计算此次伤害
|
AttackHandler.CalculateDamage(m_Hero, _target, skill, i, ref _hurtValue, ref _attackType);
|
|
// 服务端伤害赋值
|
_hurtObj.HurtHP = (uint)(_hurtValue % Constants.ExpPointValue);
|
_hurtObj.HurtHPEx = (uint)(_hurtValue / Constants.ExpPointValue);
|
_hurtObj.AttackType = _attackType;
|
|
if (_target.ActorInfo.Hp < _hurtValue)
|
{
|
_target.ActorInfo.SyncServerHp = 0;
|
}
|
else
|
{
|
_target.ActorInfo.SyncServerHp = _target.ActorInfo.Hp - _hurtValue;
|
}
|
|
_serverHurtList[_serverHurtList.Count - 1] = _hurtObj;
|
|
AttackHandler.HurtObjs _hurtObject = new AttackHandler.HurtObjs
|
{
|
ObjID = _target.ServerInstID,
|
ObjType = (byte)_target.ActorType,
|
clientInstID = _target.ClientInstID
|
};
|
|
// 客户端表现用伤害赋值
|
_hurtObject.HurtHP = _hurtValue;
|
_hurtObject.RealHurtHP = _hurtValue;
|
_hurtObject.AttackType = _attackType;
|
|
skill.hurtClientList.Add(_hurtObject);
|
}
|
|
if (_b405 != null)
|
{
|
_b405.HurtCount = (ushort)_serverHurtList.Count;
|
_b405.HurtList = new CB405_tagCMSuperAtk.tagSkillPosHurtObj[_b405.HurtCount];
|
for (int i = 0; i < _b405.HurtCount; ++i)
|
{
|
_b405.HurtList[i] = new CB405_tagCMSuperAtk.tagSkillPosHurtObj()
|
{
|
ObjType = _serverHurtList[i].ObjType,
|
ObjID = _serverHurtList[i].ObjID,
|
AttackType = _serverHurtList[i].AttackType,
|
HurtHP = _serverHurtList[i].HurtHP,
|
HurtHPEx = _serverHurtList[i].HurtHPEx
|
};
|
}
|
if (!ArenaManager.IsArenaClientNotMirrorFight)
|
{
|
if (!CrossServerUtility.IsCrossServer())
|
{
|
GameNetSystem.Instance.SendInfo(_b405);
|
}
|
else
|
{
|
GameNetSystem.Instance.SendToCrossServer(_b405);
|
}
|
}
|
}
|
|
#if UNITY_EDITOR
|
string _content = string.Format("# CB405_tagCMSuperAtk => {0} 使用技能 {1}",
|
m_Hero.ServerInstID,
|
skill.id);
|
RuntimeLogUtility.AddLog_Blue(_content);
|
#endif
|
}
|
}
|
|
if (skill.hitClientBattleTargetList.Count > 0)
|
{
|
GActorFight _target = null;
|
|
for (int i = 0; i < skill.hitClientBattleTargetList.Count; ++i)
|
{
|
_target = GAMgr.Instance.GetByCID(skill.hitClientBattleTargetList[i]) as GActorFight;
|
|
if (PersonalEnemy.m_CBinSdDict.ContainsKey(_target.ServerInstID))
|
{
|
continue;
|
}
|
|
AttackHandler.HurtObjs _hurtObject = new AttackHandler.HurtObjs
|
{
|
ObjID = (uint)_target.ServerInstID,
|
ObjType = (byte)_target.ActorType,
|
clientInstID = _target.ClientInstID
|
};
|
|
AttackHandler.CalculateDamage(m_Hero, _target, skill, i, ref _hurtValue, ref _attackType);
|
|
_hurtObject.HurtHP = _hurtValue;
|
if (_target.ActorInfo.RealHp < _hurtValue)
|
{
|
_hurtObject.CurHP = 0;
|
}
|
else
|
{
|
_hurtObject.CurHP = _target.ActorInfo.RealHp - _hurtValue;
|
}
|
_hurtObject.RealHurtHP = _hurtValue;
|
_hurtObject.AttackType = _attackType;
|
_target.ActorInfo.SyncServerHp = _hurtObject.CurHP;
|
|
var _clientNpc = _target as GA_NpcClientFightNorm;
|
if (_clientNpc != null)
|
{
|
_clientNpc.BeAttacked();
|
}
|
|
HandleExpertSkill(skill.id, m_Hero.ServerInstID, _target.ServerInstID);
|
|
skill.hurtClntFightNpcList.Add(_hurtObject);
|
|
if (_target.ActorInfo.RealHp <= _hurtValue && (_clientNpc == null || _clientNpc.lockHp <= 0))
|
{
|
if (_clientNpc != null && _clientNpc.NpcConfig.AIType != 198)
|
{
|
_target.KillerServerInstID = m_Hero.ServerInstID;
|
_target.ActorInfo.serverDie = true;
|
GAMgr.Instance.ServerDie(_target.ServerInstID);
|
GAMgr.Instance.DoDelayDie(_target);
|
|
if (m_Hero.LockTarget == _target)
|
{
|
m_Hero.LockTarget = null;
|
}
|
if (m_Hero.SelectTarget == _target)
|
{
|
m_Hero.SelectTarget = null;
|
}
|
|
if (_clientNpc != null
|
&& _clientNpc.belongEventID != -1)
|
{
|
ClientSceneManager.Instance.NpcDead(_clientNpc.belongEventID, _clientNpc, _clientNpc.NpcConfig.NPCID);
|
}
|
|
ClientSceneManager.Instance.lastDeadPos = _clientNpc.Pos;
|
}
|
// 前期战斗只发送石头人的
|
//if (1000 == _target.NpcConfig.NPCID)
|
//{
|
// CA225_tagCMClientTaskCount _a225 = new CA225_tagCMClientTaskCount
|
// {
|
// CountID = (uint)_target.NpcConfig.NPCID
|
// };
|
// GameNetSystem.Instance.SendInfo(_a225);
|
//}
|
}
|
}
|
}
|
|
if (onCastSkill != null)
|
{
|
onCastSkill(skill.id);
|
}
|
}
|
|
private void AddToHitTargetList(Skill skill, GActor target)
|
{
|
if (skill.hitTargetList.Contains(target.ClientInstID))
|
{
|
return;
|
}
|
skill.hitTargetList.Add(target.ClientInstID);
|
}
|
|
private void AddToHitClientBattleTargetList(Skill skill, GActor target)
|
{
|
if (skill.hitClientBattleTargetList.Contains(target.ClientInstID))
|
{
|
return;
|
}
|
skill.hitClientBattleTargetList.Add(target.ClientInstID);
|
}
|
|
private bool CheckCanAttackTarget(GActorFight actor, Skill skill, SoSkill soSkill, Vector3 basePosition)
|
{
|
if (ArenaManager.IsArenaClientNotMirrorFight)
|
{
|
soSkill.chkDistance = ArenaManager.ArenaCheckDistance;
|
soSkill.chkRange = ArenaManager.ArenaCheckAngle;
|
}
|
|
|
// 取得可攻击的目标类型
|
E_SkillCastTarget _targetType = (E_SkillCastTarget)(skill.skillInfo.config.Tag / 10);
|
E_SkillCastType _castType = (E_SkillCastType)(skill.skillInfo.config.Tag % 10);
|
|
if (actor == null
|
|| actor.ActorInfo.serverDie)
|
{
|
return false;
|
}
|
|
if (actor.ServerInstID == m_Hero.ServerInstID)
|
{
|
return false;
|
}
|
|
GActorNpcFight _fightNpc = actor as GActorNpcFight;
|
GA_NpcFightSgzcZZ _sgzcRobot = actor as GA_NpcFightSgzcZZ;
|
|
if (_fightNpc != null)
|
{
|
if (_fightNpc.NpcConfig.NPCType != (int)E_NpcType.PersonalEnemy)
|
{
|
if (_fightNpc.Group != E_ActorGroup.Enemy
|
|| _fightNpc.NpcConfig.Country == 1)
|
{
|
return false;
|
}
|
}
|
}
|
|
//Debug.LogFormat(" |-- 只对: {0} 伤害的技能", _targetType);
|
// 只对小怪进行伤害的类型
|
if (_targetType == E_SkillCastTarget.Monster)
|
{
|
// 不是怪物类型无法伤害
|
if (_fightNpc == null)
|
{
|
Debug.LogFormat(" |-- 目标: {0} 不是战斗npc,不能对其造成伤害");
|
Debug.LogFormat("<color=red>|-- 对象类型不对</color>");
|
return false;
|
}
|
}
|
// 可攻击怪物
|
else if (_targetType == E_SkillCastTarget.CanAttackedMonster)
|
{
|
if (_fightNpc == null)
|
{
|
Debug.LogFormat("<color=red>|-- 对象类型不对</color>");
|
Debug.LogFormat(" |-- 目标: {0} 不是战斗npc,不能对其造成伤害");
|
return false;
|
}
|
|
if (_fightNpc.ActorType != GameObjType.gotNPC)
|
{
|
Debug.LogFormat("<color=red>|-- 对象类型不对</color>");
|
Debug.LogFormat(" |-- 目标: {0} 不是战斗npc,不能对其造成伤害");
|
return false;
|
}
|
|
}
|
// 可攻击对象类型
|
else if (_targetType == E_SkillCastTarget.CanAttacked)
|
{
|
if (actor.ActorType == GameObjType.gotPlayer)
|
{
|
GA_Player _player = actor as GA_Player;
|
if (_player != null)
|
{
|
if (!_player.CanAtked())
|
{
|
return false;
|
}
|
}
|
}
|
else
|
{
|
if (_fightNpc == null && _sgzcRobot == null)
|
{
|
Debug.LogFormat("<color=red>|-- 对象类型不对</color>");
|
Debug.LogFormat(" |-- 目标: {0} 不是战斗npc,不能对其造成伤害");
|
return false;
|
}
|
}
|
}
|
|
// -----------------------
|
// 这里检测是否在技能释放范围内
|
if (soSkill != null)
|
{
|
if (soSkill.chkDistance == 0)
|
{
|
//Debug.LogFormat("<color=red>|-- 配置的检测范围为空: {0}</color>", skill.id);
|
return false;
|
}
|
|
float _chkDistance = soSkill.chkDistance;
|
|
if (!PreFightMission.Instance.IsFinished())
|
{
|
_chkDistance = GeneralDefine.PrefightAtkRange;
|
}
|
|
SkillHelper.EffectValue _effectValue;
|
List<SkillHelper.SkillInfo> _spSkillInfo = SkillHelper.Instance.GetSpSkill(skill.id);
|
if (_spSkillInfo != null)
|
{
|
for (int i = 0; i < _spSkillInfo.Count; ++i)
|
{
|
if (_spSkillInfo[i].effectValue.TryGetValue(4045, out _effectValue))
|
{
|
_chkDistance += (_effectValue.value1 * .5f);
|
#if UNITY_EDITOR
|
if (RuntimeLogUtility.s_SkillEffectLog)
|
{
|
Debug.LogFormat("技能 {0} 触发了效果 {1} , 搜怪范围 增加了 {2}", _spSkillInfo[i].config.SkillID, 4045, (_effectValue.value1 * .5f));
|
}
|
#endif
|
}
|
}
|
}
|
|
Vector3 _centerPos = m_Hero.Pos;
|
|
if (soSkill.hitTestType == E_HitTestType.Sector
|
&& soSkill.chkRange == 0)
|
{
|
// 非自身的时候,执行目标点索引
|
if (_castType != E_SkillCastType.None)
|
{
|
_centerPos = skill.targetPosition;
|
}
|
}
|
|
// 默认取1的范围内的怪, 没有的情况再判断范围
|
float _defaultCircleDisSqrt = MathUtility.DistanceSqrtXZ(_centerPos, actor.Pos);
|
|
if (_defaultCircleDisSqrt > 1)
|
{
|
//Debug.LogFormat(" |-- 检测方式为: {0}, center: {1}, range: {2}, distance: {3}",
|
// soSkill.hitTestType,
|
// m_Hero.Pos,
|
// soSkill.chkRange,
|
// soSkill.chkDistance);
|
|
if (soSkill.hitTestType == E_HitTestType.Rect)
|
{
|
if (!CollisionUtility.IsPointInRectangle(_centerPos, m_Hero.destForward,
|
soSkill.chkRange, soSkill.chkDistance,
|
actor.Pos))
|
{
|
//Debug.LogFormat("<color=red>|-- 对象不再范围内: {0}</color>", actor.ServerObjID);
|
//Debug.LogFormat(" |-- 目标: {0} 不在检测范围内", actor.ServerObjID);
|
return false;
|
}
|
}
|
else if (soSkill.hitTestType == E_HitTestType.Sector)
|
{
|
int _chkAngle = soSkill.chkRange == 0 ? 360 : soSkill.chkRange;
|
if (!CollisionUtility.IsPointInSector2(_centerPos, m_Hero.destForward,
|
soSkill.chkDistance, _chkAngle,
|
actor.Pos))
|
{
|
//Debug.LogFormat("<color=red>|-- 对象不再范围内: {0}</color>", actor.ServerObjID);
|
//Debug.LogFormat(" |-- 目标: {0} 不在检测范围内", actor.ServerObjID);
|
return false;
|
}
|
}
|
}
|
}
|
|
return true;
|
}
|
|
|
private void HandleExpertSkill(int skillID, uint aSid, uint tSid)
|
{
|
// if (!ClientSceneManager.Instance.IsClientFightMode)
|
// {
|
// return;
|
// }
|
|
// 增加一些buff效果
|
int _expertSkillId = 0;
|
if (tsModel.TryGetExpertSkill(skillID, out _expertSkillId))
|
{
|
var _skillInfo = SkillHelper.Instance.Get(_expertSkillId);
|
|
SkillHelper.EffectValue _effectValue;
|
// 不满足概率
|
if (_skillInfo.effectValue.TryGetValue(4004, out _effectValue))
|
{
|
if (UnityEngine.Random.Range(0, 10000) > _effectValue.value1)
|
{
|
return;
|
}
|
}
|
|
if (_skillInfo.config.SkillType == (int)E_SkillType.PassiveSustainedReduction)
|
{
|
StatusMgr.Instance.AddClientBuff(tSid, _expertSkillId, aSid, 0, _skillInfo.config.LastTime6);
|
}
|
}
|
}
|
}
|