From 1b6291368be04b9bdcf9f31f50768426f06f643b Mon Sep 17 00:00:00 2001
From: hch <305670599@qq.com>
Date: 星期四, 11 十二月 2025 00:04:12 +0800
Subject: [PATCH] 0312 一级界面的按钮

---
 Main/System/Battle/BattleUtility.cs |  734 ++++++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 610 insertions(+), 124 deletions(-)

diff --git a/Main/System/Battle/BattleUtility.cs b/Main/System/Battle/BattleUtility.cs
index c37887b..75513bb 100644
--- a/Main/System/Battle/BattleUtility.cs
+++ b/Main/System/Battle/BattleUtility.cs
@@ -61,11 +61,14 @@
 
 
     public static TweenerCore<Vector2, Vector2, DG.Tweening.Plugins.Options.VectorOptions> MoveToTarget(
-        RectTransform transform, RectTransform target, Vector2 offset, float duration, Action onComplete = null)
+        RectTransform transform, RectTransform target, Vector2 offset, Action onComplete = null, float speed = 500f)
     {
+        // 鑾峰彇鐩爣鑺傜偣鐨勪笘鐣屽潗鏍囷紙閿氱偣浣嶇疆锛�
+        Vector3 worldPos = target.position;
 
-        // 鑾峰彇鐩爣鑺傜偣鐨勪笘鐣屽潗鏍囷紙涓績鐐癸級
-        Vector3 worldPos = target.TransformPoint(target.rect.center + offset);
+        // 濡傛灉闇�瑕佸姞 offset锛岄渶鑰冭檻 scale
+        Vector3 offsetWorld = target.TransformVector(offset);
+        worldPos += offsetWorld;
 
         RectTransform canvasRect = transform.parent as RectTransform;
 
@@ -77,7 +80,8 @@
             null,
             out localPoint);
 
-        // 鍒涘缓RawImage
+        float distance = Vector2.Distance(transform.anchoredPosition, localPoint);
+        float duration = distance / speed;
 
         var tween = transform.DOAnchorPos(localPoint, duration).SetEase(Ease.Linear);
         tween.onComplete += () =>
@@ -85,69 +89,12 @@
             onComplete?.Invoke();
         };
 
-        // MarkStartAndEnd(transform as RectTransform, target);
-
-
-        // // 1. 鑾峰彇鐩爣鐨勪笘鐣屽潗鏍囷紙鍔� offset锛�
-        // Vector3 targetWorldPos = target.TransformPoint(target.anchoredPosition + offset);
-
-        // // 2. 鑾峰彇婧愯妭鐐圭殑 parent
-        // RectTransform sourceParent = transform.parent as RectTransform;
-        // if (sourceParent == null)
-        // {
-        //     BattleDebug.LogError("婧愯妭鐐规病鏈夌埗鑺傜偣锛屾棤娉曡浆鎹㈠潗鏍囷紒");
-        //     return null;
-        // }
-
-        // // 3. 鎶婄洰鏍囦笘鐣屽潗鏍囪浆鎹㈠埌婧� parent 鐨勬湰鍦板潗鏍�
-        // Vector2 targetAnchoredPos;
-        // RectTransformUtility.ScreenPointToLocalPointInRectangle(
-        //     sourceParent,
-        //     RectTransformUtility.WorldToScreenPoint(CameraManager.uiCamera, targetWorldPos),
-        //     CameraManager.uiCamera,
-        //     out targetAnchoredPos);
-
-        // // 4. DOTween 绉诲姩
-        // var tween = transform.DOAnchorPos(targetAnchoredPos, duration).SetEase(Ease.Linear);
-        // tween.onComplete += () =>
-        // {
-        //     onComplete?.Invoke();
-        // };
-
         return tween;
     }
 
     public static string DisplayDamageNum(long num, int attackType)
     {
-        // 鏈嶅姟鍣ㄤ綅鏁板埌瀹㈡埛绔被鍨婭D鐨勬槧灏�
-        Dictionary<int, int> serverToClientTypeMap = new Dictionary<int, int>
-        {
-            { 1, 2 },    // 鏅�氫激琛�
-            { 2, 4 },    // 鎭㈠鍥炶
-            { 3, 8 },    // 鍙嶅脊浼よ
-            { 4, 16 },   // 鎸佺画浼よ
-            { 5, 32 },   // 鏍兼尅
-            { 7, 64 },   // 鏆村嚮浼ゅ
-            { 9, 128 },  // 闂伩
-            // 鍏跺畠绫诲瀷濡傞渶琛ュ厖鍙户缁坊鍔�
-        };
-
-        int damageTypeValue = 0;
-        for (int i = 0; i < 32; i++)
-        {
-            int flag = 1 << i;
-            if ((attackType & flag) != 0)
-            {
-                // 鍙鐞嗘湁鏄犲皠鐨勭被鍨�
-                if (serverToClientTypeMap.TryGetValue(i + 1, out int clientTypeId))
-                {
-                    damageTypeValue += clientTypeId;
-                }
-            }
-        }
-        DamageType damageType = (DamageType)damageTypeValue;
-
-        var config = DamageNumConfig.Get(damageTypeValue);
+        var config = DamageNumConfig.Get(attackType);
         var basePowerStr = UIHelper.ReplaceLargeArtNum(num);
         var result = string.Empty;
         for (int i = 0; i < basePowerStr.Length; i++)
@@ -161,7 +108,49 @@
         return result;
     }
 
