| | |
| | | using System.Collections.Generic; |
| | | using UnityEngine; |
| | | |
| | | public class BattleDmg |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | public class BattleDmgInfo |
| | | { |
| | | |
| | | public string battleFieldGuid { get; private set; } |
| | | |
| | | public BattleHurtParam battleHurtParam { get; private set; } |
| | | |
| | | public List<long> damageList { get { return battleHurtParam.damageList; } } |
| | | public BattleObject hurtObj { get { return battleHurtParam.hurtObj; } } |
| | | |
| | | public BattleObject casterObj { get { return battleHurtParam.casterObj; } } |
| | | |
| | | public HB427_tagSCUseSkill.tagSCUseSkillHurt hurt { get { return battleHurtParam.hurt; } } |
| | | |
| | | public SkillConfig skillConfig { get { return battleHurtParam.skillConfig; } } |
| | | |
| | | // 是否被格挡了 |
| | | public bool isBlocked = false; |
| | | |
| | | public bool isLastHit = false; |
| | | |
| | | public List<BattleDmg> targetDamageList = new List<BattleDmg>(); |
| | | |
| | | public List<BattleDmg> casterDamageList = new List<BattleDmg>(); |
| | | |
| | | #region Initialization |
| | | |
| | | public BattleDmgInfo(string battleFieldGuid, BattleHurtParam battleHurtParam) |
| | | { |
| | | this.battleFieldGuid = battleFieldGuid; |
| | | this.battleHurtParam = battleHurtParam; |
| | | this.isLastHit = battleHurtParam.hitIndex >= battleHurtParam.skillConfig.DamageDivide.Length - 1; |
| | | |
| | | HandleDamageType(); |
| | | HandleAttackTypeAndDamage(); |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region Damage Type Processing |
| | | |
| | | private void HandleDamageType() |
| | | { |
| | | if (hurt == null) return; |
| | | |
| | | int attackTypes = 0; |
| | | foreach (ServerDamageType serverDamageType in System.Enum.GetValues(typeof(ServerDamageType))) |
| | | { |
| | |
| | | hurt.AttackTypes = (uint)attackTypes; |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region Damage List Generation |
| | | |
| | | private void HandleAttackTypeAndDamage() |
| | | { |
| | | isBlocked = HaveBlockDamage(); |
| | | int rawAttackType = (int)hurt.AttackTypes; |
| | | float blockRatio = GeneralDefine.blockRatio; // 格挡减伤率 |
| | | int rawAttackType = hurt == null ? 0 : (int)hurt.AttackTypes; |
| | | |
| | | int maxCount = CalculateMaxDamageSegmentCount(); |
| | | |
| | | // 处理每一段伤害及其对应的反伤和吸血 |
| | | for (int i = 0; i < damageList.Count; i++) |
| | | for (int i = 0; i < maxCount; i++) |
| | | { |
| | | long actualDamage = damageList[i]; |
| | | |
| | | // ============ 1. 先处理当前段对应的反伤 ============ |
| | | if (battleHurtParam.reflectHpList != null && i < battleHurtParam.reflectHpList.Count) |
| | | { |
| | | long reflectHp = battleHurtParam.reflectHpList[i]; |
| | | if (reflectHp > 0) |
| | | { |
| | | casterDamageList.Add(new BattleDmg |
| | | { |
| | | damage = reflectHp, |
| | | attackType = (int)DamageType.Reflect |
| | | }); |
| | | } |
| | | } |
| | | |
| | | // ============ 2. 然后处理当前段对应的吸血 ============ |
| | | if (battleHurtParam.suckHpList != null && i < battleHurtParam.suckHpList.Count) |
| | | { |
| | | long suckHp = battleHurtParam.suckHpList[i]; |
| | | if (suckHp > 0) |
| | | { |
| | | casterDamageList.Add(new BattleDmg |
| | | { |
| | | damage = suckHp, |
| | | attackType = (int)DamageType.SuckHP |
| | | }); |
| | | } |
| | | } |
| | | |
| | | // ============ 3. 最后处理主要伤害 ============ |
| | | // 格挡处理 |
| | | if (isBlocked) |
| | | { |
| | | // 去掉格挡类型 |
| | | int attackType = rawAttackType & (~(int)DamageType.Block); |
| | | |
| | | // 计算格挡伤害 |
| | | long totalDamage = (long)(actualDamage / (1 - blockRatio)); |
| | | long blockDmg = totalDamage - actualDamage; |
| | | targetDamageList.Add(new BattleDmg { damage = blockDmg, attackType = (int)DamageType.Block }); |
| | | |
| | | // 真实伤害特殊处理 |
| | | if (IsRealdamage()) |
| | | { |
| | | int showAttackType = (int)DamageType.Realdamage + (IsCrit() ? (int)DamageType.Crit : 0); |
| | | targetDamageList.Add(new BattleDmg { damage = actualDamage, attackType = showAttackType }); |
| | | } |
| | | else |
| | | { |
| | | // 普通伤害/治疗处理 |
| | | if (DamageNumConfig.Get(attackType) == null) |
| | | { |
| | | UnityEngine.Debug.LogError($"服务器给的伤害类型不对,强制转换为普通伤害/治疗, attackType: {attackType}"); |
| | | if ((attackType & (int)DamageType.Damage) != 0) |
| | | attackType = (int)DamageType.Damage; |
| | | else if ((attackType & (int)DamageType.Recovery) != 0) |
| | | attackType = (int)DamageType.Recovery; |
| | | else |
| | | UnityEngine.Debug.LogError($"强制转换失败,该类型不是治疗也不是伤害 {attackType}"); |
| | | } |
| | | targetDamageList.Add(new BattleDmg { damage = actualDamage, attackType = attackType }); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | int attackType = rawAttackType; |
| | | |
| | | // 真实伤害特殊处理 |
| | | if (IsRealdamage()) |
| | | { |
| | | int showAttackType = (int)DamageType.Realdamage + (IsCrit() ? (int)DamageType.Crit : 0); |
| | | targetDamageList.Add(new BattleDmg { damage = actualDamage, attackType = showAttackType }); |
| | | } |
| | | else |
| | | { |
| | | // 普通伤害/治疗处理 |
| | | if (DamageNumConfig.Get(attackType) == null) |
| | | { |
| | | UnityEngine.Debug.LogError($"服务器给的伤害类型不对,强制转换为普通伤害/治疗, attackType: {attackType}"); |
| | | if ((attackType & (int)DamageType.Damage) != 0) |
| | | attackType = (int)DamageType.Damage; |
| | | else if ((attackType & (int)DamageType.Recovery) != 0) |
| | | attackType = (int)DamageType.Recovery; |
| | | else |
| | | UnityEngine.Debug.LogError($"强制转换失败,该类型不是治疗也不是伤害 {attackType}"); |
| | | } |
| | | targetDamageList.Add(new BattleDmg { damage = actualDamage, attackType = attackType }); |
| | | } |
| | | } |
| | | ProcessReflectDamage(i); |
| | | ProcessSuckHpDamage(i); |
| | | ProcessMainDamage(i, rawAttackType); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 计算最大伤害段数 |
| | | /// </summary> |
| | | private int CalculateMaxDamageSegmentCount() |
| | | { |
| | | int maxCount = damageList != null ? damageList.Count : 0; |
| | | maxCount = Mathf.Max(maxCount, battleHurtParam.suckHpList != null ? battleHurtParam.suckHpList.Count : 0); |
| | | maxCount = Mathf.Max(maxCount, battleHurtParam.reflectHpList != null ? battleHurtParam.reflectHpList.Count : 0); |
| | | return maxCount; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 处理反伤伤害 |
| | | /// </summary> |
| | | private void ProcessReflectDamage(int segmentIndex) |
| | | { |
| | | if (battleHurtParam.reflectHpList == null || segmentIndex >= battleHurtParam.reflectHpList.Count) |
| | | return; |
| | | |
| | | long reflectHp = battleHurtParam.reflectHpList[segmentIndex]; |
| | | if (reflectHp > 0) |
| | | { |
| | | casterDamageList.Add(new BattleDmg |
| | | { |
| | | damage = reflectHp, |
| | | attackType = (int)DamageType.Reflect |
| | | }); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 处理吸血伤害 |
| | | /// </summary> |
| | | private void ProcessSuckHpDamage(int segmentIndex) |
| | | { |
| | | if (battleHurtParam.suckHpList == null || segmentIndex >= battleHurtParam.suckHpList.Count) |
| | | return; |
| | | |
| | | long suckHp = battleHurtParam.suckHpList[segmentIndex]; |
| | | if (suckHp > 0) |
| | | { |
| | | casterDamageList.Add(new BattleDmg |
| | | { |
| | | damage = suckHp, |
| | | attackType = (int)DamageType.SuckHP |
| | | }); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 处理主要伤害 |
| | | /// </summary> |
| | | private void ProcessMainDamage(int segmentIndex, int rawAttackType) |
| | | { |
| | | if (damageList == null || segmentIndex >= damageList.Count) |
| | | return; |
| | | |
| | | long actualDamage = damageList[segmentIndex]; |
| | | |
| | | if (isBlocked) |
| | | { |
| | | ProcessBlockedDamage(actualDamage, rawAttackType); |
| | | } |
| | | else |
| | | { |
| | | ProcessNormalDamage(actualDamage, rawAttackType); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 处理被格挡的伤害 |
| | | /// </summary> |
| | | private void ProcessBlockedDamage(long actualDamage, int rawAttackType) |
| | | { |
| | | float blockRatio = GeneralDefine.blockRatio; |
| | | int attackType = rawAttackType & (~(int)DamageType.Block); |
| | | |
| | | // 添加格挡伤害显示 |
| | | long totalDamage = (long)(actualDamage / (1 - blockRatio)); |
| | | long blockDmg = totalDamage - actualDamage; |
| | | targetDamageList.Add(new BattleDmg { damage = blockDmg, attackType = (int)DamageType.Block }); |
| | | |
| | | // 添加实际伤害显示 |
| | | if (IsRealdamage()) |
| | | { |
| | | AddRealdamageToList(actualDamage); |
| | | } |
| | | else |
| | | { |
| | | AddNormalDamageToList(actualDamage, attackType); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 处理正常伤害(未被格挡) |
| | | /// </summary> |
| | | private void ProcessNormalDamage(long actualDamage, int rawAttackType) |
| | | { |
| | | if (IsRealdamage()) |
| | | { |
| | | AddRealdamageToList(actualDamage); |
| | | } |
| | | else |
| | | { |
| | | AddNormalDamageToList(actualDamage, rawAttackType); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 添加真实伤害到列表 |
| | | /// </summary> |
| | | private void AddRealdamageToList(long damage) |
| | | { |
| | | int showAttackType = (int)DamageType.Realdamage + (IsCrit() ? (int)DamageType.Crit : 0); |
| | | targetDamageList.Add(new BattleDmg { damage = damage, attackType = showAttackType }); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 添加普通伤害/治疗到列表 |
| | | /// </summary> |
| | | private void AddNormalDamageToList(long damage, int attackType) |
| | | { |
| | | attackType = ValidateAndFixAttackType(attackType); |
| | | targetDamageList.Add(new BattleDmg { damage = damage, attackType = attackType }); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 验证并修复攻击类型 |
| | | /// </summary> |
| | | private int ValidateAndFixAttackType(int attackType) |
| | | { |
| | | if (DamageNumConfig.Get(attackType) != null) |
| | | return attackType; |
| | | |
| | | UnityEngine.Debug.LogError($"服务器给的伤害类型不对,强制转换为普通伤害/治疗, attackType: {attackType}"); |
| | | |
| | | if ((attackType & (int)DamageType.Damage) != 0) |
| | | return (int)DamageType.Damage; |
| | | |
| | | if ((attackType & (int)DamageType.Recovery) != 0) |
| | | return (int)DamageType.Recovery; |
| | | |
| | | UnityEngine.Debug.LogError($"强制转换失败,该类型不是治疗也不是伤害 {attackType}"); |
| | | return attackType; |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region Type Checking |
| | | |
| | | public bool IsType(DamageType damageType) |
| | | { |
| | | return (hurt.AttackTypes & (int)damageType) == (int)damageType; |
| | | return hurt != null && (hurt.AttackTypes & (int)damageType) == (int)damageType; |
| | | } |
| | | |
| | | public bool IsCrit() |
| | |
| | | return skillConfig.HurtType / 10 == 1; |
| | | } |
| | | |
| | | public bool IsDamage() |
| | | { |
| | | return IsType(DamageType.Damage) || IsRealdamage() || IsType((DamageType)11) || IsType((DamageType)12); |
| | | } |
| | | |
| | | #endregion |
| | | } |
| | | |
| | | public class BattleHurtParam |
| | |
| | | public List<long> suckHpList; |
| | | public List<long> reflectHpList; |
| | | |
| | | public long fromShieldValue; |
| | | public long toShieldValue; |
| | | public long fromHp; |
| | | |
| | | public long toHp; |
| | | |
| | | public BattleDrops battleDrops; |
| | | |
| | | public HB427_tagSCUseSkill.tagSCUseSkillHurt hurt; |
| | | |
| | | public int hitIndex; |
| | | |
| | | public HB422_tagMCTurnFightObjDead deadPack; |
| | | |
| | | public SkillConfig skillConfig; |
| | | public long maxHp; |
| | | |
| | | #region Shield Value Calculations |
| | | |
| | | public long MaxSheildValue |
| | | { |
| | | get |
| | | { |
| | | return hurtObj == null ? 0 : hurtObj.teamHero.maxHp; |
| | | } |
| | | } |
| | | |
| | | public long phase1FromShieldValue |
| | | { |
| | | get |
| | | { |
| | | if (fromShieldValue > 0) |
| | | { |
| | | return Mathf.Min((int)fromShieldValue, (int)MaxSheildValue); |
| | | } |
| | | else |
| | | { |
| | | return 0; |
| | | } |
| | | } |
| | | } |
| | | |
| | | public long phase1ToShieldValue |
| | | { |
| | | get |
| | | { |
| | | if (toShieldValue > 0) |
| | | { |
| | | return Mathf.Min((int)toShieldValue, (int)MaxSheildValue); |
| | | } |
| | | else |
| | | { |
| | | return 0; |
| | | } |
| | | } |
| | | } |
| | | |
| | | public long phase2FromShieldValue |
| | | { |
| | | get |
| | | { |
| | | if (fromShieldValue > MaxSheildValue) |
| | | { |
| | | return fromShieldValue - MaxSheildValue; |
| | | } |
| | | else |
| | | { |
| | | return 0; |
| | | } |
| | | } |
| | | } |
| | | |
| | | public long phase2ToShieldValue |
| | | { |
| | | get |
| | | { |
| | | if (toShieldValue > MaxSheildValue) |
| | | { |
| | | return toShieldValue - MaxSheildValue; |
| | | } |
| | | else |
| | | { |
| | | return 0; |
| | | } |
| | | } |
| | | } |
| | | |
| | | #endregion |
| | | } |