yyl
2025-09-04 cdf7098c937c5f4a70383ef70897bf9fedbb3d99
删除大部分log 修复技能有时候播不出来的问题
34个文件已修改
1171 ■■■■■ 已修改文件
Main/Component/UI/Effect/BattleEffectPlayer.cs 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/ConfigManager.cs 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/DamageNumConfig.cs 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/EffectConfig.cs 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/SkillConfig.cs 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/CustomServerPack/CustomB421ActionPack.cs 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/CustomServerPack/CustomHB426CombinePack.cs 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/GameNetPackBasic.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleEffectMgr.cs 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleField/BattleField.cs 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleField/OperationAgent/HandModeOperationAgent.cs 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleField/RecordActions/SkillRecordAction.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleField/StoryBattleField.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleManager.cs 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleObject/BattleObject.cs 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleObject/BattleObjectFactory.cs 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleUtility.cs 147 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/Define/BattleDmgInfo.cs 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/Define/DamageType.cs 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/Motion/MotionBase.cs 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/RecordPlayer/RecordPlayer.cs 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/Skill/DirectlyDamageSkill.cs 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/Skill/DirectlyHealSkill.cs 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/Skill/SkillBase.cs 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/Skill/SkillFactory.cs 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/SkillEffect/BulletCurve/BounceBulletCurve.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/SkillEffect/BulletCurve/StraightBulletCurve.cs 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/SkillEffect/BulletSkillEffect.cs 188 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/SkillEffect/NormalSkillEffect.cs 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/TestMoveToTarget.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/UIComp/BattleTips.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/UIComp/DamageContent.cs 42 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/UIComp/DamageLine.cs 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/GeneralConfig/GeneralDefine.cs 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Component/UI/Effect/BattleEffectPlayer.cs
@@ -121,6 +121,10 @@
            rectTrans.anchoredPosition += new Vector2(effectConfig.effectPos[0], effectConfig.effectPos[1]);
        }
        if (effectConfig.effectScale > 0f)
        {
            rectTrans.localScale *= effectConfig.effectScale;
        }
    }
    protected virtual void Clear()
