| Main/Component/UI/Common/BossLifeBar.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| Main/Core/NetworkPackage/DTCFile/ServerPack/HB4_FightDefine/DTCB430_tagSCTurnFightReport.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| Main/System/Battle/BattleField/BattleField.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| Main/System/Battle/BattleObject/BattleObject.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| Main/System/Battle/BattleUtility.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| Main/System/Battle/Define/BattleDmgInfo.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| Main/System/Battle/Skill/SkillBase.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| Main/System/Battle/StoryBossBattleWin.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| Main/System/Battle/UIComp/BattleHeroInfoBar.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
Main/Component/UI/Common/BossLifeBar.cs
@@ -83,6 +83,8 @@ // 立刻显示基准百分比(使用 percentage) m_SurplusPercent.text = (percentage * 100f).ToString("F2") + "%"; // Debug.LogError("BossLifeBar SetBaseInfo: totalSegments=" + totalSegments + ", hp=" + _hp + ", maxHp=" + _maxHp + ", percentage=" + percentage); } public void Show(ulong _hp, ulong _maxHp) @@ -99,6 +101,7 @@ // 立即更新百分比显示(直接使用 percentage) m_SurplusPercent.text = (percentage * 100f).ToString("F2") + "%"; // Debug.LogError("BossLifeBar Show: totalSegments=" + totalSegments + ", hp=" + _hp + ", maxHp=" + _maxHp + ", percentage=" + percentage); } private void LateUpdate() Main/Core/NetworkPackage/DTCFile/ServerPack/HB4_FightDefine/DTCB430_tagSCTurnFightReport.cs
@@ -86,6 +86,38 @@ vPackList = AnalysisPackQueueAndDistribute(guid, vPackList); #if UNITY_EDITOR if (Launch.Instance.isOpenSkillLogFile) { string packDetail = "AnalysisPackQueueAndDistribute 处理后的包列表:\n"; packDetail += PrintPackListDetail(vPackList, 0); // 分段打印,避免消息被截断 int chunkSize = 15000; // Unity日志单条消息最大长度约16000字符 if (packDetail.Length > chunkSize) { int totalChunks = (packDetail.Length + chunkSize - 1) / chunkSize; for (int i = 0; i < totalChunks; i++) { int startIndex = i * chunkSize; int length = Mathf.Min(chunkSize, packDetail.Length - startIndex); string chunk = packDetail.Substring(startIndex, length); Debug.LogError($"[Part {i + 1}/{totalChunks}]\n{chunk}"); } } else { Debug.LogError(packDetail); } // 或者写入文件 string filePath = Application.dataPath + "/../BattleReport/PackageAnalysis_" + DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".txt"; System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(filePath)); System.IO.File.WriteAllText(filePath, packDetail); Debug.LogError("包分析结果已保存到: " + filePath); } #endif for (int i = 0; i < vPackList.Count; i++) { BattleManager.Instance.PushPackage(guid, vPackList[i]); @@ -99,6 +131,70 @@ } } private string PrintPackListDetail(List<GameNetPackBasic> packList, int indent) { string result = string.Empty; string indentStr = new string(' ', indent * 2); for (int i = 0; i < packList.Count; i++) { var pack = packList[i]; if (pack is HB427_tagSCUseSkill skill) { result += $"{indentStr}[{i}] HB427_tagSCUseSkill - ObjID:{skill.ObjID} SkillID:{skill.SkillID} RelatedSkillID:{skill.RelatedSkillID} BattleType:{skill.BattleType} UID:{skill.packUID}\n"; // 打印子技能列表 if (skill.subSkillList != null && skill.subSkillList.Count > 0) { result += $"{indentStr} SubSkills ({skill.subSkillList.Count}):\n"; int j = 0; foreach (var subSkill in skill.subSkillList) { result += $"{indentStr} [{j}] SubSkill - SkillID:{subSkill.SkillID} RelatedSkillID:{subSkill.RelatedSkillID}\n"; j++; } } // 打印子技能CombinePack列表 if (skill.subSkillCombinePackList != null && skill.subSkillCombinePackList.Count > 0) { result += $"{indentStr} SubSkillCombinePacks ({skill.subSkillCombinePackList.Count}):\n"; int j = 0; foreach (var subCombinePack in skill.subSkillCombinePackList) { var subMainSkill = subCombinePack.GetMainHB427SkillPack(); result += $"{indentStr} [{j}] SubCombinePack - Tag:{subCombinePack.startTag?.Tag} MainSkill:{subMainSkill?.SkillID} PackCount:{subCombinePack.packList.Count}\n"; // 递归打印子CombinePack内部 if (subCombinePack.packList.Count > 0) { result += PrintPackListDetail(subCombinePack.packList, indent + 3); } j++; } } } else if (pack is CustomHB426CombinePack combinePack) { var mainSkill = combinePack.GetMainHB427SkillPack(); result += $"{indentStr}[{i}] CustomHB426CombinePack - Tag:{combinePack.startTag?.Tag} MainSkill:{mainSkill?.SkillID} PackCount:{combinePack.packList.Count}\n"; // 递归打印内部包 if (combinePack.packList.Count > 0) { result += PrintPackListDetail(combinePack.packList, indent + 1); } } else { result += $"{indentStr}[{i}] {pack.GetType().Name} UID:{pack.packUID}\n"; } } return result; } //约定第一个包是B424,先发过来的过滤报错通知 bool FilterBeforeB424(GameNetPackBasic npk) { Main/System/Battle/BattleField/BattleField.cs
@@ -3,6 +3,7 @@ using System; using LitJson; using DG.Tweening; using System.IO; public class BattleField @@ -66,6 +67,10 @@ // 记录正在处理死亡的角色ID,防止重复处理 private HashSet<uint> processingDeathObjIds = new HashSet<uint>(); #if UNITY_EDITOR public static Dictionary<string, string> battleHpRecorder = new Dictionary<string, string>(); #endif public BattleField(string _guid) { @@ -132,6 +137,43 @@ SetRootNodePosition(); rejectNewPackage = false; OnRoundChange?.Invoke(round, turnMax); #if UNITY_EDITOR if (Launch.Instance.isOpenSkillLogFile) { string battleHpRecord = $"初始化战场: MapID={MapID}, FuncLineID={FuncLineID}, TurnMax={turnMax}\n"; for (int i = 0; i < redTeamList.Count; i++) { battleHpRecord += $"红方队伍 {i}:\n"; if (redTeamList[i] == null) continue; foreach (var hero in redTeamList[i].serverHeroes) { if (hero == null) continue; battleHpRecord += $" 角色ID: {hero.ObjID}, 初始血量: {hero.curHp}/{hero.maxHp}\n"; } } for (int i = 0; blueTeamList != null && i < blueTeamList.Count; i++) { battleHpRecord += $"蓝方队伍 {i}:\n"; if (blueTeamList[i] == null) continue; foreach (var hero in blueTeamList[i].serverHeroes) { if (hero == null) continue; battleHpRecord += $" 角色ID: {hero.ObjID}, 初始血量: {hero.curHp}/{hero.maxHp}\n"; } } battleHpRecord += "------------------ END ------------------\n"; battleHpRecorder.Add(guid, battleHpRecord); } #endif } protected virtual void LoadMap(int mapID) @@ -535,7 +577,20 @@ //内部结算需要处理的逻辑,不含UI protected virtual void OnSettlement(JsonData turnFightStateData) { #if UNITY_EDITOR if (Launch.Instance.isOpenSkillLogFile) { string finalReport = battleHpRecorder[guid]; SkillBase.changeListDict.TryGetValue(guid, out string skillChanges); finalReport += "技能变更记录:\n"; finalReport += skillChanges ?? "无技能变更记录\n"; File.WriteAllText(Application.dataPath + "/../BattleReport/HpReport" + guid.Replace("-", "_") + ".txt", finalReport); } #endif } //UI结算后回调需要处理的逻辑 Main/System/Battle/BattleObject/BattleObject.cs
@@ -310,8 +310,15 @@ { bool isLastHit = battleHurtParam.hitIndex >= battleHurtParam.skillConfig.DamageDivide.Length - 1; bool firstHit = battleHurtParam.hitIndex == 0; // 添加调试日志 bool isHealing = BattleUtility.IsHealing(battleHurtParam.hurt); BattleDmgInfo dmgInfo = PopDamage(battleHurtParam); // ============ 应用目标的血量和护盾变化 ============ ApplyHurtToTarget(battleHurtParam, isLastHit); // 这里 if (dmgInfo.IsType(DamageType.Dodge) /*&& !buffMgr.isControled[BattleConst.HardControlGroup]*/)//如果被控制了还闪避了 要看看服务器怎么处理了 @@ -327,8 +334,6 @@ OnDodgeBegin(); } } bool isFatalAttack = (null != battleHurtParam.deadPack) && isLastHit; @@ -361,6 +366,27 @@ } } /// <summary> /// 应用目标的血量和护盾变化 /// </summary> private void ApplyHurtToTarget(BattleHurtParam battleHurtParam, bool isLastHit) { BattleHurtObj hurter = battleHurtParam.hurter; // 应用血量变化 teamHero.curHp = hurter.toHp; // 护盾值由buff系统自动管理,不需要手动设置 // buffMgr会根据服务器的HB428_tagSCBuffRefresh包更新护盾值 #if UNITY_EDITOR // 最后一击时验证血量是否与服务器一致 if (isLastHit) { BattleUtility.ValidateHpConsistency(battleHurtParam, "目标受伤"); } #endif } const float pingpongTime = 0.4f; // 闪避开始 @@ -437,7 +463,8 @@ BattleDmgInfo battleDmgInfo = new BattleDmgInfo(battleField.guid, battleHurtParam); // 天子的挑战拦截血条逻辑 BattleObject boss = battleField.FindBoss(); if (boss != null && battleField.MapID == 30020 && boss.ObjID == battleHurtParam.hurtObj.ObjID) // 修复:battleHurtParam.hurtObj.ObjID -> battleHurtParam.hurter.hurtObj.ObjID if (boss != null && battleField.MapID == 30020 && boss.ObjID == battleHurtParam.hurter.hurtObj.ObjID) { EventBroadcast.Instance.Broadcast(EventName.BATTLE_DAMAGE_TAKEN, battleDmgInfo); return battleDmgInfo; @@ -451,6 +478,28 @@ return battleDmgInfo; } } /// <summary> /// 为施法者创建伤害信息(吸血/反伤) /// </summary> protected virtual BattleDmgInfo PopDamageForCaster(BattleHurtParam battleHurtParam) { // 传入 isCasterView=true 表示这是施法者视角 BattleDmgInfo battleDmgInfo = new BattleDmgInfo(battleField.guid, battleHurtParam, isCasterView: true); BattleObject boss = battleField.FindBoss(); if (boss != null && battleField.MapID == 30020 && boss.ObjID == this.ObjID) { EventBroadcast.Instance.Broadcast(EventName.BATTLE_DAMAGE_TAKEN, battleDmgInfo); return battleDmgInfo; } else { heroInfoBar.UpdateDamage(battleDmgInfo); EventBroadcast.Instance.Broadcast(EventName.BATTLE_DAMAGE_TAKEN, battleDmgInfo); return battleDmgInfo; } } public RectTransform GetAliasTeamNode() @@ -602,4 +651,55 @@ } #endif // BattleObject.cs public virtual void OnHurtTarget(BattleHurtParam battleHurtParam) { // 检查是否有吸血或反伤 bool hasSuckHp = battleHurtParam.caster.suckHpList != null && battleHurtParam.caster.suckHpList.Count > 0; bool hasReflectHp = battleHurtParam.caster.reflectHpList != null && battleHurtParam.caster.reflectHpList.Count > 0; if (!hasSuckHp && !hasReflectHp) { return; } // ============ 应用施法者的血量和护盾变化 ============ bool isLastHit = battleHurtParam.hitIndex >= battleHurtParam.skillConfig.DamageDivide.Length - 1; ApplyHurtToCaster(battleHurtParam, isLastHit); // 和Hurt一样,调用PopDamage处理吸血/反伤的显示 BattleDmgInfo casterDmgInfo = PopDamageForCaster(battleHurtParam); // 如果有反伤,施法者播放受击动画 if (hasReflectHp && casterDmgInfo.casterDamageList != null && casterDmgInfo.casterDamageList.Count > 0) { long totalReflect = casterDmgInfo.casterDamageList.Sum(d => d.damage); if (totalReflect > 0 && !buffMgr.isControled[BattleConst.HardControlGroup]) { motionBase.PlayAnimation(MotionName.hit, false); } } } /// <summary> /// 应用施法者的血量和护盾变化(吸血和反伤) /// </summary> private void ApplyHurtToCaster(BattleHurtParam battleHurtParam, bool isLastHit) { BattleCastObj caster = battleHurtParam.caster; // 应用血量变化 teamHero.curHp = caster.toHp; // 护盾值由buff系统自动管理,不需要手动设置 #if UNITY_EDITOR // 最后一击时验证血量是否与服务器一致 if (isLastHit) { BattleUtility.ValidateHpConsistencyForCaster(battleHurtParam, "施法者吸血/反伤"); } #endif } } Main/System/Battle/BattleUtility.cs
@@ -311,6 +311,169 @@ (hurt.AttackTypes & (int)ServerDamageType.SuckHpReverse) == 0 && (hurt.AttackTypes & (int)ServerDamageType.SelfHarm) == 0; } public static long GetSuckHp(HB427_tagSCUseSkill hB427_TagSCUseSkill) { long totalSuckHp = 0; for (int i = 0; i < hB427_TagSCUseSkill.HurtList.Length; i++) { var hurt = hB427_TagSCUseSkill.HurtList[i]; totalSuckHp += hurt.SuckHP; } return totalSuckHp; } public static BattleHurtParam CalcBattleHurtParam(SkillBase skillBase, int hitIndex, BattleObject target, HB427_tagSCUseSkill.tagSCUseSkillHurt hurt, BattleDrops battleDrops, HB422_tagMCTurnFightObjDead deadPack) { long suckHp = GetSuckHp(skillBase.tagUseSkillAttack); SkillConfig skillConfig = skillBase.skillConfig; long totalDamage = GeneralDefine.GetFactValue(hurt.HurtHP, hurt.HurtHPEx); long totalReflectHp = hurt.BounceHP; // 计算伤害分段 long currentHitDamage = 0; List<long> damageList = DivideDamageToList(skillConfig.DamageDivide, hitIndex, totalDamage, ref currentHitDamage); // 计算吸血分段 long currentHitSuckHp = 0; List<long> suckHpList = DivideDamageToList(skillConfig.DamageDivide, hitIndex, suckHp, ref currentHitSuckHp); // 计算反伤分段 long currentHitReflectHp = 0; List<long> reflectHpList = DivideDamageToList(skillConfig.DamageDivide, hitIndex, totalReflectHp, ref currentHitReflectHp); // 创建目标受伤对象 BattleHurtObj hurter = CreateHurter(target, damageList, hurt, hitIndex, skillConfig, currentHitDamage); // 创建施法者对象 BattleCastObj caster = CreateCaster(skillBase, suckHpList, reflectHpList, currentHitSuckHp, currentHitReflectHp); // 组装BattleHurtParam BattleHurtParam battleHurtParam = new BattleHurtParam(); battleHurtParam.caster = caster; battleHurtParam.hurter = hurter; battleHurtParam.battleDrops = battleDrops; battleHurtParam.hurt = hurt; battleHurtParam.hitIndex = hitIndex; battleHurtParam.deadPack = deadPack; battleHurtParam.skillConfig = skillConfig; return battleHurtParam; } public static BattleHurtObj CreateHurter(BattleObject target, List<long> damageList, HB427_tagSCUseSkill.tagSCUseSkillHurt hurt, int hitIndex, SkillConfig skillConfig, long currentHitDamage) { BattleHurtObj hurter = new BattleHurtObj(); hurter.hurtObj = target; hurter.damageList = damageList; hurter.fromHp = target.teamHero.curHp; hurter.fromShieldValue = target.buffMgr.GetShieldValue(); // 判断是否是最后一击 bool isLastHit = hitIndex >= skillConfig.DamageDivide.Length - 1; // 判断是治疗还是伤害 bool isHealing = IsHealing(hurt); // 计算目标血量变化 if (isLastHit) { // 最后一击:使用服务器下发的最终血量 hurter.toHp = GeneralDefine.GetFactValue(hurt.CurHP, hurt.CurHPEx); } else { // 非最后一击:客户端计算中间血量 long maxHp = target.teamHero.maxHp; if (isHealing) { // 治疗逻辑:直接加血 hurter.toHp = Math.Min(maxHp, hurter.fromHp + currentHitDamage); } else { // 伤害逻辑:先扣护盾,护盾不足再扣血 if (hurter.fromShieldValue >= currentHitDamage) { hurter.toHp = hurter.fromHp; } else { long remainingDamage = currentHitDamage - hurter.fromShieldValue; hurter.toHp = Math.Max(0, hurter.fromHp - remainingDamage); } } } // 计算护盾变化 if (isHealing) { hurter.toShieldValue = hurter.fromShieldValue; } else { if (hurter.fromShieldValue >= currentHitDamage) { hurter.toShieldValue = hurter.fromShieldValue - currentHitDamage; } else { hurter.toShieldValue = 0; } } return hurter; } public static BattleCastObj CreateCaster(SkillBase skillBase, List<long> suckHpList, List<long> reflectHpList, long currentHitSuckHp, long currentHitReflectHp) { BattleCastObj caster = new BattleCastObj(); caster.casterObj = skillBase.caster; caster.suckHpList = suckHpList; caster.reflectHpList = reflectHpList; // 获取施法者当前状态 long casterFromHp = skillBase.caster.teamHero.curHp; long casterMaxHp = skillBase.caster.teamHero.maxHp; long casterFromShield = skillBase.caster.buffMgr.GetShieldValue(); caster.fromHp = casterFromHp; caster.fromShieldValue = casterFromShield; // 计算施法者血量变化(吸血和反伤) long casterToHp = casterFromHp; long casterToShield = casterFromShield; // 处理吸血 if (currentHitSuckHp > 0) { casterToHp = Math.Min(casterMaxHp, casterToHp + currentHitSuckHp); } // 处理反伤(施法者受到伤害) if (currentHitReflectHp > 0) { if (casterToShield >= currentHitReflectHp) { // 施法者护盾足够,只扣护盾 casterToShield -= currentHitReflectHp; } else { // 施法者护盾不足,先扣完护盾,剩余扣血 long remainingReflect = currentHitReflectHp - casterToShield; casterToShield = 0; casterToHp = Math.Max(0, casterToHp - remainingReflect); } } caster.toHp = casterToHp; caster.toShieldValue = casterToShield; return caster; } /// <summary> /// 将整个技能的总伤害按命中次数和分段配置分配 @@ -319,7 +482,7 @@ /// <param name="hitIndex">当前是第几击(从0开始)</param> /// <param name="totalDamage">整个技能的总伤害</param> /// <returns>这一击内每一段的伤害值列表</returns> public static List<long> DivideDamageToList(int[][] damageDivideList, int hitIndex, long totalDamage) public static List<long> DivideDamageToList(int[][] damageDivideList, int hitIndex, long totalDamage, ref long currentHitDamage) { if (totalDamage <= 0) { @@ -400,6 +563,8 @@ // 非最后一击: 按权重计算 currentHitTotalDamage = (long)((float)totalDamage * (float)currentHitWeight / (float)totalWeight); } currentHitDamage = currentHitTotalDamage; // ============ 第二步: 将当前这一击的伤害分配到各分段 ============ List<long> fixedDamageList = new List<long>(); @@ -519,4 +684,142 @@ } return rebornPackList; } // ============================================================ // 文件 2: BattleUtility.cs // 添加血量一致性验证函数 // ============================================================ /// <summary> /// 验证目标血量是否与服务器包一致(仅在最后一击时调用) /// </summary> public static void ValidateHpConsistency(BattleHurtParam hurtParam, string context) { #if UNITY_EDITOR BattleHurtObj hurter = hurtParam.hurter; HB427_tagSCUseSkill.tagSCUseSkillHurt hurt = hurtParam.hurt; // 获取服务器下发的最终血量 long serverFinalHp = GeneralDefine.GetFactValue(hurt.CurHP, hurt.CurHPEx); // 获取客户端计算的最终血量 long clientFinalHp = hurter.toHp; // 验证是否一致 bool isConsistent = (serverFinalHp == clientFinalHp); string logColor = isConsistent ? "<color=green>" : "<color=red>"; string resultStr = isConsistent ? "✓ 一致" : "✗ 不一致"; BattleDebug.LogError( $"{logColor}========== 血量一致性验证 [{context}] {resultStr} ==========</color>\n" + $"目标: {hurter.hurtObj.teamHero.name} (ObjID:{hurter.hurtObj.ObjID})\n" + $"击数: 第{hurtParam.hitIndex + 1}击 (最后一击)\n" + $"服务器最终血量: {serverFinalHp}\n" + $"客户端计算血量: {clientFinalHp}\n" + $"血量差异: {clientFinalHp - serverFinalHp}\n" + $"\n" + $"---- 血量变化过程 ----\n" + $"初始血量: {hurter.fromHp}\n" + $"本次伤害/治疗: {(hurter.damageList != null ? hurter.damageList.Sum() : 0)}\n" + $"最终血量: {clientFinalHp}\n" + $"最大血量: {hurter.hurtObj.teamHero.maxHp}\n" + $"\n" + $"---- 护盾变化过程 ----\n" + $"初始护盾: {hurter.fromShieldValue}\n" + $"最终护盾: {hurter.toShieldValue}\n" + $"护盾变化: {hurter.toShieldValue - hurter.fromShieldValue}\n" ); // 如果不一致,额外输出警告 if (!isConsistent) { Debug.LogWarning( $"[血量验证失败] 目标:{hurter.hurtObj.teamHero.name} " + $"服务器:{serverFinalHp} vs 客户端:{clientFinalHp} " + $"差异:{clientFinalHp - serverFinalHp}" ); } #endif } /// <summary> /// 验证施法者血量是否正确(仅在最后一击时调用) /// </summary> public static void ValidateHpConsistencyForCaster(BattleHurtParam hurtParam, string context) { #if UNITY_EDITOR BattleCastObj caster = hurtParam.caster; // 施法者没有服务器下发的最终血量,只能验证计算逻辑是否正确 long clientFinalHp = caster.toHp; long calculatedHp = caster.fromHp; // 计算预期的血量变化 long totalSuckHp = caster.suckHpList != null ? caster.suckHpList.Sum() : 0; long totalReflectHp = caster.reflectHpList != null ? caster.reflectHpList.Sum() : 0; // 模拟计算过程 long expectedHp = calculatedHp; long expectedShield = caster.fromShieldValue; // 应用吸血 if (totalSuckHp > 0) { expectedHp = Math.Min(caster.casterObj.teamHero.maxHp, expectedHp + totalSuckHp); } // 应用反伤 if (totalReflectHp > 0) { if (expectedShield >= totalReflectHp) { expectedShield -= totalReflectHp; } else { long remainingReflect = totalReflectHp - expectedShield; expectedShield = 0; expectedHp = Math.Max(0, expectedHp - remainingReflect); } } bool isConsistent = (expectedHp == clientFinalHp); string logColor = isConsistent ? "<color=cyan>" : "<color=red>"; string resultStr = isConsistent ? "✓ 计算正确" : "✗ 计算错误"; BattleDebug.LogError( $"{logColor}========== 施法者血量验证 [{context}] {resultStr} ==========</color>\n" + $"施法者: {caster.casterObj.teamHero.name} (ObjID:{caster.casterObj.ObjID})\n" + $"击数: 第{hurtParam.hitIndex + 1}击 (最后一击)\n" + $"预期最终血量: {expectedHp}\n" + $"实际最终血量: {clientFinalHp}\n" + $"血量差异: {clientFinalHp - expectedHp}\n" + $"\n" + $"---- 血量变化过程 ----\n" + $"初始血量: {caster.fromHp}\n" + $"吸血总量: {totalSuckHp}\n" + $"反伤总量: {totalReflectHp}\n" + $"最终血量: {clientFinalHp}\n" + $"最大血量: {caster.casterObj.teamHero.maxHp}\n" + $"\n" + $"---- 护盾变化过程 ----\n" + $"初始护盾: {caster.fromShieldValue}\n" + $"预期护盾: {expectedShield}\n" + $"实际护盾: {caster.toShieldValue}\n" + $"护盾差异: {caster.toShieldValue - expectedShield}\n" ); // 如果不一致,额外输出警告 if (!isConsistent) { Debug.LogWarning( $"[施法者血量计算错误] {caster.casterObj.teamHero.name} " + $"预期:{expectedHp} vs 实际:{clientFinalHp} " + $"差异:{clientFinalHp - expectedHp}" ); } #endif } } Main/System/Battle/Define/BattleDmgInfo.cs
@@ -17,9 +17,50 @@ 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; } } 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; } } @@ -34,10 +75,11 @@ #region Initialization public BattleDmgInfo(string battleFieldGuid, BattleHurtParam battleHurtParam) 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; m_rawAttackType = hurt == null ? 0 : hurt.AttackTypes; @@ -134,20 +176,19 @@ } hurt.AttackTypes = (uint)convertedAttackTypes; Debug.Log($"[BattleDmgInfo] 伤害类型转换: {originalAttackTypes} -> {hurt.AttackTypes}"); } #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 @@ -162,9 +203,19 @@ for (int i = 0; i < maxCount; i++) { ProcessReflectDamage(i); ProcessSuckHpDamage(i); ProcessMainDamage(i, rawAttackType); if (isCasterView) { // 施法者视角:只处理吸血和反伤,添加到targetDamageList用于飘字 ProcessSuckHpDamage(i); ProcessReflectDamage(i); } else { // 目标视角:处理反伤和吸血添加到casterDamageList,主伤害添加到targetDamageList ProcessReflectDamage(i); ProcessSuckHpDamage(i); ProcessMainDamage(i, rawAttackType); } } } @@ -173,9 +224,21 @@ /// </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); 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; } @@ -184,17 +247,33 @@ /// </summary> private void ProcessReflectDamage(int segmentIndex) { if (battleHurtParam.reflectHpList == null || segmentIndex >= battleHurtParam.reflectHpList.Count) if (battleHurtParam.caster == null || battleHurtParam.caster.reflectHpList == null) return; if (segmentIndex >= battleHurtParam.caster.reflectHpList.Count) return; long reflectHp = battleHurtParam.reflectHpList[segmentIndex]; long reflectHp = battleHurtParam.caster.reflectHpList[segmentIndex]; if (reflectHp > 0) { casterDamageList.Add(new BattleDmg if (isCasterView) { damage = reflectHp, attackType = (int)DamageType.Reflect }); // 施法者视角:反伤显示在自己身上(targetDamageList) targetDamageList.Add(new BattleDmg { damage = reflectHp, attackType = (int)DamageType.Reflect }); } else { // 目标视角:反伤显示在施法者身上(casterDamageList) casterDamageList.Add(new BattleDmg { damage = reflectHp, attackType = (int)DamageType.Reflect }); } } } @@ -203,17 +282,33 @@ /// </summary> private void ProcessSuckHpDamage(int segmentIndex) { if (battleHurtParam.suckHpList == null || segmentIndex >= battleHurtParam.suckHpList.Count) if (battleHurtParam.caster == null || battleHurtParam.caster.suckHpList == null) return; if (segmentIndex >= battleHurtParam.caster.suckHpList.Count) return; long suckHp = battleHurtParam.suckHpList[segmentIndex]; long suckHp = battleHurtParam.caster.suckHpList[segmentIndex]; if (suckHp > 0) { casterDamageList.Add(new BattleDmg if (isCasterView) { damage = suckHp, attackType = (int)DamageType.SuckHP }); // 施法者视角:吸血显示在自己身上(targetDamageList) targetDamageList.Add(new BattleDmg { damage = suckHp, attackType = (int)DamageType.SuckHP }); } else { // 目标视角:吸血显示在施法者身上(casterDamageList) casterDamageList.Add(new BattleDmg { damage = suckHp, attackType = (int)DamageType.SuckHP }); } } } @@ -222,10 +317,14 @@ /// </summary> private void ProcessMainDamage(int segmentIndex, int rawAttackType) { if (damageList == null || segmentIndex >= damageList.Count) // 只处理目标受伤的主要伤害 if (battleHurtParam.hurter == null || battleHurtParam.hurter.damageList == null) return; if (segmentIndex >= battleHurtParam.hurter.damageList.Count) return; long actualDamage = damageList[segmentIndex]; long actualDamage = battleHurtParam.hurter.damageList[segmentIndex]; if (isBlocked) { @@ -351,28 +450,27 @@ #endregion } public class BattleHurtParam public class BattleHurtObj { 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 maxHp { get { return hurtObj != null ? hurtObj.teamHero.maxHp : 0; } } public long fromShieldValue; public long toShieldValue; public long totalDamage { get @@ -389,4 +487,41 @@ 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 int hitIndex; public HB422_tagMCTurnFightObjDead deadPack; public SkillConfig skillConfig; } Main/System/Battle/Skill/SkillBase.cs
@@ -53,6 +53,87 @@ packList = _packList; SafetyCheck(); #if UNITY_EDITOR if (Launch.Instance.isOpenSkillLogFile) { PinrtHB427Hp(); } #endif } #if UNITY_EDITOR public static Dictionary<string, string> changeListDict = new Dictionary<string, string>(); #endif private void PinrtHB427Hp() { #if UNITY_EDITOR string skillDetail = "SkillCaster : " + tagUseSkillAttack.ObjID + " -> cast SkillID: " + skillConfig.SkillID + "\n"; skillDetail += "------------------ HurtList ------------------\n"; for (int i = 0; i < tagUseSkillAttack.HurtCount; i++) { var Hurt = tagUseSkillAttack.HurtList[i]; BattleObject battleObject = caster.battleField.battleObjMgr.GetBattleObject((int)Hurt.ObjID); string targetName = battleObject != null ? battleObject.teamHero.name : "Unknown"; long hurtHp = GeneralDefine.GetFactValue(Hurt.HurtHP, Hurt.HurtHPEx); long curHp = GeneralDefine.GetFactValue(Hurt.CurHP, Hurt.CurHPEx); skillDetail += $" [{i}] Target: {targetName} (ObjID:{Hurt.ObjID})\n"; skillDetail += $" HurtHP: {hurtHp}\n"; skillDetail += $" CurHP: {curHp}\n"; skillDetail += $" SuckHP: {Hurt.SuckHP}\n"; skillDetail += $" BounceHP: {Hurt.BounceHP}\n"; skillDetail += $" AttackTypes: {Hurt.AttackTypes}\n"; if (Hurt.HurtListEx != null && Hurt.HurtListEx.Length > 0) { skillDetail += $" HurtListEx ({Hurt.HurtListEx.Length}):\n"; for (int j = 0; j < Hurt.HurtListEx.Length; j++) { var hurtEx = Hurt.HurtListEx[j]; long hurtExHp = GeneralDefine.GetFactValue(hurtEx.HurtHP, hurtEx.HurtHPEx); long curExHp = GeneralDefine.GetFactValue(hurtEx.CurHP, hurtEx.CurHPEx); skillDetail += $" [{j}] ObjID:{hurtEx.ObjID} HurtHP:{hurtExHp} CurHP:{curExHp} SuckHP:{hurtEx.SuckHP} AttackTypes:{hurtEx.AttackTypes}\n"; } } } skillDetail += "------------------ HurtListEx ------------------\n"; if (tagUseSkillAttack.HurtListEx != null) { for (int i = 0; i < tagUseSkillAttack.HurtListEx.Length; i++) { var HurtEx = tagUseSkillAttack.HurtListEx[i]; BattleObject battleObject = caster.battleField.battleObjMgr.GetBattleObject((int)HurtEx.ObjID); string targetName = battleObject != null ? battleObject.teamHero.name : "Unknown"; long hurtHp = GeneralDefine.GetFactValue(HurtEx.HurtHP, HurtEx.HurtHPEx); long curHp = GeneralDefine.GetFactValue(HurtEx.CurHP, HurtEx.CurHPEx); skillDetail += $" [{i}] Target: {targetName} (ObjID:{HurtEx.ObjID})\n"; skillDetail += $" HurtHP: {hurtHp}\n"; skillDetail += $" CurHP: {curHp}\n"; skillDetail += $" SuckHP: {HurtEx.SuckHP}\n"; skillDetail += $" AttackTypes: {HurtEx.AttackTypes}\n"; } } skillDetail += "------------------ END ------------------\n"; if (changeListDict.ContainsKey(caster.battleField.guid)) { string origin = changeListDict[caster.battleField.guid]; origin += skillDetail; changeListDict[caster.battleField.guid] = origin; } else changeListDict.Add(caster.battleField.guid, skillDetail); Debug.LogError("skillDetail : " + skillDetail); #endif } private void SafetyCheck() @@ -358,8 +439,14 @@ // 技能开始回调:处理死亡、子技能、技能效果初始化 public void OnSkillStart() { if (isPlay) { Debug.LogError(" play twice OnSkillStart skillId :" + skillConfig.SkillID); return; } HandleDead(); skillEffect = SkillEffectFactory.CreateSkillEffect(this, caster, skillConfig, tagUseSkillAttack); skillEffect.Play(OnHitTargets); foreach (var subSkillPack in tagUseSkillAttack.subSkillList) @@ -369,6 +456,7 @@ otherSkillActionList.Add(recordAction); battleField.recordPlayer.ImmediatelyPlay(recordAction); } tagUseSkillAttack.subSkillList.Clear(); foreach (var subCombinePack in tagUseSkillAttack.subSkillCombinePackList) { SkillRecordAction recordAction = CustomHB426CombinePack.CreateSkillAction(battleField.guid, subCombinePack.packList); @@ -376,6 +464,7 @@ otherSkillActionList.Add(recordAction); battleField.recordPlayer.ImmediatelyPlay(recordAction); } tagUseSkillAttack.subSkillCombinePackList.Clear(); isPlay = true; } @@ -475,189 +564,65 @@ } } // protected void RecoveryHp(long suckHp, int _hitIndex) // { // // long suckHp = hurt.SuckHP; // if (suckHp <= 0) // { // return; // } // List<long> suckHpList = BattleUtility.DivideDamageToList(skillConfig.DamageDivide, _hitIndex, suckHp); // long currentHitSuckHp = 0; // foreach (long suck in suckHpList) // { // currentHitSuckHp += suck; // } // long fromHp = caster.teamHero.curHp; // long toHp = caster.teamHero.curHp + currentHitSuckHp; // // 参数打包 // BattleHurtParam hurtParam = new BattleHurtParam() // { // casterObj = caster, // hurtObj = null, // damageList = new List<long>(), // suckHpList = suckHpList, // reflectHpList = new List<long>(), // fromHp = fromHp, // toHp = toHp, // battleDrops = null, // hurt = null, // hitIndex = _hitIndex, // deadPack = null, // skillConfig = skillConfig // }; // caster.Hurt(hurtParam); // } // 处理单个目标被命中:应用伤害和施法者效果 protected virtual void OnHitEachTarget(int _hitIndex, BattleObject target, HB427_tagSCUseSkill.tagSCUseSkillHurt hurt) { // 计算总伤害和分段伤害列表 long totalDamage = GeneralDefine.GetFactValue(hurt.HurtHP, hurt.HurtHPEx); List<long> damageList = BattleUtility.DivideDamageToList(skillConfig.DamageDivide, _hitIndex, totalDamage); long totalSuckHp = suckHp; List<long> suckHpList = BattleUtility.DivideDamageToList(skillConfig.DamageDivide, _hitIndex, totalSuckHp); long totalReflectHp = hurt.BounceHP; List<long> reflectHpList = BattleUtility.DivideDamageToList(skillConfig.DamageDivide, _hitIndex, totalReflectHp); // 计算当前这一击的各项数值 long currentHitDamage = 0; foreach (long dmg in damageList) { currentHitDamage += dmg; } long currentHitSuckHp = 0; foreach (long suck in suckHpList) { currentHitSuckHp += suck; } long currentHitReflectHp = 0; foreach (long reflect in reflectHpList) { currentHitReflectHp += reflect; } // ============ 第二步:获取目标当前状态 ============ long fromHp = target.teamHero.curHp; long maxHp = target.teamHero.maxHp; long fromShieldValue = target.buffMgr.GetShieldValue(); // 判断是治疗还是伤害 bool isHealing = BattleUtility.IsHealing(hurt); // ============ 第三步:计算目标血量和护盾变化 ============ long toHp; long toShieldValue; if (isHealing) { // 治疗逻辑:直接加血,护盾不变 toHp = Math.Min(maxHp, fromHp + currentHitDamage); toShieldValue = fromShieldValue; } else { // 伤害逻辑:先扣护盾,护盾不足再扣血 if (fromShieldValue >= currentHitDamage) { // 护盾足够承受所有伤害 toShieldValue = fromShieldValue - currentHitDamage; toHp = fromHp; } else { // 护盾不足,先扣完护盾,剩余伤害扣血 long remainingDamage = currentHitDamage - fromShieldValue; toShieldValue = 0; toHp = Math.Max(0, fromHp - remainingDamage); } } // ============ 第四步:更新目标实际血量 ============ target.teamHero.curHp = toHp; // ============ 第五步:计算并更新施法者血量变化 ============ long casterFromHp = caster.teamHero.curHp; long casterMaxHp = caster.teamHero.maxHp; long casterToHp = casterFromHp; // 处理吸血 if (currentHitSuckHp > 0) { casterToHp = Math.Min(casterMaxHp, casterToHp + currentHitSuckHp); } // 处理反伤(施法者受到伤害) if (currentHitReflectHp > 0) { long casterShieldValue = caster.buffMgr.GetShieldValue(); if (casterShieldValue >= currentHitReflectHp) { // 施法者护盾足够,血量不变 } else { // 施法者护盾不足,扣血 long remainingReflect = currentHitReflectHp - casterShieldValue; casterToHp = Math.Max(0, casterToHp - remainingReflect); } } // 更新施法者血量 caster.teamHero.curHp = casterToHp; #if UNITY_EDITOR BattleDebug.LogError( (caster.Camp == BattleCamp.Red ? "【红方行动】" : "【蓝方行动】 ") + $"攻击者: {caster.teamHero.name}\n" + $"目标: {target.teamHero.name}\n" + $"技能: {skillConfig.SkillName} (第{_hitIndex}击)\n" + $"伤害: {currentHitDamage} (总伤害: {totalDamage})\n" + $"吸血: {currentHitSuckHp}\n" + $"反伤: {currentHitReflectHp}\n" + $"目标护盾变化: {fromShieldValue} -> {toShieldValue}\n" + $"目标血量变化: {fromHp} -> {toHp}\n" + $"施法者血量变化: {casterFromHp} -> {casterToHp}\n" ); #endif // ============ 第六步:获取临时数据(掉落、死亡等) ============ // ============ 获取临时数据(掉落、死亡等) ============ int objID = (int)target.ObjID; tempDropList.TryGetValue(objID, out BattleDrops battleDrops); tempDeadPackList.TryGetValue(objID, out HB422_tagMCTurnFightObjDead deadPack); // ============ 第七步:参数打包并调用目标Hurt ============ BattleHurtParam hurtParam = new BattleHurtParam() { casterObj = caster, hurtObj = target, damageList = damageList, suckHpList = suckHpList, // 用于casterDamageList飘字 reflectHpList = reflectHpList, // 用于casterDamageList飘字 fromHp = fromHp, toHp = toHp, maxHp = maxHp, fromShieldValue = fromShieldValue, toShieldValue = toShieldValue, battleDrops = battleDrops, hurt = hurt, hitIndex = _hitIndex, deadPack = deadPack, skillConfig = skillConfig }; // ============ 参数打包 ============ BattleHurtParam hurtParam = BattleUtility.CalcBattleHurtParam(this, _hitIndex, target, hurt, battleDrops, deadPack); #if UNITY_EDITOR PrintHurtParamDebugInfo(hurtParam); #endif // 先调用目标受伤 target.Hurt(hurtParam); // 再调用施法者吸血/反伤 caster.OnHurtTarget(hurtParam); } #if UNITY_EDITOR private void PrintHurtParamDebugInfo(BattleHurtParam hurtParam) { bool isLastHit = hurtParam.hitIndex >= hurtParam.skillConfig.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.teamHero.name} (ObjID:{hurtParam.caster.casterObj.ObjID})\n" + $"目标: {hurtParam.hurter.hurtObj.teamHero.name} (ObjID:{hurtParam.hurter.hurtObj.ObjID})\n" + $"技能: {hurtParam.skillConfig.SkillName} (ID:{hurtParam.skillConfig.SkillID})\n" + $"击数: 第{hurtParam.hitIndex + 1}击 / 共{hurtParam.skillConfig.DamageDivide.Length}击" + (isLastHit ? " [最后一击]" : " [中间击]") + "\n" + $"\n" + $"========== 目标受伤数据 ==========\n" + $"伤害: {currentHitDamage} / 总伤害: {totalDamage}\n" + $"伤害分段: [{string.Join(", ", hurtParam.hurter.damageList ?? new List<long>())}]\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 List<long>())}]\n" + $"反伤: {currentHitReflectHp} / 总反伤: {totalReflectHp}\n" + $"反伤分段: [{string.Join(", ", hurtParam.caster.reflectHpList ?? new List<long>())}]\n" + $"施法者血量: {hurtParam.caster.fromHp} -> {hurtParam.caster.toHp} (最大:{hurtParam.caster.maxHp})\n" + $"施法者护盾: {hurtParam.caster.fromShieldValue} -> {hurtParam.caster.toShieldValue}\n" ); } #endif // 处理HP刷新包(简化逻辑) private void HandleRefreshHP() @@ -841,6 +806,7 @@ { if (!isPlay) return false; bool tempRetValue = true; // 检查技能效果是否完成 if (skillEffect != null) @@ -848,7 +814,7 @@ if (!skillEffect.IsFinished()) return false; skillEffect = null; OnSkillFinished(); return false; tempRetValue = false; } // 检查其他技能动作是否完成 @@ -863,7 +829,15 @@ OnSkillFinished(); } } if (otherSkillActionList.Count > 0) return false; if (otherSkillActionList.Count > 0) { tempRetValue = false; } } if (!tempRetValue) { return false; } // 检查最终完成状态 Main/System/Battle/StoryBossBattleWin.cs
@@ -116,12 +116,21 @@ protected override void OnDamageTaken(BattleDmgInfo info) { // Debug.LogError("OnDamageTaken 被调用 调用者是 " + info.battleHurtParam.caster.casterObj?.teamHero.name + " 对象 " + info.battleHurtParam.hurter.hurtObj?.teamHero.name); base.OnDamageTaken(info); if (battleField == null || info.battleFieldGuid != battleField.guid) return; if (bossBattleObject != null && info.hurtObj != null && info.hurtObj.ObjID == bossBattleObject.ObjID) if (null == bossBattleObject) return; if (bossBattleObject.teamHero.ObjID == info.battleHurtParam.hurter.hurtObj.teamHero.ObjID) { RefreshHP(); bossLifeBar.Show((ulong)info.battleHurtParam.hurter.toHp, (ulong)bossBattleObject.teamHero.maxHp); } else if (bossBattleObject.teamHero.ObjID == info.battleHurtParam.caster.casterObj.teamHero.ObjID) { bossLifeBar.Show((ulong)info.battleHurtParam.caster.toHp, (ulong)bossBattleObject.teamHero.maxHp); } } Main/System/Battle/UIComp/BattleHeroInfoBar.cs
@@ -259,13 +259,37 @@ } /// <summary> /// 实际执行伤害更新 /// 实际执行伤害更新(统一处理目标和施法者) /// </summary> private void ExecuteDamageUpdate(BattleDmgInfo dmgInfo) { KillTween(ref damageSequence); long maxHp = dmgInfo.battleHurtParam.maxHp; // 判断是目标视角还是施法者视角,使用对应的数据 bool isCasterView = dmgInfo.hurtObj == dmgInfo.casterObj; long maxHp, fromHp, toHp, fromShield, toShield; if (isCasterView) { // 施法者视角:使用 caster 数据 BattleCastObj caster = dmgInfo.battleHurtParam.caster; maxHp = caster.maxHp; fromHp = caster.fromHp; toHp = caster.toHp; fromShield = caster.fromShieldValue; toShield = caster.toShieldValue; } else { // 目标视角:使用 hurter 数据 BattleHurtObj hurter = dmgInfo.battleHurtParam.hurter; maxHp = hurter.maxHp; fromHp = hurter.fromHp; toHp = hurter.toHp; fromShield = hurter.fromShieldValue; toShield = hurter.toShieldValue; } if (maxHp <= 0) { @@ -274,32 +298,21 @@ return; } long fromHp = dmgInfo.battleHurtParam.fromHp; long toHp = dmgInfo.battleHurtParam.toHp; long fromShield = dmgInfo.battleHurtParam.fromShieldValue; long toShield = dmgInfo.battleHurtParam.toShieldValue; damageSequence = DOTween.Sequence(); // 设置初始值 // 护盾动画 if (fromShield > 0) { // 护盾1的值 = min(当前血量 + 当前护盾值, maxHp) / maxHp float fromShield1Value = Mathf.Min((float)(fromHp + fromShield), (float)maxHp) / (float)maxHp; // 护盾2的值 = max(当前血量 + 当前护盾值 - maxHp, 0) / maxHp float fromShield2Value = Mathf.Max((float)(fromHp + fromShield - maxHp), 0f) / (float)maxHp; sliderShield1.value = fromShield1Value; sliderShield2.value = fromShield2Value; // 如果护盾2有值,先播放护盾2的动画 // 护盾2动画 if (fromShield2Value > 0) { // 计算护盾2的初始值和目标值 long beginShield2Value = fromHp + fromShield - maxHp; long endShield2Value = Mathf.Max(0, (int)(toHp + toShield - maxHp)); float toShield2Value = (float)endShield2Value / (float)maxHp; float toShield2Value = Mathf.Max((float)(toHp + toShield - maxHp), 0f) / (float)maxHp; if (Mathf.Abs(fromShield2Value - toShield2Value) > 0.001f) { @@ -307,10 +320,9 @@ } } // 播放护盾1的动画 // 护盾1动画 if (fromShield1Value > 0) { // 计算护盾1的目标值 float toShield1Value = Mathf.Min((float)(toHp + toShield), (float)maxHp) / (float)maxHp; if (Mathf.Abs(fromShield1Value - toShield1Value) > 0.001f) @@ -321,7 +333,6 @@ } else { // 没有护盾,直接设置为0 sliderShield1.value = 0f; sliderShield2.value = 0f; } @@ -338,7 +349,6 @@ } damageSequence.Play(); battleObject.battleField.battleTweenMgr.OnPlayTween(damageSequence); }