yyl
2025-08-29 21488796efae93ab7f074d7ad9bfc9d15d82a182
125 【战斗】战斗系统
22个文件已修改
14个文件已添加
809 ■■■■ 已修改文件
Main/Component/UI/Effect/BattleEffectPlayer.cs 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/EffectConfig.cs 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/SkillConfig.cs 65 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/DTCFile/ServerPack/HB4_FightDefine/DTCB428_tagSCBuffRefresh.cs 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/ServerPack/HB4_FightDefine/HB428_tagSCBuffRefresh.cs 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleEffectMgr.cs 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleField/BattleField.cs 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleField/RecordActions/BuffMountAction.cs 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleField/RecordActions/BuffMountAction.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleHUDWin.cs 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleManager.cs 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleObject/BattleObjMgr.cs 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleObject/BattleObject.cs 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleTweenMgr.cs 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/Buff/BattleObjectBuffMgr.cs 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/Define/BattleDmgInfo.cs 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/Define/BattleDmgInfo.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/RecordPlayer/RecordActionType.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/Skill/DirectlyDamageSkill.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/SkillEffect/BulletCurve/StraightBulletCurve.cs 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/SkillEffect/BulletSkillEffect.cs 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/SkillEffect/NormalSkillEffect.cs 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/SkillEffect/SkillEffect.cs 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/UIComp/BasicHeroInfoContainer.cs 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/UIComp/BasicHeroInfoContainer.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/UIComp/BattleBuffCell.cs 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/UIComp/BattleBuffCell.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/UIComp/BattleBuffLineCell.cs 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/UIComp/BattleBuffLineCell.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/UIComp/BattleHeroInfoBar.cs 147 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/UIComp/BattleHeroInfoBar.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/UIComp/BattleTips.cs 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/UIComp/BattleTips.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/UIComp/DamageContent.cs 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/UIComp/DamageLine.cs 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Team/TeamHero.cs 37 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Component/UI/Effect/BattleEffectPlayer.cs
@@ -115,6 +115,12 @@
        }
        //  有特效可能带spine又带unity特效的情况
        spineComp = gameObject.GetComponentInChildren<SkeletonAnimation>(true);
        if (effectConfig.effectPos != null && effectConfig.effectPos.Length >= 2)
        {
            rectTrans.anchoredPosition += new Vector2(effectConfig.effectPos[0], effectConfig.effectPos[1]);
        }
    }
    protected virtual void Clear()