@@ -351,6 +355,9 @@
    protected void OnSortingChanged(string _sortingLayer, int _sortingOrder)
    {
        if (null == spineComp)
            return;
        sortingLayer = _sortingLayer;
        sortingOrder = _sortingOrder;
        // 处理排序变化
Main/Config/ConfigManager.cs
@@ -38,32 +38,15 @@
        // 加载配置文件
        HashSet<Type> configTypes = new HashSet<Type>() {
            typeof(ChestsAwardConfig),
            typeof(CTGConfig),
            typeof(DamageNumConfig),
            typeof(DirtyWordConfig),
            typeof(FaceConfig),
            typeof(FightPowerRatioConfig),
            typeof(HeroLineupHaloConfig),
            typeof(HeroQualityLVConfig),
            typeof(InvestConfig),
            typeof(ItemConfig),
            typeof(MainChapterConfig),
            typeof(MainLevelConfig),
            typeof(NPCConfig),
            typeof(NPCExConfig),
            typeof(NPCLineupConfig),
            typeof(OrderInfoConfig),
            typeof(PlayerAttrConfig),
            typeof(PlayerFaceConfig),
            typeof(StoreConfig),
            typeof(SuccessConfig),
            typeof(SysInfoConfig),
            typeof(TitleStarUpConfig),
            typeof(TreasureSetConfig),
            typeof(TreeLVConfig),
            typeof(WindowSearchConfig),
            typeof(XBGetItemConfig)
            typeof(PlayerLVConfig),
            typeof(TitleStarUpConfig)
        };
#if UNITY_EDITOR
@@ -213,16 +196,8 @@
    public override void Release()
    {
        // 清空 ChestsAwardConfig 字典
        ClearConfigDictionary<ChestsAwardConfig>();
        // 清空 CTGConfig 字典
        ClearConfigDictionary<CTGConfig>();
        // 清空 DamageNumConfig 字典
        ClearConfigDictionary<DamageNumConfig>();
        // 清空 DirtyWordConfig 字典
        ClearConfigDictionary<DirtyWordConfig>();
        // 清空 FaceConfig 字典
        ClearConfigDictionary<FaceConfig>();
        // 清空 FightPowerRatioConfig 字典
        ClearConfigDictionary<FightPowerRatioConfig>();
        // 清空 HeroLineupHaloConfig 字典
@@ -233,38 +208,12 @@
        ClearConfigDictionary<InvestConfig>();
        // 清空 ItemConfig 字典
        ClearConfigDictionary<ItemConfig>();
        // 清空 MainChapterConfig 字典
        ClearConfigDictionary<MainChapterConfig>();
        // 清空 MainLevelConfig 字典
        ClearConfigDictionary<MainLevelConfig>();
        // 清空 NPCConfig 字典
        ClearConfigDictionary<NPCConfig>();
        // 清空 NPCExConfig 字典
        ClearConfigDictionary<NPCExConfig>();
        // 清空 NPCLineupConfig 字典
        ClearConfigDictionary<NPCLineupConfig>();
        // 清空 OrderInfoConfig 字典
        ClearConfigDictionary<OrderInfoConfig>();
        // 清空 PlayerAttrConfig 字典
        ClearConfigDictionary<PlayerAttrConfig>();
        // 清空 PlayerFaceConfig 字典
        ClearConfigDictionary<PlayerFaceConfig>();
        // 清空 StoreConfig 字典
        ClearConfigDictionary<StoreConfig>();
        // 清空 SuccessConfig 字典
        ClearConfigDictionary<SuccessConfig>();
        // 清空 SysInfoConfig 字典
        ClearConfigDictionary<SysInfoConfig>();
        // 清空 PlayerLVConfig 字典
        ClearConfigDictionary<PlayerLVConfig>();
        // 清空 TitleStarUpConfig 字典
        ClearConfigDictionary<TitleStarUpConfig>();
        // 清空 TreasureSetConfig 字典
        ClearConfigDictionary<TreasureSetConfig>();
        // 清空 TreeLVConfig 字典
        ClearConfigDictionary<TreeLVConfig>();
        // 清空 WindowSearchConfig 字典
        ClearConfigDictionary<WindowSearchConfig>();
        // 清空 XBGetItemConfig 字典
        ClearConfigDictionary<XBGetItemConfig>();
    }
#if UNITY_EDITOR
Main/Config/Configs/DamageNumConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年8月6日
//    [  Date ]:           2025年9月3日
//--------------------------------------------------------
using System.Collections.Generic;
@@ -8,7 +8,7 @@
using UnityEngine;
using LitJson;
public partial class DamageNumConfig : ConfigBase<string, DamageNumConfig>
public partial class DamageNumConfig : ConfigBase<int, DamageNumConfig>
{
    static DamageNumConfig()
    {
@@ -16,15 +16,16 @@
        visit = true; 
    }
    public string id;
    public int TypeID;
    public string id;
    public int prefix;
    public int plus;
    public int minus;
    public int[] nums;
    public override string LoadKey(string _key)
    public override int LoadKey(string _key)
    {
        string key = GetKey(_key);
        int key = GetKey(_key);
        return key;
    }
@@ -32,21 +33,23 @@
    {
        try {
        string[] tables = input.Split('\t');
        id = tables[0];
        int.TryParse(tables[0],out TypeID);
            int.TryParse(tables[1],out prefix);
            id = tables[1];
            int.TryParse(tables[2],out plus);
            int.TryParse(tables[2],out prefix);
            int.TryParse(tables[3],out minus);
            int.TryParse(tables[3],out plus);
            if (tables[4].Contains("["))
            int.TryParse(tables[4],out minus);
            if (tables[5].Contains("["))
            {
                nums = JsonMapper.ToObject<int[]>(tables[4]);
                nums = JsonMapper.ToObject<int[]>(tables[5]);
            }
            else
            {
                string[] numsStringArray = tables[4].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
                string[] numsStringArray = tables[5].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
                nums = new int[numsStringArray.Length];
                for (int i=0;i<numsStringArray.Length;i++)
                {
Main/Config/Configs/EffectConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年8月26日
//    [  Date ]:           2025年9月2日
//--------------------------------------------------------
using System.Collections.Generic;
@@ -30,6 +30,7 @@
    public int frontBack;
    public float delayPlay;
    public int[] effectPos;
    public float effectScale;
    public override int LoadKey(string _key)
    {
@@ -92,6 +93,8 @@
                     int.TryParse(effectPosStringArray[i],out effectPos[i]);
                }
            }
            float.TryParse(tables[14],out effectScale);
        }
        catch (Exception exception)
        {
Main/Config/Configs/SkillConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           Friday, August 29, 2025
//    [  Date ]:           2025年9月2日
//--------------------------------------------------------
using System.Collections.Generic;
@@ -47,8 +47,10 @@
    public int BulletEffectId;
    public int BulletPath;
    public float BulletFlyTime;
    public int Scattering;
    public int ExplosionEffectId;
    public int ExplosionEffect2;
    public int ExplosionEffect3;
    public int EffectId;
    public int EffectId2;
    public int MStartEffectId;
@@ -138,17 +140,21 @@
            float.TryParse(tables[30],out BulletFlyTime); 
            int.TryParse(tables[31],out ExplosionEffectId);
            int.TryParse(tables[31],out Scattering);
            int.TryParse(tables[32],out ExplosionEffect2);
            int.TryParse(tables[32],out ExplosionEffectId);
            int.TryParse(tables[33],out EffectId);
            int.TryParse(tables[33],out ExplosionEffect2);
            int.TryParse(tables[34],out EffectId2);
            int.TryParse(tables[34],out ExplosionEffect3);
            int.TryParse(tables[35],out MStartEffectId);
            int.TryParse(tables[35],out EffectId);
            int.TryParse(tables[36],out TriggerEffect);
            int.TryParse(tables[36],out EffectId2);
            int.TryParse(tables[37],out MStartEffectId);
            int.TryParse(tables[38],out TriggerEffect);
        }
        catch (Exception exception)
        {
Main/Core/NetworkPackage/CustomServerPack/CustomB421ActionPack.cs
@@ -4,15 +4,24 @@
public class CustomB421ActionPack : GameNetPackBasic
{
    public int actionPackId = 0;
    private static int autoincreaseId = 10000;
    public CustomB421ActionPack()
    {
        actionPackId = autoincreaseId++;
    }
    public string guid;
    public Queue<GameNetPackBasic> actionPacks = new Queue<GameNetPackBasic>();
    public static CustomB421ActionPack CreateB421ActionPack(string _guid, List<GameNetPackBasic> packList)
    {
        CustomB421ActionPack actionPack = new CustomB421ActionPack();
        //  合并一下这个角色的行动内容的技能 制作成CustomB421ActionPack
        List<GameNetPackBasic> combinedPackList = CustomHB426CombinePack.CombineToSkillPackFromList(_guid, packList);
        CustomB421ActionPack actionPack = new CustomB421ActionPack();
        actionPack.guid = _guid;
        actionPack.actionPacks = new Queue<GameNetPackBasic>(combinedPackList);
        return actionPack;
@@ -24,16 +33,13 @@
        {
            GameNetPackBasic pack = actionPacks.Dequeue();
            BattleDebug.LogError("CustomB421ActionPack distribute pack " + pack.GetType().Name);
            if (pack is CustomHB426CombinePack)
            if (pack is CustomHB426CombinePack b426Pack)
            {
                var b426Pack = pack as CustomHB426CombinePack;
                b426Pack.Distribute();
            }
            else
            {
                BattleDebug.LogError("distribute pack " + pack.GetType().Name);
                PackageRegedit.Distribute(pack);
            }
        }
Main/Core/NetworkPackage/CustomServerPack/CustomHB426CombinePack.cs
@@ -31,8 +31,6 @@
        }
        endTag = _endTag;
        toIndex = _toIndex;
        packList = CombineToSkillPackFromList(guid, packList);
    }
@@ -74,66 +72,96 @@
        return startTag.Tag == tag.Tag && tag.Sign == 1;
    }
    public static List<GameNetPackBasic> CombineToSkillPackFromList(string _guid, List<GameNetPackBasic> b421SeriesPackList)
    {
        CustomHB426CombinePack combinePack = null;
        Dictionary<string, CustomHB426CombinePack> combineDict = new Dictionary<string, CustomHB426CombinePack>();
        Dictionary<int, GameNetPackBasic> indexDict = new Dictionary<int, GameNetPackBasic>();
        for (int i = 0; i < b421SeriesPackList.Count; i++)
        {
            var pack = b421SeriesPackList[i];
            if (pack is HB426_tagSCTurnFightTag)
            {
                var tag = pack as HB426_tagSCTurnFightTag;
                if (null == combinePack)
                CustomHB426CombinePack combinePack;
                if (!combineDict.TryGetValue(tag.Tag, out combinePack))
                {
                    combinePack = new CustomHB426CombinePack();
                    combinePack.guid = _guid;
                    combineDict.Add(tag.Tag, combinePack);
                    indexDict.Add(i, combinePack);
                }
                if (tag.Sign == 0)
                {
                    combinePack.SetHB426Start(i, tag);
                    continue;
                }
                else
                //  找到对应的开始标签
                if (combinePack.IsEndPack(tag))
                {
                    if (combinePack.IsEndPack(tag))
                    combinePack.SetHB426End(i, tag);
                    continue;
                }
                Debug.LogError("No matching start tag or end tag found: " + tag.Tag);
                continue;
            }
            else
            {
                indexDict.Add(i, pack);
            }
        }
        //  嵌套包内的包合并
        foreach (var combinePack in combineDict.Values)
        {
            for (int i = combinePack.fromIndex + 1; i < combinePack.toIndex; i++)
            {
                if (indexDict.TryGetValue(i, out var pack))
                {
                    if (pack is CustomHB426CombinePack)
                    {
                        combinePack.SetHB426End(i, tag);
                        break;
                        //  如果是嵌套的包 加入之后 调整i
                        combinePack.AddPack(pack);
                        i = (pack as CustomHB426CombinePack).toIndex;
                    }
                    else
                    {
                        combinePack.AddPack(pack);
                        indexDict.Remove(i);
                    }
                }
            }
            if (null != combinePack)
            {
                combinePack.AddPack(pack);
            }
        }
        List<GameNetPackBasic> newPackList = new List<GameNetPackBasic>();
        if (null != combinePack)
        // string temp = string.Empty;
        for (int i = 0; i < b421SeriesPackList.Count; i++)
        {
            //  技能包前面的包(不包括b426的开始标签)
            for (int i = 0; i < combinePack.fromIndex; i++)
            if (indexDict.TryGetValue(i, out var pack))
            {
                newPackList.Add(b421SeriesPackList[i]);
                newPackList.Add(pack);
                if (pack is CustomHB426CombinePack)
                {
                    var cbpack = pack as CustomHB426CombinePack;
                    // temp += "pack type is " + pack.GetType().Name + " tag is " + cbpack.startTag.Tag + "\n";
                }
                else
                {
                    // temp += "pack type is " + pack.GetType().Name + "\n";
                }
            }
            //  把合并的技能包加进来
            newPackList.Add(combinePack);
            //  技能包后面的包(不包括b426的结束标签)
            for (int i = combinePack.toIndex + 1; i < b421SeriesPackList.Count; i++)
            {
                newPackList.Add(b421SeriesPackList[i]);
            }
            return CombineToSkillPackFromList(_guid, newPackList);
        }
        else
        {
            return b421SeriesPackList;
        }
        // Debug.LogError(temp);
        return newPackList;
    }
    public void Distribute()
@@ -151,6 +179,7 @@
        {
            battleField.PlayRecord(skillAction);
        }
    }
    public SkillRecordAction CreateSkillAction()
Main/Core/NetworkPackage/GameNetPackBasic.cs
@@ -21,6 +21,7 @@
        packUID = AutoIncreaseUID++;
    }
    public bool isDistribute = false;
    public ServerType socketType = ServerType.Main; //默认且唯一
Main/System/Battle/BattleEffectMgr.cs
@@ -62,7 +62,6 @@
            effectDict[effectId] = new List<BattleEffectPlayer>();
        }
        BattleDebug.LogError("播放特效 " + effectId);
        BattleEffectPlayer effectPlayer = BattleEffectPlayer.Create(effectId, battleField.battleRootNode.transform);
        // 设置特效缩放和方向
@@ -95,7 +94,7 @@
        }
        else
        {
            BattleDebug.LogError("could not find effect in list, effectid : " + effectId);
            Debug.LogError("could not find effect in list, effectid : " + effectId);
        }
    }
Main/System/Battle/BattleField/BattleField.cs
@@ -153,7 +153,7 @@
        if (operationAgent == null)
        {
            BattleDebug.LogError("you should SetBattleMode before Run");
            Debug.LogError("you should SetBattleMode before Run");
            return;
        }
@@ -185,7 +185,6 @@
                break;
        }
        BattleDebug.LogError("battleMode is " + battleMode.ToString());
    }
    public virtual void AutoSetBattleMode()
@@ -245,6 +244,8 @@
        //  TurnNum;    // 当前轮次
        //  Len;
        //  Msg;    //size = Len   +
        if (State == 4)
        {
            //已经结束并结算
@@ -293,7 +294,7 @@
        if (deadPackList.Count > 0)
        {
            DeathRecordAction recordAction = new DeathRecordAction(this, deadPackList);
            recordPlayer.PlayRecord(recordAction);
            recordPlayer.ImmediatelyPlay(recordAction);
        }
    }
@@ -338,7 +339,7 @@
    {
        if (index < 0 || index >= battleRootNode.redTeamNodeList.Count)
        {
            BattleDebug.LogError($"GetTeamNode: Index {index} is out of range for {battleCamp} camp.");
            Debug.LogError($"GetTeamNode: Index {index} is out of range for {battleCamp} camp.");
            return null;
        }
@@ -413,7 +414,7 @@
        }
        else
        {
            BattleDebug.LogError($"BattleObject with ID {vNetData.ObjID} not found for reborn.");
            Debug.LogError($"BattleObject with ID {vNetData.ObjID} not found for reborn.");
        }
    }
