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; }
|
|
private bool isCasterView = false; // 标记是否是施法者视角
|
|
// 新增属性:自动判断是处理目标还是施法者
|
public List<long> damageList
|
{
|
get
|
{
|
// 施法者视角:使用吸血和反伤列表的总和
|
if (isCasterView)
|
{
|
List<long> casterDamages = new List<long>();
|
if (battleHurtParam.caster?.suckHpList != null)
|
casterDamages.AddRange(battleHurtParam.caster.suckHpList);
|
if (battleHurtParam.caster?.reflectHpList != null)
|
casterDamages.AddRange(battleHurtParam.caster.reflectHpList);
|
return casterDamages;
|
}
|
// 目标视角:使用目标的伤害列表
|
if (battleHurtParam.hurter != null && battleHurtParam.hurter.damageList != null)
|
return battleHurtParam.hurter.damageList;
|
return new List<long>();
|
}
|
}
|
|
public BattleObject hurtObj
|
{
|
get
|
{
|
// 如果是施法者视角,返回施法者作为受伤对象
|
if (isCasterView)
|
return battleHurtParam.caster?.casterObj;
|
// 否则返回目标
|
return battleHurtParam.hurter?.hurtObj;
|
}
|
}
|
|
public BattleObject casterObj
|
{
|
get
|
{
|
return battleHurtParam.caster?.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 bool isFirstHit = 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, bool isCasterView = false)
|
{
|
this.battleFieldGuid = battleFieldGuid;
|
this.battleHurtParam = battleHurtParam;
|
this.isCasterView = isCasterView;
|
this.isLastHit = battleHurtParam.hitIndex >= battleHurtParam.skillConfig.DamageDivide.Length - 1;
|
this.isFirstHit = battleHurtParam.hitIndex == 0;
|
|
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.Stunned:
|
convertedAttackTypes |= (int)DamageType.Stunned;
|
break;
|
|
case ServerDamageType.Dodge:
|
convertedAttackTypes |= (int)DamageType.Dodge;
|
break;
|
|
case ServerDamageType.DamageReverse:
|
convertedAttackTypes |= (int)DamageType.Damage;
|
break;
|
|
case ServerDamageType.SuckHpReverse:
|
convertedAttackTypes |= (int)DamageType.Damage;
|
break;
|
|
case ServerDamageType.SelfHarm:
|
convertedAttackTypes |= (int)DamageType.Damage;
|
break;
|
|
default:
|
Debug.LogError($"[BattleDmgInfo] 未知的服务器伤害类型: {serverDamageType}({serverValue})");
|
break;
|
}
|
}
|
|
// DOT技能特殊处理(SkillType == 3 或 4)
|
if (skillConfig != null && (skillConfig.SkillType == 3 || skillConfig.SkillType == 4))
|
{
|
// 如果是伤害类型,替换为流血类型
|
if ((convertedAttackTypes & (int)DamageType.Damage) != 0)
|
{
|
// 流血标记
|
convertedAttackTypes = (int)DamageType.Bloody;
|
}
|
// 治疗类型保持不变
|
}
|
|
hurt.AttackTypes = (uint)convertedAttackTypes;
|
}
|
|
#endregion
|
|
#region Damage List Generation
|
|
// HandleAttackTypeAndDamage 中只生成对应视角的飘字列表
|
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++)
|
{
|
if (isCasterView)
|
{
|
// 施法者视角:只处理吸血和反伤,添加到targetDamageList用于飘字
|
ProcessSuckHpDamage(i);
|
ProcessReflectDamage(i);
|
}
|
else
|
{
|
// 目标视角:处理反伤和吸血添加到casterDamageList,主伤害添加到targetDamageList
|
ProcessReflectDamage(i);
|
ProcessSuckHpDamage(i);
|
ProcessMainDamage(i, rawAttackType);
|
}
|
}
|
}
|
|
/// <summary>
|
/// 计算最大伤害段数
|
/// </summary>
|
private int CalculateMaxDamageSegmentCount()
|
{
|
int maxCount = 0;
|
|
// 目标受伤的伤害段数
|
if (battleHurtParam.hurter != null && battleHurtParam.hurter.damageList != null)
|
maxCount = Mathf.Max(maxCount, battleHurtParam.hurter.damageList.Count);
|
|
// 施法者的吸血和反伤段数
|
if (battleHurtParam.caster != null)
|
{
|
if (battleHurtParam.caster.suckHpList != null)
|
maxCount = Mathf.Max(maxCount, battleHurtParam.caster.suckHpList.Count);
|
if (battleHurtParam.caster.reflectHpList != null)
|
maxCount = Mathf.Max(maxCount, battleHurtParam.caster.reflectHpList.Count);
|
}
|
|
return maxCount;
|
}
|
|
/// <summary>
|
/// 处理反伤伤害
|
/// </summary>
|
private void ProcessReflectDamage(int segmentIndex)
|
{
|
if (battleHurtParam.caster == null || battleHurtParam.caster.reflectHpList == null)
|
return;
|
|
if (segmentIndex >= battleHurtParam.caster.reflectHpList.Count)
|
return;
|
|
long reflectHp = battleHurtParam.caster.reflectHpList[segmentIndex];
|
if (reflectHp > 0)
|
{
|
if (isCasterView)
|
{
|
// 施法者视角:反伤显示在自己身上(targetDamageList)
|
targetDamageList.Add(new BattleDmg
|
{
|
damage = reflectHp,
|
attackType = (int)DamageType.Reflect
|
});
|
}
|
else
|
{
|
// 目标视角:反伤显示在施法者身上(casterDamageList)
|
casterDamageList.Add(new BattleDmg
|
{
|
damage = reflectHp,
|
attackType = (int)DamageType.Reflect
|
});
|
}
|
}
|
}
|
|
/// <summary>
|
/// 处理吸血伤害
|
/// </summary>
|
private void ProcessSuckHpDamage(int segmentIndex)
|
{
|
if (battleHurtParam.caster == null || battleHurtParam.caster.suckHpList == null)
|
return;
|
|
if (segmentIndex >= battleHurtParam.caster.suckHpList.Count)
|
return;
|
|
long suckHp = battleHurtParam.caster.suckHpList[segmentIndex];
|
if (suckHp > 0)
|
{
|
if (isCasterView)
|
{
|
// 施法者视角:吸血显示在自己身上(targetDamageList)
|
targetDamageList.Add(new BattleDmg
|
{
|
damage = suckHp,
|
attackType = (int)DamageType.SuckHP
|
});
|
}
|
else
|
{
|
// 目标视角:吸血显示在施法者身上(casterDamageList)
|
casterDamageList.Add(new BattleDmg
|
{
|
damage = suckHp,
|
attackType = (int)DamageType.SuckHP
|
});
|
}
|
}
|
}
|
|
/// <summary>
|
/// 处理主要伤害
|
/// </summary>
|
private void ProcessMainDamage(int segmentIndex, int rawAttackType)
|
{
|
// 只处理目标受伤的主要伤害
|
if (battleHurtParam.hurter == null || battleHurtParam.hurter.damageList == null)
|
return;
|
|
if (segmentIndex >= battleHurtParam.hurter.damageList.Count)
|
return;
|
|
long actualDamage = battleHurtParam.hurter.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 (IsType(DamageType.Stunned))
|
{
|
// 特殊处理击晕类型
|
// 去掉击晕类型
|
attackType &= ~(int)DamageType.Stunned;
|
}
|
|
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 BattleHurtObj
|
{
|
public BattleObject hurtObj;
|
public List<long> damageList;
|
|
public long fromHp;
|
|
public long toHp;
|
|
public long maxHp
|
{
|
get
|
{
|
return hurtObj != null ? hurtObj.teamHero.maxHp : 0;
|
}
|
}
|
|
public long fromShieldValue;
|
|
public long toShieldValue;
|
|
public long totalDamage
|
{
|
get
|
{
|
long total = 0;
|
if (damageList != null)
|
{
|
foreach (var dmg in damageList)
|
{
|
total += dmg;
|
}
|
}
|
|
return total;
|
}
|
}
|
}
|
|
public class BattleCastObj
|
{
|
public BattleObject casterObj;
|
public List<long> suckHpList;
|
public List<long> reflectHpList;
|
|
public long fromHp;
|
|
public long toHp;
|
|
public long maxHp
|
{
|
get
|
{
|
return casterObj != null ? casterObj.teamHero.maxHp : 0;
|
}
|
}
|
|
public long fromShieldValue;
|
|
public long toShieldValue;
|
}
|
|
public class BattleHurtParam
|
{
|
public BattleCastObj caster;
|
public BattleHurtObj hurter;
|
|
public BattleDrops battleDrops;
|
public HB427_tagSCUseSkill.tagSCUseSkillHurt hurt;
|
public HB427_tagSCUseSkill hB427_TagSCUseSkill;
|
public int hitIndex;
|
public HB422_tagMCTurnFightObjDead deadPack;
|
public SkillConfig skillConfig;
|
|
|
}
|