hch
1 天以前 8a2d52c24c60af2bf6e3968e8dde9ddcb5ccffba
Main/System/Battle/Skill/SkillBase.cs
@@ -36,6 +36,9 @@
    private Dictionary<int, BattleDrops> tempDropList = new Dictionary<int, BattleDrops>();
    private Dictionary<int, HB422_tagMCTurnFightObjDead> tempDeadPackList = new Dictionary<int, HB422_tagMCTurnFightObjDead>();
    protected List<HB428_tagSCBuffRefresh> buffCollections = new List<HB428_tagSCBuffRefresh>();
    // 构造函数:初始化技能基础数据
    public SkillBase(BattleObject _caster, SkillConfig _skillCfg, HB427_tagSCUseSkill vNetData, List<GameNetPackBasic> _packList, BattleField _battleField = null)
    {
@@ -150,7 +153,7 @@
            
            if (hintConfig != null)
            {
                caster.heroInfoBar.ShowTips(((char)hintConfig.prefix).ToString(), true);
                caster.heroInfoBar.ShowTips(((char)hintConfig.prefix).ToString(), true, false, 1.25f);
                // Debug.Break();
            }
        }
@@ -161,6 +164,7 @@
        // 根据释放模式执行相应逻辑
        switch (skillConfig.castMode)
        {
            case SkillCastMode.None:
            case SkillCastMode.Self:
                CastImpl(OnAttackFinish);
                break;
@@ -335,6 +339,7 @@
    public void OnSkillStart()
    {
        HandleDead();
        skillEffect = SkillEffectFactory.CreateSkillEffect(caster, skillConfig, tagUseSkillAttack);
        skillEffect.Play(OnHitTargets);
        foreach (var subSkillPack in tagUseSkillAttack.subSkillList)
@@ -370,6 +375,7 @@
    // 技能后摇结束回调:通知技能效果处理后摇结束
    public virtual void OnFinalFrameEnd()
    {
        skillEffect?.OnFinalFrameEnd(); // 修复:添加空值检查
    }
@@ -384,18 +390,18 @@
        List<BattleObject> targetList = battleField.battleObjMgr.GetBattleObjList(tagUseSkillAttack);
        List<BattleObject> highlightList = new List<BattleObject>(targetList) { caster };
        List<BattleObject> allList = battleField.battleObjMgr.allBattleObjDict.Values.ToList<BattleObject>();
        // 修复:使用HashSet优化性能,避免重复设置
        var targetSet = new HashSet<BattleObject>(targetList);
        var highlightSet = new HashSet<BattleObject>(highlightList);
        caster.heroInfoBar.SetActive(false);
        foreach (BattleObject bo in allList)
        {
            bool isHighlight = highlightSet.Contains(bo);
            bool isTarget = targetSet.Contains(bo);
            if (isHighlight)
            {
                bo.layerMgr.SetFront();
@@ -412,11 +418,23 @@
        // battleField.battleRootNode.SetSortingOrder();
    }
    protected long suckHp = 0;
    // 命中目标回调:处理所有被命中的目标
    protected virtual void OnHitTargets(int _hitIndex, List<HB427_tagSCUseSkill.tagSCUseSkillHurt> hitList)
    {
        //  造成伤害前先处理血量刷新包
        HandleRefreshHP();
        suckHp = 0;
        foreach (var hurt in hitList)
        {
            suckHp += hurt.SuckHP;
        }
        foreach (var hurt in hitList)
        {
            BattleObject target = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID);
            if (target == null)
            {
@@ -428,9 +446,50 @@
        }
    }
    // 处理单个目标被命中:应用伤害和施法者效果
    // 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)
    {
        // ============ 第一步:计算伤害分布 ============
        List<int> damageDivide = new List<int>();
        if (_hitIndex == 0 && skillConfig.DamageDivide.Length <= 0)
        {
@@ -449,19 +508,155 @@
            }
        }
        // 伤害分布计算和应用
        // 计算总伤害和分段伤害列表
        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 totalSuckHp = suckHp;
        List<long> suckHpList = BattleUtility.DivideDamageToList(skillConfig.DamageDivide, _hitIndex, totalSuckHp);
        // ============ 第二步:刷新实际血量 ============
        long fromHp = target.teamHero.curHp;
        // ============处理反伤 ===============
        //  也要按每一击平均算 最后要补齐伤害
        long reflectHp = hurt.BounceHP;
        List<long> reflectHpList = BattleUtility.DivideDamageToList(skillConfig.DamageDivide, _hitIndex, reflectHp);
        // long currentSuckHp = suckHp / tagUseSkillAttack.HurtCount;
        // 计算当前这一击的实际伤害(所有分段伤害之和)
        long currentHitDamage = 0;
        foreach (long dmg in damageList)
        {
            currentHitDamage += dmg;
        }
        long currentHitReflectHp = 0;
        foreach (long reflect in reflectHpList)
        {
            currentHitReflectHp += reflect;
        }
        long shieldValue = target.buffMgr.GetShieldValue();
        long remainSheild = shieldValue - currentHitDamage;
        long toShieldValue = Math.Max(0, shieldValue - currentHitDamage);
        long shieldRecieveDamage = shieldValue - toShieldValue;
        // if (shieldValue > 0 && remainSheild >= 0)
        // {
        //     currentHitDamage = 0;
        //     target.buffMgr.ReduceShieldValue(currentHitDamage);
        // }
        // else if (shieldValue > 0 && remainSheild < 0)
        // {
        //     currentHitDamage = Math.Abs(remainSheild);
        //     target.buffMgr.ClearShield();
        // }
        long toHp = fromHp; //Math.Max(0, fromHp - currentHitDamage);
        // 判断是治疗还是伤害
        bool isHealing = ((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;
        if (isHealing)
        {
            // 治疗逻辑:直接加血,不考虑护盾
            toHp = Math.Min(target.teamHero.maxHp, fromHp + currentHitDamage);
        }
        else
        {
            // 伤害逻辑:先扣护盾,再扣血
            if (remainSheild < 0)
            {
                // 盾被打破
                toHp = Math.Max(0, fromHp + remainSheild);
            }
        }
        // 更新目标血量
        target.teamHero.curHp = toHp;
#if UNITY_EDITOR
        BattleDebug.LogError(
            (caster.Camp == BattleCamp.Red ? "【红方行动】" : "【蓝方行动】 ") +
            $"攻击者: {caster.teamHero.name}\n" +
            $"目标: {target.teamHero.name}\n" +
            $"技能: {skillConfig.SkillName} (第{_hitIndex}击)\n" +
            $"伤害: {currentHitDamage} 实际受到伤害: {fromHp-toHp} (总伤害: {totalDamage})\n" +
            $"承伤前护盾值: {shieldValue}\n" +
            $"承伤后护盾值: {toShieldValue}\n" +
            $"护盾承受伤害: {shieldRecieveDamage}\n" +
            $"反伤: {currentHitReflectHp}\n" +
            $"血量变化: {fromHp} -> {toHp}\n" +
            $"技能包里的血量是: {GeneralDefine.GetFactValue(hurt.CurHP, hurt.CurHPEx)}\n"
        );
#endif
        bool isLastHit = _hitIndex >= skillConfig.DamageDivide.Length - 1;
        // ============ 第三步:获取临时数据(掉落、死亡等) ============
        int objID = (int)target.ObjID;
        tempDropList.TryGetValue(objID, out BattleDrops battleDrops);
        tempDeadPackList.TryGetValue(objID, out HB422_tagMCTurnFightObjDead deadPack);
        target.Hurt(damageList, totalDamage, hurt, skillConfig, _hitIndex, battleDrops, deadPack);
        // 处理施法者相关效果
        caster.SuckHp(hurt.SuckHP, skillConfig);
        caster.HurtByReflect(hurt.BounceHP, skillConfig);
        //  参数打包
        BattleHurtParam hurtParam = new BattleHurtParam()
        {
            casterObj = caster,
            hurtObj = target,
            damageList = damageList,
            suckHpList = suckHpList, //suckHpList,
            reflectHpList = reflectHpList,
            fromHp = fromHp,
            toHp = toHp,
            maxHp = target.teamHero.maxHp,
            fromShieldValue = shieldValue,
            toShieldValue = toShieldValue,
            battleDrops = battleDrops,
            hurt = hurt,
            hitIndex = _hitIndex,
            deadPack = deadPack,
            skillConfig = skillConfig
        };
        // ============ 第四步:执行表现(飘字、动画等) ============
        target.Hurt(hurtParam);
    }
    // 处理HP刷新包(简化逻辑)
    private void HandleRefreshHP()
    {
        // 查找HP刷新包
        HB419_tagSCObjHPRefresh refreshPack = BattleUtility.FindObjHPRefreshPack(packList);
        if (refreshPack != null)
        {
            // 分发HP刷新包
            PackageRegedit.Distribute(refreshPack);
            packList.Remove(refreshPack);
        }
    }
    // 处理死亡相关逻辑:分配掉落和经验
@@ -579,8 +774,8 @@
                long assignExp = avgExp + (i < remain ? 1 : 0);
                var newPack = new HB405_tagMCAddExp
                {
                    Exp = (uint)(assignExp % 100000000),
                    ExpPoint = (uint)(assignExp / 100000000),
                    Exp = (uint)(assignExp % Constants.ExpPointValue),
                    ExpPoint = (uint)(assignExp / Constants.ExpPointValue),
                    Source = expPack.Source
                };
                expAssign[i].Add(newPack);
@@ -712,76 +907,118 @@
        // 修复:使用循环代替递归,避免栈溢出风险
        // try
        // {
            while (true)
        while (true)
        {
            // 验证技能效果是否完成
            if (skillEffect != null && !skillEffect.IsFinished())
                return;
            if (skillEffect != null)
            {
                // 验证技能效果是否完成
                if (skillEffect != null && !skillEffect.IsFinished())
                    return;
                if (skillEffect != null)
                skillEffect = null;
                continue; // 使用continue代替递归调用
            }
            // 验证其他技能动作是否完成
            if (otherSkillActionList.Count > 0)
            {
                bool hasFinishedAction = false;
                for (int i = otherSkillActionList.Count - 1; i >= 0; i--)
                {
                    skillEffect = null;
                    var action = otherSkillActionList[i];
                    if (action.IsFinished())
                    {
                        otherSkillActionList.RemoveAt(i);
                        hasFinishedAction = true;
                    }
                }
                if (hasFinishedAction)
                {
                    continue; // 使用continue代替递归调用
                }
                // 验证其他技能动作是否完成
                if (otherSkillActionList.Count > 0)
                {
                    bool hasFinishedAction = false;
                    for (int i = otherSkillActionList.Count - 1; i >= 0; i--)
                    {
                        var action = otherSkillActionList[i];
                        if (action.IsFinished())
                        {
                            otherSkillActionList.RemoveAt(i);
                            hasFinishedAction = true;
                        }
                    }
                    if (hasFinishedAction)
                    {
                        continue; // 使用continue代替递归调用
                    }
                    return;
                }
                break; // 没有更多需要处理的,退出循环
                return;
            }
            // 处理剩余包
            while (packList.Count > 0)
            {
                var pack = packList[0];
                packList.RemoveAt(0);
            break; // 没有更多需要处理的,退出循环
        }
                if (pack is CustomHB426CombinePack combinePack && combinePack.startTag.Tag.StartsWith("Skill_"))
                {
                    BattleDebug.LogError("other skill casting " + combinePack.startTag.Tag);
                    var otherSkillAction = combinePack.CreateSkillAction();
                    otherSkillAction.fromSkillId = skillConfig.SkillID;
                    otherSkillActionList.Add(otherSkillAction);
                    return;
                }
                if (pack is CustomB421ActionPack actionPack)
                {
                    actionPack.Distribute();
                }
                else
                {
                    PackageRegedit.Distribute(pack);
                }
            }
        // }
        // catch (Exception ex)
        // {
        //     Debug.LogError($"OnSkillFinished异常: {ex.Message},技能ID={skillConfig.SkillID}");
        //     // 确保状态一致性,即使出现异常也要标记完成
        //     isFinished = true;
        //     throw; // 重新抛出异常供上层处理
        // }
        // 处理剩余包
        if (!ResolvePackList())
        {
            return;
        }
            // }
            // catch (Exception ex)
            // {
            //     Debug.LogError($"OnSkillFinished异常: {ex.Message},技能ID={skillConfig.SkillID}");
            //     // 确保状态一致性,即使出现异常也要标记完成
            //     isFinished = true;
            //     throw; // 重新抛出异常供上层处理
            // }
        isFinished = true;
    }
    protected virtual bool ResolvePackList()
    {
        while (packList.Count > 0)
        {
            var pack = packList[0];
            packList.RemoveAt(0);
            if (pack is CustomHB426CombinePack combinePack && combinePack.startTag.Tag.StartsWith("Skill_"))
            {
                BattleDebug.LogError("other skill casting " + combinePack.startTag.Tag);
                var otherSkillAction = combinePack.CreateSkillAction();
                otherSkillAction.fromSkillId = skillConfig.SkillID;
                otherSkillActionList.Add(otherSkillAction);
                return false;
            }
            else if (pack is HB428_tagSCBuffRefresh buffRefresh)
            {
                //   从找到第一个HB428开始 找出连续的HB428_tagSCBuffRefresh包 如果找到一个B428后 之后碰到非HB428包就停止
                buffCollections.Add(buffRefresh);
                while (packList.Count > 0)
                {
                    var nextPack = packList[0];
                    if (nextPack is HB428_tagSCBuffRefresh nextBuffRefresh)
                    {
                        buffCollections.Add(nextBuffRefresh);
                        packList.RemoveAt(0);
                    }
                    else
                    {
                        break;
                    }
                }
                // 同时刷新所有对象的buff,不分组
                foreach (var buff in buffCollections)
                {
                    BattleObject battleObj = battleField.battleObjMgr.GetBattleObject((int)buff.ObjID);
                    if (battleObj != null)
                    {
                        battleObj.buffMgr.RefreshBuff(buff, true);
                    }
                }
                // 清空已处理的buff集合
                buffCollections.Clear();
                continue;
            }
            if (pack is CustomB421ActionPack actionPack)
            {
                actionPack.Distribute();
            }
            else
            {
                PackageRegedit.Distribute(pack);
            }
        }
        return true;
    }
    // 添加清理方法:防止内存泄漏
    public virtual void Cleanup()