Main/System/Battle/BattleField/OperationAgent/HandModeOperationAgent.cs
@@ -19,8 +19,6 @@
    //    通过主界面的按钮推动(调用)DoNext
    public override void DoNext()
    {
        BattleDebug.LogError("HandModeOperationAgent DoNext");
        base.DoNext();
        storyBattleField.RequestFight();
Main/System/Battle/BattleField/RecordActions/SkillRecordAction.cs
@@ -11,7 +11,6 @@
        : base(RecordActionType.Skill, _battleField, _caster)
    {
        skillBase = SkillFactory.CreateSkill(_caster, vNetData, packList, _battleField);
        BattleDebug.LogError("skill record action tpye : " + skillBase.GetType().Name);
    }
    public override bool IsFinished()
Main/System/Battle/BattleField/StoryBattleField.cs
@@ -194,12 +194,10 @@
        //    当前没有在播放战斗录像
        if (!recordPlayer.IsPlaying())
        {
            BattleDebug.LogError("HandModeOperationAgent DoNext  1");
            // 没有下一个包可以发了
            if (!BattleManager.Instance.DistributeNextPackage())
            {
                BattleDebug.LogError("HandModeOperationAgent DoNext  2");
                //再检查一次有没装备未处理
                if (PackManager.Instance.GetSinglePack(PackType.DropItem).GetItems().Count > 0)
@@ -234,7 +232,6 @@
                // BOSS挑战说明:休息中挑战BOSS恢复到休息状态 不发包;
                //              战斗中挑战BOSS恢复到战斗状态 发4包;服务端挑战boss已经清小怪场
                BattleDebug.LogError("HandModeOperationAgent DoNext  3");
                byte reqType;
                if (battleState == StoryBattleState.Break)
@@ -251,7 +248,6 @@
                    return;
                }
                BattleDebug.LogError("HandModeOperationAgent DoNext  4   reqType is " + reqType);
                //    如果请求的是2 说明要初始化一下战场
Main/System/Battle/BattleManager.cs
@@ -143,14 +143,13 @@
                List<GameNetPackBasic> b421PackList = new List<GameNetPackBasic>();
                i++;    // 跳过当前的B421包
                // 收集所有非B421包,直到遇到下一个B421或队列结束
                for (; i < packQueueSnapshot.Count; i++)
                {
                    GameNetPackBasic nextPack = packQueueSnapshot[i];
                    if (nextPack is HB421_tagMCTurnFightObjAction)
                    {
                        // 遇到了其他B421 启动角色的Action开始,
                        // B421后再碰到B421一定是有一个人的行动结束了 回退一个位置
                        i--;
                        i--; // 回退一个位置,留给外层循环处理
                        break;
                    }
                    else
@@ -160,7 +159,7 @@
                    }
                }
                // 可能没用了 主要就是利用一下skill的combine 暂留 看之后还有没有别的需求
                // 合并所有相关包
                CustomB421ActionPack actionPack = CustomB421ActionPack.CreateB421ActionPack(GetGUID(b421Pack.packUID), b421PackList);
                newPackList.Add(actionPack);
@@ -178,7 +177,7 @@
            Debug.LogWarning($"连续空战斗片段封包次数:{continousEmptyCount}");
            if (continousEmptyCount >= MaxContinousEmptyCount)
            {
                BattleDebug.LogError("连续多次没有战斗片段封包,自动回城休息!");
                Debug.LogError("连续多次没有战斗片段封包,自动回城休息!");
                MainFightRequest(0); // 0-停止战斗回城
                continousEmptyCount = 0;
                packQueue.Clear();
@@ -190,8 +189,9 @@
            continousEmptyCount = 0; // 有包就重置
        }
        // b421跟b426的包已经处理完了
        packQueue = new Queue<GameNetPackBasic>(newPackList);
            packQueue = new Queue<GameNetPackBasic>(newPackList);
        DistributeNextPackage();
    }
@@ -199,42 +199,55 @@
    //  专属于主线战斗的派发
    public bool DistributeNextPackage()
    {
        if (packQueue.Count > 0)
        if (packQueue == null)
        {
            GameNetPackBasic pack = packQueue.Peek();
            bool dequeue = false;
            if (pack is CustomHB426CombinePack)
            {
                CustomHB426CombinePack combinePack = pack as CustomHB426CombinePack;
                packQueue.Dequeue();
                combinePack.Distribute();
            }
            else if (pack is CustomB421ActionPack)
            {
                CustomB421ActionPack actionPack = pack as CustomB421ActionPack;
                dequeue = !actionPack.Distribute();
            }
            else
            {
                BattleDebug.LogError("distribute pack " + pack.GetType().Name);
                packQueue.Dequeue();
                PackageRegedit.Distribute(pack);
            }
            if (dequeue && packQueue.Count > 0)
            {
                packQueue.Dequeue();
            }
            return true;
            Debug.LogWarning("DistributeNextPackage: packQueue为空或已处理完毕");
            return false;
        }
        else
        if (packQueue.Count <= 0)
        {
            return false;
        }
        GameNetPackBasic pack = null;
        try
        {
            pack = packQueue.Dequeue();
        }
        catch (Exception ex)
        {
            Debug.LogError("DistributeNextPackage: Peek异常 " + ex);
            return false;
        }
        try
        {
            if (pack is CustomHB426CombinePack combinePack)
            {
                combinePack.Distribute();
            }
            else if (pack is CustomB421ActionPack actionPack)
            {
                actionPack.Distribute();
            }
            else
            {
                PackageRegedit.Distribute(pack);
            }
        }
        catch (Exception ex)
        {
            Debug.LogError("DistributeNextPackage: 分发包异常 " + ex);
            // 出错时主动移除当前包,防止死循环
            if (packQueue.Count > 0)
            {
                packQueue.Dequeue();
            }
            return false;
        }
        return packQueue.Count > 0;
    }
    public void OnConnected()
@@ -314,7 +327,6 @@
        }
        var pack = queue.Dequeue();
        BattleDebug.LogError("distribute pack " + pack.GetType().Name);
        PackageRegedit.Distribute(pack);
@@ -324,7 +336,6 @@
            battlePackRelationList.Remove(guid);
        }
        BattleDebug.LogError("BattlePackage count is " + queue.Count);
    }
    #endregion
Main/System/Battle/BattleObject/BattleObject.cs
@@ -151,7 +151,7 @@
                teamHero.rage = (int)GeneralDefine.GetFactValue(_refreshInfo.Value, _refreshInfo.ValueEx);
                break;
            default:
                BattleDebug.LogError("BattleObject.ObjInfoRefresh 出现意外类型 " + _refreshInfo.RefreshType.ToString());
                Debug.LogError("BattleObject.ObjInfoRefresh 出现意外类型 " + _refreshInfo.RefreshType.ToString());
                break;
        }
    }
@@ -239,23 +239,22 @@
        return true;
    }
    public virtual void Hurt(List<long> damageValues, long _totalDamage, uint attackType)
    public virtual void Hurt(List<long> damageValues, long _totalDamage, HB427_tagSCUseSkill.tagSCUseSkillHurt hurt, SkillConfig skillConfig)
    {
        PopDamage(teamHero.curHp, damageValues, attackType);
        PopDamage(damageValues, hurt, skillConfig);
        motionBase.PlayAnimation(MotionName.hit, false);
        //  扣血
        //  扣血流给别的敌方刷新好了
        teamHero.curHp -= _totalDamage;
    }
    }
    public void SuckHp(uint suckHP)
    public void SuckHp(uint suckHP, SkillConfig skillConfig)
    {
    }
    public void HurtByReflect(uint bounceHP)
    public void HurtByReflect(uint bounceHP, SkillConfig skillConfig)
    {
        
    }
