yyl
4 天以前 ca85c0a70922aa219f6cad5e8af8ad004c3cb4b3
125 战斗 天子血条刷新包
7个文件已修改
4个文件已添加
320 ■■■■ 已修改文件
Main/Common/EventName.cs 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/DTCFile/ServerPack/HB4_FightDefine/DTCB419_tagSCObjHPRefresh.cs 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/DTCFile/ServerPack/HB4_FightDefine/DTCB419_tagSCObjHPRefresh.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/ServerPack/HB4_FightDefine/HB419_tagSCObjHPRefresh.cs 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/ServerPack/HB4_FightDefine/HB419_tagSCObjHPRefresh.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleField/BattleField.cs 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleObject/BattleObject.cs 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleUtility.cs 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/Motion/MotionBase.cs 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/Skill/SkillBase.cs 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/UIComp/BattleHeroInfoBar.cs 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Common/EventName.cs
@@ -16,4 +16,6 @@
    
    public const string BATTLE_END = "BATTLE_END";//战斗结束
    public const string RECORDPLAYER_END = "RECORDPLAYER_END"; //战斗小片段结束
    public const string BATTLE_TIANZI_REFRESH_HP = "BATTLE_TIANZI_REFRESH_HP";//天子考验 刷新血量
}
Main/Core/NetworkPackage/DTCFile/ServerPack/HB4_FightDefine/DTCB419_tagSCObjHPRefresh.cs
New file
@@ -0,0 +1,18 @@
using UnityEngine;
using System.Collections;
// B4 19 对象最新生命刷新 #tagSCObjHPRefresh
public class DTCB419_tagSCObjHPRefresh : DtcBasic {
    public override void Done(GameNetPackBasic vNetPack) {
        base.Done(vNetPack);
        HB419_tagSCObjHPRefresh vNetData = vNetPack as HB419_tagSCObjHPRefresh;
        BattleField battleField = BattleManager.Instance.GetBattleField(vNetData.packUID);
        if (null != battleField)
        {
            battleField.OnRefreshObjHP(vNetData);
            battleField.DistributeNextPackage();
        }
    }
}
Main/Core/NetworkPackage/DTCFile/ServerPack/HB4_FightDefine/DTCB419_tagSCObjHPRefresh.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3d2361817f6a81a4ea0d05eaf7b8f59e
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Core/NetworkPackage/ServerPack/HB4_FightDefine/HB419_tagSCObjHPRefresh.cs
New file
@@ -0,0 +1,25 @@
using UnityEngine;
using System.Collections;
// B4 19 对象最新生命刷新 #tagSCObjHPRefresh
public class HB419_tagSCObjHPRefresh : GameNetPackBasic {
    public uint ObjID;
    public uint HP;    // 当前血量,求余20亿部分
    public uint HPEx;    // 当前血量,整除20亿部分
    public uint MaxHP;    // 最大血量,求余20亿部分
    public uint MaxHPEx;    // 最大血量,整除20亿部分
    public HB419_tagSCObjHPRefresh () {
        _cmd = (ushort)0xB419;
    }
    public override void ReadFromBytes (byte[] vBytes) {
        TransBytes (out ObjID, vBytes, NetDataType.DWORD);
        TransBytes (out HP, vBytes, NetDataType.DWORD);
        TransBytes (out HPEx, vBytes, NetDataType.DWORD);
        TransBytes (out MaxHP, vBytes, NetDataType.DWORD);
        TransBytes (out MaxHPEx, vBytes, NetDataType.DWORD);
    }
}
Main/Core/NetworkPackage/ServerPack/HB4_FightDefine/HB419_tagSCObjHPRefresh.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4d172d7090e7f3b42958b6ce5bf20dc3
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Battle/BattleField/BattleField.cs
@@ -592,4 +592,20 @@
    {
        return null;
    }
    public void OnRefreshObjHP(HB419_tagSCObjHPRefresh vNetData)
    {
        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, battleObj.teamHero.maxHp
        }
    }
}
Main/System/Battle/BattleObject/BattleObject.cs
@@ -293,11 +293,12 @@
    public virtual void Hurt(List<long> damageValues, long _totalDamage,
        HB427_tagSCUseSkill.tagSCUseSkillHurt hurt, SkillConfig skillConfig, int hitIndex,
        BattleDrops battleDrops, HB422_tagMCTurnFightObjDead deadPack)
        BattleDrops battleDrops, HB422_tagMCTurnFightObjDead deadPack,
        long fromHp, long toHp)
    {
        bool isLastHit = hitIndex >= skillConfig.DamageDivide.Length - 1;
        bool firstHit = hitIndex == 0;
        BattleDmgInfo dmgInfo = PopDamage(damageValues, _totalDamage, hurt, skillConfig, isLastHit);
        BattleDmgInfo dmgInfo = PopDamage(damageValues, _totalDamage, hurt, skillConfig, isLastHit, fromHp, toHp);
        //  这里
@@ -346,18 +347,16 @@
            }
        }
    }
    public void SuckHp(uint suckHP, SkillConfig skillConfig)
    {
        teamHero.curHp = Math.Min(teamHero.maxHp, teamHero.curHp + (int)suckHP);
        // teamHero.curHp = Math.Min(teamHero.maxHp, teamHero.curHp + (int)suckHP);
    }
    public void HurtByReflect(uint bounceHP, SkillConfig skillConfig)
    {
        teamHero.curHp = Math.Max(0, teamHero.curHp - (int)bounceHP);
        // teamHero.curHp = Math.Max(0, teamHero.curHp - (int)bounceHP);
    }
