yyl
4 天以前 b75bf9422e886b9bda37d5e3e2acf975b304ffc4
125 战斗血量问题修复
3个文件已修改
141 ■■■■ 已修改文件
Main/System/Battle/BattleField/BattleField.cs 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleUtility.cs 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/Skill/SkillBase.cs 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleField/BattleField.cs
@@ -598,10 +598,10 @@
        BattleObject battleObj = battleObjMgr.GetBattleObject((int)vNetData.ObjID);
        if (null != battleObj)
        {
            battleObj.teamHero.curHp = GeneralDefine.GetFactValue(vNetData.HP, vNetData.HPEx);
            battleObj.teamHero.maxHp = GeneralDefine.GetFactValue(vNetData.MaxHP, vNetData.MaxHPEx);
            EventBroadcast.Instance.Broadcast<string, BattleObject>(
                EventName.BATTLE_TIANZI_REFRESH_HP, guid, battleObj);
            // battleObj.teamHero.curHp = GeneralDefine.GetFactValue(vNetData.HP, vNetData.HPEx);
            // battleObj.teamHero.maxHp = GeneralDefine.GetFactValue(vNetData.MaxHP, vNetData.MaxHPEx);
            EventBroadcast.Instance.Broadcast<HB419_tagSCObjHPRefresh>(
                EventName.BATTLE_TIANZI_REFRESH_HP, vNetData);
            //battleObj.teamHero.curHp, battleObj.teamHero.maxHp
        }
Main/System/Battle/BattleUtility.cs
@@ -185,7 +185,7 @@
                break;
            case 1:
                // 1    对位:
                // 默认只选1个,对位规则为A1优先打B1,A2优先打B2,A3优先打B3,对位目标死亡时,优先前排,比如B2已经死亡,那么A2将优先打B1,前排1、2、3号位置全部死亡之后才开始选择后排4、5、6号位置,对位只可选1个目标,即主目标
                // 默认只选1个,对位规则为A1优先打B1,A2优先打B2,A3优先打B3,对位目标死亡时,优先前排,比如B2已经死亡,那么A2将优先打B
                if (targetList.Count > 0)
                {
                    BattleObject battleObject = caster.battleField.battleObjMgr.GetBattleObject((int)targetList[0].ObjID);
@@ -283,19 +283,129 @@
    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];
    }
    /// <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)
    {
        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);
        }
        // ============ 第二步: 将当前这一击的伤害分配到各分段 ============
        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>
    /// 保证所有分配项加起来等于totalDamage,避免因整除导致的误差
Main/System/Battle/Skill/SkillBase.cs
@@ -421,6 +421,9 @@
    // 命中目标回调:处理所有被命中的目标
    protected virtual void OnHitTargets(int _hitIndex, List<HB427_tagSCUseSkill.tagSCUseSkillHurt> hitList)
    {
        //  造成伤害前先处理血量刷新包
        HandleRefreshHP();
        foreach (var hurt in hitList)
        {
            BattleObject target = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID);
@@ -458,7 +461,7 @@
        // 计算总伤害和分段伤害列表
        long totalDamage = GeneralDefine.GetFactValue(hurt.HurtHP, hurt.HurtHPEx);
        List<long> damageList = BattleUtility.DivideDamageToList(damageDivide.ToArray(), totalDamage);
        List<long> damageList = BattleUtility.DivideDamageToList(skillConfig.DamageDivide, _hitIndex, totalDamage);
        // ============ 第二步:刷新实际血量 ============
        long fromHp = target.teamHero.curHp;
@@ -474,7 +477,7 @@
        // 更新目标血量
        target.teamHero.curHp = toHp;
#if UNITY_EDITOR
        BattleDebug.LogError(
            (caster.Camp == BattleCamp.Red ? "【红方行动】" : "【蓝方行动】") + "\n" +
@@ -485,13 +488,9 @@
            $"血量变化: {fromHp} -> {toHp}"
        );
#endif
        
        // 只在最后一击时同步HP刷新包
        bool isLastHit = _hitIndex >= skillConfig.DamageDivide.Length - 1;
        if (isLastHit)
        {
            HandleRefreshHP(hurt);
        }
        // ============ 第三步:获取临时数据(掉落、死亡等) ============
        int objID = (int)target.ObjID;
@@ -507,7 +506,7 @@
    }
    // 处理HP刷新包(简化逻辑)
    private void HandleRefreshHP(HB427_tagSCUseSkill.tagSCUseSkillHurt hurt)
    private void HandleRefreshHP()
    {
        // 查找HP刷新包
        HB419_tagSCObjHPRefresh refreshPack = BattleUtility.FindObjHPRefreshPack(packList);