@@ -285,14 +284,13 @@
    public virtual void OnDeath(Action _onDeathAnimationComplete)
    {
        BattleDebug.LogError(ObjID + " OnDeath called");
        onDeathAnimationComplete = _onDeathAnimationComplete;
        motionBase.PlayAnimation(MotionName.dead, false);
    }
    protected virtual void OnAnimationComplete(MotionName motionName)
    protected virtual void OnAnimationComplete(string motionName)
    {
        if (motionName == MotionName.dead)
        if (motionName == MotionName.dead.ToString().ToLower())
        {
            OnDeadAnimationComplete();
            onDeathAnimationComplete?.Invoke();
@@ -315,18 +313,9 @@
    }
    // 伤害还要看 是否闪避 暴击 and so on 需要有一个DamageType 服务器应该会给
    protected virtual void PopDamage(long curHp, List<long> damageValues, uint attackType)
    protected virtual void PopDamage(List<long> damageValues, HB427_tagSCUseSkill.tagSCUseSkillHurt hurt, SkillConfig skillConfig)
    {
        //  其实应该通知出去给UI界面解耦 让UI界面自己来显示的 YYL TODO
        //  播放伤害数字
        //  这里可以实现一个伤害数字的弹出效果
        //  比如使用一个UI组件来显示伤害数字
        foreach (var damage in damageValues)
        {
            Debug.Log($"Damage: {damage}");
        }
        BattleDmgInfo battleDmgInfo = new BattleDmgInfo(battleField.guid, damageValues, this, (int)attackType);
        BattleDmgInfo battleDmgInfo = new BattleDmgInfo(battleField.guid, damageValues, this, hurt, skillConfig);
        // YYL TODO 是否需要挂在在自身的follow点上
        EventBroadcast.Instance.Broadcast(EventName.BATTLE_DAMAGE_TAKEN, battleDmgInfo);
Main/System/Battle/BattleObject/BattleObjectFactory.cs
@@ -17,19 +17,13 @@
        HeroSkinConfig skinCfg = teamHero.skinConfig;
        if (skinCfg == null)
        {
            BattleDebug.LogError(teamHero.heroId + "BattleObjectFactory.CreateBattleObject: skinCfg is null for " + teamHero.SkinID);
            Debug.LogError(teamHero.heroId + "BattleObjectFactory.CreateBattleObject: skinCfg is null for " + teamHero.SkinID);
            return null;
        }
        GameObject battleGO = ResManager.Instance.LoadAsset<GameObject>("Hero/SpineRes", "Hero_001"/*skinCfg.SpineRes*/);
        if (battleGO == null)
        {
            BattleDebug.LogError("BattleObjectFactory.CreateBattleObject: battleGO is null for " + teamHero.heroId);
            return null;
        }
        BattleDebug.LogError("1 BattleObjectFactory.CreateBattleObject: Creating BattleObject for " + teamHero.ObjID + " at position " + teamHero.positionNum);
        GameObject goParent = posNodeList[teamHero.positionNum];
        BattleObject battleObject = new BattleObject(_battleField);
@@ -41,11 +35,10 @@
        var skeletonDataAsset = ResManager.Instance.LoadAsset<SkeletonDataAsset>("Hero/SpineRes/", skinCfg.SpineRes);
        if (skeletonDataAsset == null)
        {
            BattleDebug.LogError("BattleObjectFactory.CreateBattleObject: skeletonDataAsset is null for " + skinCfg.SpineRes);
            Debug.LogError("BattleObjectFactory.CreateBattleObject: skeletonDataAsset is null for " + skinCfg.SpineRes);
            return null;
        }
        BattleDebug.LogError("2 BattleObjectFactory.CreateBattleObject: Creating BattleObject for " + teamHero.ObjID + " at position " + teamHero.positionNum);
        float finalScaleRate = modelScaleRate * teamHero.modelScale;
@@ -57,15 +50,12 @@
        rectTrans.anchoredPosition = Vector2.zero;
        battleObject.Init(realGO, teamHero, _Camp);
        BattleDebug.LogError(realGO.name +  " /3 BattleObjectFactory.CreateBattleObject: Creating BattleObject for " + teamHero.ObjID + " at position " + teamHero.positionNum);
        return battleObject;
    }
    public static void DestroyBattleObject(int key, BattleObject battleObj)
    {
        BattleDebug.LogError("BattleObject destroy");
        battleObj.Destroy();
        battleObj = null;
    }
Main/System/Battle/BattleUtility.cs
@@ -4,7 +4,7 @@
using UnityEngine.UI;
using DG.Tweening;
using DG.Tweening.Core;
using System.Linq;
public static class BattleUtility
{
@@ -23,7 +23,7 @@
        var battleField = BattleManager.Instance.storyBattleField;
        if (battleField == null)
        {
            BattleDebug.LogError("BattleManager.storyBattleField 未初始化!");
            Debug.LogError("BattleManager.storyBattleField 未初始化!");
            return;
        }
@@ -119,11 +119,40 @@
    public static string DisplayDamageNum(long num, int attackType)
    {
        // 服务器位数到客户端类型ID的映射
        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 basePowerStr = UIHelper.ReplaceLargeArtNum(num);
        var result = string.Empty;
        for (int i = 0; i < basePowerStr.Length; i++)
        {
            var numChar = (char)GetDamageNumKey((DamageType)attackType, basePowerStr[i]);
            var numChar = (char)GetDamageNumKey(config, basePowerStr[i]);
            if (numChar > 0)
            {
                result += numChar;
@@ -132,34 +161,96 @@
        return result;
    }
    public static int GetDamageNumKey(DamageType damageType, int _num)
    public static int GetMainTargetPositionNum(BattleObject caster, List<HB427_tagSCUseSkill.tagSCUseSkillHurt> targetList, SkillConfig skillConfig)
    {
        var config = DamageNumConfig.Get(damageType.ToString());
        //.的ASCII码是46
        if (_num == 46)
        int returnIndex = 0;
        //  根据敌方血量阵营 存活人数来选择
        BattleCamp battleCamp = skillConfig.TagFriendly != 0 ? caster.Camp : caster.GetEnemyCamp();
        List<BattleObject> targetObjList = caster.battleField.battleObjMgr.GetBattleObjList(battleCamp);
        // 瞄准的目标范围,如果目标个数为0则为范围内全部
        // 0    全部范围
        // 1    对位,默认只选1个
        // 2    前排
        // 3    后排
        // 4    纵排,按对位规则选择纵排
        // 5    自己,默认只选自己
        // 6    继承主技能/来源技能目标
        //      一般是额外触发的技能使用,如概率附加某buff
        //      额外触发的技能如果目标与主技能不一致,则重新设定目标即可
        //      或被动触发的技能,可继承触发来源技能的攻防双方关系
        switch (skillConfig.TagAim)
        {
            return config.nums[10];
            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)
                {
                    returnIndex = opposite[0].teamHero.positionNum;
                }
                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;
                }
                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)
                {
                    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)
                {
                    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
                break;
            // 5    自己,默认只选自己
            case 5:
                returnIndex = caster.teamHero.positionNum;
                break;
            default:
                break;
        }
        //k的ASCII码是107
        else if (_num == 107)
        {
            return config.nums[11];
        }
        //m的ASCII码是109
        else if (_num == 109)
        {
            return config.nums[12];
        }
        //b的ASCII码是98
        else if (_num == 98)
        {
            return config.nums[13];
        }
        //t的ASCII码是116
        else if (_num == 116)
        {
            return config.nums[14];
        }
        return returnIndex;
    }
    public static int GetDamageNumKey(DamageNumConfig config, int _num)
    {
        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 == 116) return config.nums[14]; // 't'
        return config.nums[_num - 48];
    }
Main/System/Battle/Define/BattleDmgInfo.cs
@@ -1,21 +1,125 @@
using System.Collections.Generic;
public class BattleDmg
{
    public long damage;
    public int attackType;
}
public class BattleDmgInfo
{
    public string battleFieldGuid { get; private set; }
    public List<long> damageList { get; private set; }
    public int attackType { get; private set; }
    public BattleObject hurtObj { get; private set; }
    public BattleDmgInfo(string battleFieldGuid, List<long> damageList, BattleObject hurtObj, int attackType)
    public HB427_tagSCUseSkill.tagSCUseSkillHurt hurt { get; private set; }
    public SkillConfig skillConfig { get; private set; }
    //  是否被格挡了
    public bool isBlocked = false;
    public List<BattleDmg> battleDamageList = new List<BattleDmg>();
    public BattleDmgInfo(string battleFieldGuid, List<long> damageList, BattleObject hurtObj, HB427_tagSCUseSkill.tagSCUseSkillHurt hurt, SkillConfig skillConfig)
    {
        this.battleFieldGuid = battleFieldGuid;
        this.damageList = damageList;
        this.hurtObj = hurtObj;
        this.attackType = attackType;
        this.hurt = hurt;
        this.skillConfig = skillConfig;
        HandleAttackTypeAndDamage();
    }
    private void HandleAttackTypeAndDamage()
    {
        isBlocked = HaveBlockDamage();
        int rawAttackType = (int)hurt.AttackTypes;
        float blockRatio = float.Parse(GeneralDefine.parryCfg.Numerical3); // 格挡减伤率
        for (int i = 0; i < damageList.Count; i++)
        {
            long actualDamage = damageList[i];
            // 格挡处理
            if (isBlocked)
            {
                // 去掉格挡类型
                int attackType = rawAttackType & (~(int)DamageType.Block);
                // 计算格挡伤害
                long totalDamage = (long)(actualDamage / (1 - blockRatio));
                long blockDmg = totalDamage - actualDamage;
                battleDamageList.Add(new BattleDmg { damage = blockDmg, attackType = (int)DamageType.Block });
                // 真实伤害特殊处理
                if (IsRealdamage())
                {
                    int showAttackType = (int)DamageType.Realdamage + (IsCrit() ? (int)DamageType.Crit : 0);
                    battleDamageList.Add(new BattleDmg { damage = actualDamage, attackType = showAttackType });
                    continue;
                }
                // 普通伤害/治疗处理
                if (DamageNumConfig.Get(attackType) == null)
                {
                    UnityEngine.Debug.LogError($"服务器给的伤害类型不对,强制转换为普通伤害/治疗, attackType: {attackType}");
                    if ((attackType & (int)DamageType.Damage) != 0)
                        attackType = (int)DamageType.Damage;
                    else if ((attackType & (int)DamageType.Recovery) != 0)
                        attackType = (int)DamageType.Recovery;
                    else
                        UnityEngine.Debug.LogError($"强制转换失败,该类型不是治疗也不是伤害 {attackType}");
                }
                battleDamageList.Add(new BattleDmg { damage = actualDamage, attackType = attackType });
            }
            else
            {
                int attackType = rawAttackType;
                // 真实伤害特殊处理
                if (IsRealdamage())
                {
                    int showAttackType = (int)DamageType.Realdamage + (IsCrit() ? (int)DamageType.Crit : 0);
                    battleDamageList.Add(new BattleDmg { damage = actualDamage, attackType = showAttackType });
                    continue;
                }
                // 普通伤害/治疗处理
                if (DamageNumConfig.Get(attackType) == null)
                {
                    UnityEngine.Debug.LogError($"服务器给的伤害类型不对,强制转换为普通伤害/治疗, attackType: {attackType}");
                    if ((attackType & (int)DamageType.Damage) != 0)
                        attackType = (int)DamageType.Damage;
                    else if ((attackType & (int)DamageType.Recovery) != 0)
                        attackType = (int)DamageType.Recovery;
                    else
                        UnityEngine.Debug.LogError($"强制转换失败,该类型不是治疗也不是伤害 {attackType}");
                }
                battleDamageList.Add(new BattleDmg { damage = actualDamage, attackType = attackType });
            }
        }
    }
    public bool IsType(DamageType damageType)
    {
        return (hurt.AttackTypes & (int)damageType) == (int)damageType;
    }
    public bool IsCrit()
    {
        return IsType(DamageType.Crit);
    }
    public bool HaveBlockDamage()
    {
        return IsType(DamageType.Block);
    }
    public bool IsRealdamage()
    {
        return skillConfig.HurtType / 10 == 1;
    }
}
Main/System/Battle/Define/DamageType.cs
@@ -3,16 +3,30 @@
public enum DamageType
{
    Damage, //普通伤害
    Recovery,   //治疗
    Reflect, //反弹伤害
    Bloody, //流血伤害
    Block, //格挡
    Critical, //暴击
    Dodge, //闪避
    Combo, //连击
    CounterAttack, //反击
    RageUp, //怒气提升
    Damage = 1, //普通伤害
}
    Recovery = 2, //治疗
    Reflect = 4, //反弹伤害
    Bloody = 8, //流血伤害
    Block = 16, //格挡
    Crit = 32, //暴击
    Dodge = 64, //闪避
    RageUp = 128, //怒气提升
    SuckHP = 256, //吸血
    Realdamage = 512, //真伤
    CritDamage = Crit + Damage, //暴击伤害
    CritHeal = Crit + Recovery, //暴击回血
    CritRealdamage = Crit + Realdamage, //暴击真伤
}
Main/System/Battle/Motion/MotionBase.cs
@@ -14,9 +14,9 @@
    public static List<string> AttackMotionList = new List<string>
    {
        MotionName.attack.ToString(),
        MotionName.angerSkill.ToString(),
        MotionName.passiveSkill.ToString(),
        MotionName.attack.ToString().ToLower(),
        MotionName.angerSkill.ToString().ToLower(),
        MotionName.passiveSkill.ToString().ToLower(),
    };
    private Dictionary<Spine.TrackEntry, Action> trackEntryCompleteDict = new Dictionary<Spine.TrackEntry, Action>();
