using System.Collections.Generic;
|
using UnityEngine;
|
|
public class BattleDmg
|
{
|
public long damage;
|
public int attackType;
|
|
public bool IsType(DamageType damageType)
|
{
|
return (attackType & (int)damageType) == (int)damageType;
|
}
|
}
|
|
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 isImmune = false;
|
public bool isLastHit = false;
|
|
public List<BattleDmg> targetDamageList = new List<BattleDmg>();
|
public List<BattleDmg> casterDamageList = new List<BattleDmg>();
|
|
public uint m_rawAttackType;
|
|
#region Initialization
|
|
public BattleDmgInfo(string battleFieldGuid, BattleHurtParam battleHurtParam)
|
{
|
this.battleFieldGuid = battleFieldGuid;
|
this.battleHurtParam = battleHurtParam;
|
this.isLastHit = battleHurtParam.hitIndex >= battleHurtParam.skillConfig.DamageDivide.Length - 1;
|
|
m_rawAttackType = hurt == null ? 0 : hurt.AttackTypes;
|
|
HandleDamageType();
|
HandleAttackTypeAndDamage();
|
}
|
|
#endregion
|
|
#region Damage Type Processing
|
|
private void HandleDamageType()
|
{
|
if (hurt == null) return;
|
|
uint originalAttackTypes = hurt.AttackTypes;
|
int convertedAttackTypes = 0;
|
|
// 遍历服务器发来的所有伤害类型标记
|
foreach (ServerDamageType serverDamageType in System.Enum.GetValues(typeof(ServerDamageType)))
|
{
|
int serverValue = (int)serverDamageType;
|
|
// 检查服务器类型是否存在
|
if ((originalAttackTypes & serverValue) != serverValue)
|
continue;
|
|
// 转换映射
|
switch (serverDamageType)
|
{
|
case ServerDamageType.Damage:
|
convertedAttackTypes |= (int)DamageType.Damage;
|
break;
|
|
case ServerDamageType.Recovery:
|
convertedAttackTypes |= (int)DamageType.Recovery;
|
break;
|
|
case ServerDamageType.Immune:
|
convertedAttackTypes |= (int)DamageType.Immune;
|
break;
|
|
case ServerDamageType.Block:
|
convertedAttackTypes |= (int)DamageType.Block;
|
break;
|
|
case ServerDamageType.Realdamage:
|
convertedAttackTypes |= (int)DamageType.Realdamage;
|
break;
|
|
case ServerDamageType.Crit:
|
convertedAttackTypes |= (int)DamageType.Crit;
|
break;
|
|
case ServerDamageType.Dodge:
|
convertedAttackTypes |= (int)DamageType.Dodge;
|
break;
|
|
case ServerDamageType.DamageReverse:
|
convertedAttackTypes |= (int)DamageType.Damage;
|
// Debug.LogWarning($"[BattleDmgInfo] 服务器伤害类型 DamageReverse({serverValue}) 在客户端没有对应的枚举值");
|
break;
|
|
case ServerDamageType.SuckHpReverse:
|
convertedAttackTypes |= (int)DamageType.Damage;
|
// Debug.LogWarning($"[BattleDmgInfo] 服务器伤害类型 SuckHpReverse({serverValue}) 在客户端没有对应的枚举值");
|
break;
|
|
case ServerDamageType.SelfHarm:
|
convertedAttackTypes |= (int)DamageType.Damage;
|
// Debug.LogWarning($"[BattleDmgInfo] 服务器伤害类型 SelfHarm({serverValue}) 在客户端没有对应的枚举值");
|
break;
|
|
default:
|
Debug.LogError($"[BattleDmgInfo] 未知的服务器伤害类型: {serverDamageType}({serverValue})");
|
break;
|
}
|
}
|
|
// 检查是否包含占位符类型
|
if ((convertedAttackTypes & (int)DamageType.TakePlace2) == (int)DamageType.TakePlace2)
|
{
|
Debug.LogWarning($"[BattleDmgInfo] 转换后的伤害类型包含占位符 TakePlace2(256)");
|
}
|
|
hurt.AttackTypes = (uint)convertedAttackTypes;
|
Debug.Log($"[BattleDmgInfo] 伤害类型转换: {originalAttackTypes} -> {hurt.AttackTypes}");
|
}
|
|
#endregion
|
|
#region Damage List Generation
|
|
private void HandleAttackTypeAndDamage()
|
{
|
isBlocked = HaveBlockDamage();
|
isImmune = IsImmune();
|
int rawAttackType = hurt == null ? 0 : (int)hurt.AttackTypes;
|
|
// 如果是免疫,直接添加免疫显示,不处理其他伤害
|
if (isImmune)
|
{
|
targetDamageList.Add(new BattleDmg
|
{
|
damage = 0,
|
attackType = (int)DamageType.Immune
|
});
|
return;
|
}
|
|
int maxCount = CalculateMaxDamageSegmentCount();
|
|
for (int i = 0; i < maxCount; i++)
|
{
|
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} rawAttackType: {m_rawAttackType}");
|
|
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 != null && (hurt.AttackTypes & (int)damageType) == (int)damageType;
|
}
|
|
public bool IsCrit()
|
{
|
return IsType(DamageType.Crit);
|
}
|
|
public bool HaveBlockDamage()
|
{
|
return IsType(DamageType.Block);
|
}
|
|
public bool IsImmune()
|
{
|
return IsType(DamageType.Immune);
|
}
|
|
public bool IsRealdamage()
|
{
|
return skillConfig.HurtType / 10 == 1;
|
}
|
|
public bool IsDamage()
|
{
|
return IsType(DamageType.Damage) || IsRealdamage() || IsType((DamageType)11) || IsType((DamageType)12);
|
}
|
|
#endregion
|
}
|
|
public class BattleHurtParam
|
{
|
public BattleObject casterObj;
|
public BattleObject hurtObj;
|
public List<long> damageList;
|
public List<long> suckHpList;
|
public List<long> reflectHpList;
|
public BattleDrops battleDrops;
|
public HB427_tagSCUseSkill.tagSCUseSkillHurt hurt;
|
public int hitIndex;
|
public HB422_tagMCTurnFightObjDead deadPack;
|
public SkillConfig skillConfig;
|
public long maxHp;
|
|
public long fromShieldValue;
|
public long toShieldValue;
|
|
public long fromHp;
|
|
public long toHp;
|
|
// 未被护盾抵消前的伤害
|
public long totalDamage
|
{
|
get
|
{
|
long total = 0;
|
if (damageList != null)
|
{
|
foreach (var dmg in damageList)
|
{
|
total += dmg;
|
}
|
}
|
|
return total;
|
}
|
}
|
}
|