using System.Collections.Generic;
|
using vnxbqy.UI;
|
using UnityEngine;
|
|
public static class AttackHandler
|
{
|
/// <summary>
|
/// 攻击者服务器id, 被击者服务器id, 攻击类型, 伤害
|
/// </summary>
|
public static UnityEngine.Events.UnityAction<uint, uint, byte, ulong> OnAttackTarget;
|
|
private static TreasureSkillModel m_tsModel;
|
private static TreasureSkillModel TsSkillModel
|
{
|
get
|
{
|
return m_tsModel ?? (m_tsModel = ModelCenter.Instance.GetModel<TreasureSkillModel>());
|
}
|
}
|
|
|
public static void HandlerAttackTarget(GActorFight attacker,
|
GActorFight target,
|
ulong hurtValue,
|
ulong realHurtValue,
|
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);
|
|
bool _isPlayHurtAudio = false;
|
var _cNpc = target as GA_NpcClientFightNorm;
|
if (_cNpc != null)
|
{
|
if (_cNpc.hitSoundId > 0)
|
{
|
target.PlaySkillAudio(_cNpc.hitSoundId);
|
_isPlayHurtAudio = true;
|
}
|
}
|
|
if (!_isPlayHurtAudio)
|
{
|
// 播放受击音效
|
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))
|
{
|
float _extDis = 0;
|
SkillHelper.EffectValue _effectValue;
|
if (_skill.skillInfo.effectValue.TryGetValue(4015, out _effectValue))
|
{
|
_extDis += _effectValue.value1 * .5f;
|
}
|
target.StartBeatBack(attacker.ServerInstID, soConfig.bodyControlId, MathUtility.ForwardXZ(target.Pos, attacker.Pos), (HurtAttackType)attackType, _extDis);
|
}
|
}
|
|
// 是否计算血量
|
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)
|
{
|
ulong _realHurt = hurtValue;
|
ulong _limit = (ulong)(PlayerDatas.Instance.extersion.MaxHP * 0.4f);
|
if (PlayerDatas.Instance.baseData.HP - hurtValue < _limit)
|
{
|
_realHurt = hurtValue - (_limit - (PlayerDatas.Instance.baseData.HP - hurtValue));
|
}
|
float _pencent = PlayerDatas.Instance.baseData.HP * 1f / PlayerDatas.Instance.extersion.MaxHP;
|
if (_pencent > 0.4f)
|
{
|
target.ActorInfo.ReduceHp(_realHurt);
|
PlayerDatas.Instance.FightRefreshPlayerHp(target.ActorInfo.Hp);
|
}
|
}
|
else if (target is GA_NpcClientFightBoss)
|
{
|
if (target.ActorInfo.RealHp > 10 && target.ActorInfo.RealHp - hurtValue < 10)
|
{
|
hurtValue = target.ActorInfo.RealHp - 10;
|
}
|
|
target.ActorInfo.ReduceHp(hurtValue);
|
}
|
else
|
{
|
target.ActorInfo.ReduceHp(hurtValue);
|
}
|
}
|
else
|
{
|
// 处理封魔坛英雄伤害
|
JiaDemonJarDungeonStage _dungeon = StageLoad.Instance.currentStage as JiaDemonJarDungeonStage;
|
if (_dungeon != null)
|
{
|
if (attacker.ServerInstID == PlayerDatas.Instance.PlayerId)
|
{
|
_dungeon.AddHeroHurt(hurtValue);
|
}
|
var _cnpc = target as GA_NpcClientFightNorm;
|
if (_cnpc != null)
|
{
|
_cnpc.StartCantAtkedRotate();
|
}
|
}
|
else
|
{
|
bool _doReduceHp = true;
|
|
if (attacker is GA_NpcClientFightNorm)
|
{
|
if ((target.ActorInfo.RealHp - realHurtValue) <= (target.ActorInfo.RealMaxHp * .5f))
|
{
|
hurtValue = 0;
|
realHurtValue = 0;
|
}
|
}
|
else if (target is GA_NpcClientFightNorm)
|
{
|
var _cnpc = target as GA_NpcClientFightNorm;
|
_cnpc.StartCantAtkedRotate();
|
if (_cnpc.NpcConfig.AIType == 196)
|
{
|
_doReduceHp = false;
|
}
|
else if (_cnpc.lockHp > 0)
|
{
|
var _lockHp = (ulong)(target.ActorInfo.RealMaxHp * _cnpc.lockHp);
|
if (realHurtValue >= target.ActorInfo.Hp)
|
{
|
target.ActorInfo.ResetHp((long)_lockHp);
|
_doReduceHp = false;
|
}
|
else if (target.ActorInfo.Hp - realHurtValue < _lockHp)
|
{
|
realHurtValue = target.ActorInfo.Hp - _lockHp;
|
hurtValue = 0;
|
}
|
}
|
}
|
|
if (_doReduceHp)
|
{
|
target.ActorInfo.ReduceHp(realHurtValue);
|
}
|
|
if (target.ServerInstID == PlayerDatas.Instance.baseData.PlayerID)
|
{
|
PlayerDatas.Instance.FightRefreshPlayerHp(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);
|
GA_ILClientPlayer.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.serverDie || target.ActorInfo.RealHp == 0))
|
{
|
target.Die(attacker.ServerInstID, soConfig.deadFlyId, (byte)attackType);
|
}
|
|
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, 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 ulong hurtValue,
|
ref byte attackType)
|
{
|
SkillHelper.SkillInfo _exceptSkill = SkillHelper.Instance.GetExpertSkill(skill.id);
|
|
int _hitRate = 1;
|
int _missRate = 0;
|
|
int _aSuperHitRate = 0;
|
int _aLuckyHitRate = 0;
|
int _aZhuXianHitRate = 0;
|
|
bool _isMiss = false;
|
bool _isCrit = false;
|
bool _isZhongJi = 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 _aDamagePVP = 0;// 伤害加成 固定值
|
int _aDamagePerPVP = 0;// PVP伤害加成 万分率
|
int _aFinalHurt = 0;// 最终伤害加成 固定值
|
//int _aIceAtkSuperHit = 1;// 真实伤害暴击倍值 倍值, 默认1
|
int _aOnlyFinalHurt = 0;
|
int _aFinalHurtPer = 0;
|
int _aDamagePVE = 0;
|
int _superHit = 0;
|
int _luckyHit = 0;
|
int _aNPCHurtAddPer = 0;
|
int _aRealmLv = 0;
|
int _suppressLV = 0;
|
float _suppressLV_0 = 0;
|
int _dLuckyHitReduce = 0;// 会心一击伤害减少 固定值
|
int _dLuckyHitRateReduce = 0; //会心一击抵抗 万分率
|
int _dSuperHitReduce = 0;// 暴击伤害减少 固定值
|
int _dSuperHitRateReduce = 0;// 暴击伤害减少 万分率
|
int _dDamChanceDef = 0;// 抵御伤害比例 万分率, 默认0, 只在格挡成功才有值, 格挡成功率默认20%
|
int _dDef = 0;// 防御值 固定值
|
int _dIceDef = 1;// 真实伤害防御 固定值
|
int _dIgnoreDefRateReduce = 0;// 无视防御比率抗性 万分率
|
int _dSkillAtkRateReduce = 0;// 技能伤害减少 万分率
|
int _dDamagePerPVPReduce = 0;// PVP伤害减少 万分率
|
int _dDamagePVPReduce = 0;// PVP伤害减少 固定值
|
int _dFinalHurtReduce = 0;// 最终伤害减少 固定值
|
int _dFinalHurtReducePer = 0;// 最终伤害减少 万分率
|
int _dRealmLv = 0;
|
|
int _suppressValueRealmRate = 10000;
|
float _suppressFightPower = 0;
|
float _suppressValueFP_0 = 0;
|
float _superHitAdd = 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)
|
|
if (skill.skillInfo.config.FuncType == 1
|
|| skill.skillInfo.config.FuncType == 2)
|
{
|
_atkSkillValue += PlayerDatas.Instance.baseData.FabaoHurt;
|
_aAtkSkillPer += PlayerDatas.Instance.baseData.FabaoHurtPer;
|
}
|
else if (skill.skillInfo.config.FuncType == 8)
|
{
|
_atkSkillValue += PlayerDatas.Instance.baseData.NormalHurt;
|
_aAtkSkillPer += PlayerDatas.Instance.baseData.NormalHurtPer;
|
}
|
|
#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;
|
_dRealmLv = _npcBase.NpcConfig.Realm;
|
_dIceDef = _npcBase.NpcConfig.IceDef;
|
}
|
else if (target.ActorType == GameObjType.gotPlayer)
|
{
|
|
|
if (ArenaManager.isArenaClient && target is GA_ILClientPlayer)
|
{
|
|
if (ArenaManager.isArenaRobot)
|
{
|
//防守方是守护者
|
_dDef = ArenaManager.playInfo[0][2];
|
_missRate = ArenaManager.playInfo[0][4];
|
|
//取玩家境界
|
_dRealmLv = PlayerDatas.Instance.baseData.realmLevel;
|
}
|
else
|
{
|
//防守方是玩家机器人
|
_dDef = ArenaManager.playInfo[1][2];
|
_missRate = ArenaManager.playInfo[1][4];
|
_dSkillAtkRateReduce = (int)(ArenaManager.playInfo[1][6]);
|
_dLuckyHitRateReduce = ArenaManager.playInfo[1][9];
|
_dLuckyHitReduce = ArenaManager.playInfo[1][10];
|
_dSuperHitRateReduce = ArenaManager.playInfo[1][13];
|
_dSuperHitReduce = ArenaManager.playInfo[1][14];
|
_dIceDef = (int)(ArenaManager.playInfo[1][16]);
|
_dIgnoreDefRateReduce = (int)(ArenaManager.playInfo[1][18]); // 无视防御伤害减免
|
_dDamagePerPVPReduce = ArenaManager.playInfo[1][22];
|
_dDamagePVPReduce = ArenaManager.playInfo[1][24];
|
_dFinalHurtReduce = (int)(ArenaManager.playInfo[1][26]);
|
_dFinalHurtReducePer = (ArenaManager.playInfo[1][28]);
|
_dDamChanceDef = (int)(ArenaManager.playInfo[1][30]);
|
_dRealmLv = (int)(ArenaManager.playInfo[1][32]);
|
|
}
|
}
|
else
|
{
|
//防守方为真玩家
|
_dDef = PlayerDatas.Instance.extersion.DEF;
|
_missRate = PlayerDatas.Instance.extersion.Miss;
|
_dSkillAtkRateReduce = PlayerDatas.Instance.extersion.skillAtkRateReduce;
|
_dLuckyHitRateReduce = PlayerDatas.Instance.extersion.LuckyHitRateReduce;
|
_dLuckyHitReduce = PlayerDatas.Instance.baseData.reduceHeartHurt;
|
_dSuperHitRateReduce = PlayerDatas.Instance.baseData.reduceCrit;
|
_dSuperHitReduce = PlayerDatas.Instance.extersion.SuperHitReduce;
|
_dIceDef = PlayerDatas.Instance.extersion.realDEF;
|
_dIgnoreDefRateReduce = PlayerDatas.Instance.extersion.IgnoreDefRateReduce;
|
_dFinalHurtReduce = PlayerDatas.Instance.extersion.FinalHurtReduce;
|
_dDamChanceDef = PlayerDatas.Instance.extersion.DamChanceDef;
|
_dRealmLv = PlayerDatas.Instance.baseData.realmLevel;
|
_dDamagePerPVPReduce = PlayerDatas.Instance.extersion.DamagePerPVPReduce;
|
_dDamagePVPReduce = PlayerDatas.Instance.extersion.DamagePerPVPReduce;
|
_dFinalHurtReducePer = PlayerDatas.Instance.baseData.reduceFinalHurt;
|
}
|
}
|
|
// -------------- 指定攻击方属性 --------------
|
if (attacker.ActorType == GameObjType.gotPlayer)
|
{
|
if (ArenaManager.isArenaClient && attacker is GA_ILClientPlayer)
|
{
|
|
if (ArenaManager.isArenaRobot)
|
{
|
//攻击方是守护者
|
_aMinAtk = (int)(ArenaManager.playInfo[0][0]);
|
_aMaxAtk = (int)(ArenaManager.playInfo[0][1]);
|
//_dDef = PlayerDatas.Instance.extersion.DEF;
|
_hitRate = (int)(ArenaManager.playInfo[0][3]);
|
//_missRate = PlayerDatas.Instance.extersion.Miss;
|
|
float _rate = 0.1f; //守护者没有的属性取玩家 此处只是为了做表现
|
_aSuperHitRate = PlayerDatas.Instance.extersion.SuperHitRate;
|
_aLuckyHitRate = PlayerDatas.Instance.extersion.luckHitRate;
|
_luckyHit = (int)(PlayerDatas.Instance.extersion.luckHitVal * _rate);
|
_superHit = (int)(PlayerDatas.Instance.extersion.SuperHit * _rate);
|
//取玩家境界
|
_aRealmLv = PlayerDatas.Instance.baseData.realmLevel;
|
|
}
|
else
|
{
|
//攻击方是玩家机器人
|
_aMinAtk = (int)(ArenaManager.playInfo[1][0]);
|
_aMaxAtk = (int)(ArenaManager.playInfo[1][1]);
|
//_dDef = PlayerDatas.Instance.extersion.DEF;
|
_hitRate = (int)(ArenaManager.playInfo[1][3]);
|
//_missRate = PlayerDatas.Instance.extersion.Miss;
|
_aSkillAtkRate = (int)(ArenaManager.playInfo[1][5]);
|
//_dSkillAtkRateReduce = (int)(ArenaManager.playInfo[1][6]);
|
_aLuckyHitRate = (int)(ArenaManager.playInfo[1][7]);
|
_luckyHit = (int)(ArenaManager.playInfo[1][8]);
|
_aSuperHitRate = (int)(ArenaManager.playInfo[1][11]);
|
_superHit = (int)(ArenaManager.playInfo[1][12]);
|
_aIceAtk = (int)(ArenaManager.playInfo[1][15]);
|
//_dIceDef = (int)(ArenaManager.playInfo[1][16]);
|
_aIgnoreDefRate = (int)(ArenaManager.playInfo[1][17]);
|
//_dIgnoreDefRateReduce = (int)(ArenaManager.playInfo[1][18]); // 无视防御伤害减免
|
_aDamagePVE = (int)(ArenaManager.playInfo[1][20]);
|
_aDamagePerPVP = (int)(ArenaManager.playInfo[1][21]);
|
_aDamagePVP = (int)(ArenaManager.playInfo[1][23]);
|
_aFinalHurt = (int)(ArenaManager.playInfo[1][25]);
|
//_dFinalHurtReduce = (int)(ArenaManager.playInfo[1][26]);
|
_aFinalHurtPer = (int)(ArenaManager.playInfo[1][27]);
|
_aOnlyFinalHurt = (int)(ArenaManager.playInfo[1][29]);
|
//_dDamChanceDef = (int)(ArenaManager.playInfo[1][30]);
|
_aNPCHurtAddPer = (int)(ArenaManager.playInfo[1][31]);
|
_aRealmLv = (int)(ArenaManager.playInfo[1][32]);
|
}
|
|
}
|
else
|
{
|
//攻击方为真玩家
|
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;
|
_aDamagePVP = PlayerDatas.Instance.extersion.DamagePVP;
|
_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;
|
_aDamagePVE = PlayerDatas.Instance.extersion.DamagePVE;
|
_aRealmLv = PlayerDatas.Instance.baseData.realmLevel;
|
_aDamagePerPVP = PlayerDatas.Instance.extersion.DamagePerPVP;
|
|
}
|
if (attacker.ServerInstID == PlayerDatas.Instance.PlayerId)
|
{
|
_isZhongJi = IsZhongji(skill.id, target);
|
}
|
|
}
|
else if (attacker.ActorType == GameObjType.gotNPC)
|
{
|
GActorNpcFight _npcBase = attacker as GActorNpcFight;
|
if (_npcBase == null)
|
{
|
return;
|
}
|
var _config = _npcBase.NpcConfig;
|
|
_hitRate = _config.Hit;
|
|
_aSuperHitRate = _config.SuperHiteRate;
|
|
_aMaxAtk = _config.MaxAtk;
|
_aMinAtk = _config.MinAtk;
|
_aRealmLv = _config.Realm;
|
_aIceAtk = _config.IceAtk;
|
|
//战力压制
|
ulong _aNPCFightPower = _npcBase.NpcConfigEx == null ? 0 : (ulong)_npcBase.NpcConfigEx.SuppressFightPower;
|
|
if (target.ActorType == GameObjType.gotPlayer)
|
{
|
_suppressLV = Mathf.Max(0, _config.NPCLV - PlayerDatas.Instance.baseData.LV);
|
_suppressFightPower = Mathf.Max(0, _aNPCFightPower - PlayerDatas.Instance.baseData.FightPoint);
|
|
/* 等级压制
|
(min(max(suppressLV-10,0),10)*0.02
|
+min(max(suppressLV-20,0),10)*0.03
|
+min(max(suppressLV-30,0),10)*0.05
|
+min(max(suppressLV-40,0),10)*1
|
+min(max(suppressLV-50,0),50)*0.1)
|
*/
|
_suppressLV_0 = Mathf.Min(Mathf.Max(_suppressLV - 10, 0), 10) * .02f
|
+ Mathf.Min(Mathf.Max(_suppressLV - 20, 0), 10) * .03f
|
+ Mathf.Min(Mathf.Max(_suppressLV - 30, 0), 10) * .05f
|
+ Mathf.Min(Mathf.Max(_suppressLV - 40, 0), 10)
|
+ Mathf.Min(Mathf.Max(_suppressLV - 50, 0), 10) * .1f;
|
/* 战力压制
|
min(max(suppressFightPower*1.0/suppressNPCFightPower-0,0),0.05)*5
|
+min(max(suppressFightPower*1.0/suppressNPCFightPower-0.05,0),0.15)*8
|
+min(max(suppressFightPower*1.0/suppressNPCFightPower-0.2,0),1)*10
|
*/
|
_suppressValueFP_0 = Mathf.Min(Mathf.Max(_suppressFightPower * 1f / _aNPCFightPower, 0), .05f) * 5
|
+ Mathf.Min(Mathf.Max(_suppressFightPower * 1f / _aNPCFightPower - .05f, 0), .15f) * 8
|
+ Mathf.Min(Mathf.Max(_suppressFightPower * 1f / _aNPCFightPower - .2f, 0), 1f) * 10;
|
}
|
}
|
|
#region 4094,4507 增加暴击概率
|
if (_exceptSkill != null && _exceptSkill.effectValue.TryGetValue(4094, out _effectValue))
|
{
|
bool _vaild = true;
|
if (_effectValue.value2 != 0)
|
{
|
if (!target.ActorInfo.status4012.ContainsKey((byte)_effectValue.value2))
|
{
|
_vaild = false;
|
}
|
}
|
if (_vaild)
|
{
|
_aSuperHitRate += _effectValue.value1;
|
}
|
}
|
|
if (StatusMgr.Instance.TryGetSkillEffectValue(attacker.ServerInstID, 4507, out _effectValue))
|
{
|
bool _vaild = true;
|
if (_effectValue.value2 == 1)
|
{
|
if (attacker.SelectTarget == null
|
|| attacker.SelectTarget.ServerInstID != target.ServerInstID)
|
{
|
_vaild = false;
|
}
|
}
|
if (_effectValue.value3 == 0)
|
{
|
if (skill.skillInfo.config.FuncType != (int)E_SkillFuncType.NormalAttack)
|
{
|
_vaild = false;
|
}
|
}
|
if (_vaild)
|
{
|
_aSuperHitRate += _effectValue.value1;
|
}
|
}
|
|
#endregion
|
|
if (_aRealmLv != 0 && _dRealmLv != 0)
|
{
|
_suppressValueRealmRate = Mathf.Max(_aRealmLv - _dRealmLv, 0) * 200 + 10000;
|
}
|
|
if (Random.Range(0, 10000) >= 2000)
|
{
|
//只在格挡成功才有值, 格挡成功率默认20%
|
_dDamChanceDef = 0;
|
}
|
|
_isMiss = IsMiss(_hitRate, _missRate, 10000, 0);
|
_isCrit = Random.Range(0, 10000) < (_aSuperHitRate - _dSuperHitRateReduce);
|
_isLucky = Random.Range(0, 10000) < (_aLuckyHitRate - _dLuckyHitRateReduce);
|
_isZhuxianHit = false;//IsZhuXianHit(_aZhuXianHitRate);
|
if (_isZhongJi)
|
{
|
_isCrit = true;
|
}
|
// 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;
|
if (_isZhongJi)
|
{
|
_aSuperHit *= 2;
|
#if UNITY_EDITOR
|
Debug.LogFormat("技能: {0} 计算伤害的时候发生重击, 暴击伤害翻倍: {1}", skill.id, _aSuperHit);
|
#endif
|
|
#region 4528,4083 增加重击伤害
|
|
if (StatusMgr.Instance.TryGetSkillEffectValue(attacker.ServerInstID, 4528, out _effectValue))
|
{
|
bool _vaild = true;
|
if (_effectValue.value2 == 1)
|
{
|
if (attacker.SelectTarget == null
|
|| attacker.SelectTarget.ServerInstID != target.ServerInstID)
|
{
|
_vaild = false;
|
}
|
}
|
if (_effectValue.value3 == 1)
|
{
|
if (skill.skillInfo.config.FuncType != (int)E_SkillFuncType.NormalAttack
|
&& skill.skillInfo.config.FuncType != (int)E_SkillFuncType.FaBaoActiveSkill)
|
{
|
_vaild = false;
|
}
|
}
|
if (_vaild)
|
{
|
if (_vaild)
|
{
|
_superHitAdd += _effectValue.value1;
|
}
|
}
|
}
|
|
if (_exceptSkill != null)
|
{
|
if (_exceptSkill.effectValue.TryGetValue(4083, out _effectValue))
|
{
|
bool _vaild = true;
|
if (_effectValue.value2 == 1)
|
{
|
if (attacker.SelectTarget == null
|
|| attacker.SelectTarget.ServerInstID != target.ServerInstID)
|
{
|
_vaild = false;
|
}
|
}
|
if (_vaild)
|
{
|
_superHitAdd += _effectValue.value1;
|
}
|
}
|
|
if (_exceptSkill.effectValue.TryGetValue(4030, out _effectValue))
|
{
|
_superHit += _effectValue.value1;
|
}
|
|
if (_exceptSkill.effectValue.TryGetValue(4075, out _effectValue))
|
{
|
float _val = (PlayerDatas.Instance.extersion.battleValEx1 - 10000) * _effectValue.value1;
|
_superHitAdd += _val;
|
}
|
}
|
|
#endregion
|
}
|
|
|
// 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 _aFinalHurtPer, ref _aAtkSkillPer, ref _atkSkillValue, ref _aIceAtk, ref _aFinalHurt, ref _superHitAdd, ref _aDamagePVE, _isCrit);
|
|
// 处理sp技能
|
List<SkillHelper.SkillInfo> _spSkillList = SkillHelper.Instance.GetSpSkill(skill.id);
|
|
if (_spSkillList != null)
|
{
|
for (int i = 0; i < _spSkillList.Count; ++i)
|
{
|
CalculateSkillEffect(attacker, target, _spSkillList[i], ref _aFinalHurtPer, ref _aAtkSkillPer, ref _atkSkillValue, ref _aIceAtk, ref _aFinalHurt, ref _superHitAdd, ref _aDamagePVE, _isCrit);
|
}
|
}
|
}
|
|
Dictionary<int, int> _attrValues;
|
if (vnxbqy.UI.CalculateSkillGetAttrHurtUtility.Instance.TryGetAttrDictBySkill(skill.id, out _attrValues))
|
{
|
foreach (var _per in _attrValues.Values)
|
{
|
_aAtkSkillPer += (_per * Constants.F_DELTA);
|
}
|
}
|
_aAtkSkillPer = _aAtkSkillPer * Constants.F_DELTA;
|
|
_aSuperHit *= (1 + _superHitAdd * Constants.F_DELTA);
|
|
// -------------- 公式计算 --------------
|
// PVE
|
if (attacker.ActorType == GameObjType.gotPlayer
|
&& (target.ActorType == GameObjType.gotNPC || target is GA_PVPClientPlayer))
|
{
|
/* "PVE_1" :"int(SuppressValueRealmRate/10000*
|
max((((
|
max((aMaxAtk if isLuckyHit else (aMinAtk + (aMaxAtk - aMinAtk)*rand))-dDef*(1-max(aIgnoreDefRate-dIgnoreDefRateReduce,0)/10000.0),0)
|
+(max(aLuckyHit,0) if isLuckyHit else 0)
|
+(max(aSuperHit,0) if isSuperHit else 0)
|
+max(aIceAtk-dIceDef,0))
|
*max((atkSkillPer
|
+(aZhuxianHurtPer/10000.0 if isZhuxianHit else 0)
|
+(aSkillAtkRate-dSkillAtkRateReduce)/10000.0)
|
+aNPCHurtAddPer/10000.0-(min(dDamChanceDef,8000)/10000.0),0.5))
|
+aFinalHurt-dFinalHurtReduce+atkSkillValue+aDamagePVE)
|
*max((1+aFinalHurtPer/10000.0)*(1-dFinalHurtReducePer/10000.0),0.2),(aMaxAtk+aMinAtk)/2*0.05+(aMaxAtk+aMinAtk)/2*0.1*rand))"
|
*/
|
|
hurtValue = (ulong)Mathf.Ceil(_suppressValueRealmRate /10000.0f * (Mathf.Max((((Mathf.Max((_isLucky ? _aMaxAtk : _aMinAtk + (_aMaxAtk - _aMinAtk) * Random.Range(0f, 1f)) - _dDef * (1 - Mathf.Max(_aIgnoreDefRate - _dIgnoreDefRateReduce, 0) * Constants.F_DELTA), 0)
|
+ (_isLucky ? Mathf.Max(_aLuckyHit, 0) : 0)
|
+ (_isCrit ? Mathf.Max(_aSuperHit, 0) : 0)
|
+ Mathf.Max(_aIceAtk - _dIceDef, 0))
|
* Mathf.Max((_aAtkSkillPer
|
+ (_isZhuxianHit ? _aZhuxianHurtPer * Constants.F_DELTA : 0)
|
+ (_aSkillAtkRate - _dSkillAtkRateReduce) * Constants.F_DELTA)
|
+ _aNPCHurtAddPer * Constants.F_DELTA - Mathf.Min(_dDamChanceDef, 8000) * Constants.F_DELTA, .5f))
|
+ _aFinalHurt - _dFinalHurtReduce + _atkSkillValue + _aDamagePVE)
|
* Mathf.Max((1 + _aFinalHurtPer * Constants.F_DELTA) * (1 - _dFinalHurtReduce * Constants.F_DELTA), .2f), (_aMaxAtk + _aMinAtk) * .5f * .05f + (_aMaxAtk + _aMinAtk) * .5f * .1f * Random.Range(0, 1))));
|
|
}
|
// EVP
|
else if ((attacker.ActorType == GameObjType.gotNPC
|
&& target.ActorType == GameObjType.gotPlayer) || attacker is GA_PVPClientPlayer)
|
{
|
/* int(max(((max((aMinAtk+aMaxAtk)/2.0*(1+suppressValueLV)-dDef,0)
|
+max(aIceAtk - dIceDef, 0))
|
*max(atkSkillPer+aSkillAtkRate/10000.0-min(dDamChanceDef,8000)/10000.0,0.5)
|
+aFinalHurt-dFinalHurtReduce+atkSkillValue)
|
*max((1+aFinalHurtPer/10000.0)*(1-dFinalHurtReducePer/10000.0),0.2)*(1+suppressValueFP),aMaxAtk*0.05+rand*aMaxAtk*0.05)) */
|
hurtValue = (ulong)Mathf.Ceil((Mathf.Max(((Mathf.Max((_aMinAtk + _aMaxAtk) * .5f * (1 + _suppressLV_0) - _dDef, 0)
|
+ Mathf.Max(_aIceAtk - _dIceDef, 0))
|
* Mathf.Max(_aAtkSkillPer + _aSkillAtkRate * Constants.F_DELTA - Mathf.Min(_dDamChanceDef, 8000) * Constants.F_DELTA, .5f)
|
+ _aFinalHurt - _dFinalHurtReduce + _atkSkillValue)
|
* Mathf.Max((1 + _aFinalHurtPer * Constants.F_DELTA)
|
* (1 - _dFinalHurtReduce * Constants.F_DELTA), .2f) * (1 + _suppressValueFP_0), _aMaxAtk * .05f + Random.Range(0f, 1f) * _aMaxAtk * .05f)));
|
}
|
//竞技场战斗
|
else if (attacker is GA_ILClientPlayer || target is GA_ILClientPlayer)
|
{
|
/*
|
* int(SuppressValueRealmRate/10000.0*max((((max((aMaxAtk if isLuckyHit else (aMinAtk+(aMaxAtk-aMinAtk)*rand))-dDef*(1-max(aIgnoreDefRate-dIgnoreDefRateReduce,0)/10000.0),0)
|
* +(max(aLuckyHit-dLuckyHitReduce,0) if isLuckyHit else 0)
|
* +(max(aSuperHit-dSuperHitReduce,0) if isSuperHit else 0)
|
* +max(aIceAtk-dIceDef,0))
|
* *max((atkSkillPer/10000.0
|
* +(aZhuxianHurtPer/10000.0 if isZhuxianHit else 0)
|
* +(aSkillAtkRate-dSkillAtkRateReduce)/10000.0)
|
* +(aDamagePerPVP/10000.0-dDamagePerPVPReduce/10000.0)-(min(dDamChanceDef,8000)/10000.0),0.5))
|
* +(aFinalHurt-dFinalHurtReduce)+atkSkillValue+aOnlyFinalHurt+(aDamagePVP-dDamagePVPReduce))
|
* *max((1+aFinalHurtPer/10000.0)*(1-dFinalHurtReducePer/10000.0),0),(aMaxAtk+aMinAtk)/2*0.05+(aMaxAtk+aMinAtk)/2*0.1*rand))",
|
*/
|
hurtValue = (ulong)Mathf.Ceil(_suppressValueRealmRate/10000.0f * (Mathf.Max((((Mathf.Max((_isLucky ? _aMaxAtk : _aMinAtk + (_aMaxAtk - _aMinAtk) * Random.Range(0f, 1f)) - _dDef * (1 - Mathf.Max(_aIgnoreDefRate - _dIgnoreDefRateReduce, 0) * Constants.F_DELTA), 0)
|
+ (_isLucky ? Mathf.Max(_aLuckyHit -_dLuckyHitReduce, 0) : 0)
|
+ (_isCrit ? Mathf.Max(_aSuperHit - _dSuperHitReduce, 0) : 0)
|
+ Mathf.Max(_aIceAtk - _dIceDef, 0))
|
* Mathf.Max((_aAtkSkillPer
|
+ (_aSkillAtkRate - _dSkillAtkRateReduce) * Constants.F_DELTA)
|
+ (_aDamagePerPVP - _dDamagePerPVPReduce) * Constants.F_DELTA - Mathf.Min(_dDamChanceDef, 8000) * Constants.F_DELTA, .5f))
|
+ _aFinalHurt - _dFinalHurtReduce + _atkSkillValue + _aOnlyFinalHurt + _aDamagePVP - _dDamagePVPReduce)
|
* Mathf.Max((1 + _aFinalHurtPer * Constants.F_DELTA) * (1 - _dFinalHurtReducePer * Constants.F_DELTA), 0f), (_aMaxAtk + _aMinAtk) * .5f * .05f + (_aMaxAtk + _aMinAtk) * .5f * .1f * Random.Range(0, 1))));
|
|
}
|
|
if (_isZhuxianHit)
|
{
|
attackType = (byte)HurtAttackType.ZhuXianAtk;
|
}
|
else if (_isZhongJi)
|
{
|
attackType = (byte)HurtAttackType.ThumpHit;
|
}
|
else if (_isCrit
|
#if UNITY_EDITOR
|
|| RuntimeLogUtility.s_ForceSupperHit
|
#endif
|
)
|
{
|
attackType = (byte)HurtAttackType.SuperHit;
|
}
|
else if (_isLucky
|
#if UNITY_EDITOR
|
|| RuntimeLogUtility.s_ForceLuckHit
|
#endif
|
)
|
{
|
attackType = (byte)HurtAttackType.LuckyHit;
|
}
|
else
|
{
|
attackType = (byte)HurtAttackType.Normal;
|
}
|
|
GActorNpcFight _actorFight = target as GActorNpcFight;
|
|
if (ClientSceneManager.Instance.IsClientFightMode || (_actorFight != null && _actorFight.NpcConfig.IsBoss == 0))
|
{
|
if (_exceptSkill != null && _exceptSkill.effectValue.ContainsKey(4092))
|
{
|
if (PlayerDatas.Instance.baseData.yinjiCount >= _exceptSkill.effectValue[4092].value1)
|
{
|
attackType = (byte)HurtAttackType.Yinji;
|
}
|
}
|
}
|
}
|
|
private static bool IsMiss(int hit, int miss, int hitSuccessRate, int missSuccessRate)
|
{
|
// max(min(max(min(aHit*9.0 / max(aHit*9.0 + dMiss , 1),0.99),0.7) + max(aHitSuccessRate-10000,0)/10000.0 - dMissSuccessRate/10000.0,1),0.6) - random.random()
|
return Mathf.Max(Mathf.Min(Mathf.Max(Mathf.Min(hit * 9.0f / Mathf.Max(hit * 9.0f + miss, 1), 0.99f), 0.7f) + Mathf.Max(hitSuccessRate - 10000, 0) / 10000 - missSuccessRate / 10000, 1), 0.6f) - Random.Range(0.0f, 1.0f) < 0;
|
}
|
|
private static bool IsZhongji(int skillId, GActorFight target)
|
{
|
var _hero = PlayerDatas.Instance.hero;
|
if (_hero == null
|
|| target == null)
|
{
|
return false;
|
}
|
|
SkillHelper.EffectValue _effectValue;
|
SkillHelper.SkillInfo _skillInfo;
|
|
int _rate = 0;
|
|
var _dict = StatusMgr.Instance.ZhongJiDict;
|
foreach (var _info in _dict.Values)
|
{
|
if (_info.onlyFirstTarget)
|
{
|
if (_hero.SelectTarget.ServerInstID == target.ServerInstID)
|
{
|
_rate += _info.rate;
|
}
|
}
|
else
|
{
|
_rate += _info.rate;
|
}
|
}
|
|
_skillInfo = SkillHelper.Instance.GetExpertSkill(skillId);
|
if (_skillInfo != null && _skillInfo.effectValue.TryGetValue(4081, out _effectValue))
|
{
|
if (_effectValue.value2 == 1)
|
{
|
if (_hero.SelectTarget.ServerInstID == target.ServerInstID)
|
{
|
_rate += _effectValue.value1;
|
}
|
}
|
else
|
{
|
_rate += _effectValue.value1;
|
}
|
}
|
|
var _skill = _hero.SkillMgr.Get(skillId);
|
|
if (StatusMgr.Instance.TryGetSkillEffectValue(_hero.ServerInstID, 4526, out _effectValue))
|
{
|
bool _vaild = true;
|
if (_effectValue.value2 == 1)
|
{
|
if (_hero.SelectTarget == null
|
|| _hero.SelectTarget.ServerInstID != target.ServerInstID)
|
{
|
_vaild = false;
|
}
|
}
|
if (_effectValue.value3 == 1)
|
{
|
if (_skill.skillInfo.config.FuncType != (int)E_SkillFuncType.NormalAttack
|
&& _skill.skillInfo.config.FuncType != (int)E_SkillFuncType.FaBaoActiveSkill)
|
{
|
_vaild = false;
|
}
|
}
|
if (_vaild)
|
{
|
_rate += _effectValue.value1;
|
}
|
}
|
|
#if UNITY_EDITOR
|
var _random = Random.Range(0, 10000);
|
var _result = _random < _rate;
|
// Debug.LogFormat("攻击目标: {3}, 重击概率为: {0}, 随机为: {1}, 是否可以重击: {2}", _rate, _random, _result, target.ServerInstID);
|
return _result;
|
#else
|
return Random.Range(0, 10000) < _rate;
|
#endif
|
}
|
|
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 _aSuperHitAdd,
|
ref int _aDamagePVE,
|
bool _isCrit)
|
{
|
|
|
SkillHelper.EffectValue _effectValue;
|
SkillHelper.SkillInfo _skillInfo;
|
|
SkillHelper.SkillInfo _exceptSkill = null;
|
if (attacker is GA_Hero)
|
{
|
_exceptSkill = SkillHelper.Instance.GetExpertSkill(skillInfo.config.SkillID);
|
}
|
|
#region 伤害增加
|
|
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
|
}
|
}
|
}
|
|
if (attacker is GA_Hero)
|
{
|
if (_exceptSkill != null && _exceptSkill.effectValue.TryGetValue(4102, out _effectValue))
|
{
|
int _val = _effectValue.value1;
|
int _needCount = _effectValue.value2;
|
bool _valid = true;
|
if (_exceptSkill.effectValue.TryGetValue(4092, out _effectValue))
|
{
|
if (_effectValue.value2 == 0)
|
{
|
if (PlayerDatas.Instance.baseData.yinjiCount != _needCount)
|
{
|
_valid = false;
|
}
|
}
|
else if (_effectValue.value2 == 1)
|
{
|
if (PlayerDatas.Instance.baseData.yinjiCount == 0
|
|| PlayerDatas.Instance.baseData.yinjiCount < _effectValue.value1)
|
{
|
_valid = false;
|
}
|
}
|
}
|
if (_valid)
|
{
|
if (PlayerDatas.Instance.baseData.yinjiCount > _needCount)
|
{
|
_aDamagePVE += _val;
|
}
|
}
|
}
|
|
if (_exceptSkill != null && _exceptSkill.effectValue.TryGetValue(4086, out _effectValue))
|
{
|
bool _vaild = true;
|
if (_effectValue.value3 == 1)
|
{
|
if (attacker.SelectTarget == null
|
|| attacker.SelectTarget.ServerInstID != target.ServerInstID)
|
{
|
_vaild = false;
|
}
|
}
|
|
if (_vaild)
|
{
|
int _limit = PlayerDatas.Instance.baseData.yinjiCount > _effectValue.value2 ?
|
_effectValue.value2 : PlayerDatas.Instance.baseData.yinjiCount;
|
_aAtkSkillPer += _limit * _effectValue.value1;
|
}
|
}
|
|
if (_exceptSkill != null && _exceptSkill.effectValue.TryGetValue(4087, out _effectValue))
|
{
|
if (PlayerDatas.Instance.baseData.yinjiCount > _effectValue.value2)
|
{
|
_aAtkSkillPer += _effectValue.value1;
|
}
|
}
|
|
if (_exceptSkill != null && _exceptSkill.effectValue.TryGetValue(4088, out _effectValue))
|
{
|
int _per = _effectValue.value1;
|
int _needCount = _effectValue.value2;
|
bool _valid = true;
|
if (_exceptSkill != null && _exceptSkill.effectValue.TryGetValue(4092, out _effectValue))
|
{
|
if (_effectValue.value2 == 0)
|
{
|
if (PlayerDatas.Instance.baseData.yinjiCount != _needCount)
|
{
|
_valid = false;
|
}
|
}
|
else if (_effectValue.value2 == 1)
|
{
|
if (PlayerDatas.Instance.baseData.yinjiCount == 0
|
|| PlayerDatas.Instance.baseData.yinjiCount < _effectValue.value1)
|
{
|
_valid = false;
|
}
|
}
|
}
|
if (_valid)
|
{
|
_needCount = PlayerDatas.Instance.baseData.yinjiCount > _needCount ?
|
_needCount : PlayerDatas.Instance.baseData.yinjiCount;
|
_aAtkSkillPer += _per * _needCount;
|
}
|
}
|
|
if (_exceptSkill != null && _exceptSkill.effectValue.TryGetValue(4015, out _effectValue))
|
{
|
if (target.ActorInfo.status4012.ContainsKey((byte)_effectValue.value2))
|
{
|
uint _selfSID = _effectValue.value3 == 1 ? attacker.ServerInstID : 0;
|
if (StatusMgr.Instance.IsBurning(target.ServerInstID, _selfSID))
|
{
|
_aAtkSkillPer += _effectValue.value1;
|
|
if (attacker.SkillMgr.TryGetPassiveEffectValue(4538, out _effectValue, out _skillInfo))
|
{
|
_aDamagePVE += _effectValue.value1;
|
}
|
if (attacker.SkillMgr.TryGetPassiveEffectValue(4002, out _effectValue, out _skillInfo))
|
{
|
_aDamagePVE += _effectValue.value1;
|
}
|
}
|
}
|
}
|
|
if (StatusMgr.Instance.TryGetSkillEffectValue(attacker.ServerInstID, 4505, out _effectValue))
|
{
|
if (target.ActorInfo.status4012.ContainsKey((byte)_effectValue.value2))
|
{
|
uint _selfSID = _effectValue.value3 == 1 ? attacker.ServerInstID : 0;
|
if (StatusMgr.Instance.IsBurning(target.ServerInstID, _selfSID))
|
{
|
_aAtkSkillPer += _effectValue.value1;
|
}
|
}
|
}
|
|
if (_exceptSkill != null && _exceptSkill.effectValue.TryGetValue(4098, out _effectValue))
|
{
|
var _skillInfo1 = SkillHelper.Instance.Get(_effectValue.value2);
|
if (_skillInfo1 != null)
|
{
|
SkillHelper.EffectValue _tmpEffectValue;
|
if (_skillInfo1.effectValue.TryGetValue(4012, out _tmpEffectValue))
|
{
|
if (target.ActorInfo.status4012.ContainsKey((byte)_tmpEffectValue.value1))
|
{
|
if (target.ActorInfo.GetStatusCount((byte)_tmpEffectValue.value1, attacker.ServerInstID) >= _effectValue.value3)
|
{
|
_aAtkSkillPer += _effectValue.value1;
|
}
|
}
|
}
|
}
|
}
|
|
if (_exceptSkill != null && _exceptSkill.effectValue.TryGetValue(4096, out _effectValue))
|
{
|
if (StatusMgr.Instance.IsExist(target.ServerInstID, _effectValue.value3))
|
{
|
int _count = target.ActorInfo.GetStatusCount((byte)_effectValue.value2, attacker.ServerInstID);
|
_aAtkSkillPer += _effectValue.value1 * _count;
|
}
|
}
|
}
|
|
// 4005 概率增加攻击(技能)伤害万分率
|
if (_exceptSkill != null && _exceptSkill.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 (_exceptSkill != null && _exceptSkill.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 (attacker.SkillMgr.TryGetPassiveEffectValue(4011, out _effectValue, out _skillInfo))
|
{
|
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 (attacker.SkillMgr.TryGetPassiveEffectValue(4015, out _effectValue, out _skillInfo))
|
{
|
if (target.ActorInfo.GetStatusCount((byte)_effectValue.value2, attacker.ServerInstID) > 0)
|
{
|
_aAtkSkillPer += _effectValue.value1;
|
|
#if UNITY_EDITOR
|
if (RuntimeLogUtility.s_SkillEffectLog)
|
{
|
Debug.LogFormat("技能 {0} 触发了效果 {1} , _aAtkSkillPer 增加了 {2}", skillInfo.config.SkillID, 4015, _effectValue.value1);
|
}
|
#endif
|
}
|
}
|
|
// 4025 攻击附加真实伤害
|
if (attacker.SkillMgr.TryGetPassiveEffectValue(4025, out _effectValue, out _skillInfo))
|
{
|
_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;
|
|
// 基于目标状态
|
if (_effectValue.value3 != 0)
|
{
|
if (!target.ActorInfo.status4012.ContainsKey((byte)_effectValue.value3))
|
{
|
_rate = 0;
|
}
|
}
|
|
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.GetStatusCount((byte)_effectValue.value2, attacker.ServerInstID) > 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))
|
{
|
MountModel _mountData = vnxbqy.UI.ModelCenter.Instance.GetModel<MountModel>();
|
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 (attacker.SkillMgr.TryGetPassiveEffectValue(4007, out _effectValue, out _skillInfo))
|
{
|
bool _condition = true;
|
|
// 判断buff
|
if (_effectValue.value2 != 0)
|
{
|
if (!StatusMgr.Instance.IsExist(attacker.ServerInstID, _effectValue.value2))
|
{
|
_condition = false;
|
}
|
}
|
|
// 是否可以执行
|
if (_condition && _isCrit)
|
{
|
_aSuperHitAdd += _effectValue.value1;
|
|
#if UNITY_EDITOR
|
if (RuntimeLogUtility.s_SkillEffectLog)
|
{
|
Debug.LogFormat("技能 {0} 触发了效果 {1} , _aSuperHitAdd 增加了 {2}", skillInfo.config.SkillID, 4007, _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 || attacker 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 ulong HurtHP;
|
public ulong CurHP;
|
public ulong RealHurtHP;
|
}
|
|
public static bool CanAttack(E_SkillCastTarget castTarget, GActorFight caster, GActorFight target)
|
{
|
if (target == null || caster == null || caster.ActorInfo.serverDie)
|
{
|
return false;
|
}
|
|
switch (castTarget)
|
{
|
case E_SkillCastTarget.None:
|
return false;
|
case E_SkillCastTarget.Self:
|
return target == caster;
|
case E_SkillCastTarget.TeamMate:
|
return target.ActorInfo.teamID == caster.ActorInfo.teamID;
|
case E_SkillCastTarget.Friend:
|
break;
|
case E_SkillCastTarget.CanAttacked:
|
return target.CanAtked();
|
case E_SkillCastTarget.SelfAndFriend:
|
return target == caster;
|
case E_SkillCastTarget.PlayerDeadBody:
|
return target.ActorInfo.serverDie && target is GActorPlayerBase;
|
case E_SkillCastTarget.UnDeadPlayer:
|
return !target.ActorInfo.serverDie && target is GActorPlayerBase;
|
case E_SkillCastTarget.CanAttackedMonster:
|
return target is GA_NpcFightNorm && target.CanAtked();
|
case E_SkillCastTarget.CanAttackedPlayer:
|
return target is GActorPlayerBase && target.CanAtked();
|
case E_SkillCastTarget.All:
|
return true;
|
case E_SkillCastTarget.PetToOwner:
|
return target.ActorInfo.ownerSID == caster.ServerInstID && caster is GA_Pet;
|
case E_SkillCastTarget.SummonToOwner:
|
return target.ActorInfo.ownerSID == caster.ServerInstID && caster is GA_NpcSummonFight;
|
case E_SkillCastTarget.Monster:
|
var _npc = target as GActorNpcFight;
|
if (_npc == null)
|
{
|
return false;
|
}
|
return _npc.NpcConfig.IsBoss < 2;
|
case E_SkillCastTarget.FriendNpc:
|
return (target is GActorNpcFight && target.ActorInfo.faction != 0 && target.ActorInfo.faction == PlayerDatas.Instance.baseData.faction);
|
}
|
return true;
|
}
|
}
|