using System.Collections.Generic; using System.Linq; using UnityEngine; // SkillBase(Hit 部分):命中阶段——OnHit 分发到主目标 / 溅射目标 / 命中提示。 public partial class SkillBase { // 命中目标回调:处理所有被命中的目标(包括主目标、弹射目标、溅射目标) protected virtual void OnHitTargets(int _hitIndex, List hitList) { // Debug.LogError($"Skill {skillConfig.SkillID} hit targets _hitIndex: {_hitIndex} hit {string.Join(", ", hitList.Select(h => h.ObjID + ":" + battleField.battleObjMgr.GetBattleObject((int)h.ObjID)?.GetName()))}"); // 造成伤害前先处理血量刷新包 HandleRefreshHP(); bool suckHp = true; // 处理主目标列表 foreach (var hurt in hitList) { BattleObject target = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID); if (target == null) { Debug.LogError("目标为空 target == null ObjId : " + hurt.ObjID); continue; } OnHitEachTarget(_hitIndex, target, hurt, suckHp); suckHp = false; // 处理该目标的额外目标列表(如弹射伤害的平摊目标) if (hurt.HurtListEx != null && hurt.HurtListEx.Length > 0) { foreach (var hurtEx in hurt.HurtListEx) { BattleObject exTarget = caster.battleField.battleObjMgr.GetBattleObject((int)hurtEx.ObjID); if (exTarget == null) { Debug.LogError($"额外目标为空 HurtListEx target == null ObjId : {hurtEx.ObjID}"); continue; } OnHitEachTargetEx(_hitIndex, exTarget, hurtEx); } } } // 处理技能包顶层的额外目标列表(如溅射伤害、平摊伤害) if (tagUseSkillAttack.HurtListEx != null && tagUseSkillAttack.HurtListEx.Length > 0) { foreach (var hurtEx in tagUseSkillAttack.HurtListEx) { BattleObject exTarget = caster.battleField.battleObjMgr.GetBattleObject((int)hurtEx.ObjID); if (exTarget == null) { Debug.LogError($"顶层额外目标为空 tagUseSkillAttack.HurtListEx target == null ObjId : {hurtEx.ObjID}"); continue; } OnHitEachTargetEx(_hitIndex, exTarget, hurtEx); } } HandleHint(_hitIndex, hitList); } protected void HandleHint(int _hitIndex, List hitList) { if (0 == _hitIndex) { bool needhint = false; for (int i = 0; i < hitList.Count; i++) { var hurt = hitList[i]; //8-击晕 if ((hurt.AttackTypes & (int)DamageType.Stunned) == (int)DamageType.Stunned) { needhint = true; break; } for (int j = 0; j < hurt.HurtListEx?.Length; j++) { var hurtex = hurt.HurtListEx[j]; //8-击晕 if ((hurtex.AttackTypes & (int)ServerDamageType.Stunned) == (int)ServerDamageType.Stunned) { needhint = true; break; } } if (needhint) break; } if (needhint) { DamageNumConfig hintConfig = DamageNumConfig.Get(BattleConst.BattleStun); Hint(caster, hintConfig); } for (int i = 0; i < hitList.Count; i++) { var hurt = hitList[i]; if ((hurt.AttackTypes & (int)DamageType.BreakArmor) == (int)DamageType.BreakArmor) { BattleObject battleObject = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID); if (battleObject != null) { DamageNumConfig hintConfig = DamageNumConfig.Get(BattleConst.BreakArmor); Hint(battleObject, hintConfig); battleField.battleEffectMgr.PlayEffect(battleObject, BattleConst.BreakArmorEffectID, battleObject.GetRectTransform(), battleObject.Camp, battleObject.GetModelScale()); } } else if ((hurt.AttackTypes & (int)DamageType.Parry) == (int)DamageType.Parry) { BattleObject battleObject = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID); if (battleObject != null) { DamageNumConfig hintConfig = DamageNumConfig.Get(BattleConst.Parry); Hint(battleObject, hintConfig); battleField.battleEffectMgr.PlayEffect(battleObject, BattleConst.ParryEffectID, battleObject.GetRectTransform(), battleObject.Camp, battleObject.GetModelScale()); } } } } } // 处理单个目标被命中:应用伤害和施法者效果 protected virtual void OnHitEachTarget(int _hitIndex, BattleObject target, HB427_tagSCUseSkill.tagSCUseSkillHurt hurt, bool suckHp) { // ============ 获取临时数据(掉落、死亡等) ============ int objID = (int)target.ObjID; tempDropList.TryGetValue(objID, out BattleDrops battleDrops); tempDeadPackList.TryGetValue(objID, out BattleDeadPack deadPack); // 如果目标正在释放技能,跳过死亡处理(延迟到技能结束) if (battleField != null && battleField.IsCastingSkill(target.ObjID)) { deadPack = null; } // ============ 参数打包 ============ BattleHurtParam hurtParam = BattleUtility.CalcBattleHurtParam(this, _hitIndex, target, hurt, battleDrops, deadPack, suckHp); #if UNITY_EDITOR PrintHurtParamDebugInfo(hurtParam); #endif // 先调用目标受伤 DeathRecordAction recordAc = target.Hurt(hurtParam, ownRecordAction); if (null != recordAc) { tempDeadPackList.Remove(hurtParam.hurter.hurtObj.ObjID); ownRecordAction.GetInnerRecordPlayer().ImmediatelyPlay(recordAc, ownRecordAction, true); currentWaitingSkill.Add(recordAc); } // 再调用施法者吸血/反伤 caster.OnHurtTarget(hurtParam); } // 处理额外目标被命中(HurtListEx):溅射、弹射、平摊伤害等 protected virtual void OnHitEachTargetEx(int _hitIndex, BattleObject target, HB427_tagSCUseSkill.tagSCUseSkillHurtEx hurtEx) { // ============ 获取临时数据(掉落、死亡等) ============ int objID = (int)target.ObjID; tempDropList.TryGetValue(objID, out BattleDrops battleDrops); tempDeadPackList.TryGetValue(objID, out BattleDeadPack deadPack); // 如果目标正在释放技能,跳过死亡处理(延迟到技能结束) if (battleField != null && battleField.IsCastingSkill(target.ObjID)) { deadPack = null; } // ============ 参数打包(将 tagSCUseSkillHurtEx 转换为 tagSCUseSkillHurt)============ HB427_tagSCUseSkill.tagSCUseSkillHurt hurt = new HB427_tagSCUseSkill.tagSCUseSkillHurt { ObjID = hurtEx.ObjID, AttackTypes = hurtEx.AttackTypes, HurtHP = hurtEx.HurtHP, HurtHPEx = hurtEx.HurtHPEx, CurHP = hurtEx.CurHP, CurHPEx = hurtEx.CurHPEx, SuckHP = 0,//hurtEx.SuckHP, 获取全部吸血时已经计算过 这里就不再计算 BounceHP = 0, // HurtEx 没有反伤字段 HurtCountEx = 0, HurtListEx = null }; OnHitEachTarget(_hitIndex, target, hurt, false);//获取全部吸血时已经计算过 这里就不再计算 } #if UNITY_EDITOR private void PrintHurtParamDebugInfo(BattleHurtParam hurtParam) { bool isLastHit = hurtParam.hitIndex >= hurtParam.skillSkinConfig.DamageDivide.Length - 1; long currentHitDamage = hurtParam.hurter.damageList != null ? hurtParam.hurter.damageList.Sum() : 0; long currentHitSuckHp = hurtParam.caster.suckHpList != null ? hurtParam.caster.suckHpList.Sum() : 0; long currentHitReflectHp = hurtParam.caster.reflectHpList != null ? hurtParam.caster.reflectHpList.Sum() : 0; long totalDamage = GeneralDefine.GetFactValue(hurtParam.hurt.HurtHP, hurtParam.hurt.HurtHPEx); long totalSuckHp = BattleUtility.GetSuckHp(tagUseSkillAttack); long totalReflectHp = hurtParam.hurt.BounceHP; BattleDebug.LogError( (hurtParam.caster.casterObj.Camp == BattleCamp.Red ? "【红方行动】" : "【蓝方行动】 ") + $"攻击者: {hurtParam.caster.casterObj.GetName()} (ObjID:{hurtParam.caster.casterObj.ObjID})\n" + $"目标: {hurtParam.hurter.hurtObj.GetName()} (ObjID:{hurtParam.hurter.hurtObj.ObjID})\n" + $"技能: {hurtParam.skillConfig.SkillName} (ID:{hurtParam.skillConfig.SkillID})\n" + $"击数: 第{hurtParam.hitIndex + 1}击 / 共{hurtParam.skillSkinConfig.DamageDivide.Length}击" + (isLastHit ? " [最后一击]" : " [中间击]") + "\n" + $"\n" + $"========== 目标受伤数据 ==========\n" + $"伤害: {currentHitDamage} / 总伤害: {totalDamage}\n" + $"伤害分段: [{string.Join(", ", hurtParam.hurter.damageList ?? new System.Collections.Generic.List())}]\n" + $"目标血量: {hurtParam.hurter.fromHp} -> {hurtParam.hurter.toHp} (最大:{hurtParam.hurter.maxHp})\n" + $"目标护盾: {hurtParam.hurter.fromShieldValue} -> {hurtParam.hurter.toShieldValue}\n" + $"攻击类型: {hurtParam.hurt.AttackTypes}\n" + $"\n" + $"========== 施法者数据 ==========\n" + $"吸血: {currentHitSuckHp} / 总吸血: {totalSuckHp}\n" + $"吸血分段: [{string.Join(", ", hurtParam.caster.suckHpList ?? new System.Collections.Generic.List())}]\n" + $"反伤: {currentHitReflectHp} / 总反伤: {totalReflectHp}\n" + $"反伤分段: [{string.Join(", ", hurtParam.caster.reflectHpList ?? new System.Collections.Generic.List())}]\n" + $"施法者血量: {hurtParam.caster.fromHp} -> {hurtParam.caster.toHp} (最大:{hurtParam.caster.maxHp})\n" + $"施法者护盾: {hurtParam.caster.fromShieldValue} -> {hurtParam.caster.toShieldValue}\n" ); } #endif }