@@ -24,7 +24,7 @@
    // 动画事件
    public Action OnAttackAnimationComplete;
    public Action OnHitAnimationComplete;
    public Action<MotionName> onAnimationComplete;
    public Action<string> onAnimationComplete;
    #region 组件引用
    
@@ -147,8 +147,24 @@
            return null;
        }
        // 获取动画
        Spine.Animation anim = skeleton.Data.FindAnimation(skillConfig.SkillMotionName);
        if (null == anim)
        {
            for (int i = 0; i < skeleton.Data.Animations.Count; i++)
            {
                var skeletonAnim = skeleton.Data.Animations.Items[i];
                if (skeletonAnim.Name.ToLower() == skillConfig.SkillMotionName.ToLower())
                {
                    anim = skeletonAnim;
                    // 找到动画
                    break;
                }
            }
        }
        // 获取动画
        if (anim == null)
        {
            BattleDebug.LogError($"找不到动画: {skillConfig.SkillMotionName}");
@@ -288,7 +304,7 @@
    /// </summary>
    protected virtual void OnAnimationComplete(Spine.TrackEntry trackEntry)
    {
        string animation = trackEntry.Animation.Name;
        string animation = trackEntry.Animation.Name.ToLower();
        // 攻击动画完成后恢复到待机状态
        if (AttackMotionList.Contains(animation))
@@ -297,12 +313,13 @@
            PlayAnimation(MotionName.idle, true);
        }
        // 受伤动画完成后恢复到待机状态 可能触发多次 因为有多段攻击的存在
        else if (animation == MotionName.hit.ToString())
        else if (animation == MotionName.hit.ToString().ToLower())
        {
            OnHitAnimationComplete?.Invoke();
            PlayAnimation(MotionName.idle, true);
        }
        onAnimationComplete?.Invoke((MotionName)Enum.Parse(typeof(MotionName), animation));
        onAnimationComplete?.Invoke(animation);
        
        // 只调用本次TrackEntry的回调
        if (trackEntryCompleteDict.TryGetValue(trackEntry, out var cb))
@@ -312,51 +329,6 @@
        }
    }
    public void Test(string animationName, int beginFrame, int activeFrame, int endFrame, int activeFrameLoopCount)
    {
        // 要处理前摇beginFrame 后摇endFrame 中摇activeFrame
        // 中摇是有多次的activeFrameLoopCount
        var state = spineAnimationState;
        var anim = skeleton.Data.FindAnimation(animationName);
        // 设定你要循环的区间(单位:秒)
        float loopStart = 0.5f;
        float loopEnd = 1.2f;
        // 播放动画
        state.SetAnimation(0, anim, true);
        // state.GetCurrent(0).TrackTime = loopStart;
        int curFrame = 0;
        skeletonGraphic.UpdateLocal += (skeletonAnim) =>
        {
            // if (curFrame == beginFrame)
            // {
            //     OnBeginFrame?.Invoke();
            // }
            // else if (curFrame == activeFrame)
            // {
            //     OnActiveFrame?.Invoke();
            // }
            // else if (curFrame == endFrame)
            // {
            //     OnEndFrame?.Invoke();
            // }
            // var trackEntry = state.GetCurrent(0);
            // if (trackEntry != null && trackEntry.Animation == anim)
            // {
            //     if (trackEntry.TrackTime > loopEnd)
            //     {
            //         // 回到loopStart,实现区间循环
            //         trackEntry.TrackTime = loopStart;
            //     }
            // }
        };
    }
    public virtual void Run()
Main/System/Battle/RecordPlayer/RecordPlayer.cs
@@ -9,6 +9,8 @@
    private Queue<RecordAction> recordActionQueue = new Queue<RecordAction>();
    protected RecordAction currentRecordAction;
    protected List<RecordAction> immediatelyActionList = new List<RecordAction>();
    private bool isWaitingNextAction = false;
    private float waitTimer = 0f;
    private const float waitInterval = 0.2f;
@@ -20,7 +22,7 @@
    public bool IsPlaying()
    {
        return currentRecordAction != null || recordActionQueue.Count > 0;
        return currentRecordAction != null || recordActionQueue.Count > 0 || immediatelyActionList.Count > 0;
    }
    public void PlayRecord(RecordAction recordAction)