-    public static int GetMainTargetPositionNum(BattleObject caster, List<HB427_tagSCUseSkill.tagSCUseSkillHurt> targetList, SkillConfig skillConfig)
+    public static string DisplayDamageNum(BattleDmg damage)
+    {
+        var config = DamageNumConfig.Get(damage.attackType);
+
+        string result = string.Empty;
+
+        //  濡傛灉鏄棯閬挎垨鍏嶇柅 鍒欏彧鏄剧ず瀵瑰簲鏂囧瓧锛屼笉鏄剧ず鏁板瓧
+        if (damage.IsType(DamageType.Dodge) || damage.IsType(DamageType.Immune))
+        {
+            result += (char)config.prefix;
+        }
+        else
+        {
+            result = ConvertToArtFont(config, damage.damage);
+        }
+
+        return result;
+    }
+
+    public static string ConvertToArtFont(DamageNumConfig config, float _num)
+    {
+        var stringBuild = new System.Text.StringBuilder();
+
+        if (0 != config.plus)
+            stringBuild.Append((char)config.plus);
+        if (0 != config.prefix)
+            stringBuild.Append((char)config.prefix);
+
+        var chars = UIHelper.ReplaceLargeArtNum(_num);
+        for (var i = 0; i < chars.Length; i++)
+        {
+            int numChar = GetDamageNumKey(config, (int)chars[i]);
+
+            if (numChar > 0)
+            {
+                stringBuild.Append((char)numChar);
+            }
+        }
+
+        return stringBuild.ToString();
+    }
+
+    public static int GetMainTargetPositionNum(SkillBase skillBase, BattleObject caster, List<HB427_tagSCUseSkill.tagSCUseSkillHurt> targetList, SkillConfig skillConfig)
     {
         int returnIndex = 0;
         //  鏍规嵁鏁屾柟琛�閲忛樀钀� 瀛樻椿浜烘暟鏉ラ�夋嫨
@@ -176,68 +165,121 @@
         // 3    鍚庢帓
         // 4    绾垫帓锛屾寜瀵逛綅瑙勫垯閫夋嫨绾垫帓
         // 5    鑷繁锛岄粯璁ゅ彧閫夎嚜宸�
-        // 6    缁ф壙涓绘妧鑳�/鏉ユ簮鎶�鑳界洰鏍�
-        //      涓�鑸槸棰濆瑙﹀彂鐨勬妧鑳戒娇鐢紝濡傛鐜囬檮鍔犳煇buff
-        //      棰濆瑙﹀彂鐨勬妧鑳藉鏋滅洰鏍囦笌涓绘妧鑳戒笉涓�鑷达紝鍒欓噸鏂拌瀹氱洰鏍囧嵆鍙�
-        //      鎴栬鍔ㄨЕ鍙戠殑鎶�鑳斤紝鍙户鎵胯Е鍙戞潵婧愭妧鑳界殑鏀婚槻鍙屾柟鍏崇郴
 
         switch (skillConfig.TagAim)
         {
             case 0:
-                //  鍏ㄩ儴鑼冨洿
-                //鍏ㄩ儴鑼冨洿+鏁屾垜+鐩爣鏁伴噺涓�6
-                //灏辨槸鍙栨晫鎴戠珯浣嶄腑鐨�2鍙蜂綅
-                returnIndex = 1;
-                break;
-            case 1:
-                returnIndex = caster.teamHero.positionNum;
-                //  瀵绘壘瀵逛綅鏄惁鏈変汉 娌℃湁鐨勮瘽閫夋嫨鏈�灏忕殑
-                List<BattleObject> opposite = new List<BattleObject>(from bo in targetObjList where !bo.IsDead() && bo.teamHero.positionNum == returnIndex select bo);
-                if (opposite.Count > 0)
+                // 0   鍏ㄩ儴鑼冨洿锛�
+                // 鑻agCount鐩爣涓暟涓�0鎴�6锛屾牴鎹甌agFriendly鏁屾垜閰嶇疆锛屼唬琛ㄤ綔鐢ㄤ簬鏁屾柟鍏ㄤ綋鎴栨垜鏂瑰叏浣擄紝姝ゆ椂涓荤洰鏍囦负鏁屾垜绔欎綅涓殑2鍙蜂綅缃�
+                // 鑻agCount鐩爣涓暟涓�1~5涓紝鏍规嵁TagFriendly鏁屾垜+TagAffect缁嗗垎鐩爣閰嶇疆锛屼唬琛ㄩ殢鏈轰綔鐢ㄤ簬鏁屾柟鎴栨垜鏂箈涓灏嗭紝绗竴涓负涓荤洰鏍�
+                if (skillConfig.TagCount == 0 || skillConfig.TagCount == 6)
                 {
-                    returnIndex = opposite[0].teamHero.positionNum;
+                    returnIndex = 1;
                 }
                 else
                 {
-                    opposite = new List<BattleObject>(from bo in targetObjList where !bo.IsDead() select bo);
-                    opposite.Sort((a, b) => a.teamHero.positionNum.CompareTo(b.teamHero.positionNum));
-                    returnIndex = opposite.Count > 0 ? opposite[0].teamHero.positionNum : returnIndex;
+                    uint objId = targetList[0].ObjID;
+                    BattleObject target = caster.battleField.battleObjMgr.GetBattleObject((int)objId);
+                    return target.teamHero.positionNum;
+                }
+                break;
+            case 1:
+                // 1    瀵逛綅锛�
+                // 榛樿鍙��1涓紝瀵逛綅瑙勫垯涓篈1浼樺厛鎵揃1锛孉2浼樺厛鎵揃2锛孉3浼樺厛鎵揃3锛屽浣嶇洰鏍囨浜℃椂锛屼紭鍏堝墠鎺掞紝姣斿B2宸茬粡姝讳骸锛岄偅涔圓2灏嗕紭鍏堟墦B
+                if (targetList.Count > 0)
+                {
+                    BattleObject battleObject = caster.battleField.battleObjMgr.GetBattleObject((int)targetList[0].ObjID);
+                    if (battleObject != null)
+                    {
+                        returnIndex = battleObject.teamHero.positionNum;
+                    }
+                    else
+                    {
+                        Debug.LogError("GetMainTargetPositionNum 鎵句笉鍒扮洰鏍� ObjId : " + targetList[0].ObjID);
+                        returnIndex = 0;
+                    }
+                }
+                else
+                {
+                    Debug.LogError("targetList 鐩爣鍒楄〃涓虹┖");
+                    returnIndex = 0;
                 }
                 break;
             case 2:
-                //  鐪嬬湅瀵归潰鍓嶆帓鏄惁閮芥椿鐫�
-                List<BattleObject> front = new List<BattleObject>(from bo in targetObjList where !bo.IsDead() && bo.teamHero.positionNum < 3 select bo);
-                if (front.Count > 0)
+                //  1銆�2銆�3鍙蜂綅涓哄墠鎺掞紝榛樿2鍙蜂綅缃负涓荤洰鏍囷紝褰�1銆�2銆�3鍙蜂綅缃鑹插叏閮ㄦ浜★紝鍓嶆帓灏嗘浛鎹㈡垚鍚庢帓锛�5鍙蜂綅缃彉鏇翠负涓荤洰鏍囷紝
+                //  鑻ラ厤缃甌agAffect缁嗗垎鐩爣锛屼笖浜烘暟灏忎簬3锛屽垯鎵�鏈夎閫夋嫨鐩爣鍧囦负涓荤洰鏍囷紙鏂芥硶浣嶇疆浼氱敤瀹㈡埛绔厤缃級
+                // 锛堝嵆鍓嶆帓榛樿2鍙蜂綅鎴�5鍙蜂綅瑙勫垯鏃犳晥锛屽疄闄呬綔鐢ㄥ灏戜汉灏辨槸澶氬皯涓富鐩爣锛� (YL : TagAffect>0 && TagAffect != 3灏辨槸鍏ㄤ綋閮芥槸涓荤洰鏍� 鍚庢帓涓�鏍� )
+                if (skillConfig.TagAffect != 0 || skillConfig.TagCount < 3)
                 {
-                    returnIndex = 1;
+                    uint objId = targetList[0].ObjID;
+                    BattleObject target = caster.battleField.battleObjMgr.GetBattleObject((int)objId);
+                    returnIndex = target.teamHero.positionNum;
                 }
                 else
                 {
-                    returnIndex = 4;
+                    //  鐪嬬湅瀵归潰鍓嶆帓鏄惁閮芥椿鐫�
+                    List<BattleObject> front = new List<BattleObject>(from bo in targetObjList where !bo.IsDead() && bo.teamHero.positionNum < 3 select bo);
+                    if (front.Count > 0)
+                    {
+                        returnIndex = 1;
+                    }
+                    else
+                    {
+                        returnIndex = 4;
+                    }
                 }
                 break;
             case 3:
-                //  鐪嬬湅瀵归潰鍚庢帓鏄惁閮芥椿鐫�
-                List<BattleObject> back = new List<BattleObject>(from bo in targetObjList where !bo.IsDead() && bo.teamHero.positionNum >= 3 select bo);
-                if (back.Count > 0)
+                if (skillConfig.TagAffect != 0 || skillConfig.TagCount < 3)
                 {
-                    returnIndex = 4;
+                    uint objId = targetList[0].ObjID;
+                    BattleObject target = caster.battleField.battleObjMgr.GetBattleObject((int)objId);
+                    returnIndex = target.teamHero.positionNum;
                 }
                 else
                 {
-                    returnIndex = 1;
+                    //  鐪嬬湅瀵归潰鍚庢帓鏄惁閮芥椿鐫�
+                    List<BattleObject> back = new List<BattleObject>(from bo in targetObjList where !bo.IsDead() && bo.teamHero.positionNum >= 3 select bo);
+                    if (back.Count > 0)
+                    {
+                        returnIndex = 4;
+                    }
+                    else
+                    {
+                        returnIndex = 1;
+                    }
                 }
                 break;
             // 4    绾垫帓锛屾寜瀵逛綅瑙勫垯閫夋嫨绾垫帓
             case 4:
-                List<BattleObject> vertical = new List<BattleObject>(from bo in targetObjList where !bo.IsDead() && (bo.teamHero.positionNum - caster.teamHero.positionNum) % 3 == 0 select bo);
-                //  TODO YYL
+                returnIndex = int.MaxValue;
+                for (int i = 0; i < targetList.Count; i++)
+                {
+                    var hurt = targetList[i];
+                    BattleObject target = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID);
+                    if (target == null)
+                    {
+                        Debug.LogError("GetMainTargetPositionNum 鎵句笉鍒扮洰鏍� ObjId : " + hurt.ObjID);
+                        continue;
+                    }
+                    else
+                    {
+                        returnIndex = Mathf.Min(returnIndex, target.teamHero.positionNum);
+                    }
+                }
                 break;
             // 5    鑷繁锛岄粯璁ゅ彧閫夎嚜宸�
             case 5:
                 returnIndex = caster.teamHero.positionNum;
                 break;
+            case 6:
+                //  璺熼殢涓绘妧鑳界殑鐩爣
+                var fromSkill = skillBase.fromSkill;
+                returnIndex = GetMainTargetPositionNum(fromSkill, fromSkill.caster, fromSkill.tagUseSkillAttack.HurtList.ToList(), fromSkill.skillConfig);
+                break;
             default:
+                Debug.LogError("鏆傛椂涓嶆敮鎸佸叾浠栫殑鏂瑰紡閫夋嫨涓荤洰鏍� 鏈夐渶姹傝鑱旂郴绛栧垝 鎶�鑳絠d:" + skillConfig.SkillID + " TagAim " + skillConfig.TagAim);
+                returnIndex = 0;
                 break;
         }
 