@@ -341,6 +347,7 @@
    public string sortingLayer;
    public int sortingOrder;
    private RectTransform rectTrans;
    protected void OnSortingChanged(string _sortingLayer, int _sortingOrder)
    {
@@ -409,8 +416,8 @@
        GameObject newGo = new GameObject("BattleEffectPlayer_" + effectId);
        newGo.transform.SetParent(parent, false);
        newGo.AddMissingComponent<RectTransform>();
        battleEffectPlayer = newGo.AddComponent<BattleEffectPlayer>();
        battleEffectPlayer.rectTrans = newGo.AddMissingComponent<RectTransform>();
        
        battleEffectPlayer.effectId = effectId;
        battleEffectPlayer.SetActive(true);
Main/Config/Configs/EffectConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           Thursday, August 21, 2025
//    [  Date ]:           2025年8月26日
//--------------------------------------------------------
using System.Collections.Generic;
@@ -29,6 +29,7 @@
    public int isLoop;
    public int frontBack;
    public float delayPlay;
    public int[] effectPos;
    public override int LoadKey(string _key)
    {
@@ -77,6 +78,20 @@
            int.TryParse(tables[11],out frontBack); 
            float.TryParse(tables[12],out delayPlay); 
            if (tables[13].Contains("["))
            {
                effectPos = JsonMapper.ToObject<int[]>(tables[13]);
            }
            else
            {
                string[] effectPosStringArray = tables[13].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
                effectPos = new int[effectPosStringArray.Length];
                for (int i=0;i<effectPosStringArray.Length;i++)
                {
                     int.TryParse(effectPosStringArray[i],out effectPos[i]);
                }
            }
        }
        catch (Exception exception)
        {
Main/Config/Configs/SkillConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           Monday, August 25, 2025
//    [  Date ]:           2025年8月26日
//--------------------------------------------------------
using System.Collections.Generic;
@@ -40,6 +40,9 @@
    public int CoolDownTime;
    public int[] EnhanceSkillList;
    public int FightPower;
    public string SkillMotionName;
    public string IconName;
    public int EffectType;
    public int StartupFrames;
    public int[] ActiveFrames;
    public int RecoveryFrames;
@@ -49,17 +52,13 @@
    public float CastDistance;
    public int[][] DamageDivide;
    public int BulletEffectId;
    public int BulletPos;
    public int BulletPath;
    public float BulletFlyTime;
    public int ExplosionEffectId;
    public int ExplosionPos;
    public string SkillMotionName;
    public int EffectId;
    public int EffectPos;
    public int EffectType;
    public string IconName;
    public int ExplosionEffect2;
    public int EffectId;
    public int EffectId2;
    public int MStartEffectId;
    public override int LoadKey(string _key)
    {
@@ -167,15 +166,21 @@
            int.TryParse(tables[23],out FightPower); 
            int.TryParse(tables[24],out StartupFrames);
            SkillMotionName = tables[24];
            if (tables[25].Contains("["))
            IconName = tables[25];
            int.TryParse(tables[26],out EffectType);
            int.TryParse(tables[27],out StartupFrames);
            if (tables[28].Contains("["))
            {
                ActiveFrames = JsonMapper.ToObject<int[]>(tables[25]);
                ActiveFrames = JsonMapper.ToObject<int[]>(tables[28]);
            }
            else
            {
                string[] ActiveFramesStringArray = tables[25].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
                string[] ActiveFramesStringArray = tables[28].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
                ActiveFrames = new int[ActiveFramesStringArray.Length];
                for (int i=0;i<ActiveFramesStringArray.Length;i++)
                {
@@ -183,41 +188,33 @@
                }
            }
            int.TryParse(tables[26],out RecoveryFrames);
            int.TryParse(tables[29],out RecoveryFrames);
            int.TryParse(tables[27],out LoopCount);
            int.TryParse(tables[30],out LoopCount);
            int.TryParse(tables[28],out CastPosition);
            int.TryParse(tables[31],out CastPosition);
            int.TryParse(tables[29],out CastIndexNum);
            int.TryParse(tables[32],out CastIndexNum);
            float.TryParse(tables[30],out CastDistance);
            float.TryParse(tables[33],out CastDistance);
            DamageDivide = JsonMapper.ToObject<int[][]>(tables[31].Replace("(", "[").Replace(")", "]"));
            DamageDivide = JsonMapper.ToObject<int[][]>(tables[34].Replace("(", "[").Replace(")", "]"));
            int.TryParse(tables[32],out BulletEffectId);
            int.TryParse(tables[35],out BulletEffectId);
            int.TryParse(tables[33],out BulletPos);
            int.TryParse(tables[36],out BulletPath);
            int.TryParse(tables[34],out BulletPath);
            float.TryParse(tables[37],out BulletFlyTime);
            float.TryParse(tables[35],out BulletFlyTime);
            int.TryParse(tables[38],out ExplosionEffectId);
            int.TryParse(tables[36],out ExplosionEffectId);
            int.TryParse(tables[39],out ExplosionEffect2);
            int.TryParse(tables[37],out ExplosionPos);
            int.TryParse(tables[40],out EffectId);
            SkillMotionName = tables[38];
            int.TryParse(tables[41],out EffectId2);
            int.TryParse(tables[39],out EffectId);
            int.TryParse(tables[40],out EffectPos);
            int.TryParse(tables[41],out EffectType);
            IconName = tables[42];
            int.TryParse(tables[43],out ExplosionEffect2);
            int.TryParse(tables[42],out MStartEffectId);
        }
        catch (Exception exception)
        {
Main/Core/NetworkPackage/DTCFile/ServerPack/HB4_FightDefine/DTCB428_tagSCBuffRefresh.cs
@@ -4,8 +4,15 @@
// B4 28 Buff刷新 #tagSCBuffRefresh
public class DTCB428_tagSCBuffRefresh : DtcBasic {
    public override void Done(GameNetPackBasic vNetPack) {
    public override void Done(GameNetPackBasic vNetPack)
    {
        base.Done(vNetPack);
        HB428_tagSCBuffRefresh vNetData = vNetPack as HB428_tagSCBuffRefresh;
        BattleField battleField = BattleManager.Instance.GetBattleField(vNetData.packUID);
        if (null != battleField)
        {
            battleField.OnRefreshBuff(vNetData);
        }
    }
}
Main/Core/NetworkPackage/ServerPack/HB4_FightDefine/HB428_tagSCBuffRefresh.cs
@@ -11,6 +11,9 @@
    public uint LastTime;    // 剩余时长毫秒/回合数
    public ushort Layer;    // 层数,不需要默认0
    public uint OwnerID;    // buff来源者,即施法方
    public uint Value1;
    public uint Value2;
    public uint Value3;
    public HB428_tagSCBuffRefresh () {
        _cmd = (ushort)0xB428;
@@ -24,6 +27,9 @@
        TransBytes (out LastTime, vBytes, NetDataType.DWORD);
        TransBytes (out Layer, vBytes, NetDataType.WORD);
        TransBytes (out OwnerID, vBytes, NetDataType.DWORD);
        TransBytes (out Value1, vBytes, NetDataType.DWORD);
        TransBytes (out Value2, vBytes, NetDataType.DWORD);
        TransBytes (out Value3, vBytes, NetDataType.DWORD);
    }
}
Main/System/Battle/BattleEffectMgr.cs
@@ -42,18 +42,18 @@
        }
    }
    public BattleEffectPlayer PlayEffect(int ObjID, int effectId, Transform parent)
    public BattleEffectPlayer PlayEffect(int ObjID, int effectId, Transform parent, BattleCamp camp)
    {
        if (effectId <= 0)
        {
            BattleDebug.LogError("effect id <= 0");
            Debug.LogError("effect id <= 0");
            return null;
        }
        var effectCfg = EffectConfig.Get(effectId);
        if (null == effectCfg)
        {
            BattleDebug.LogError("effect config is null, effectId : " + effectId);
            Debug.LogError("effect config is null, effectId : " + effectId);
            return null;
        }
@@ -62,16 +62,24 @@
            effectDict[effectId] = new List<BattleEffectPlayer>();
        }
        BattleDebug.LogError("播放特效 " + effectId);
        BattleEffectPlayer effectPlayer = BattleEffectPlayer.Create(effectId, battleField.battleRootNode.transform);
        // 设置特效缩放和方向
        effectPlayer.transform.position = parent.position;
        float effectScale = parent.transform.localScale.x;
        effectPlayer.transform.localScale *= effectScale;
        effectPlayer.onDestroy += OnEffectDestroy;
        if (effectPlayer != null)
        {
            effectDict[effectId].Add(effectPlayer);
        }
        effectPlayer.Play(true);
        var effectScale = effectPlayer.transform.localScale;
        effectScale.x *= camp == BattleCamp.Red ? 1 : -1;
        effectPlayer.transform.localScale = effectScale;
        return effectPlayer;
    }