@@ -37,8 +39,60 @@
        }
    }
    public void InsertRecord(RecordAction recordAction)
    {
        BattleDebug.LogError("Insert record action " + recordAction.GetType());
        if (currentRecordAction != null)
        {
            Queue<RecordAction> tempQueue = new Queue<RecordAction>();
            tempQueue.Enqueue(recordAction);
            while (recordActionQueue.Count > 0)
            {
                tempQueue.Enqueue(recordActionQueue.Dequeue());
            }
            recordActionQueue = tempQueue;
        }
        else
        {
            recordActionQueue.Enqueue(recordAction);
        }
    }
    public void ImmediatelyPlay(RecordAction recordAction)
    {
        immediatelyActionList.Add(recordAction);
    }
    protected void ImmediatelyPlayRun()
    {
        if (immediatelyActionList.Count > 0)
        {
            List<int> removeIndexList = new List<int>();
            for (int i = immediatelyActionList.Count - 1; i >= 0; i--)
            {
                var action = immediatelyActionList[i];
                if (action.IsFinished())
                {
                    removeIndexList.Add(i);
                }
                else
                {
                    action.Run();
                }
            }
            for (int i = removeIndexList.Count - 1; i >= 0; i--)
            {
                immediatelyActionList.RemoveAt(removeIndexList[i]);
            }
        }
    }
    public virtual void Run()
    {
        ImmediatelyPlayRun();
        // 等待下一个action
        if (isWaitingNextAction)
        {
Main/System/Battle/Skill/DirectlyDamageSkill.cs
@@ -12,10 +12,7 @@
            HB427_tagSCUseSkill _vNetData, List<GameNetPackBasic> _packList, BattleField _battleField)
            : base(_caster, _skillCfg, _vNetData, _packList, _battleField)
    {
        foreach (var pack in packList)
        {
            BattleDebug.LogError("directly damage skill pack type is " + pack.GetType());
        }
    }
    protected override void OnHitTargets(int _hitIndex, List<HB427_tagSCUseSkill.tagSCUseSkillHurt> hitList)
Main/System/Battle/Skill/DirectlyHealSkill.cs
@@ -12,10 +12,7 @@
            HB427_tagSCUseSkill _vNetData, List<GameNetPackBasic> _packList, BattleField _battleField)
            : base(_caster, _skillCfg, _vNetData, _packList, _battleField)
    {
        foreach (var pack in packList)
        {
            BattleDebug.LogError("directly heal skill pack type is " + pack.GetType());
        }
    }
    public override void Run()
Main/System/Battle/Skill/SkillBase.cs
@@ -39,6 +39,8 @@
    protected List<HB405_tagMCAddExp> expPackList = new List<HB405_tagMCAddExp>();
    protected bool moveFinished = false;
    public SkillBase(BattleObject _caster, SkillConfig _skillCfg, HB427_tagSCUseSkill vNetData, List<GameNetPackBasic> _packList, BattleField _battleField = null)
    {
        caster = _caster;
@@ -46,6 +48,8 @@
        tagUseSkillAttack = vNetData;
        battleField = _battleField;
        packList = _packList;
    }
@@ -95,12 +99,10 @@
    {
        EventBroadcast.Instance.Broadcast<string, SkillConfig, TeamHero>(EventName.BATTLE_CAST_SKILL, battleField.guid, skillConfig, caster.teamHero);
        BattleDebug.LogError(GetType().Name + " Skill Cast Start");
        //    高亮所有本次技能相关的目标
        HighLightAllTargets();
        //    距离配成负数要转身 TurnBack
        BattleDebug.LogError(GetType().Name + " Skill CastMode : " + skillConfig.castMode);
        switch (skillConfig.castMode)
        {
            case SkillCastMode.Self:
@@ -119,15 +121,15 @@
            //     DashToTarget(() => BackToOrigin(OnSkillFinished));
            //     break;
            default:
                BattleDebug.LogError("暂时不支持其他的方式释放 有需求请联系策划 技能id:" + skillConfig.SkillID + " cast position " + skillConfig.CastPosition);
                Debug.LogError("暂时不支持其他的方式释放 有需求请联系策划 技能id:" + skillConfig.SkillID + " cast position " + skillConfig.CastPosition);
                OnSkillFinished();
                break;
        }
    }
    protected void MoveToTarget(RectTransform target, Vector2 offset, float duration, Action onComplete = null)
    {
        BattleDebug.LogError("Move to target , target is " + target.name);
        //    原地释放
        if (skillConfig.CastDistance >= 9999)
        {
@@ -193,7 +195,7 @@
        // 目标是敌方主目标
        if (tagUseSkillAttack.HurtCount <= 0)
        {
            BattleDebug.LogError("技能攻击包没有目标 HurtCount <= 0");
            Debug.LogError("技能攻击包没有目标 HurtCount <= 0");
            OnSkillFinished();
            return;
        }
@@ -203,7 +205,7 @@
        BattleObject mainTarget = battleField.battleObjMgr.GetBattleObject((int)mainHurt.ObjID);
        if (mainTarget == null)
        {
            BattleDebug.LogError("目标为空 mainTarget == null ObjID : " + mainHurt.ObjID);
            Debug.LogError("目标为空 mainTarget == null ObjID : " + mainHurt.ObjID);
            OnSkillFinished();
            return;
        }
@@ -235,7 +237,7 @@
    protected virtual void OnAllAttackMoveFinished()
    {
        moveFinished = true;
    }
    protected void CastToAllies()
@@ -285,7 +287,7 @@
    }
    //    技能开始
    public virtual void OnSkillStart()
    public void OnSkillStart()
    {
        skillEffect = SkillEffectFactory.CreateSkillEffect(
                caster,
@@ -296,6 +298,9 @@
        {
            skillEffect.Play(OnHitTargets);
        }
    }
    //    技能前摇帧结束
@@ -310,12 +315,18 @@
    /// <param name="times"></param>
    public virtual void OnMiddleFrameStart(int times)
    {
        skillEffect.OnMiddleFrameStart(times);
        if (skillEffect != null)
        {
            skillEffect.OnMiddleFrameStart(times);
        }
    }
    public virtual void OnMiddleFrameEnd(int times, int hitIndex)
    {
        skillEffect.OnMiddleFrameEnd(times, hitIndex);
        if (skillEffect != null)
        {
            skillEffect.OnMiddleFrameEnd(times, hitIndex);
        }
    }
    /// <summary>
@@ -358,13 +369,12 @@
            BattleObject target = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID);
            if (target == null)
            {
                BattleDebug.LogError("目标为空 target == null ObjId : " + hurt.ObjID);
                Debug.LogError("目标为空 target == null ObjId : " + hurt.ObjID);
                continue;
            }
            OnHitEachTarget(_hitIndex, target, hurt);
        }
        HandleDead();
    }
@@ -389,11 +399,11 @@
        //    TODO YYL AttackTypes  要表现成什么样呢? 支持多种类型并存,如无视防御且暴击同时被格挡,二进制或运算最终值;0-失败;1-普通;2-回血;5-格挡;6-无视防御;7-暴击;9-闪避
        target.Hurt(damageList, totalDamage, hurt.AttackTypes);
        target.Hurt(damageList, totalDamage, hurt, skillConfig);
        //    TODO YYL 这里是要做统一计算后再hurt跟suckhp还是怎样
        // caster.SuckHp(hurt.SuckHP);//    吸血
        // caster.HurtByReflect(hurt.BounceHP);// 反弹伤害
        caster.SuckHp(hurt.SuckHP, skillConfig);//    吸血
        caster.HurtByReflect(hurt.BounceHP, skillConfig);// 反弹伤害
    }
@@ -413,7 +423,6 @@
        // 处理掉落包 提前distribute之后 PackManager才有掉落物 所以不跟assignexp一样distribute
        foreach (var _dropPack in dropPackList)
        {
            BattleDebug.LogError("distribute pack " + _dropPack.GetType().Name);
            PackageRegedit.Distribute(_dropPack);
            packList.Remove(_dropPack);
        }
@@ -456,8 +465,6 @@
            packList.Remove(deadPack);
        }
        deadPackList.Clear();
    }
@@ -575,7 +582,7 @@
            }
        }
        return isFinished;
        return isFinished && moveFinished;
    }
    public virtual void ForceFinished()
@@ -593,7 +600,6 @@
            }
        }
        BattleDebug.LogError(GetType().Name + " Skill Finished");
        while (packList.Count > 0)
        {
            var pack = packList[0];
@@ -604,11 +610,11 @@
                var combinePack = pack as CustomHB426CombinePack;
                if (combinePack.startTag.Tag.StartsWith("Skill_"))
                {
                    BattleDebug.LogError("other skill casting " + combinePack.startTag.Tag);
                    otherSkillAction = combinePack.CreateSkillAction();
                    return;
                }
            }
            BattleDebug.LogError("distribute pack " + pack.GetType().Name);
            PackageRegedit.Distribute(pack);
        }
Main/System/Battle/Skill/SkillFactory.cs
@@ -53,9 +53,6 @@
            return null;
        }
        Debug.LogError("skill type is " + skillConfig.SkillType + " skill id is " + vNetData.SkillID);
        SkillBase skill = null;
        switch (skillConfig.SkillType)
        {
Main/System/Battle/SkillEffect/BulletCurve/BounceBulletCurve.cs
@@ -67,7 +67,7 @@
            }
            else
            {
                BattleDebug.LogError("弹射找不到下一个目标");
                Debug.LogError("弹射找不到下一个目标");
                // 如果目标丢失,直接用上一个end
                end = start;
            }
Main/System/Battle/SkillEffect/BulletCurve/StraightBulletCurve.cs
@@ -10,7 +10,7 @@
    public StraightBulletCurve(BattleObject caster, SkillConfig skillConfig, BattleEffectPlayer bulletEffect, RectTransform target, HB427_tagSCUseSkill tagUseSkillAttack, Action<int, List<HB427_tagSCUseSkill.tagSCUseSkillHurt>> onHit)
        : base(caster, skillConfig, bulletEffect, target, tagUseSkillAttack, onHit)
    { 
        BattleDebug.LogError("StraightBulletCurve created bulletTrans is null = " + (bulletTrans == null).ToString());
    }
    public override void Reset()