@@ -246,18 +288,309 @@
 
     public static int GetDamageNumKey(DamageNumConfig config, int _num)
     {
-        if (_num == 46)      return config.nums[10]; // '.'
+        if (_num == 46) return config.nums[10]; // '.'
         else if (_num == 107) return config.nums[11]; // 'k'
         else if (_num == 109) return config.nums[12]; // 'm'
-        else if (_num == 98)  return config.nums[13]; // 'b'
+        else if (_num == 98) return config.nums[13]; // 'b'
         else if (_num == 116) return config.nums[14]; // 't'
         int targetNum = _num - 48;
         if (targetNum >= config.nums.Length || targetNum < 0)
         {
-            Debug.LogError("damage config " + config.TypeID + " _num is " +  _num + " out of range");
+            Debug.LogError("damage config " + config.TypeID + " _num is " + _num + " out of range");
             return _num;
         }
         return config.nums[_num - 48];
+    }
+
+    public static bool IsHealing(HB427_tagSCUseSkill.tagSCUseSkillHurt hurt)
+    {
+        return ((hurt.AttackTypes & (int)ServerDamageType.Recovery) != 0 || 
+                          (hurt.AttackTypes & (int)ServerDamageType.DamageReverse) != 0) &&
+                         (hurt.AttackTypes & (int)ServerDamageType.Damage) == 0 &&
+                         (hurt.AttackTypes & (int)ServerDamageType.Realdamage) == 0 &&
+                         (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.hB427_TagSCUseSkill = skillBase.tagUseSkillAttack;
+        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
+            {
+                // 浼ゅ閫昏緫锛氬厛鎵f姢鐩撅紝鎶ょ浘涓嶈冻鍐嶆墸琛�
+                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
+            {
+                // 鏂芥硶鑰呮姢鐩句笉瓒筹紝鍏堟墸瀹屾姢鐩撅紝鍓╀綑鎵h
+                long remainingReflect = currentHitReflectHp - casterToShield;
+                casterToShield = 0;
+                casterToHp = Math.Max(0, casterToHp - remainingReflect);
+            }
+        }
+
+        caster.toHp = casterToHp;
+        caster.toShieldValue = casterToShield;
+
+        return caster;
+    }
+    
+    /// <summary>
+    /// 灏嗘暣涓妧鑳界殑鎬讳激瀹虫寜鍛戒腑娆℃暟鍜屽垎娈甸厤缃垎閰�
+    /// </summary>
+    /// <param name="damageDivideList">鏁翠釜鎶�鑳界殑鎵�鏈夊懡涓垎娈甸厤缃�</param>
+    /// <param name="hitIndex">褰撳墠鏄鍑犲嚮(浠�0寮�濮�)</param>
+    /// <param name="totalDamage">鏁翠釜鎶�鑳界殑鎬讳激瀹�</param>
+    /// <returns>杩欎竴鍑诲唴姣忎竴娈电殑浼ゅ鍊煎垪琛�</returns>
+    public static List<long> DivideDamageToList(int[][] damageDivideList, int hitIndex, long totalDamage, ref long currentHitDamage)
+    {
+        if (totalDamage <= 0)
+        {
+            return new List<long>{};
+        }
+
+        if (damageDivideList == null || damageDivideList.Length == 0)
+        {
+            Debug.LogError("damageDivideList 涓虹┖鎴栭暱搴︿负0");
+            return new List<long> { totalDamage };
+        }
+
+        if (hitIndex < 0 || hitIndex >= damageDivideList.Length)
+        {
+            Debug.LogError($"hitIndex={hitIndex} 瓒呭嚭鑼冨洿, damageDivideList.Length={damageDivideList.Length}");
+            return new List<long> { totalDamage };
+        }
+
+        int[] currentHitDivide = damageDivideList[hitIndex];
+        if (currentHitDivide == null || currentHitDivide.Length == 0)
+        {
+            Debug.LogError($"damageDivide[{hitIndex}] 涓虹┖鎴栭暱搴︿负0");
+            return new List<long> { totalDamage };
+        }
+
+        // ============ 绗竴姝�: 璁$畻姣忎竴鍑诲簲璇ラ�犳垚鐨勪激瀹� ============
+        // 鍏堣绠楁墍鏈夊嚮鐨勬�绘潈閲�
+        int totalWeight = 0;
+        for (int i = 0; i < damageDivideList.Length; i++)
+        {
+            if (damageDivideList[i] != null && damageDivideList[i].Length > 0)
+            {
+                // 姣忎竴鍑荤殑鏉冮噸鏄叾鎵�鏈夊垎娈典箣鍜�
+                for (int j = 0; j < damageDivideList[i].Length; j++)
+                {
+                    totalWeight += damageDivideList[i][j];
+                }
+            }
+        }
+
+        if (totalWeight == 0)
+        {
+            Debug.LogError("totalWeight 涓� 0");
+            return new List<long> { totalDamage };
+        }
+
+        // 璁$畻褰撳墠杩欎竴鍑荤殑鏉冮噸
+        int currentHitWeight = 0;
+        for (int i = 0; i < currentHitDivide.Length; i++)
+        {
+            currentHitWeight += currentHitDivide[i];
+        }
+
+        // 璁$畻褰撳墠杩欎竴鍑诲簲璇ラ�犳垚鐨勬�讳激瀹�
+        long currentHitTotalDamage;
+        bool isLastHit = hitIndex >= damageDivideList.Length - 1;
+        
+        if (isLastHit)
+        {
+            // 鏈�鍚庝竴鍑�: 璁$畻鍓嶉潰鎵�鏈夊嚮宸茬粡閫犳垚鐨勪激瀹�,鍓╀綑鐨勫叏閮ㄧ粰鏈�鍚庝竴鍑�
+            long previousHitsDamage = 0;
+            for (int i = 0; i < hitIndex; i++)
+            {
+                if (damageDivideList[i] != null)
+                {
+                    int hitWeight = 0;
+                    for (int j = 0; j < damageDivideList[i].Length; j++)
+                    {
+                        hitWeight += damageDivideList[i][j];
+                    }
+                    previousHitsDamage += (long)((float)totalDamage * (float)hitWeight / (float)totalWeight);
+                }
+            }
+            currentHitTotalDamage = totalDamage - previousHitsDamage;
+        }
+        else
+        {
+            // 闈炴渶鍚庝竴鍑�: 鎸夋潈閲嶈绠�
+            currentHitTotalDamage = (long)((float)totalDamage * (float)currentHitWeight / (float)totalWeight);
+        }
+
+        currentHitDamage = currentHitTotalDamage;
+
+        // ============ 绗簩姝�: 灏嗗綋鍓嶈繖涓�鍑荤殑浼ゅ鍒嗛厤鍒板悇鍒嗘 ============
+        List<long> fixedDamageList = new List<long>();
+        long accumulatedDamage = 0;
+
+        for (int i = 0; i < currentHitDivide.Length; i++)
+        {
+            long damage;
+            
+            // 褰撳墠鍑荤殑鏈�鍚庝竴娈佃繘琛岃宸ˉ鍋�
+            if (i == currentHitDivide.Length - 1)
+            {
+                damage = currentHitTotalDamage - accumulatedDamage;
+            }
+            else
+            {
+                // 鎸夊綋鍓嶅嚮鐨勬潈閲嶅垎閰�
+                damage = (long)((float)currentHitTotalDamage * (float)currentHitDivide[i] / (float)currentHitWeight);
+                accumulatedDamage += damage;
+            }
+            
+            fixedDamageList.Add(damage);
+        }
+
+        return fixedDamageList;
     }
 
     /// <summary>
@@ -265,26 +598,52 @@
     /// </summary>
     public static List<long> DivideDamageToList(int[] damageDivide, long totalDamage)
     {
-        List<long> fixedDamageList = new List<long>();
-        long assigned = 0;
-        int count = damageDivide.Length;
+        if (damageDivide == null || damageDivide.Length == 0)
+        {
+            Debug.LogError("damageDivide 涓虹┖鎴栭暱搴︿负0");
+            return new List<long> { totalDamage };
+        }
 
-        for (int i = 0; i < count; i++)
+        List<long> fixedDamageList = new List<long>();
+        long accumulatedDamage = 0; // 绱宸插垎閰嶇殑浼ゅ
+
+        for (int i = 0; i < damageDivide.Length; i++)
         {
             long damage;
-            if (i == count - 1)
+            
+            // 鏈�鍚庝竴娆″垎閰嶏細鐢ㄦ�讳激瀹冲噺鍘诲凡鍒嗛厤鐨勪激瀹筹紝纭繚鎬诲拰绮剧‘
+            if (i == damageDivide.Length - 1)
             {
-                // 鏈�鍚庝竴涓垎閰嶉」淇涓哄墿浣�
-                damage = totalDamage - assigned;
+                damage = totalDamage - accumulatedDamage;
             }
             else
             {
-                damage = (totalDamage * damageDivide[i] + 5000) / 10000; // 鍥涜垗浜斿叆
-                assigned += damage;
+                // 璁$畻褰撳墠鍒嗘浼ゅ锛堝悜涓嬪彇鏁达級
+                damage = (long)((float)totalDamage * (float)damageDivide[i] / 10000f);
+                accumulatedDamage += damage;
             }
+            
             fixedDamageList.Add(damage);
         }
+
         return fixedDamageList;
+    }
+    
+    public static HB419_tagSCObjHPRefresh FindObjHPRefreshPack(List<GameNetPackBasic> packList)
+    {
+        for (int i = 0; i < packList.Count; i++)
+        {
+            var pack = packList[i];
+            if (pack is HB419_tagSCObjHPRefresh hpRefreshPack)
+            {
+                return hpRefreshPack;
+            }
+            else if (pack is CustomHB426CombinePack)
+            {
+                break;
+            }
+        }
+        return null;
     }
 
     public static List<HB422_tagMCTurnFightObjDead> FindDeadPack(List<GameNetPackBasic> packList)
@@ -294,47 +653,174 @@
         {
             var pack = packList[i];
             //	瀵绘壘姝讳骸鍖� 鎵惧埌姝讳骸鍖呬箣鍚庤鎵炬帀钀藉寘 涓嶈兘瓒呰繃鎶�鑳藉寘
-            if (pack is HB422_tagMCTurnFightObjDead)
+            if (pack is HB422_tagMCTurnFightObjDead deadPack)
             {
-                var deadPack = pack as HB422_tagMCTurnFightObjDead;
                 deadPacks.Add(deadPack);
             }
             else if (pack is CustomHB426CombinePack)
             {
-                //	鎵炬浜″寘涓嶈瓒婅繃鎶�鑳藉寘
-                var combinePack = pack as CustomHB426CombinePack;
-                if (combinePack.startTag.Tag.StartsWith("Skill_"))
-                {
-                    break;
-                }
+                break;
             }
         }
+        // Debug.LogError("find dead pack " + deadPacks.Count);
         return deadPacks;
     }
 
 
     public static List<HB423_tagMCTurnFightObjReborn> FindRebornPack(List<GameNetPackBasic> packList)
     {
-        List<HB423_tagMCTurnFightObjReborn> rebornPack = new List<HB423_tagMCTurnFightObjReborn>();
+        List<HB423_tagMCTurnFightObjReborn> rebornPackList = new List<HB423_tagMCTurnFightObjReborn>();
         for (int i = 0; i < packList.Count; i++)
         {
             var pack = packList[i];
             //	瀵绘壘姝讳骸鍖� 鎵惧埌姝讳骸鍖呬箣鍚庤鎵炬帀钀藉寘 涓嶈兘瓒呰繃鎶�鑳藉寘
-            if (pack is HB423_tagMCTurnFightObjReborn)
+            if (pack is HB423_tagMCTurnFightObjReborn rebornPack)
             {
-                var deadPack = pack as HB423_tagMCTurnFightObjReborn;
-                rebornPack.Add(deadPack);
+                rebornPackList.Add(rebornPack);
             }
             else if (pack is CustomHB426CombinePack)
             {
-                //	鎵炬浜″寘涓嶈瓒婅繃鎶�鑳藉寘
-                var combinePack = pack as CustomHB426CombinePack;
-                if (combinePack.startTag.Tag.StartsWith("Skill_"))
-                {
-                    break;
-                }
+                break;
             }
         }
-        return rebornPack;
+        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;
+        
+        // 鏂芥硶鑰呮病鏈夋湇鍔″櫒涓嬪彂鐨勬渶缁堣閲忥紝鍙兘楠岃瘉璁$畻閫昏緫鏄惁姝g‘
+        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 ? "鉁� 璁$畻姝g‘" : "鉁� 璁$畻閿欒";
+        
+        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
     }
 }
\ No newline at end of file

--
Gitblit v1.8.0