Main/System/Battle/BattleField/BattleField.cs
@@ -366,12 +366,13 @@
    public void StartBattle(Action onMoveComplete)
    {
        List<BattleObject> redTeam = battleObjMgr.GetBattleObjList(BattleCamp.Red);
        List<BattleObject> blueTeam = battleObjMgr.GetBattleObjList(BattleCamp.Blue);
        Tween tween = null;
        foreach (var obj in redTeam)
        foreach (var obj in blueTeam)
        {
            obj.heroGo.SetActive(true);
            obj.motionBase.PlayAnimation(MotionName.run, true);
            RectTransform trans = obj.heroRectTrans;
            trans.anchoredPosition = new Vector2(-800, 0);
@@ -381,7 +382,7 @@
        tween.onComplete = () =>
        {
            foreach (var obj in redTeam)
            foreach (var obj in blueTeam)
            {
                obj.motionBase.PlayAnimation(MotionName.idle, true);
            }
@@ -517,4 +518,17 @@
    {
    }
    public void OnRefreshBuff(HB428_tagSCBuffRefresh vNetData)
    {
        BattleObject battleObj = battleObjMgr.GetBattleObject((int)vNetData.ObjID);
        if (null != battleObj)
        {
            battleObj.buffMgr.RefreshBuff(vNetData);
        }
        else
        {
            Debug.LogError($"BattleObject with ID {vNetData.ObjID} not found for buff refresh.");
        }
    }
}
Main/System/Battle/BattleField/RecordActions/BuffMountAction.cs
New file
@@ -0,0 +1,48 @@
using UnityEngine;
using System.Collections.Generic;
using System;
public class BuffMountAction : RecordAction
{
    protected HB428_tagSCBuffRefresh hB428_TagSCBuffRefresh;
    protected Action onComplete;
    public BuffMountAction(BattleField _battleField, BattleObject _battleObj, HB428_tagSCBuffRefresh vNetData, Action _onComplete)
        : base(RecordActionType.BuffMount, _battleField, _battleObj)
    {
        isFinish = false;
        hB428_TagSCBuffRefresh = vNetData;
        onComplete = _onComplete;
    }
    public override bool IsFinished()
    {
        return isFinish;
    }
    public override void Run()
    {
        base.Run();
        if (!isRunOnce)
        {
            SkillConfig skillConfig = SkillConfig.Get((int)hB428_TagSCBuffRefresh.SkillID);
            if (null != skillConfig)
            {
                //  飘字
                battleObject.heroInfoBar.ShowTips(skillConfig.SkillName);
            }
            //  加buff(onComplete写了)
            onComplete?.Invoke();
            isFinish = true;
            return;
        }
    }
}
Main/System/Battle/BattleField/RecordActions/BuffMountAction.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 03f12da82f639b04790f1cff4480e17a
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Battle/BattleHUDWin.cs
@@ -40,7 +40,7 @@
    protected override void OnPreOpen()
    {
        base.OnPreOpen();
        EventBroadcast.Instance.AddListener<string, BattleObject, List<long>>(EventName.BATTLE_DAMAGE_TAKEN, OnDamageTaken);
        EventBroadcast.Instance.AddListener<BattleDmgInfo>(EventName.BATTLE_DAMAGE_TAKEN, OnDamageTaken);
        EventBroadcast.Instance.AddListener<BattleObject, SkillConfig>(EventName.BATTLE_BUFF_MOUNTED, OnBuffMounted);
        EventBroadcast.Instance.AddListener<BattleObject, SkillConfig>(EventName.BATTLE_BUFF_DISAPEAR, OnBuffDisapear);
        damagePrefabPool = GameObjectPoolManager.Instance.RequestPool(UILoader.LoadPrefab("DamageContent"));
@@ -51,7 +51,7 @@
    protected override void OnPreClose()
    {
        base.OnPreClose();
        EventBroadcast.Instance.RemoveListener<string, BattleObject, List<long>>(EventName.BATTLE_DAMAGE_TAKEN, OnDamageTaken);
        EventBroadcast.Instance.RemoveListener<BattleDmgInfo>(EventName.BATTLE_DAMAGE_TAKEN, OnDamageTaken);
        EventBroadcast.Instance.RemoveListener<BattleObject, SkillConfig>(EventName.BATTLE_BUFF_MOUNTED, OnBuffMounted);
        EventBroadcast.Instance.RemoveListener<BattleObject, SkillConfig>(EventName.BATTLE_BUFF_DISAPEAR, OnBuffDisapear);
    }
@@ -84,18 +84,18 @@
        damagePrefabPool.Release(content.gameObject);
    }
    private void OnDamageTaken(string guid, BattleObject bo, List<long> damageList)
    private void OnDamageTaken(BattleDmgInfo damageInfo)
    {
        GameObject damageContent = damagePrefabPool.Request();
        DamageContent content = damageContent.GetComponent<DamageContent>();
        damageContent.transform.SetParent(damageNode, false);
        damageContent.transform.localPosition = new Vector3(damageContent.transform.localPosition.x, damageContent.transform.localPosition.y, 0);
        content.SetDamage(damageList, () => RemoveDamageContent(content));
        content.SetDamage(damageInfo, () => RemoveDamageContent(content));
        damageContentList.Add(content);
        // heroGo 的 parent 作为参考节点
        var heroRect = bo.heroRectTrans;
        var heroRect = damageInfo.hurtObj.heroRectTrans;
        if (heroRect == null)
            return;
Main/System/Battle/BattleManager.cs
@@ -10,7 +10,6 @@
    //  同时只能有一场战斗在进行 guid, battlefield
    protected Dictionary<string, BattleField> battleFields = new Dictionary<string, BattleField>();
    protected LogicUpdate logicUpdate = new LogicUpdate();
    public Action<string, BattleField> onBattleFieldCreate;
@@ -19,14 +18,15 @@
    public override void Init()
    {
        base.Init();
        logicUpdate.Start(Run);
        LogicEngine.Instance.OnUpdate += Run;
        DTC0403_tagPlayerLoginLoadOK.playerLoginOkEvent += OnPlayerLoginOk;
    }
    public override void Release()
    {
        base.Release();
        logicUpdate.Destroy();
        LogicEngine.Instance.OnUpdate -= Run;
        DTC0403_tagPlayerLoginLoadOK.playerLoginOkEvent -= OnPlayerLoginOk;
    }
Main/System/Battle/BattleObject/BattleObjMgr.cs
@@ -20,17 +20,17 @@
    {
        battleField = _battleField;
        ReloadTeam(_redTeam, BattleCamp.Red);
        ReloadTeam(_blueTeam, BattleCamp.Blue);
        ReloadTeam(_blueTeam, BattleCamp.Blue, false);
    }
    public void ReloadTeam(TeamBase teamBase, BattleCamp _camp)
    public void ReloadTeam(TeamBase teamBase, BattleCamp _camp, bool active = true)
    {
        var posNodeList = _camp == BattleCamp.Red ? battleField.battleRootNode.redTeamNodeList : battleField.battleRootNode.blueTeamNodeList;
        var campDict = _camp == BattleCamp.Red ? redCampDict : blueCampDict;
        CreateTeam(posNodeList, campDict, teamBase, _camp);
        CreateTeam(posNodeList, campDict, teamBase, _camp, active);
    }
    protected void CreateTeam(List<GameObject> posNodeList, Dictionary<int, BattleObject> campDict, TeamBase teamBase, BattleCamp _Camp)
    protected void CreateTeam(List<GameObject> posNodeList, Dictionary<int, BattleObject> campDict, TeamBase teamBase, BattleCamp _Camp, bool active)
    {
        DestroyTeam(campDict);
        if (teamBase == null)
@@ -45,6 +45,7 @@
            if (teamHero != null)
            {
                BattleObject battleObj = BattleObjectFactory.CreateBattleObject(battleField, posNodeList, teamHero, _Camp);
                battleObj.heroGo.SetActive(active);
                allBattleObjDict.Add(battleObj.ObjID, battleObj);
                campDict.Add(teamHero.positionNum, battleObj);
            }
Main/System/Battle/BattleObject/BattleObject.cs
@@ -52,6 +52,8 @@
    private RectTransform m_heroRectTrans;
    private BattleHeroInfoBar battleHeroInfoBar;
    public RectTransform heroRectTrans
    {
        get
@@ -68,9 +70,8 @@
    protected Renderer[] renderers;
    public Transform effectNode;
    private List<HB405_tagMCAddExp> hB405_tagMCAddExps = new List<HB405_tagMCAddExp>();
    public BattleHeroInfoBar heroInfoBar;
    public BattleObject(BattleField _battleField)
    {
@@ -89,13 +90,16 @@
        buffMgr.Init(this);
        renderers = heroGo.GetComponentsInChildren<Renderer>(true);
    }
        heroInfoBar = heroGo.GetComponentInChildren<BattleHeroInfoBar>(true);
        heroInfoBar.SetBattleObject(this);
    }
    public virtual void Run()
    {
        motionBase.Run();
        battleHeroInfoBar.Run();
    }
    public virtual void Pause()
@@ -129,6 +133,8 @@
        switch ((PlayerDataType)_refreshInfo.RefreshType)
        {
            case PlayerDataType.HP:
                long toHp = GeneralDefine.GetFactValue(_refreshInfo.Value, _refreshInfo.ValueEx);
                battleHeroInfoBar.UpdateHP(teamHero.curHp, toHp, teamHero.maxHp);
                teamHero.curHp = GeneralDefine.GetFactValue(_refreshInfo.Value, _refreshInfo.ValueEx);
                break;
            case PlayerDataType.MaxHP:
@@ -302,8 +308,10 @@
            Debug.Log($"Damage: {damage}");
        }
        BattleDmgInfo battleDmgInfo = new BattleDmgInfo(battleField.guid, damageValues, this, (int)attackType);
        // YYL TODO 是否需要挂在在自身的follow点上
        EventBroadcast.Instance.Broadcast(EventName.BATTLE_DAMAGE_TAKEN, battleField.guid, this, damageValues);
        EventBroadcast.Instance.Broadcast(EventName.BATTLE_DAMAGE_TAKEN, battleDmgInfo);
    }
    public RectTransform GetAliasTeamNode()
Main/System/Battle/BattleTweenMgr.cs
@@ -49,7 +49,16 @@
            tweenList.Remove(tween);
        };
        // tween.Play();
        tween.Play();
    }
    public void OnKillTween(Tween tween)
    {
        tween.Kill();
        if (tween != null && tweenList.Contains(tween))
        {
            tweenList.Remove(tween);
        }
    }
    public void HaveRest()
Main/System/Battle/Buff/BattleObjectBuffMgr.cs
@@ -1,10 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class BattleObjectBuffMgr
{
    // private Dictionary<BuffBase, EffectPlayer> buffDict = new Dictionary<BuffBase, EffectPlayer>();
    // buffId, effectId, EffectPlayer
    private Dictionary<uint, Dictionary<int, BattleEffectPlayer>> buffEffectDict = new Dictionary<uint, Dictionary<int, BattleEffectPlayer>>();
    //  buffId, buffdata
    private Dictionary<uint, HB428_tagSCBuffRefresh> buffDataDict = new Dictionary<uint, HB428_tagSCBuffRefresh>();
    private BattleObject battleObject;
@@ -34,7 +41,80 @@
    //  删除buff
    public void RemoveBuff(HB429_tagSCBuffDel vNetData)
    {
        HB428_tagSCBuffRefresh buffData = null;
        // buffBase.OnRemove();
        if (buffDataDict.TryGetValue(vNetData.BuffID, out buffData))
        {
            buffDataDict.Remove(vNetData.BuffID);
        }
        if (buffData != null)
        {
            Dictionary<int, BattleEffectPlayer> effectDict = null;
            if (buffEffectDict.TryGetValue(vNetData.BuffID, out effectDict))
            {
                SkillConfig skillConfig = SkillConfig.Get((int)buffData.SkillID);
                if (null != skillConfig)
                {
                    BattleEffectPlayer effectPlayer = null;
                    if (effectDict.TryGetValue(skillConfig.EffectId, out effectPlayer))
                    {
                        battleObject.battleField.battleEffectMgr.RemoveEffect(skillConfig.EffectId, effectPlayer);
                    }
                }
            }
        }
        //  不做表现
        battleObject.heroInfoBar.RefreshBuff(buffDataDict.Values.ToList());
    }
    public void RefreshBuff(HB428_tagSCBuffRefresh vNetData)
    {
        bool isNew = false;
        if (buffDataDict.ContainsKey(vNetData.BuffID))
        {
            buffDataDict[vNetData.BuffID] = vNetData;
        }
        else
        {
            isNew = true;
            buffDataDict.Add(vNetData.BuffID, vNetData);
        }
        if (isNew)
        {
            BuffMountAction buffMountAction = new BuffMountAction(battleObject.battleField, battleObject, vNetData, () =>
            {
                SkillConfig skillConfig = SkillConfig.Get((int)vNetData.SkillID);
                if (null != skillConfig && skillConfig.EffectId > 0)
                {
                    // Dictionary<uint, Dictionary<int, BattleEffectPlayer>> buffEffectDict
                    Dictionary<int, BattleEffectPlayer> effectDict = null;
                    if (buffEffectDict.TryGetValue(vNetData.BuffID, out effectDict))
                    {
                        //  存在这个buffid的特效字典
                        if (effectDict.ContainsKey(skillConfig.EffectId))
                        {
                            Debug.LogError("已存在同样的buff特效 " + skillConfig.EffectId);
                        }
                        else
                        {
                            BattleEffectPlayer effect = battleObject.battleField.battleEffectMgr.PlayEffect(battleObject.ObjID, skillConfig.EffectId, battleObject.heroRectTrans, battleObject.Camp);
                            effectDict.Add(skillConfig.EffectId, effect);
                        }
                    }
                    else
                    {
                        effectDict = new Dictionary<int, BattleEffectPlayer>();
                        BattleEffectPlayer effect = battleObject.battleField.battleEffectMgr.PlayEffect(battleObject.ObjID, skillConfig.EffectId, battleObject.heroRectTrans, battleObject.Camp);
                        effectDict.Add(skillConfig.EffectId, effect);
                        buffEffectDict.Add(vNetData.BuffID, effectDict);
                    }
                }
            });
            battleObject.battleField.recordPlayer.PlayRecord(buffMountAction);
        }
    }
}
Main/System/Battle/Define/BattleDmgInfo.cs
New file
@@ -0,0 +1,21 @@
using System.Collections.Generic;
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)
    {
        this.battleFieldGuid = battleFieldGuid;
        this.damageList = damageList;
        this.hurtObj = hurtObj;
        this.attackType = attackType;
    }
}
Main/System/Battle/Define/BattleDmgInfo.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 36e9ba972525e3a469d210dd67ac05b3
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Battle/RecordPlayer/RecordActionType.cs
@@ -5,6 +5,7 @@
    Guard,//格挡
    Skill,//技能
    Death,//死亡
    BuffMount,//挂载增益
    BattleStart,//战斗开始
}
Main/System/Battle/Skill/DirectlyDamageSkill.cs
@@ -29,5 +29,4 @@
        OnSkillFinished();
    }
}
Main/System/Battle/SkillEffect/BulletCurve/StraightBulletCurve.cs
@@ -33,14 +33,17 @@
        }
        elapsed += Time.deltaTime;
        float t = Mathf.Clamp01(elapsed / 0.3f);
        float t = Mathf.Clamp01(elapsed / duration);
        Vector2 pos = Vector2.Lerp(start, end, t);
        bulletTrans.anchoredPosition = pos;
        Vector2 dir = end - start;
        float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
        bulletTrans.localRotation = Quaternion.Euler(0, 0, angle);
        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);
        // }
        if (t >= 1f)
        {
            finished = true;
Main/System/Battle/SkillEffect/BulletSkillEffect.cs
@@ -19,8 +19,10 @@
    }
    public override void OnMiddleFrameStart(int times)
    {
        base.OnMiddleFrameStart(times);
        //  弹射 另外的做法了
        if (skillConfig.effectType == SkillEffectType.Bullet && skillConfig.BulletPath == 4)
        {
@@ -75,16 +77,9 @@
        }
    }
    public override void Play(Action<int, List<HB427_tagSCUseSkill.tagSCUseSkillHurt>> _onHit)
    {
        base.Play(_onHit);
    }
    protected void ShotToFormation(RectTransform target, Action<int, List<HB427_tagSCUseSkill.tagSCUseSkillHurt>> _onHit)
    {
        BattleEffectPlayer effectPlayer = caster.battleField.battleEffectMgr.PlayEffect(caster.ObjID, skillConfig.BulletEffectId, caster.effectNode);
        BattleEffectPlayer effectPlayer = caster.battleField.battleEffectMgr.PlayEffect(caster.ObjID, skillConfig.BulletEffectId, caster.heroRectTrans, caster.Camp);
        RectTransform effectTrans = effectPlayer.transform as RectTransform;
@@ -106,8 +101,8 @@
                    continue;
                }
                var effect1 = caster.battleField.battleEffectMgr.PlayEffect(targetObj.ObjID, skillConfig.ExplosionEffectId, targetObj.heroGo.transform);
                var effect2 = caster.battleField.battleEffectMgr.PlayEffect(targetObj.ObjID, skillConfig.ExplosionEffect2, targetObj.heroGo.transform);
                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;