@@ -28,18 +28,23 @@
        if (bulletTrans == null)
        {
            BattleDebug.LogError("BulletTrans is null, cannot run StraightBulletCurve");
            return;
            Debug.LogError("BulletTrans is null, cannot run StraightBulletCurve");
        }
        elapsed += Time.deltaTime;
        float t = Mathf.Clamp01(elapsed / duration);
        Vector2 pos = Vector2.Lerp(start, end, t);
        bulletTrans.anchoredPosition = pos;
        if (null != bulletTrans)
        {
            bulletTrans.anchoredPosition = pos;
        }
        Vector2 dir = end - start;
        float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
        bulletTrans.localRotation = Quaternion.Euler(0, bulletTrans.transform.localScale.x < 0f ? 180 : 0, angle);
        if (null != bulletTrans)
        {
            bulletTrans.localRotation = Quaternion.Euler(0, bulletTrans.transform.localScale.x < 0f ? 180 : 0, angle);
        }
        // if (bulletTrans.transform.localScale.x < 0f)
        // {
        //     bulletTrans.transform.localRotation *= Quaternion.Euler(0, 180, 0);
Main/System/Battle/SkillEffect/BulletSkillEffect.cs
@@ -30,7 +30,7 @@
            BattleObject targetObject = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID);
            if (targetObject == null)
            {
                BattleDebug.LogError("目标为空 target == null ObjId : " + hurt.ObjID);
                Debug.LogError("目标为空 target == null ObjId : " + hurt.ObjID);
                return;
            }
            ShotToTarget(targetObject);
@@ -38,43 +38,85 @@
        //  普通的做法 区分打向阵营或者打向个体
        else
        {
            Action<int, List<HB427_tagSCUseSkill.tagSCUseSkillHurt>> onHitFormation = (_hitIndex, _hurtList) =>
            {
                onHit?.Invoke(_hitIndex, tagUseSkillAttack.HurtList.ToList());
            };
            switch (skillConfig.castMode)
            {
                case SkillCastMode.Self:
                    onHitFormation?.Invoke(0, tagUseSkillAttack.HurtList.ToList());
                    BattleDebug.LogError("子弹的目标是自己,暂时不支持 协商程序完成");
                    break;
                case SkillCastMode.Enemy:
                    var targetNode = caster.battleField.GetTeamNode(caster.GetEnemyCamp(), skillConfig);
                    ShotToFormation(targetNode, onHitFormation);
                    break;
                case SkillCastMode.Target:
                    for (int i = 0; i < tagUseSkillAttack.HurtList.Length; i++)
                    {
                        var hurt = tagUseSkillAttack.HurtList[i];
                        BattleObject target = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID);
                        if (target == null)
                        {
                            BattleDebug.LogError("特效目标为空 target == null ObjId : " + hurt.ObjID);
                            continue;
                        }
            //  区分散射跟范围攻击
                        ShotToTarget(target);
            if (skillConfig.Scattering == 1)
            {
                //  散射
                for (int i = 0; i < tagUseSkillAttack.HurtList.Length; i++)
                {
                    var hurt = tagUseSkillAttack.HurtList[i];
                    BattleObject target = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID);
                    if (target == null)
                    {
                        Debug.LogError("特效目标为空 target == null ObjId : " + hurt.ObjID);
                        continue;
                    }
                    break;
                case SkillCastMode.Allies:
                    var healNode = caster.battleField.GetTeamNode(caster.Camp, skillConfig);
                    ShotToFormation(healNode, onHitFormation);
                    break;
                default:
                    BattleDebug.LogError("暂时不支持其他的方式释放 有需求请联系程序 " + skillConfig.SkillID);
                    break;
                    ShotToTarget(target);
                }
            }
            else
            {
                //  范围攻击
                //  攻击向关键位置 然后所有人受伤
                int mainTargetIndex = BattleUtility.GetMainTargetPositionNum(caster, tagUseSkillAttack.HurtList.ToList(), skillConfig);
                BattleCamp battleCamp = skillConfig.TagFriendly != 0 ? caster.Camp : caster.GetEnemyCamp();
                RectTransform rectTarget = caster.battleField.GetTeamNode(battleCamp, mainTargetIndex);
                Action<int, List<HB427_tagSCUseSkill.tagSCUseSkillHurt>> onHitFormation = (_hitIndex, _hurtList) =>
                {
                    onHit?.Invoke(_hitIndex, tagUseSkillAttack.HurtList.ToList());
                };
                if (skillConfig.TagCount >= 6)
                {
                    ShotToFormation(rectTarget, onHitFormation);
                }
                else
                {
                    ShotToFormationEx(rectTarget, onHitFormation);
                }
            }
        }
    }
    private void ShotToFormationEx(RectTransform target, Action<int, List<HB427_tagSCUseSkill.tagSCUseSkillHurt>> _onHit)
    {
        BattleEffectPlayer effectPlayer = caster.battleField.battleEffectMgr.PlayEffect(caster.ObjID, skillConfig.BulletEffectId, caster.heroRectTrans, caster.Camp);
        RectTransform effectTrans = effectPlayer.transform as RectTransform;
        var bulletCurve = BulletCurveFactory.CreateBulletCurve(caster, skillConfig, effectPlayer, target, tagUseSkillAttack, (index, hitList) =>
        {
            // 击中就销毁子弹
            caster.battleField.battleEffectMgr.RemoveEffect(skillConfig.BulletEffectId, effectPlayer);
            // 播放子弹爆炸特效
            BattleCamp battleCamp = skillConfig.TagFriendly != 0 ? caster.Camp : caster.GetEnemyCamp();
            foreach (var hurt in hitList)
            {
                BattleObject targetObj = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID);
                if (targetObj == null)
                {
                    Debug.LogError("目标为空 target == null ObjId : " + hurt.ObjID);
                    continue;
                }
                PlayExplosionEffect(skillConfig.ExplosionEffectId, targetObj.heroGo.transform, targetObj.Camp);
                PlayExplosionEffect(skillConfig.ExplosionEffect2, targetObj.heroGo.transform, targetObj.Camp);
                PlayExplosionEffect(skillConfig.ExplosionEffect3, targetObj.heroGo.transform, targetObj.Camp);
            }
            // 表现子弹飞行到目标位置
            _onHit?.Invoke(index, hitList);
            isFinish = true;
        });
        bulletCurves.Add(bulletCurve);
    }
    protected void ShotToFormation(RectTransform target, Action<int, List<HB427_tagSCUseSkill.tagSCUseSkillHurt>> _onHit)
@@ -85,34 +127,31 @@
        var bulletCurve = BulletCurveFactory.CreateBulletCurve(caster, skillConfig, effectPlayer, target, tagUseSkillAttack, (index, hitList) =>
        {
            // 表现子弹飞行到目标位置
            _onHit?.Invoke(index, hitList);
            // 击中就销毁子弹
            caster.battleField.battleEffectMgr.RemoveEffect(skillConfig.BulletEffectId, effectPlayer);
            // 播放子弹爆炸特效
            BattleCamp battleCamp = skillConfig.TagFriendly != 0 ? caster.Camp : caster.GetEnemyCamp();
            //  首先是目标身上爆炸
            PlayExplosionEffect(skillConfig.ExplosionEffectId, target, battleCamp);
            PlayExplosionEffect(skillConfig.ExplosionEffect2, target, battleCamp);
            foreach (var hurt in hitList)
            {
                BattleObject targetObj = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID);
                if (targetObj == null)
                {
                    BattleDebug.LogError("目标为空 target == null ObjId : " + hurt.ObjID);
                    Debug.LogError("目标为空 target == null ObjId : " + hurt.ObjID);
                    continue;
                }
                var effect1 = caster.battleField.battleEffectMgr.PlayEffect(targetObj.ObjID, skillConfig.ExplosionEffectId, targetObj.heroGo.transform, targetObj.Camp);
                var effect2 = caster.battleField.battleEffectMgr.PlayEffect(targetObj.ObjID, skillConfig.ExplosionEffect2, targetObj.heroGo.transform, targetObj.Camp);
                if (effect1 != null)
                {
                    effect1.transform.localRotation = effectTrans.localRotation;
                }
                if (effect2 != null)
                {
                    effect2.transform.localRotation = effectTrans.localRotation;
                }
                PlayExplosionEffect(skillConfig.ExplosionEffectId, targetObj.heroGo.transform, targetObj.Camp);
            }
            // 表现子弹飞行到目标位置
            _onHit?.Invoke(index, hitList);
            isFinish = true;
        });
        bulletCurves.Add(bulletCurve);