@@ -422,22 +421,14 @@
    }
    // 伤害还要看 是否闪避 暴击 and so on 需要有一个DamageType 服务器应该会给
    protected virtual BattleDmgInfo PopDamage(List<long> damageValues, long _totalDamage, HB427_tagSCUseSkill.tagSCUseSkillHurt hurt, SkillConfig skillConfig, bool isLastHit)
    protected virtual BattleDmgInfo PopDamage(List<long> damageValues, long _totalDamage,
        HB427_tagSCUseSkill.tagSCUseSkillHurt hurt, SkillConfig skillConfig, bool isLastHit,
        long fromHp, long toHp)
    {
        BattleDmgInfo battleDmgInfo = new BattleDmgInfo(battleField.guid, damageValues, this, hurt, skillConfig, isLastHit);
        int currentHurtHp = 0;
        for (int i = 0; i < damageValues.Count; i++)
        {
            currentHurtHp += (int)damageValues[i];
        }
        bool isRecovery = battleDmgInfo.IsType(DamageType.Recovery);
        long toHp = Math.Max(0, teamHero.curHp + (isRecovery ? currentHurtHp : -currentHurtHp));
        heroInfoBar.UpdateHP(teamHero.curHp, toHp, teamHero.maxHp);
        teamHero.curHp = toHp;
        // 使用传入的 fromHp 和 toHp 更新血条显示
        heroInfoBar.UpdateHP(fromHp, toHp, teamHero.maxHp);
        // YYL TODO 是否需要挂在在自身的follow点上
        EventBroadcast.Instance.Broadcast(EventName.BATTLE_DAMAGE_TAKEN, battleDmgInfo);
Main/System/Battle/BattleUtility.cs
@@ -302,17 +302,54 @@
    /// </summary>
    public static List<long> DivideDamageToList(int[] damageDivide, long totalDamage)
    {
        if (damageDivide == null || damageDivide.Length == 0)
        {
            Debug.LogError("damageDivide 为空或长度为0");
            return new List<long> { totalDamage };
        }
        List<long> fixedDamageList = new List<long>();
        long accumulatedDamage = 0; // 累计已分配的伤害
        for (int i = 0; i < damageDivide.Length; i++)
        {
            float fixedDamage = (float)totalDamage * (float)damageDivide[i] / 10000f;
            fixedDamageList.Add((int)fixedDamage);
            long damage;
            // 最后一次分配:用总伤害减去已分配的伤害,确保总和精确
            if (i == damageDivide.Length - 1)
            {
                damage = totalDamage - accumulatedDamage;
            }
            else
            {
                // 计算当前分段伤害(向下取整)
                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)
    {
        List<HB422_tagMCTurnFightObjDead> deadPacks = new List<HB422_tagMCTurnFightObjDead>();
Main/System/Battle/Motion/MotionBase.cs
@@ -23,7 +23,12 @@
    protected Spine.Skeleton skeleton;
    protected float defaultMixDuration = 0f;
    private Spine.TrackEntry currentTrack;
    private Dictionary<int, Spine.TrackEntry> activeSkillTracks = new Dictionary<int, Spine.TrackEntry>(); // 改为字典:trackIndex -> TrackEntry
    private Dictionary<int, Spine.TrackEntry> activeSkillTracks = new Dictionary<int, Spine.TrackEntry>();
    // 子技能轨道池管理(在Init中初始化,不要在这里初始化)
    private Queue<int> availableSubTracks;
    private Dictionary<SkillBase, int> subSkillTrackMap = new Dictionary<SkillBase, int>();
    private SkeletonIllusionShadow illusionShadow;
    private bool playingSkillAnim = false;
@@ -52,6 +57,11 @@
        if (animState != null)
            animState.Data.DefaultMix = defaultMixDuration;
        // 初始化子技能轨道池
        availableSubTracks = new Queue<int>();
        for (int i = 1; i <= 8; i++)
            availableSubTracks.Enqueue(i);
        PlayAnimation(MotionName.idle, true);
        SetupAnimationHandlers();
        
@@ -63,6 +73,8 @@
    {
        trackEntryCallbacks.Clear();
        activeSkillTracks.Clear();
        availableSubTracks?.Clear();
        subSkillTrackMap.Clear();
        if (animState != null)
        {
            animState.Complete -= OnAnimationComplete;
@@ -109,8 +121,8 @@
            return null;
        }
        // 子技能强制使用无动画模式,或者如果没有动画名称
        if (isSubSkill || string.IsNullOrEmpty(skillConfig.SkillMotionName))
        // 如果没有动画名称,使用无动画模式
        if (string.IsNullOrEmpty(skillConfig.SkillMotionName))
        {
            PlaySkillNoAnim(skillConfig, skillBase, onComplete, isSubSkill);
            return null;
@@ -136,13 +148,41 @@
        int frameCount = activeFrames.Length;
        float recoveryFrame = skillConfig.RecoveryFrames;
        // 主技能用 track 0,子技能用 track 1
        int trackIndex = isSubSkill ? 1 : 0;
        // 轨道分配策略:主技能用 track 0,子技能从轨道池分配
        int trackIndex = 0;
        if (isSubSkill)
        {
            if (availableSubTracks != null && availableSubTracks.Count > 0)
            {
                trackIndex = availableSubTracks.Dequeue();
                subSkillTrackMap[skillBase] = trackIndex;
            }
            else
            {
                // 轨道池耗尽或未初始化,回退到无动画模式
                Debug.LogWarning($"子技能轨道池已满或未初始化,技能{skillConfig.SkillID}使用无动画模式");
                PlaySkillNoAnim(skillConfig, skillBase, onComplete, isSubSkill);
                return null;
            }
        }
        Spine.TrackEntry skillTrack = null;
        
        if (hasAnim)
        {
            skillTrack = animState.SetAnimation(trackIndex, targetAnim, false);
            if (null == skillTrack)
            {
                Debug.LogError($"技能 {skillConfig.SkillID} 动画设置失败");
                // 如果是子技能且分配了轨道,需要回收
                if (isSubSkill && subSkillTrackMap.ContainsKey(skillBase))
                {
                    if (availableSubTracks != null)
                        availableSubTracks.Enqueue(subSkillTrackMap[skillBase]);
                    subSkillTrackMap.Remove(skillBase);
                }
                return null;
            }
            
            // 只有主技能才更新 currentTrack
            if (!isSubSkill)
@@ -175,6 +215,14 @@
                {
                    if (activeSkillTracks[trackIndex] == skillTrack)
                        activeSkillTracks.Remove(trackIndex);
                }
                // 回收子技能轨道
                if (isSubSkill && subSkillTrackMap.ContainsKey(skillBase))
                {
                    if (availableSubTracks != null)
                        availableSubTracks.Enqueue(subSkillTrackMap[skillBase]);
                    subSkillTrackMap.Remove(skillBase);
                }
                
                // 只有当没有其他活跃技能时才复位 playingSkillAnim
@@ -214,6 +262,15 @@
                    // 清理并确保状态复位
                    RemoveAction(frameHandler);
                    // 回收子技能轨道
                    if (isSubSkill && subSkillTrackMap.ContainsKey(skillBase))
                    {
                        if (availableSubTracks != null)
                            availableSubTracks.Enqueue(subSkillTrackMap[skillBase]);
                        subSkillTrackMap.Remove(skillBase);
                    }
                    if (activeSkillTracks.Count == 0)
                        playingSkillAnim = false;
                    return;
@@ -227,6 +284,15 @@
                    RemoveAction(frameHandler);
                    if (activeSkillTracks.ContainsKey(trackIndex))
                        activeSkillTracks.Remove(trackIndex);
                    // 回收子技能轨道
                    if (isSubSkill && subSkillTrackMap.ContainsKey(skillBase))
                    {
                        if (availableSubTracks != null)
                            availableSubTracks.Enqueue(subSkillTrackMap[skillBase]);
                        subSkillTrackMap.Remove(skillBase);
                    }
                    if (activeSkillTracks.Count == 0)
                        playingSkillAnim = false;
                    return;
@@ -303,6 +369,14 @@
                    {
                        if (activeSkillTracks[trackIndex] == skillTrack)
                            activeSkillTracks.Remove(trackIndex);
                    }
                    // 回收子技能轨道
                    if (isSubSkill && subSkillTrackMap.ContainsKey(skillBase))
                    {
                        if (availableSubTracks != null)
                            availableSubTracks.Enqueue(subSkillTrackMap[skillBase]);
                        subSkillTrackMap.Remove(skillBase);
                    }
                    // 只有当没有其他活跃技能时才复位 playingSkillAnim
@@ -436,6 +510,17 @@
        trackEntryCallbacks.Clear();
        runningActions.Clear();
        activeSkillTracks.Clear();
        // 重置子技能轨道池
        if (availableSubTracks == null)
            availableSubTracks = new Queue<int>();
        else
            availableSubTracks.Clear();
        subSkillTrackMap.Clear();
        for (int i = 1; i <= 8; i++)
            availableSubTracks.Enqueue(i);
        playingSkillAnim = false;
        PlayAnimation(MotionName.idle, true);
    }
Main/System/Battle/Skill/SkillBase.cs
@@ -339,6 +339,7 @@
    public void OnSkillStart()
    {
        HandleDead();
        skillEffect = SkillEffectFactory.CreateSkillEffect(caster, skillConfig, tagUseSkillAttack);
        skillEffect.Play(OnHitTargets);
        foreach (var subSkillPack in tagUseSkillAttack.subSkillList)
@@ -374,6 +375,7 @@
    // 技能后摇结束回调:通知技能效果处理后摇结束
    public virtual void OnFinalFrameEnd()
    {
        skillEffect?.OnFinalFrameEnd(); // 修复:添加空值检查
    }
@@ -432,9 +434,10 @@
        }
    }
    // 处理单个目标被命中:应用伤害和施法者效果
    // 处理单个目标被命中:应用伤害和施法者效果
    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)
        {
@@ -453,21 +456,70 @@
            }
        }
        // 伤害分布计算和应用
        // 计算总伤害和分段伤害列表
        long totalDamage = GeneralDefine.GetFactValue(hurt.HurtHP, hurt.HurtHPEx);
        List<long> damageList = BattleUtility.DivideDamageToList(damageDivide.ToArray(), totalDamage);
        // 获取临时数据并应用伤害
        // ============ 第二步:刷新实际血量 ============
        long fromHp = target.teamHero.curHp;
        // 计算当前这一击的实际伤害(所有分段伤害之和)
        long currentHitDamage = 0;
        foreach (long dmg in damageList)
        {
            currentHitDamage += dmg;
        }
        long toHp = Math.Max(0, fromHp - currentHitDamage);
        // 更新目标血量
        target.teamHero.curHp = toHp;
#if UNITY_EDITOR
        BattleDebug.LogError(
            (caster.Camp == BattleCamp.Red ? "【红方行动】" : "【蓝方行动】") + "\n" +
            $"攻击者: {caster.teamHero.name}\n" +
            $"目标: {target.teamHero.name}\n" +
            $"技能: {skillConfig.SkillName} (第{_hitIndex}击)\n" +
            $"伤害: {currentHitDamage} (总伤害: {totalDamage})\n" +
            $"血量变化: {fromHp} -> {toHp}"
        );
#endif
        // 只在最后一击时同步HP刷新包
        bool isLastHit = _hitIndex >= skillConfig.DamageDivide.Length - 1;
        if (isLastHit)
        {
            HandleRefreshHP(hurt);
        }
        // ============ 第三步:获取临时数据(掉落、死亡等) ============
        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);
        // 处理施法者相关效果
        // ============ 第四步:执行表现(飘字、动画等) ============
        target.Hurt(damageList, totalDamage, hurt, skillConfig, _hitIndex, battleDrops, deadPack, fromHp, toHp);
        // ============ 第五步:处理施法者相关效果 ============
        caster.SuckHp(hurt.SuckHP, skillConfig);
        caster.HurtByReflect(hurt.BounceHP, skillConfig);
    }
    // 处理HP刷新包(简化逻辑)
    private void HandleRefreshHP(HB427_tagSCUseSkill.tagSCUseSkillHurt hurt)
    {
        // 查找HP刷新包
        HB419_tagSCObjHPRefresh refreshPack = BattleUtility.FindObjHPRefreshPack(packList);
        if (refreshPack != null)
        {
            // 分发HP刷新包
            PackageRegedit.Distribute(refreshPack);
            packList.Remove(refreshPack);
        }
    }
    // 处理死亡相关逻辑:分配掉落和经验
    protected void HandleDead()
    {
Main/System/Battle/UIComp/BattleHeroInfoBar.cs
@@ -150,11 +150,14 @@
    {
        KillTween(ref hpTween);
        
        float fromValue = (float)fromHp / (float)maxHp;
        float targetValue = (float)toHp / (float)maxHp;
        
        if (tween)
        {
            hpTween = sliderHp.DOValue(targetValue, 0.3f);
            // 关键修复:先设置起始值,再播放动画到目标值
            sliderHp.value = fromValue;  // ← 这行是关键!
            hpTween = sliderHp.DOValue(targetValue, 0.3f).SetAutoKill(false);
            battleObject.battleField.battleTweenMgr.OnPlayTween(hpTween);
        }
        else
@@ -170,11 +173,14 @@
    {
        KillTween(ref xpTween);
        
        float fromValue = (float)fromXp / (float)maxXp;
        float targetValue = (float)toXp / (float)maxXp;
        
        if (tween)
        {
            xpTween = sliderXp.DOValue(targetValue, 0.2f);
            // 同样的修复
            sliderXp.value = fromValue;  // ← 这行是关键!
            xpTween = sliderXp.DOValue(targetValue, 0.2f).SetAutoKill(false);
            battleObject.battleField.battleTweenMgr.OnPlayTween(xpTween);
        }
        else