@@ -127,7 +122,7 @@
    protected void ShotToTarget(BattleObject target)
    {
        BattleDebug.LogError("发射子弹 " + skillConfig.BulletEffectId);
        BattleEffectPlayer effectPlayer = caster.battleField.battleEffectMgr.PlayEffect(caster.ObjID, skillConfig.BulletEffectId, caster.heroRectTrans);
        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) =>
@@ -151,14 +146,22 @@
                if (skillConfig.ExplosionEffectId > 0)
                {
                    var eft = caster.battleField.battleEffectMgr.PlayEffect(targetObj.ObjID, skillConfig.ExplosionEffectId, targetObj.heroGo.transform);
                    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);
                    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);
                    }
                }
            }
Main/System/Battle/SkillEffect/NormalSkillEffect.cs
@@ -17,23 +17,6 @@
    }
    //  技能动作第一帧
    //  不用理会回调
    public override void Play(Action<int, List<HB427_tagSCUseSkill.tagSCUseSkillHurt>> _onHit)
    {
        // 播放技能特效
        BattleEffectPlayer battleEffectPlayer = caster.battleField.battleEffectMgr.PlayEffect(
            caster.ObjID,
            skillConfig.EffectId,
            caster.heroGo.transform
        );
    }
    public override void Run()
    {
        base.Run();
    }
    public override void OnMiddleFrameEnd(int times, int hitIndex)
    {
@@ -48,27 +31,11 @@
                continue;
            }
            /*var effect1 = */
            caster.battleField.battleEffectMgr.PlayEffect(target.ObjID, skillConfig.ExplosionEffectId, target.heroGo.transform);
            /*var effect2 = */
            caster.battleField.battleEffectMgr.PlayEffect(target.ObjID, skillConfig.ExplosionEffect2, target.heroGo.transform);
            // if (effect1 != null)
            // {
            //     effect1.transform.localRotation = effectTrans.localRotation;
            // }
            // if (effect2 != null)
            // {
            //     effect2.transform.localRotation = effectTrans.localRotation;
            // }
            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);
        }
        //  为什么没触发
        onHit?.Invoke(hitIndex, tagUseSkillAttack.HurtList.ToList());
        isFinish = true;
    }
    public override void OnMiddleFrameStart(int times)
    {
    }
}
Main/System/Battle/SkillEffect/SkillEffect.cs
@@ -23,6 +23,14 @@
    public virtual void Play(Action<int, List<HB427_tagSCUseSkill.tagSCUseSkillHurt>> _onHit)
    {
        onHit = _onHit;
        if (skillConfig.EffectId > 0)
        {
            caster.battleField.battleEffectMgr.PlayEffect(caster.ObjID, skillConfig.EffectId, caster.heroRectTrans, caster.Camp);
        }
        if (skillConfig.EffectId2 > 0)
        {
            caster.battleField.battleEffectMgr.PlayEffect(caster.ObjID, skillConfig.EffectId2, caster.heroRectTrans, caster.Camp);
        }
    }
    public virtual void Run()
