using System.Collections.Generic;
using UnityEngine;
public static class AttackHandler
{
///
/// 攻击者服务器id, 被击者服务器id, 攻击类型, 伤害
///
public static UnityEngine.Events.UnityAction OnAttackTarget;
public static void HandlerAttackTarget(GActorFight attacker,
GActorFight target,
int hurtValue,
byte attackType,
int skillID,
int soConfigID,
SoConfigBase soConfig,
bool canDie)
{
if (target == null)
{
return;
}
int _hitEffectId = -1;
Skill _skill = attacker.SkillMgr.Get(skillID);
foreach (var _buffId in GeneralDefine.BuffToHitEffect.Keys)
{
if (_skill.cacheBuffList.Contains(_buffId))
{
_hitEffectId = GeneralDefine.BuffToHitEffect[_buffId];
break;
}
}
if (_hitEffectId != -1)
{
SFXController _controller = target.MP_Hit ?
SFXPlayUtility.Instance.PlayEffectAsync(_hitEffectId,
target.MP_Hit.position,
Vector3.forward) :
SFXPlayUtility.Instance.PlayEffectAsync(_hitEffectId,
target.Root.position,
Vector3.forward);
if (CameraController.Instance.CameraObject)
{
_controller.transform.rotation = CameraController.Instance.CameraObject.transform.rotation * Quaternion.Euler(0, 0, Random.Range(0, 360));
}
// 播放受击音效
if (target.ActorType == GameObjType.gotNPC)
{
target.PlayHurtAudio(attacker);
}
}
else
{
if ((attacker.ServerInstID == PlayerDatas.Instance.PlayerId
|| (attacker.ActorInfo.ownerSID != 0
&& attacker.ActorInfo.ownerSID == PlayerDatas.Instance.PlayerId)))
{
if (attackType != (int)HurtAttackType.Miss
&& attackType != (int)HurtAttackType.Recovery
&& soConfig.floodPercent != 0)
{
target.DoFlashWhite();
}
if (soConfig.hitEffectId != 0)
{
SFXController _controller = target.MP_Hit
? SFXPlayUtility.Instance.PlayEffectAsync(soConfig.hitEffectId,
target.MP_Hit.position,
Vector3.forward) :
SFXPlayUtility.Instance.PlayEffectAsync(soConfig.hitEffectId,
target.Root.position,
Vector3.forward);
// 播放受击音效
if (target.ActorType == GameObjType.gotNPC)
{
target.PlayHurtAudio(attacker);
}
}
}
}
if (soConfig.floodPercent != 0)
{
if (target.CanAtkedRotate())
{
target.Forward = target.destForward = MathUtility.ForwardXZ(attacker.Pos, target.Pos);
}
}
if (!canDie && attackType != (int)HurtAttackType.Miss && attackType != (int)HurtAttackType.Recovery)
{
//if (soConfig.hitPauseTime > 0)
//{
//target.DoAnimatorPause(soConfig.hitPauseTime);//???
//}
// 决定目标是否处于释放不能打断的技能中
bool _canInterrupt = true;
if (target.SkillMgr.CurCastSkill != null)
{
if (!target.SkillMgr.CurCastSkill.SkillCompelete)
{
if (target.SkillMgr.CurCastSkill.skillInfo.soFile != null)
{
_canInterrupt = target.SkillMgr.CurCastSkill.skillInfo.soFile.interrupt;
}
}
}
if (CheckHitEffect(attacker, target, skillID))
{
if (soConfig.floodPercent > 0
&& (_skill.skillInfo.soFile != null && _canInterrupt))
{
if (soConfig.hitType == E_HitType.Hurt)
{
target.Hurt();
}
else if (soConfig.hitType == E_HitType.HitDown)
{
target.HurtDown();
}
}
}
if (CheckPull(attacker, target, soConfig.bodyControlId))
{
target.StartBeatBack(attacker.ServerInstID, soConfig.bodyControlId, MathUtility.ForwardXZ(target.Pos, attacker.Pos));
}
}
// 是否计算血量
bool _calculateHp = hurtValue != 0;
// 是否显示飘字
bool _popHp = (attackType == (byte)HurtAttackType.Miss || _calculateHp);
bool _alive = target.ActorInfo.RealHp > 0;
if (_calculateHp)
{
if (!PreFightMission.Instance.IsFinished())
{
if (target.ServerInstID == PlayerDatas.Instance.baseData.PlayerID)
{
int _realHurt = hurtValue;
int _limit = (int)(PlayerDatas.Instance.extersion.MaxHP * 0.4f);
if (PlayerDatas.Instance.baseData.HP - hurtValue < _limit)
{
_realHurt = hurtValue - (_limit - ((int)PlayerDatas.Instance.baseData.HP - hurtValue));
}
float _pencent = PlayerDatas.Instance.baseData.HP * 1f / PlayerDatas.Instance.extersion.MaxHP;
if (_pencent > 0.4f)
{
target.ActorInfo.ReduceHp((uint)_realHurt);
PlayerDatas.Instance.FightRefreshPlayerHp((uint)target.ActorInfo.Hp);
}
}
else if (target is GA_NpcClientFightBoss)
{
if ((int)target.ActorInfo.RealHp - (int)hurtValue < 10)
{
hurtValue = (int)target.ActorInfo.RealHp - 10;
}
target.ActorInfo.ReduceHp((uint)hurtValue);
}
else
{
target.ActorInfo.ReduceHp((uint)hurtValue);
}
}
else
{
// 处理封魔坛英雄伤害
FakeDemonJarDungeonStage _dungeon = StageLoad.Instance.currentStage as FakeDemonJarDungeonStage;
if (_dungeon != null)
{
if (attacker.ServerInstID == PlayerDatas.Instance.PlayerId)
{
_dungeon.AddHeroHurt(hurtValue);
}
}
else
{
target.ActorInfo.ReduceHp((uint)hurtValue);
if (target.ServerInstID == PlayerDatas.Instance.baseData.PlayerID)
{
PlayerDatas.Instance.FightRefreshPlayerHp((uint)target.ActorInfo.RealHp);
}
if (ClientDungeonStageUtility.isClientDungeon
#if UNITY_EDITOR
|| RuntimeLogUtility.TEST_CLIENT_PVP
#endif
)
{
if (target.ServerInstID == PlayerDatas.Instance.PlayerId && target.ActorInfo.RealHp == 0)
{
GA_PVPClientPlayer.Result(false);
var _hero = target as GA_Hero;
if (_hero != null)
{
_hero.Die();
if (_hero.State == E_ActorState.AutoRun)
{
_hero.StopPathFind();
}
_hero.StopRush();
_hero.Behaviour.StopHandupAI(true);
}
}
}
}
if (target.ServerInstID == PlayerDatas.Instance.PlayerId)
{
GA_Hero _hero = target as GA_Hero;
if (_hero.SelectTarget == null)
{
_hero.SelectTarget = attacker;
}
}
}
}
if (_popHp)
{
GAStaticDefine.PopHp(attacker, target, attackType, hurtValue);
}
if (_alive)
{
if (target.ActorInfo.RealHp == 0)
{
target.KillerPos = attacker.Pos;
}
}
if (canDie && target.ActorInfo.RealHp == 0)
{
target.Die(attacker.ServerInstID, soConfig.deadFlyId);
}
if (target.ActorInfo.serverDie
&& soConfig.floodPercent > 0)
{
target.ReleaseLifeBar();
if (target.ActorType != GameObjType.gotPlayer)
{
target.ReleaseName();
}
}
if (OnAttackTarget != null)
{
OnAttackTarget(attacker.ServerInstID, target.ServerInstID, attackType, (uint)hurtValue);
}
#if UNITY_EDITOR
if (hurtValue != 0 && attacker.ActorType == GameObjType.gotPlayer)
{
string _content = string.Format("STM_BaseAttack => {0} 使用技能:{1} 的 {2} 插帧, 攻击了 {3}, 伤害为: {4}, 剩余血量: {5}, 是否可以死亡: {6}",
attacker.ServerInstID,
soConfigID,
skillID,
target.ServerInstID,
hurtValue,
target.ActorInfo.RealHp,
canDie);
RuntimeLogUtility.AddLog_Blue(_content, target.ServerInstID);
}
#endif
}
public static void CalculateDamage(GActorFight attacker,
GActorFight target,
Skill skill,
int hitTime,
ref uint hurtValue,
ref byte attackType)
{
int _hitRate = 1;
int _missRate = 0;
int _aSuperHitRate = 0;
int _aLuckyHitRate = 0;
int _aZhuXianHitRate = 0;
bool _isMiss = false;
bool _isCrit = false;
bool _isLucky = false;
bool _isZhuxianHit = false;
SkillHelper.EffectValue _effectValue;
float _aAtkSkillPer = 0;
int _atkSkillValue = 0;
int _aZhuxianHurtPer = 0;
int _aLuckyHit = 0;// 会心一击伤害加成 万分率, 默认0, 会心一击时有值
float _aSuperHit = 0;// 暴击伤害 固定值, 默认0, 暴击时有值
int _aMinAtk = 1;// 最小攻击 固定值
int _aMaxAtk = 1;// 最大攻击 固定值
int _aIceAtk = 0;// 真实伤害 固定值
int _aIgnoreDefRate = 0;// 无视防御比率 万分率
int _aSkillAtkRate = 0;// 技能伤害加成 万分率
int _aDamagePer = 0;// 伤害加成 万分率
//int _aDamagePerPVP = 0;// PVP伤害加成 万分率
int _aFinalHurt = 0;// 最终伤害加成 固定值
int _aIceAtkSuperHit = 1;// 真实伤害暴击倍值 倍值, 默认1
int _aOnlyFinalHurt = 0;
int _aFinalHurtPer = 0;
int _superHit = 0;
int _luckyHit = 0;
int _aNPCHurtAddPer = 0;
//int _dLuckyHitReduce = 0;// 会心一击伤害减少 万分率, 默认0, 会心一击时有值
//int _dSuperHitReduce = 0;// 暴击伤害减少 万分率, 默认0, 暴击时有值
int _dDamChanceDef = 0;// 抵御伤害比例 万分率, 默认0, 只在格挡成功才有值, 格挡成功率默认20%
int _dDef = 0;// 防御值 固定值
int _dIceDef = 1;// 真实伤害防御 固定值
//int _dIgnoreDefRateReduce = 0;// 无视防御比率抗性 万分率
//int _dSkillAtkRateReduce = 0;// 技能伤害减少 万分率
int _dDamReduce = 0;// 伤害减少 万分率
//int _dDamagePerPVPReduce = 0;// PVP伤害减少 万分率
int _dFinalHurtReduce = 0;// 最终伤害减少 固定值
#region 伤害替换
GActorNpcFight _npc = target as GActorNpcFight;
if (_npc != null && _npc.NpcConfig.IsBoss == 0)
{
// 没有1009的时候使用1010
if (!skill.skillInfo.effectValue.TryGetValue(1009, out _effectValue))
{
skill.skillInfo.effectValue.TryGetValue(1010, out _effectValue);
}
else
{
#if UNITY_EDITOR
if (RuntimeLogUtility.s_SkillEffectLog)
{
Debug.LogFormat("替换了1010为1009", _effectValue.value1);
}
#endif
}
}
else
{
skill.skillInfo.effectValue.TryGetValue(1010, out _effectValue);
}
_aAtkSkillPer = _effectValue.value1;
_atkSkillValue = _effectValue.value2;// 技能固定值(1010或者1009的value2)
#endregion
#region 伤害衰减或者递增
skill.skillInfo.effectValue.TryGetValue(1056, out _effectValue);
float _atkReduceRate = _effectValue.value1;
if (_effectValue.value2 == 0)
{
_aAtkSkillPer = _aAtkSkillPer - (hitTime * _atkReduceRate);
}
else if (_effectValue.value2 == 1)
{
_aAtkSkillPer = _aAtkSkillPer + (hitTime * _atkReduceRate);
}
#endregion
// -------------- 指定防御方属性 --------------
if (target.ActorType == GameObjType.gotNPC)
{
GActorNpcFight _npcBase = target as GActorNpcFight;
if (_npcBase == null)
{
return;
}
_missRate = _npcBase.NpcConfig.MissRate;
_dDef = _npcBase.NpcConfig.Def;
}
else if (target.ActorType == GameObjType.gotPlayer)
{
_missRate = PlayerDatas.Instance.extersion.Miss;
}
// -------------- 指定攻击方属性 --------------
if (attacker.ActorType == GameObjType.gotPlayer)
{
float _rate = 1f;
if (attacker is GA_PVPClientPlayer)
{
_rate = GeneralDefine.ClientPvpAttributePer;
}
_hitRate = PlayerDatas.Instance.extersion.HIT;
_aSuperHitRate = PlayerDatas.Instance.extersion.SuperHitRate;
_aLuckyHitRate = PlayerDatas.Instance.extersion.luckHitRate;
_aZhuxianHurtPer = PlayerDatas.Instance.extersion.zhuxianHurtPer;
_aZhuXianHitRate = PlayerDatas.Instance.extersion.zhuxianRate;
_aMaxAtk = (int)(PlayerDatas.Instance.extersion.MAXATK * _rate);
_aMinAtk = (int)(PlayerDatas.Instance.extersion.MINATK * _rate);
_aIgnoreDefRate = PlayerDatas.Instance.extersion.IgnoreDefRate;
_aSkillAtkRate = PlayerDatas.Instance.extersion.SkillAtkRate;
_aDamagePer = PlayerDatas.Instance.extersion.DamagePer;
_aFinalHurt = (int)(PlayerDatas.Instance.extersion.FinalHurt);
_aIceAtk = (int)(PlayerDatas.Instance.extersion.realATK * _rate);
_aOnlyFinalHurt = PlayerDatas.Instance.extersion.OnlyFinalHurt;
_luckyHit = PlayerDatas.Instance.extersion.luckHitVal;
_superHit = PlayerDatas.Instance.extersion.SuperHit;
_aNPCHurtAddPer = PlayerDatas.Instance.extersion.NpcHurtAddPer;
_aFinalHurtPer = PlayerDatas.Instance.extersion.FunalHurtPer;
}
else if (attacker.ActorType == GameObjType.gotNPC)
{
GActorNpcFight _npcBase = attacker as GActorNpcFight;
if (_npcBase == null)
{
return;
}
_hitRate = _npcBase.NpcConfig.Hit;
_isCrit = IsCrit(_npcBase.NpcConfig.SuperHiteRate);
_aMaxAtk = _npcBase.NpcConfig.MaxAtk;
_aMinAtk = _npcBase.NpcConfig.MinAtk;
}
_isMiss = IsMiss(_hitRate, _missRate);
_isCrit = IsCrit(_aSuperHitRate);
_isLucky = IsLucky(_aLuckyHitRate);
_isZhuxianHit = IsZhuXianHit(_aZhuXianHitRate);
// 4014 必定触发 按位配置 1为必命中,2为必暴击,4为必会心一击
if (skill.skillInfo.effectValue.TryGetValue(4014, out _effectValue))
{
if ((_effectValue.value1 & 0x1) == 1)
{
_isMiss = false;
}
if ((_effectValue.value1 & 0x10) == 1)
{
_isCrit = true;
}
if ((_effectValue.value1 & 0x100) == 1)
{
_isLucky = true;
}
#if UNITY_EDITOR
if (RuntimeLogUtility.s_SkillEffectLog)
{
Debug.LogFormat("技能 {0} 触发了效果 {1} , 命中: {2}, 暴击: {3}, 会心: {4}",
skill.id,
4014,
(_effectValue.value1 & 0x1) == 1,
(_effectValue.value1 & 0x10) == 1,
(_effectValue.value1 & 0x100) == 1);
}
#endif
}
// 4510 buff中攻击必命中
if (StatusMgr.Instance.TryGetSkillEffectValue(attacker.ServerInstID, 4510, out _effectValue))
{
_isMiss = false;
}
// 如果MISS, 则不再进行计算
if (_isMiss)
{
hurtValue = 0;
attackType = (byte)HurtAttackType.Miss;
return;
}
_aLuckyHit = _isLucky ? _luckyHit : 0;
_aSuperHit = _isCrit ? _superHit : 0;
// 4051 当发生会心伤害时, 增加会心一击伤害
if (_isLucky
&& skill.skillInfo.effectValue.TryGetValue(4051, out _effectValue))
{
_aLuckyHit += _effectValue.value1;
}
// HurtType == 2 为pve类型
if (skill.skillInfo.config.HurtType == 2
|| skill.skillInfo.config.HurtType == 0)
{
// 处理本身的技能
CalculateSkillEffect(attacker, target, skill.skillInfo, ref _aDamagePer, ref _aAtkSkillPer, ref _atkSkillValue, ref _aIceAtk, ref _aFinalHurt, ref _aSuperHit, _isCrit);
// 处理sp技能
List _spSkillList = SkillHelper.Instance.GetSpSkill(skill.id);
if (_spSkillList != null)
{
for (int i = 0; i < _spSkillList.Count; ++i)
{
CalculateSkillEffect(attacker, target, _spSkillList[i], ref _aDamagePer, ref _aAtkSkillPer, ref _atkSkillValue, ref _aIceAtk, ref _aFinalHurt, ref _aSuperHit, _isCrit);
}
}
}
_aAtkSkillPer = _aAtkSkillPer * Constants.F_DELTA;
Dictionary _attrValues;
if (Snxxz.UI.CalculateSkillGetAttrHurtUtility.Instance.TryGetAttrDictBySkill(skill.id, out _attrValues))
{
foreach (var _per in _attrValues.Values)
{
_aAtkSkillPer += (_per * Constants.F_DELTA);
}
}
// -------------- 公式计算 --------------
float _value1;
float _value2;
float _value3;
// PVE
if (attacker.ActorType == GameObjType.gotPlayer
&& (target.ActorType == GameObjType.gotNPC || target is GA_PVPClientPlayer))
{
//"PVE_1" :"int(max((((max((aMaxAtk if isLuckyHit else (aMinAtk + (aMaxAtk - aMinAtk)*rand))
// -dDef*max(1-aIgnoreDefRate/10000.0,0),1))*(1+(aLuckyHit/10000.0 if isLuckyHit else 0))
// +(aSuperHit if isSuperHit else 0)+ max(aIceAtkSuperHit*aIceAtk - dIceDef, 0))
// *(atkSkillPer+(aZhuxianHurtPer/10000.0 if isZhuxianHit else 0)+aSkillAtkRate/10000.0)
// *(1+aDamagePer/10000.0)+max(aFinalHurt+aOnlyFinalHurt-dFinalHurtReduce, 0)
// +atkSkillValue)*(1+dBeHurtPer/10000.0)*max(1+aFinalHurtPer/10000.0,1)
// +aNPCHurtAddPer/10000.0*(aMinAtk+aMaxAtk)/2.0,(aMinAtk+aMaxAtk)/2*0.05 + (aMinAtk+aMaxAtk)/2*0.1*rand))"
float _random = Random.Range(0f, 1f);
_value1 = _aMinAtk + (_aMaxAtk - _aMinAtk) * _random;
#if UNITY_EDITOR
if (RuntimeLogUtility.s_HurtValueLog)
{
Debug.LogFormat("_aMinAtk + (_aMaxAtk - _aMinAtk) * _random = {0}", _value1);
}
#endif
_value2 = _dDef * Mathf.Max(1 - _aIgnoreDefRate * Constants.F_DELTA, 1);
#if UNITY_EDITOR
if (RuntimeLogUtility.s_HurtValueLog)
{
Debug.LogFormat("_dDef * Mathf.Max(1 - _aIgnoreDefRate * Constants.F_DELTA, 1) = {0}", _value2);
}
#endif
_value3 = _isLucky ? _aMaxAtk : _value1;
#if UNITY_EDITOR
if (RuntimeLogUtility.s_HurtValueLog)
{
Debug.LogFormat("_isLucky ? _aMaxAtk : _value1 = {0}", _value3);
}
#endif
_value3 = _value3 - _value2;
#if UNITY_EDITOR
if (RuntimeLogUtility.s_HurtValueLog)
{
Debug.LogFormat("_value3 - _value2 = {0}", _value3);
}
#endif
_value3 = Mathf.Max(_value3, 1);
#if UNITY_EDITOR
if (RuntimeLogUtility.s_HurtValueLog)
{
Debug.LogFormat("Mathf.Max(_value3, 1) = {0}", _value3);
}
#endif
_value1 = 1 + (_isLucky ? _aLuckyHit * Constants.F_DELTA : 0);
#if UNITY_EDITOR
if (RuntimeLogUtility.s_HurtValueLog)
{
Debug.LogFormat("1 + (_isLucky ? _aLuckyHit * Constants.F_DELTA : 0) = {0}", _value1);
}
#endif
_value3 *= _value1;
#if UNITY_EDITOR
if (RuntimeLogUtility.s_HurtValueLog)
{
Debug.LogFormat("_value3 *= _value1 = {0}", _value3);
}
#endif
_value3 += _aSuperHit;
#if UNITY_EDITOR
if (RuntimeLogUtility.s_HurtValueLog)
{
Debug.LogFormat("_value3 += _aSuperHit = {0}", _value3);
}
#endif
_value3 += Mathf.Max(_aIceAtkSuperHit * _aIceAtk - _dIceDef, 0);
#if UNITY_EDITOR
if (RuntimeLogUtility.s_HurtValueLog)
{
Debug.LogFormat("_value3 += Mathf.Max(_aIceAtkSuperHit * _aIceAtk - _dIceDef, 0) = {0}", _value3);
}
#endif
_value1 = (_aAtkSkillPer + (_isZhuxianHit ? _aZhuxianHurtPer * Constants.F_DELTA : 0) + _aSkillAtkRate * Constants.F_DELTA) * (1 + _aDamagePer * Constants.F_DELTA);
#if UNITY_EDITOR
if (RuntimeLogUtility.s_HurtValueLog)
{
Debug.LogFormat("(_aAtkSkillPer + _aSkillAtkRate * Constants.F_DELTA) * (1 + _aDamagePer * Constants.F_DELTA) = {0}", _value1);
}
#endif
_value3 *= _value1;
#if UNITY_EDITOR
if (RuntimeLogUtility.s_HurtValueLog)
{
Debug.LogFormat("_value3 *= _value1", _value3);
}
#endif
_value3 += _aFinalHurt + _aOnlyFinalHurt + _atkSkillValue;
#if UNITY_EDITOR
if (RuntimeLogUtility.s_HurtValueLog)
{
Debug.LogFormat("_value3 += _aFinalHurt + _aOnlyFinalHurt + _atkSkillValue = {0}", _value3);
}
#endif
_value2 = Mathf.Max(1 + _aFinalHurtPer * Constants.F_DELTA, 1);
_value3 *= _value2;
_value2 = _aNPCHurtAddPer * Constants.F_DELTA * (_aMinAtk + _aMaxAtk) * .5f;
_value3 += _value2;
//(aMinAtk+aMaxAtk)/2*0.05 + (aMinAtk+aMaxAtk)/2*0.1*rand)
_random = Random.Range(0f, 1f);
_value1 = (_aMinAtk + _aMaxAtk) * .5f * .05f + (_aMinAtk + _aMaxAtk) * .5f * .1f * _random;
#if UNITY_EDITOR
if (RuntimeLogUtility.s_HurtValueLog)
{
Debug.LogFormat("(_aMinAtk + _aMaxAtk) * .5f * .3f + (_aMinAtk + _aMaxAtk) * .5f * .2f * _random = {0}", _value3);
}
#endif
hurtValue = (uint)Mathf.Max(_value3, _value1);
#if UNITY_EDITOR
if (RuntimeLogUtility.s_HurtValueLog)
{
Debug.LogFormat("(uint)Mathf.Max(_value3, _value1) = {0}", _value3);
}
#endif
}
// EVP
else if ((attacker.ActorType == GameObjType.gotNPC
&& target.ActorType == GameObjType.gotPlayer) || attacker is GA_PVPClientPlayer)
{
// "EVP_1" :"max((max((aMinAtk+aMaxAtk)/2.0-dDef,0)+max(aIceAtk - dIceDef, 0))*(atkSkillPer+aSkillAtkRate/10000.0)*(1-min(dDamReduce,8000)/10000.0)*(1-min(dDamChanceDef,8000)/10000.0)+max(aFinalHurt-dFinalHurtReduce, 0)+atkSkillValue,1)"
_value1 = Mathf.Max((_aMaxAtk + _aMinAtk) * .5f - _dDef, 0);
_value2 = Mathf.Max(_aIceAtk - _dIceDef, 0);
_value1 += _value2;
_value2 = (1 - Mathf.Min(_dDamReduce, 8000) * Constants.F_DELTA);
_value3 = (1 - Mathf.Min(_dDamChanceDef, 8000) * Constants.F_DELTA);
_value1 = _value1 * _value2 * (_aAtkSkillPer + _aSkillAtkRate * Constants.F_DELTA) * _value3;
_value2 = Mathf.Max(_aFinalHurt - _dFinalHurtReduce, 0);
_value1 += _value2;
_value3 = 1 + 4 * Random.Range(0f, 1f);
hurtValue = (uint)Mathf.Max(_value1, _value3);
}
if (_isZhuxianHit)
{
attackType = (byte)HurtAttackType.ZhuXianAtk;
}
else if (_isLucky)
{
attackType = (byte)HurtAttackType.LuckyHit;
}
else if (_isCrit)
{
attackType = (byte)HurtAttackType.SuperHit;
}
else
{
attackType = (byte)HurtAttackType.Normal;
}
}
private static bool IsMiss(int hit, int miss)
{
return hit * 1f / (hit + miss) - Random.Range(0f, 1f) < 0;
}
private static bool IsCrit(int superHitRate)
{
return Random.Range(0, 10000) < superHitRate;
}
private static bool IsLucky(int luckHitRate)
{
return Random.Range(0, 10000) < luckHitRate;
}
private static bool IsZhuXianHit(int zxHitRate)
{
return Random.Range(0, 10000) < zxHitRate;
}
private static float HpPer(GActor actor)
{
return actor.ActorInfo.RealHp * 1f / actor.ActorInfo.RealMaxHp;
}
private static void CalculateSkillEffect(GActorFight attacker, GActorFight target, SkillHelper.SkillInfo skillInfo,
ref int _aDamagePer,
ref float _aAtkSkillPer,
ref int _atkSkillValue,
ref int _aIceAtk,
ref int _aFinalHurt,
ref float _aSuperHit,
bool _isCrit)
{
SkillHelper.EffectValue _effectValue;
#region 伤害增加
// 4002 目标血量低于XX百分比提高伤害xx
if (skillInfo.effectValue.TryGetValue(4002, out _effectValue))
{
if (HpPer(target) < _effectValue.value2 * Constants.F_DELTA)
{
_aDamagePer += _effectValue.value1;
#if UNITY_EDITOR
if (RuntimeLogUtility.s_SkillEffectLog)
{
Debug.LogFormat("技能 {0} 触发了效果 {1} , aDamagePer 增加了 {2}", skillInfo.config.SkillID, 4002, _effectValue.value1);
}
#endif
}
}
if (skillInfo.effectValue.TryGetValue(1062, out _effectValue))
{
GActorNpcFight _npcFight = target as GActorNpcFight;
if (_npcFight != null)
{
if (_npcFight.NpcConfig.PoisionDef == _effectValue.value3)
{
_aAtkSkillPer += _effectValue.value1;
_atkSkillValue += _effectValue.value2;
#if UNITY_EDITOR
if (RuntimeLogUtility.s_SkillEffectLog)
{
Debug.LogFormat("技能 {0} 触发了效果 {1} , _aAtkSkillPer 翻了 {2} 倍", skillInfo.config.SkillID, 1062, _effectValue.value2 * Constants.F_DELTA);
}
#endif
}
}
}
// 4003 目标处于XX状态提高伤害 _aDamagePer ???
if (skillInfo.effectValue.TryGetValue(4003, out _effectValue))
{
if (target.ActorInfo.status4012.ContainsKey((byte)_effectValue.value2)
&& target.ActorInfo.status4012[(byte)_effectValue.value2] > 0)
{
_aDamagePer += _effectValue.value1;
#if UNITY_EDITOR
if (RuntimeLogUtility.s_SkillEffectLog)
{
Debug.LogFormat("技能 {0} 触发了效果 {1} , aDamagePer 增加了 {2}", skillInfo.config.SkillID, 4003, _effectValue.value1);
}
#endif
}
}
// 4005 概率增加攻击(技能)伤害万分率
if (skillInfo.effectValue.TryGetValue(4005, out _effectValue))
{
if (Random.Range(0, 10000) < _effectValue.value2)
{
_aAtkSkillPer += _effectValue.value1;
#if UNITY_EDITOR
if (RuntimeLogUtility.s_SkillEffectLog)
{
Debug.LogFormat("技能 {0} 触发了效果 {1} , _aAtkSkillPer 增加了 {2}", skillInfo.config.SkillID, 4005, _effectValue.value1);
}
#endif
}
}
// 4035 增加技能伤害万分率
if (skillInfo.effectValue.TryGetValue(4035, out _effectValue))
{
bool _isValid = true;
var _mapConfig = MapConfig.Get(PlayerDatas.Instance.baseData.MapID);
if (_mapConfig.MapFBType != 0)
{
var _funcConfig = FuncConfigConfig.Get("SkillXPAddByFB");
if (!_funcConfig.Numerical1.Contains(PlayerDatas.Instance.baseData.MapID.ToString()))
{
_isValid = false;
}
}
if (_isValid)
{
_aAtkSkillPer += _effectValue.value1;
#if UNITY_EDITOR
if (RuntimeLogUtility.s_SkillEffectLog)
{
Debug.LogFormat("技能 {0} 触发了效果 {1} , _aAtkSkillPer 增加了 {2}", skillInfo.config.SkillID, 4035, _effectValue.value1);
}
#endif
}
}
// 4011 暴击时增加技能伤害
if (skillInfo.effectValue.TryGetValue(4011, out _effectValue))
{
if (_isCrit)
{
_aAtkSkillPer += _effectValue.value1;
#if UNITY_EDITOR
if (RuntimeLogUtility.s_SkillEffectLog)
{
Debug.LogFormat("技能 {0} 触发了效果 {1} , _aAtkSkillPer 增加了 {2}", skillInfo.config.SkillID, 4011, _effectValue.value1);
}
#endif
}
}
// 4015 目标处于XX状态提高技能伤害
if (skillInfo.effectValue.TryGetValue(4015, out _effectValue))
{
if (target.ActorInfo.status4012.ContainsKey((byte)_effectValue.value2)
&& target.ActorInfo.status4012[(byte)_effectValue.value2] > 0)
{
_aAtkSkillPer += _effectValue.value1;
#if UNITY_EDITOR
if (RuntimeLogUtility.s_SkillEffectLog)
{
Debug.LogFormat("技能 {0} 触发了效果 {1} , _aAtkSkillPer 增加了 {2}", skillInfo.config.SkillID, 4015, _effectValue.value1);
}
#endif
}
}
// 4024 攻击附加真实伤害百分比
if (skillInfo.effectValue.TryGetValue(4024, out _effectValue))
{
_aIceAtk *= (int)((10000 + _effectValue.value1) * Constants.F_DELTA);
#if UNITY_EDITOR
if (RuntimeLogUtility.s_SkillEffectLog)
{
Debug.LogFormat("技能 {0} 触发了效果 {1} , _aIceAtk 增加了 {2}", skillInfo.config.SkillID, 4024, _aIceAtk * _effectValue.value1 * Constants.F_DELTA);
}
#endif
}
// 4025 攻击附加真实伤害
if (skillInfo.effectValue.TryGetValue(4025, out _effectValue))
{
_aIceAtk += _effectValue.value1;
#if UNITY_EDITOR
if (RuntimeLogUtility.s_SkillEffectLog)
{
Debug.LogFormat("技能 {0} 触发了效果 {1} , _aIceAtk 增加了 {2}", skillInfo.config.SkillID, 4025, _effectValue.value1);
}
#endif
}
// 4501 buff中攻击附加技能伤害
if (StatusMgr.Instance.TryGetSkillEffectValue(attacker.ServerInstID, 4501, out _effectValue))
{
int _rate = _effectValue.value2;
SkillHelper.EffectValue _rateEffectValue;
// 判断是否存在4030 有的话提高概率
if (StatusMgr.Instance.TryGetSkillEffectValue(attacker.ServerInstID, 4030, out _rateEffectValue))
{
_rate += _rateEffectValue.value1;
#if UNITY_EDITOR
if (RuntimeLogUtility.s_SkillEffectLog)
{
Debug.LogFormat("技能 {0} 触发了效果 {1} , 增加了 4501 的概率", skillInfo.config.SkillID, 4030, _rateEffectValue.value1);
}
#endif
}
if (Random.Range(0, 10000) < _rate)
{
_aAtkSkillPer += _effectValue.value1;
#if UNITY_EDITOR
if (RuntimeLogUtility.s_SkillEffectLog)
{
Debug.LogFormat("技能 {0} 触发了效果 {1} , _aAtkSkillPer 增加了 {2}", skillInfo.config.SkillID, 4501, _effectValue.value1);
}
#endif
}
}
// 4503 buff中攻击提高增加伤害,可附加目标处于XX状态
if (StatusMgr.Instance.TryGetSkillEffectValue(attacker.ServerInstID, 4503, out _effectValue))
{
if (target.ActorInfo.status4012.ContainsKey((byte)_effectValue.value2)
&& target.ActorInfo.status4012[(byte)_effectValue.value2] > 0)
{
_aDamagePer += _effectValue.value1;
#if UNITY_EDITOR
if (RuntimeLogUtility.s_SkillEffectLog)
{
Debug.LogFormat("技能 {0} 触发了效果 {1} , _aDamagePer 增加了 {2}", skillInfo.config.SkillID, 4503, _effectValue.value1);
}
#endif
}
}
// 4511 buff中攻击造成坐骑攻击属性XX%的额外伤害
if (StatusMgr.Instance.TryGetSkillEffectValue(attacker.ServerInstID, 4511, out _effectValue))
{
PlayerMountDatas _mountData = Snxxz.UI.ModelCenter.Instance.GetModel();
int _allMountAtk = _mountData.GetAllMountAttack();
_allMountAtk = (int)(_effectValue.value1 * Constants.F_DELTA * _allMountAtk);
_aFinalHurt += _allMountAtk;
#if UNITY_EDITOR
if (RuntimeLogUtility.s_SkillEffectLog)
{
Debug.LogFormat("技能 {0} 触发了效果 {1} , _aFinalHurt 增加了 {2}", skillInfo.config.SkillID, 4511, _allMountAtk);
}
#endif
}
#endregion
#region 暴击伤害增加
// 4007 暴击时增加暴击值, 增加暴击值万分率, 虚要判断自己身上是否有配置的buff
if (skillInfo.effectValue.TryGetValue(4007, out _effectValue))
{
bool _condition = true;
// 判断buff
if (_effectValue.value2 != 0)
{
if (!StatusMgr.Instance.IsExist(attacker.ServerInstID, _effectValue.value2))
{
_condition = false;
}
}
// 是否可以执行
if (_condition && _isCrit)
{
_aSuperHit += (_aSuperHit * _effectValue.value1 * Constants.F_DELTA);
#if UNITY_EDITOR
if (RuntimeLogUtility.s_SkillEffectLog)
{
Debug.LogFormat("技能 {0} 触发了效果 {1} , _aSuperHit 增加了 {2}", skillInfo.config.SkillID, 4007, (_aSuperHit * _effectValue.value1 * Constants.F_DELTA));
}
#endif
}
}
#endregion
}
public static bool CheckHitEffect(GActorFight attacker, GActorFight target, int skillID)
{
if (PreFightMission.Instance.faBaoSkillShow
&& target.ActorType == GameObjType.gotNPC)
{
return false;
}
if (target.ActorInfo.RealHp == 0)
{
return false;
}
if (attacker is GA_Pet
|| target is GA_NpcFightSgzcZZ)
{
return false;
}
GActorNpcFight _fightNpc = null;
// 目标是玩家
if (target.ActorType == GameObjType.gotPlayer)
{
GActorPlayerBase _player = target as GActorPlayerBase;
if (!_player.CanHurted())
{
return false;
}
// 攻击者是玩家
if (attacker.ActorType == GameObjType.gotPlayer)
{
// 默认没有任何反馈
return false;
}
// 攻击者是NPC
else if (attacker.ActorType == GameObjType.gotNPC)
{
// 这里为前期战斗的判断
if (!PreFightMission.Instance.IsFinished())
{
_fightNpc = attacker as GActorNpcFight;
if (_fightNpc.NpcConfig.NPCID == 1007
&& skillID != 10027)
{
return true;
}
}
// 1 目标无任何反馈
// 2 目标有被击特效
// 3 目标有被击特效及动作
Skill _skill = attacker.SkillMgr.Get(skillID);
// 根据配置, 如果释放的是冲锋技能, 默认都可以打断
if (_skill != null
&& !_skill.skillInfo.effectValue.ContainsKey(2100))
{
_fightNpc = attacker as GActorNpcFight;
if (_fightNpc != null)
{
// 如果配置无反馈
if (_fightNpc.NpcConfig == null
|| _fightNpc.NpcConfig.AtkFeedback < 3)
{
return false;
}
bool _IsSkillCantStop = true;
// 判断对象是否正在释放不可以被中断的技能
Skill _currentSkill = target.SkillMgr.CurCastSkill;
if (_currentSkill != null && _currentSkill.SkillCompelete == false)
{
if (!_player.CanSkillInterrupt(_currentSkill.id)
|| _player.NextAction == _currentSkill.skillInfo.config.Skillactmark)
{
_IsSkillCantStop = false;
}
}
// 如果目标正在释放技能且非普攻, 不能打断
if (target.IsIdle() == false
&& target.IsRun() == false
&& target.IsHurt() == false
&& _IsSkillCantStop)
{
return false;
}
}
}
}
}
else if (target.ActorType == GameObjType.gotNPC)
{
// 1 有被击动作
// 2 无被击动作
_fightNpc = target as GActorNpcFight;
if (_fightNpc != null)
{
if (_fightNpc.NpcConfig.NPCType == (int)E_NpcType.BreakableObj)
{
return false;
}
if (_fightNpc.NpcConfig == null
|| _fightNpc.NpcConfig.hurtFeedback == 2)
{
return false;
}
if (!_fightNpc.CanHurted())
{
return false;
}
}
}
return true;
}
public static bool CheckPull(GActorFight attacker,
GActorFight target,
int bodyControlID)
{
if (PreFightMission.Instance.faBaoSkillShow
&& target.ActorType == GameObjType.gotNPC)
{
return false;
}
if (target is GA_NpcFightSgzcZZ)
{
return false;
}
if (attacker is GA_Pet
|| attacker is GA_NpcSummonFight)
{
return false;
}
if (bodyControlID == -1)
{
return false;
}
// 目标已经客户端死亡
if (target.ActorInfo.RealHp == 0)
{
return false;
}
// 判断身体控制是否有配置,且配置的方式是否为可以推
SoBodyControl _bodyControl = ScriptableObjectLoader.LoadSoBodyControl(bodyControlID);
if (_bodyControl == null
|| _bodyControl.duration == 0)
{
return false;
}
// 目标是玩家
if (target.ActorType == GameObjType.gotPlayer)
{
// 攻击者是玩家
if (attacker.ActorType == GameObjType.gotPlayer)
{
return _bodyControl.useForPlayer && target.CanPushedBack();
}
else if (attacker.ActorType == GameObjType.gotNPC)
{
GActorNpcFight _npc = attacker as GActorNpcFight;
if (_npc == null)
{
return false;
}
// 这里为前期战斗的判断
if (!PreFightMission.Instance.IsFinished())
{
if (_npc.NpcConfig.NPCID == 1007)
{
return true;
}
}
if (_npc.NpcConfig == null
|| _npc.NpcConfig.AtkFeedback < 3)
{
return false;
}
if (!target.CanPushedBack())
{
return false;
}
}
}
// 目标是npc怪物
else if (target.ActorType == GameObjType.gotNPC)
{
// 1 有被击动作
// 2 无被击动作
if (!target.CanPushedBack())
{
return false;
}
}
return true;
}
public struct HurtObjs
{
public byte ObjType;
public uint ObjID;
public uint clientInstID;
public byte AttackType;
public uint HurtHP;
public ulong CurHP;
public uint CurHPEx;
}
}