@@ -121,58 +160,53 @@
    protected void ShotToTarget(BattleObject target)
    {
        BattleDebug.LogError("发射子弹 " + skillConfig.BulletEffectId);
        BattleEffectPlayer effectPlayer = caster.battleField.battleEffectMgr.PlayEffect(caster.ObjID, skillConfig.BulletEffectId, caster.heroRectTrans, caster.Camp);
        var bulletCurve = BulletCurveFactory.CreateBulletCurve(caster, skillConfig, effectPlayer, target.heroRectTrans, tagUseSkillAttack, (index, hitList) =>
        {
            // 表现子弹飞行到目标位置
            onHit?.Invoke(index, hitList);
            BattleDebug.LogError("回收子弹 " + skillConfig.BulletEffectId);
            // 播放子弹爆炸特效
            foreach (var hurt in hitList)
            {
                BattleObject targetObj = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID);
                if (targetObj == null)
                {
                    BattleDebug.LogError("目标为空 target == null ObjId : " + hurt.ObjID);
                    Debug.LogError("目标为空 target == null ObjId : " + hurt.ObjID);
                    continue;
                }
                if (skillConfig.ExplosionEffectId > 0)
                {
                    var eft = caster.battleField.battleEffectMgr.PlayEffect(targetObj.ObjID, skillConfig.ExplosionEffectId, targetObj.heroGo.transform, targetObj.Camp);
                    eft.transform.localRotation = effectPlayer.transform.localRotation;
                    if (eft.transform.localScale.x < 0f)
                    {
                        eft.transform.localRotation *= Quaternion.Euler(0, 180, 0);
                    }
                }
                if (skillConfig.ExplosionEffect2 > 0)
                {
                    var eft = caster.battleField.battleEffectMgr.PlayEffect(targetObj.ObjID, skillConfig.ExplosionEffect2, targetObj.heroGo.transform, targetObj.Camp);
                    eft.transform.localRotation = effectPlayer.transform.localRotation;
                    if (eft.transform.localScale.x < 0f)
                    {
                        eft.transform.localRotation *= Quaternion.Euler(0, 180, 0);
                    }
                }
                PlayExplosionEffect(skillConfig.ExplosionEffectId, targetObj.heroGo.transform, targetObj.Camp);
                PlayExplosionEffect(skillConfig.ExplosionEffect2, targetObj.heroGo.transform, targetObj.Camp);
                PlayExplosionEffect(skillConfig.ExplosionEffect3, targetObj.heroGo.transform, targetObj.Camp);
            }
            // 表现子弹飞行到目标位置
            onHit?.Invoke(index, hitList);
            // 击中就销毁子弹
            caster.battleField.battleEffectMgr.RemoveEffect(skillConfig.BulletEffectId, effectPlayer);
            // 播放子弹爆炸特效
            isFinish = true;
        });
        bulletCurves.Add(bulletCurve);
    }
    protected void PlayExplosionEffect(int effectId, Transform parent, BattleCamp camp)
    {
        if (effectId <= 0)
            return;
        var effect = caster.battleField.battleEffectMgr.PlayEffect(0, effectId, parent, camp);
        if (effect != null)
        {
            effect.transform.localRotation = parent.localRotation;
            if (effect.transform.localScale.x < 0f)
            {
                effect.transform.localRotation *= Quaternion.Euler(0, 180, 0);
            }
        }
    }
    public override void Run()
Main/System/Battle/SkillEffect/NormalSkillEffect.cs
@@ -20,19 +20,30 @@
    public override void OnMiddleFrameEnd(int times, int hitIndex)
    {
        BattleDebug.LogError($" NormalSkillEffect OnMiddleFrameEnd times : {times}, hitIndex : {hitIndex}");
        for (int i = 0; i < tagUseSkillAttack.HurtList.Length; i++)
        {
            var hurt = tagUseSkillAttack.HurtList[i];
            BattleObject target = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID);
            if (target == null)
            {
                BattleDebug.LogError("特效目标为空 target == null ObjId : " + hurt.ObjID);
                Debug.LogError("特效目标为空 target == null ObjId : " + hurt.ObjID);
                continue;
            }
            caster.battleField.battleEffectMgr.PlayEffect(target.ObjID, skillConfig.ExplosionEffectId, target.heroGo.transform, target.Camp);
            caster.battleField.battleEffectMgr.PlayEffect(target.ObjID, skillConfig.ExplosionEffect2, target.heroGo.transform, target.Camp);
            if (skillConfig.ExplosionEffectId > 0)
            {
                caster.battleField.battleEffectMgr.PlayEffect(target.ObjID, skillConfig.ExplosionEffectId, target.heroGo.transform, target.Camp);
            }
            if (skillConfig.ExplosionEffect2 > 0)
            {
                caster.battleField.battleEffectMgr.PlayEffect(target.ObjID, skillConfig.ExplosionEffect2, target.heroGo.transform, target.Camp);
            }
            if (skillConfig.ExplosionEffect3 > 0)
            {
                caster.battleField.battleEffectMgr.PlayEffect(target.ObjID, skillConfig.ExplosionEffect3, target.heroGo.transform, target.Camp);
            }
        }
        onHit?.Invoke(hitIndex, tagUseSkillAttack.HurtList.ToList());
Main/System/Battle/TestMoveToTarget.cs
@@ -13,7 +13,7 @@
    {
        if (sourceRect == null || targetRect == null)
        {
            BattleDebug.LogError("请在Inspector中指定sourceRect和targetRect!");
            Debug.LogError("请在Inspector中指定sourceRect和targetRect!");
            return;
        }
Main/System/Battle/UIComp/BattleTips.cs
@@ -35,7 +35,6 @@
        {
            OnFinish?.Invoke();
            OnFinish = null;
            gameObject.SetActive(false);
            return;
        }
Main/System/Battle/UIComp/DamageContent.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using UnityEngine;
using System;
using Cysharp.Threading.Tasks;
public class DamageContent : MonoBehaviour
{
@@ -13,14 +14,33 @@
    public PositionTween posTween;
    public ScaleTween scaleTween;
    private BattleDmgInfo battleDmgInfo;
    void Awake()
    {
        line.SetActive(false);
    }
    public void SetDamage(BattleDmgInfo damageInfo, Action _onComplete)
    public async void SetDamage(BattleDmgInfo _damageInfo, Action _onComplete)
    {
        var damages = damageInfo.damageList;
        battleDmgInfo = _damageInfo;
        var damages = battleDmgInfo.battleDamageList;
        for (int i = damages.Count; i < damageLineList.Count; i++)
        {
            damageLineList[i].SetActive(false);
        }
        posTween.Play(_onComplete);
        if (battleDmgInfo.IsCrit())
        {
            scaleTween.Play();
        }
        for (int i = 0; i < damages.Count; i++)
        {
            if (i >= damageLineList.Count)
@@ -29,24 +49,26 @@
                damageLineList.Add(newLine.GetComponent<DamageLine>());
            }
            damageLineList[i].SetActive(true);
            damageLineList[i].SetDamage(damageInfo.attackType, damages[i]);
            damageLineList[i].SetDamage(damages[i]);
            await UniTask.Delay(100);
        }
        for (int i = damages.Count; i < damageLineList.Count; i++)
        {
            damageLineList[i].SetActive(false);
        }
        posTween.Play(_onComplete);
    }
    public void Stop()
    {
        posTween.Stop();
        if (battleDmgInfo.IsCrit())
        {
            scaleTween.Stop();
        }
    }
    public void Resume()
    {
        posTween.Resume();
        if (battleDmgInfo.IsCrit())
        {
            scaleTween.Resume();
        }
    }
}
Main/System/Battle/UIComp/DamageLine.cs
@@ -5,19 +5,25 @@
public class DamageLine : MonoBehaviour
{
    public TextEx damageTypeLabel;
    public TextEx damageTypeLabel;
    public TextEx damageValueLabel;
    public TextEx damageValueLabel;
    public void SetDamage(int damageType, long damage)
    {
        damageTypeLabel.SetActive(false);
        damageTypeLabel.SetActive(false);
        damageValueLabel.text = BattleUtility.DisplayDamageNum(damage, damageType);
    }
    public void SetDamage(long damage)
    {
        damageTypeLabel.SetActive(false);
        damageValueLabel.text = damage.ToString();
        damageTypeLabel.SetActive(false);
        damageValueLabel.text = damage.ToString();
    }
    public void SetDamage(BattleDmg damage)
    {
        damageTypeLabel.SetActive(false);
        damageValueLabel.text = BattleUtility.DisplayDamageNum(damage.damage, damage.attackType);
    }
}
Main/System/GeneralConfig/GeneralDefine.cs
@@ -39,6 +39,7 @@
    public static int acutionItemHour { get; private set; }
    public static int maxXBGridCount { get; private set; }
    public static FuncConfigConfig parryCfg;
    public static void Init()
    {
@@ -754,7 +755,7 @@
            // flashOpenArr = JsonMapper.ToObject<int[]>(func.Numerical2);
            // flashCntMoreArr = JsonMapper.ToObject<int[]>(func.Numerical3);
            // flashKillMaxCount = int.Parse(func.Numerical4);
            parryCfg = FuncConfigConfig.Get("ParryCfg");
        }
        catch (Exception ex)
        {