@@ -37,7 +45,10 @@
    public virtual void OnMiddleFrameStart(int times)
    {
        if (skillConfig.MStartEffectId <= 0)
            return;
        //  中摇固定特效
        caster.battleField.battleEffectMgr.PlayEffect(caster.ObjID, skillConfig.MStartEffectId, caster.heroGo.transform, caster.Camp);
    }
    
    public virtual bool IsFinished()
Main/System/Battle/UIComp/BasicHeroInfoContainer.cs
New file
@@ -0,0 +1,9 @@
using UnityEngine;
public class BasicHeroInfoContainer : MonoBehaviour
{
    public void SetHeroInfo(TeamHero teamHero)
    {
    }
}
Main/System/Battle/UIComp/BasicHeroInfoContainer.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5c3e5adcdb7b8a74bb4a3561c9eb3a14
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Battle/UIComp/BattleBuffCell.cs
New file
@@ -0,0 +1,17 @@
using UnityEngine;
using UnityEngine.UI;
public class BattleBuffCell : CellView
{
    public Image imageIcon;
    public Text textLevel;
    public void Display(HB428_tagSCBuffRefresh hB428_TagSCBuffRefresh)
    {
        SkillConfig skillConfig = SkillConfig.Get((int)hB428_TagSCBuffRefresh.SkillID);
        imageIcon.sprite = ResManager.Instance.LoadAsset<Sprite>("", skillConfig.IconName);
        textLevel.text = hB428_TagSCBuffRefresh.Layer.ToString();
    }
}
Main/System/Battle/UIComp/BattleBuffCell.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c7e8e099ab9f4874fa6a4bce3cf9b6ab
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Battle/UIComp/BattleBuffLineCell.cs
New file
@@ -0,0 +1,25 @@
using System.Collections.Generic;
using UnityEngine;
public class BattleBuffLineCell : CellView
{
    [SerializeField] BattleBuffCell[] buffCellList;
    public void Display(List<HB428_tagSCBuffRefresh> buffList, int index)
    {
        for (int i = 0; i < buffCellList.Length; i++)
        {
            if (i + index < buffList.Count)
            {
                buffCellList[i].SetActive(true);
                buffCellList[i].Display(buffList[i + index]);
            }
            else
            {
                buffCellList[i].SetActive(false);
            }
        }
    }
}
Main/System/Battle/UIComp/BattleBuffLineCell.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ed7bc7d61144495468403b4152a0150f
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Battle/UIComp/BattleHeroInfoBar.cs
New file
@@ -0,0 +1,147 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System;
using DG.Tweening;
public class BattleHeroInfoBar : MonoBehaviour
{
    protected BattleObject battleObject;
    public Slider sliderHp;
    public Slider sliderXp; //怒气
    protected float timer = 0f;
    public float PopUpInterval = 0.2f;
    // public List<BattleBuffCell> buffCells = new List<BattleBuffCell>();
    protected List<string> messages = new List<string>();
    public BasicHeroInfoContainer heroInfoContainer;
    public BattleTips textTips;
    protected Tween hpTween;
    protected List<BattleTips> tipsList = new List<BattleTips>();
    protected List<HB428_tagSCBuffRefresh> buffList = new List<HB428_tagSCBuffRefresh>();
    public ScrollerController scroller;
    public void SetBattleObject(BattleObject _battleObject)
    {
        battleObject = _battleObject;
        heroInfoContainer.SetHeroInfo(battleObject.teamHero);
        RefreshBuff(buffList);
    }
    public void RefreshBuff(List<HB428_tagSCBuffRefresh> datas)
    {
        buffList = datas;
        //  更新buff图标 or 创建新的buff图标
        scroller.Refresh();
        for (int i = 0; i < buffList.Count; i++)
        {
            if (i % 5 == 0)
            {
                scroller.AddCell(ScrollerDataType.Header, i);
            }
        }
        scroller.Restart();
    }
    protected void OnEnable()
    {
        scroller.OnRefreshCell += OnRefreshCell;
    }
    protected void OnDisable()
    {
        //  TODO YYL 考虑池化
        messages.Clear();
        for (int i = 0; i < tipsList.Count; i++)
        {
            var tip = tipsList[i];
            tip.OnFinish = null;
            GameObject.DestroyImmediate(tip.gameObject);
        }
        tipsList.Clear();
    }
    protected void OnRefreshCell(ScrollerDataType type, CellView cell)
    {
        var _cell = cell as BattleBuffLineCell;
        _cell.Display(buffList, cell.index);
    }
    public void ShowTips(string message)
    {
        messages.Add(message);
    }
    public void SetActive(bool active)
    {
        gameObject.SetActive(active);
    }
    public void PopUpTipsDirectly(string message)
    {
        GameObject prefab = textTips.gameObject;
        GameObject go = GameObject.Instantiate(prefab, transform);
        BattleTips tips = go.GetComponent<BattleTips>();
        tips.SetText(message);
        tips.OnFinish = () =>
        {
            //  TODO YYL 考虑池化
            tipsList.Remove(tips);
            GameObject.DestroyImmediate(tips.gameObject);
        };
        tipsList.Add(tips);
    }
    public void UpdateHP(long fromHp, long toHp, long maxHp)
    {
        //  做hp增加或者减少的动画
        // sliderHp.value = ((float)fromHp) / ((float)maxHp);
        if (hpTween != null)
        {
            battleObject.battleField.battleTweenMgr.OnKillTween(hpTween);
        }
        hpTween = sliderHp.DOValue((float)toHp / maxHp, 0.3f);
        battleObject.battleField.battleTweenMgr.OnPlayTween(hpTween);
    }
    public void Run()
    {
        for (int i = tipsList.Count - 1; i >= 0; i--)
        {
            tipsList[i].Run();
        }
        timer += Time.deltaTime;
        if (messages.Count > 0 && timer >= PopUpInterval)
        {
            // 播放飘字
            string message = messages[0];
            messages.RemoveAt(0);
            PopUpTipsDirectly(message);
            timer = 0f;
        }
    }
}
Main/System/Battle/UIComp/BattleHeroInfoBar.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 91976c75be6daea45993712cce2f2110
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Battle/UIComp/BattleTips.cs
New file
@@ -0,0 +1,47 @@
using UnityEngine;
using System;
using UnityEngine.UI;
public class BattleTips : MonoBehaviour
{
    public Vector2 beginPos = Vector2.zero;
    public Vector2 endPos = new Vector2(0, 100);
    public float showTime = 0.4f;
    public float timer = 0f;
    protected RectTransform rectTransform;
    void Awake()
    {
        rectTransform = gameObject.AddMissingComponent<RectTransform>();
    }
    public Text tipText;
    public Action OnFinish;
    public void SetText(string text)
    {
        tipText.text = text;
        rectTransform.anchoredPosition = Vector2.zero;
        timer = 0f;
        gameObject.SetActive(true);
    }
    //  不要使用update
    public void Run()
    {
        if (timer >= showTime)
        {
            OnFinish?.Invoke();
            OnFinish = null;
            gameObject.SetActive(false);
            return;
        }
        rectTransform.anchoredPosition = Vector2.Lerp(beginPos, endPos, timer / showTime);
        timer += Time.deltaTime;
    }
}
Main/System/Battle/UIComp/BattleTips.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ca221a28c4019fa439e674596524bc3d
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Battle/UIComp/DamageContent.cs
@@ -18,8 +18,9 @@
        line.SetActive(false);
    }
    public void SetDamage(List<long> damages, Action _onComplete)
    public void SetDamage(BattleDmgInfo damageInfo, Action _onComplete)
    {
        var damages = damageInfo.damageList;
        for (int i = 0; i < damages.Count; i++)
        {
            if (i >= damageLineList.Count)
@@ -28,7 +29,7 @@
                damageLineList.Add(newLine.GetComponent<DamageLine>());
            }
            damageLineList[i].SetActive(true);
            damageLineList[i].SetDamage(damages[i]);
            damageLineList[i].SetDamage(damageInfo.attackType, damages[i]);
        }
        for (int i = damages.Count; i < damageLineList.Count; i++)
Main/System/Battle/UIComp/DamageLine.cs
@@ -9,10 +9,10 @@
    public TextEx damageValueLabel;
    public void SetDamage(DamageType damageType, long damage)
    public void SetDamage(int damageType, long damage)
    {
        damageTypeLabel.SetActive(true);
        damageValueLabel.text = damage.ToString();
        damageTypeLabel.SetActive(false);
        damageValueLabel.text = BattleUtility.DisplayDamageNum(damage, damageType);
    }
    public void SetDamage(long damage)
Main/System/Team/TeamHero.cs
@@ -11,6 +11,7 @@
    public float modelScale = 1f;
    public int level = 0;
    public TeamBase teamBase
    {
@@ -18,7 +19,9 @@
    }
    public int positionNum; //注意服务端的1号位是1,客户端在使用时是0,通信和策划沟通用1
//  战场数据
    //  战场数据
    public int ObjID = 0;// 战斗单位唯一ID
    public int NPCID = 0;// 战斗NPCID,不同的实例ID对应的NPCID可能一样
@@ -30,25 +33,41 @@
        //  判断一下是npc还是玩家
        heroId = (int)fightObj.HeroID;
        if (fightObj.NPCID > 0)
        // B4 24 回合战斗初始化 #tagSCTurnFightInit
        // 封包中的 HeroID、SkinID 字段不再是玩家阵容独有,NPC阵容也可能有值,一般是关联武将的NPC有值
        // 如果 HeroID、SkinID 不为空,则可认为是关联武将的NPC,外观相关默认通过HeroID读取武将相关,如名称
        // 皮肤 SkinID 不为空时,则模型默认使用该皮肤
        // 如果 HeroID、SkinID 为空, NPCID不为空,则走原NPC默认规则
        //  补充 skinid跟heroid要么同时没有 要么同时有 如果这三个id都没有的话 那就是配置严重错误 无法弥补
        if (fightObj.SkinID > 0 && fightObj.HeroID > 0)
        {
            // 走玩家逻辑
            var heroConfig = HeroConfig.Get(heroId);
            if (null == heroConfig)
            {
                Debug.LogError("hero config is null, heroId : " + heroId);
                return;
            }
            Country = (HeroCountry)heroConfig.Country;
            SkinID = (int)fightObj.SkinID;
            modelScale = 1f;
        }
        else if (fightObj.NPCID > 0)
        {
            //走NPC的逻辑
            NPCConfig npcConfig = NPCConfig.Get((int)fightObj.NPCID);
            Country = (HeroCountry)npcConfig.Country;
            SkinID = npcConfig.SkinID;
            BattleDebug.LogError("npc skin id is " + SkinID);
            modelScale = npcConfig.ModelScale;
        }
        else
        {
            //走玩家逻辑
            var heroConfig = HeroConfig.Get(heroId);
            Country = (HeroCountry)heroConfig.Country;
            SkinID = (int)fightObj.SkinID;
            BattleDebug.LogError("normal hero skin id is " + SkinID);
            modelScale = 1f;
            throw new System.Exception("hero id and skin id are both invalid, npc id is invalid too (all <= 0)");
        }
        level = (int)fightObj.LV;
        skinConfig = HeroSkinConfig.Get(SkinID);
        teamBase = _teamBase;