yyl
2025-12-08 4de42356ff71d295be7d3bf2e0b7d218b719ad9c
Merge branch 'master' of http://192.168.1.20:10010/r/Project_SG_scripts
7个文件已修改
17个文件已添加
936 ■■■■■ 已修改文件
Main/Config/ConfigManager.cs 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/HeroQualityConfig.cs 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/LineupRecommendConfig.cs 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/LineupRecommendConfig.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/DTCFile/ServerPack/HB1_Role/DTCB129_tagSCLineupRecommendInfo.cs 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/DTCFile/ServerPack/HB1_Role/DTCB129_tagSCLineupRecommendInfo.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/DataToCtl/PackageRegedit.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/ServerPack/HB1_Role/HB129_tagSCLineupRecommendInfo.cs 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/ServerPack/HB1_Role/HB129_tagSCLineupRecommendInfo.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Main.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroUI/HeroCollectionLvUpWin.cs 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroUI/HeroListWin.cs 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/LineupRecommend.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/LineupRecommend/LineupRecommendBaseWin.cs 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/LineupRecommend/LineupRecommendBaseWin.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/LineupRecommend/LineupRecommendCell.cs 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/LineupRecommend/LineupRecommendCell.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/LineupRecommend/LineupRecommendItem.cs 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/LineupRecommend/LineupRecommendItem.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/LineupRecommend/LineupRecommendManager.cs 328 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/LineupRecommend/LineupRecommendManager.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/LineupRecommend/LineupRecommendWin.cs 136 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/LineupRecommend/LineupRecommendWin.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Redpoint/MainRedDot.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/ConfigManager.cs
@@ -60,6 +60,7 @@
            typeof(HorseSkinConfig),
            typeof(ItemCompoundConfig),
            typeof(ItemConfig),
            typeof(LineupRecommendConfig),
            typeof(LLMJConfig),
            typeof(MainChapterConfig),
            typeof(MainLevelConfig),
@@ -277,6 +278,8 @@
        ClearConfigDictionary<ItemCompoundConfig>();
        // 清空 ItemConfig 字典
        ClearConfigDictionary<ItemConfig>();
        // 清空 LineupRecommendConfig 字典
        ClearConfigDictionary<LineupRecommendConfig>();
        // 清空 LLMJConfig 字典
        ClearConfigDictionary<LLMJConfig>();
        // 清空 MainChapterConfig 字典
Main/Config/Configs/HeroQualityConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年12月5日
//    [  Date ]:           Monday, December 8, 2025
//--------------------------------------------------------
using System.Collections.Generic;
@@ -24,6 +24,7 @@
    public int StarAddPer;
    public int[] BookActAwardMoney;
    public int[][] DismissReturnItems;
    public int[] RecommendAwardMoney;
    public override int LoadKey(string _key)
    {
@@ -62,6 +63,20 @@
            }
            DismissReturnItems = JsonMapper.ToObject<int[][]>(tables[7].Replace("(", "[").Replace(")", "]")); 
            if (tables[8].Contains("["))
            {
                RecommendAwardMoney = JsonMapper.ToObject<int[]>(tables[8]);
            }
            else
            {
                string[] RecommendAwardMoneyStringArray = tables[8].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
                RecommendAwardMoney = new int[RecommendAwardMoneyStringArray.Length];
                for (int i=0;i<RecommendAwardMoneyStringArray.Length;i++)
                {
                     int.TryParse(RecommendAwardMoneyStringArray[i],out RecommendAwardMoney[i]);
                }
            }
        }
        catch (Exception exception)
        {
Main/Config/Configs/LineupRecommendConfig.cs
New file
@@ -0,0 +1,77 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年12月5日
//--------------------------------------------------------
using System.Collections.Generic;
using System;
using UnityEngine;
using LitJson;
public partial class LineupRecommendConfig : ConfigBase<int, LineupRecommendConfig>
{
    static LineupRecommendConfig()
    {
        // 访问过静态构造函数
        visit = true;
    }
    public int RecommendID;
    public int[] HeroIDList;
    public int[] PosIndexList;
    public string Name;
    public string Feature;
    public string Desc;
    public override int LoadKey(string _key)
    {
        int key = GetKey(_key);
        return key;
    }
    public override void LoadConfig(string input)
    {
        try {
        string[] tables = input.Split('\t');
        int.TryParse(tables[0],out RecommendID);
            if (tables[1].Contains("["))
            {
                HeroIDList = JsonMapper.ToObject<int[]>(tables[1]);
            }
            else
            {
                string[] HeroIDListStringArray = tables[1].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
                HeroIDList = new int[HeroIDListStringArray.Length];
                for (int i=0;i<HeroIDListStringArray.Length;i++)
                {
                     int.TryParse(HeroIDListStringArray[i],out HeroIDList[i]);
                }
            }
            if (tables[2].Contains("["))
            {
                PosIndexList = JsonMapper.ToObject<int[]>(tables[2]);
            }
            else
            {
                string[] PosIndexListStringArray = tables[2].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
                PosIndexList = new int[PosIndexListStringArray.Length];
                for (int i=0;i<PosIndexListStringArray.Length;i++)
                {
                     int.TryParse(PosIndexListStringArray[i],out PosIndexList[i]);
                }
            }
            Name = tables[3];
            Feature = tables[4];
            Desc = tables[5];
        }
        catch (Exception exception)
        {
            Debug.LogError(exception);
        }
    }
}
Main/Config/Configs/LineupRecommendConfig.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1dba5f6e898ed7a41b2ef35456c8d731
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Core/NetworkPackage/DTCFile/ServerPack/HB1_Role/DTCB129_tagSCLineupRecommendInfo.cs
New file
@@ -0,0 +1,12 @@
using UnityEngine;
using System.Collections;
// B1 29 阵容推荐信息 #tagSCLineupRecommendInfo
public class DTCB129_tagSCLineupRecommendInfo : DtcBasic {
    public override void Done(GameNetPackBasic vNetPack) {
        base.Done(vNetPack);
        HB129_tagSCLineupRecommendInfo vNetData = vNetPack as HB129_tagSCLineupRecommendInfo;
        LineupRecommendManager.Instance.UpdateLineupRecommendInfo(vNetData);
    }
}
Main/Core/NetworkPackage/DTCFile/ServerPack/HB1_Role/DTCB129_tagSCLineupRecommendInfo.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c9d2c83b99b093c4f990e8ebb1bc14f2
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Core/NetworkPackage/DataToCtl/PackageRegedit.cs
@@ -133,6 +133,7 @@
        Register(typeof(HB310_tagMCTalk), typeof(DTCB310_tagMCTalk));
        Register(typeof(HB311_tagMCTalkCacheList), typeof(DTCB311_tagMCTalkCacheList));
        Register(typeof(HA319_tagMCPackDownloadRecord), typeof(DTCA319_tagMCPackDownloadRecord));
        Register(typeof(HB129_tagSCLineupRecommendInfo), typeof(DTCB129_tagSCLineupRecommendInfo));
    }
    //主工程注册封包
Main/Core/NetworkPackage/ServerPack/HB1_Role/HB129_tagSCLineupRecommendInfo.cs
New file
@@ -0,0 +1,29 @@
using UnityEngine;
using System.Collections;
// B1 29 阵容推荐信息 #tagSCLineupRecommendInfo
public class HB129_tagSCLineupRecommendInfo : GameNetPackBasic {
    public byte Count;
    public  tagSCLineupRecommend[] RecommendList;
    public HB129_tagSCLineupRecommendInfo () {
        _cmd = (ushort)0xB129;
    }
    public override void ReadFromBytes (byte[] vBytes) {
        TransBytes (out Count, vBytes, NetDataType.BYTE);
        RecommendList = new tagSCLineupRecommend[Count];
        for (int i = 0; i < Count; i ++) {
            RecommendList[i] = new tagSCLineupRecommend();
            TransBytes (out RecommendList[i].RecommendID, vBytes, NetDataType.BYTE);
            TransBytes (out RecommendList[i].AwardState, vBytes, NetDataType.DWORD);
        }
    }
    public class tagSCLineupRecommend {
        public byte RecommendID;        //推荐阵容表ID
        public uint AwardState;        //推荐武将领奖状态,按武将配置的顺序位存储是否已领取
    }
}
Main/Core/NetworkPackage/ServerPack/HB1_Role/HB129_tagSCLineupRecommendInfo.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 438f34b9f832ae1458a219768ac86057
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Main.cs
@@ -92,6 +92,7 @@
        managers.Add(AttributeManager.Instance);
        managers.Add(FuncNPCManager.Instance);
        managers.Add(GuildBossManager.Instance);
        managers.Add(LineupRecommendManager.Instance);
        foreach (var manager in managers)
        {
Main/System/HeroUI/HeroCollectionLvUpWin.cs
@@ -32,7 +32,7 @@
    
    [SerializeField] GameObject fullImg;
    [SerializeField] Text titleText;
    // [SerializeField] Text titleText;
    protected override void InitComponent()
@@ -93,29 +93,34 @@
        // }
        // else
        {
            fullPanel.SetActive(false);
            lvupPanel.SetActive(true);
            // fullPanel.SetActive(true);
            lvupPanel.SetActive(state == 1);
            fullHeadCell.Init(HeroUIManager.Instance.selectCollectHeroID, config.SkinIDList[0], colData.BookStarLV);
            name3.text = colData.BookBreakLV == 0 ? config.Name : Language.Get("herocardbreaklv", config.Name, colData.BookBreakLV);
            btn.SetActive(true);
            beforeHeadCell.Init(HeroUIManager.Instance.selectCollectHeroID, config.SkinIDList[0], colData.BookStarLV);
            name1.text = colData.BookBreakLV == 0 ? config.Name : Language.Get("herocardbreaklv", config.Name, colData.BookBreakLV);
            // beforeHeadCell.Init(HeroUIManager.Instance.selectCollectHeroID, config.SkinIDList[0], colData.BookStarLV);
            // name1.text = colData.BookBreakLV == 0 ? config.Name : Language.Get("herocardbreaklv", config.Name, colData.BookBreakLV);
            // int addPer = 0;
            var qualityConfig = HeroQualityConfig.Get(config.Quality);
            awardInfo.text = string.Empty;
            unActiveGo.SetActive(false);
            titleText.text = Language.Get("HeroAwake12");
            // titleText.text = Language.Get("HeroAwake12");
            int afterBreakLV = colData.BookBreakLV;
            int afterStarLV = colData.BookStarLV;
            if (state == 1)
            {
                lvupPanel.SetActive(true);
                //激活
                // addPer = qualityConfig.BookInitAddPer;
                btnText.text = Language.Get("L1131");   //L1131    激活
                awardInfo.text = Language.Get("HeroAwake10", UIHelper.GetIconNameWithMoneyType(qualityConfig.BookActAwardMoney[0]),
                    qualityConfig.BookActAwardMoney[1]);
                unActiveGo.SetActive(true);
                titleText.text = Language.Get("HeroAwake11");
                // titleText.text = Language.Get("HeroAwake11");
            }
            // else if (state == 3)
            // {
@@ -144,16 +149,16 @@
                    btnText.text = Language.Get("L1001");
                }
                fullPanel.SetActive(true);
                // fullPanel.SetActive(true);
                lvupPanel.SetActive(false);
                fullHeadCell.Init(HeroUIManager.Instance.selectCollectHeroID, config.SkinIDList[0], colData.BookStarLV);
                name3.text = colData.BookBreakLV == 0 ? config.Name : Language.Get("herocardbreaklv", config.Name, colData.BookBreakLV);
                // fullHeadCell.Init(HeroUIManager.Instance.selectCollectHeroID, config.SkinIDList[0], colData.BookStarLV);
                // name3.text = colData.BookBreakLV == 0 ? config.Name : Language.Get("herocardbreaklv", config.Name, colData.BookBreakLV);
            }
            afterHeadCell.Init(HeroUIManager.Instance.selectCollectHeroID, config.SkinIDList[0], afterStarLV);
            name2.text = afterBreakLV == 0 ? config.Name :Language.Get("herocardbreaklv", config.Name, afterBreakLV);
            // afterHeadCell.Init(HeroUIManager.Instance.selectCollectHeroID, config.SkinIDList[0], afterStarLV);
            // name2.text = afterBreakLV == 0 ? config.Name :Language.Get("herocardbreaklv", config.Name, afterBreakLV);
            // for (int i = 0; i < beforeAttrValues.Length; i++)
Main/System/HeroUI/HeroListWin.cs
@@ -19,6 +19,8 @@
    [SerializeField] Button changeHeroPosBtn; //布阵按钮
    [SerializeField] Transform heroSelectBehaviour;
    HeroSelectBehaviour fiterManager;  //武将筛选
    [SerializeField] ButtonEx lineupRecommendBtn;
    SinglePack singlePack;
@@ -40,6 +42,10 @@
        });
        fiterManager = HeroSelectBehaviour.Create(heroSelectBehaviour);
        lineupRecommendBtn.AddListener(() =>
        {
            UIManager.Instance.OpenWindow<LineupRecommendBaseWin>();
        });
    }
@@ -106,7 +112,7 @@
                continue;
            if (hero.heroId == heroID)
            {
                return index/4 - 1;
                return index / 4 - 1;
            }
        }
        return -1;
@@ -120,7 +126,7 @@
        RefreshPackCount();
    }
@@ -263,7 +269,7 @@
    }
    void GridRefreshEvent(PackType type)
    {
    {
        if (type != PackType.Hero)
            return;
Main/System/LineupRecommend.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 51bbd3838772ee843ac23ef8ff48b89c
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/LineupRecommend/LineupRecommendBaseWin.cs
New file
@@ -0,0 +1,20 @@
using UnityEngine;
public class LineupRecommendBaseWin : OneLevelWin
{
    protected override void OpenSubUIByTabIndex()
    {
        switch (functionOrder)
        {
            case 0:
                currentSubUI = UIManager.Instance.OpenWindow<LineupRecommendWin>();
                break;
            default:
                Debug.LogWarning("未知的标签索引: " + functionOrder);
                break;
        }
    }
}
Main/System/LineupRecommend/LineupRecommendBaseWin.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9441087b3e26ee84aa8e21ea77bd78e1
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/LineupRecommend/LineupRecommendCell.cs
New file
@@ -0,0 +1,100 @@
using System.Collections.Generic;
using System.Text;
using UnityEngine;
public class LineupRecommendCell : MonoBehaviour
{
    [SerializeField] List<LineupRecommendItem> lineupRecommendItems = new List<LineupRecommendItem>();
    [SerializeField] TextEx txtLineupName;
    [SerializeField] TextEx txtHeroCount;
    [SerializeField] ButtonEx btnUse;
    [SerializeField] Transform transOn;
    [SerializeField] ButtonEx btnOff;
    [SerializeField] RichText txtLineupDesc;
    [SerializeField] Transform transOff;
    [SerializeField] ButtonEx btnOn;
    LineupRecommendManager manager { get { return LineupRecommendManager.Instance; } }
    public void Display(int index)
    {
        var list = manager.GetSortShowList();
        if (index < 0 || index >= list.Count)
            return;
        var recommendID = list[index];
        if (!LineupRecommendConfig.HasKey(recommendID))
            return;
        var config = LineupRecommendConfig.Get(recommendID);
        if (!manager.TryGetHeroIDListByRecommendID(recommendID, out int[] heroIDArr) || heroIDArr.IsNullOrEmpty())
            return;
        if (!TryGetHasLineupHeroCount(recommendID, out int hasCout, out int totalCount))
            return;
        bool isOn = manager.IsOn(recommendID);
        transOn.SetActive(isOn);
        transOff.SetActive(!isOn);
        for (int i = 0; i < lineupRecommendItems.Count; i++)
        {
            if (i < heroIDArr.Length)
            {
                lineupRecommendItems[i].SetActive(true);
                lineupRecommendItems[i].Display(recommendID, i);
            }
            else
            {
                lineupRecommendItems[i].SetActive(false);
            }
        }
        txtLineupName.text = config.Name;
        txtHeroCount.text = Language.Get("LineupRecommend02", hasCout, totalCount);
        txtLineupDesc.text = GetDesc(recommendID);
        btnUse.SetListener(() =>
        {
            manager.UseTeam(recommendID);
        });
        btnOff.SetListener(() =>
        {
            manager.SetOn(recommendID, false);
        });
        btnOn.SetListener(() =>
        {
            manager.SetOn(recommendID, true);
        });
    }
    public bool TryGetHasLineupHeroCount(int recommendID, out int hasCout, out int totalCount)
    {
        hasCout = 0;
        totalCount = 0;
        if (!manager.TryGetHeroIDListByRecommendID(recommendID, out int[] heroIDArr) || heroIDArr.IsNullOrEmpty())
            return false;
        totalCount = heroIDArr.Length;
        foreach (var heroID in heroIDArr)
        {
            bool isHasHero = HeroManager.Instance.HasHero(heroID);
            if (isHasHero)
            {
                hasCout += 1;
            }
        }
        return true;
    }
    public string GetDesc(int recommendID)
    {
        if (!LineupRecommendConfig.HasKey(recommendID))
            return string.Empty;
        var config = LineupRecommendConfig.Get(recommendID);
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.Append(Language.Get("LineupRecommend04"));
        stringBuilder.Append(config.Feature);
        stringBuilder.AppendLine();
        stringBuilder.Append(Language.Get("LineupRecommend05"));
        stringBuilder.Append(config.Desc);
        return stringBuilder.ToString();
    }
}
Main/System/LineupRecommend/LineupRecommendCell.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2057b29ec4ef80b41a56fca1d621c514
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/LineupRecommend/LineupRecommendItem.cs
New file
@@ -0,0 +1,74 @@
using UnityEngine;
public class LineupRecommendItem : MonoBehaviour
{
    [SerializeField] ButtonEx btnClick;
    [SerializeField] ImageEx imgSquareIcon;
    [SerializeField] ImageEx imgHeroHead;
    [SerializeField] ImageEx imgCountry;
    [SerializeField] TextEx txtName;
    [SerializeField] ImageEx imgMask;
    [SerializeField] TextEx txtNoHave;
    [SerializeField] ImageEx imgMoney;
    [SerializeField] TextEx txtMoney;
    [SerializeField] Color32 colMoneyNoActivate;
    [SerializeField] Color32 colMoneyCanActivate;
    [SerializeField] TextEx txtDesc;
    [SerializeField] ImageEx imgRed;
    LineupRecommendManager manager { get { return LineupRecommendManager.Instance; } }
    public void Display(int recommendID, int index)
    {
        if (!manager.TryGetHeroConfigByIndex(recommendID, index, out HeroConfig heroConfig))
            return;
        if (!manager.TryGetMoneyInfo(recommendID, index, out int moneyType, out int moneyNeedCnt))
            return;
        int heroID = heroConfig.HeroID;
        if (!manager.TryGetHeroSkinConfig(heroID, out HeroSkinConfig heroSkinConfig))
            return;
        var sprite = UILoader.LoadSprite("HeroHead", heroSkinConfig.SquareIcon);
        if (sprite == null)
        {
            imgHeroHead.SetSprite("herohead_default");
        }
        else
        {
            imgHeroHead.overrideSprite = sprite;
        }
        imgSquareIcon.SetSprite("heroheadBG" + heroConfig.Quality);
        imgCountry.SetSprite(HeroUIManager.Instance.GetCountryIconName(heroConfig.Country));
        txtName.text = heroConfig.Name;
        txtDesc.text = heroConfig.Desc;
        LineupRecommendHeroState heroState = manager.GetHeroState(recommendID, index);
        imgMask.SetActive(heroState != LineupRecommendHeroState.ActivateAndHave);
        txtNoHave.SetActive(heroState == LineupRecommendHeroState.ActivateButNoHave);
        imgMoney.SetActive(heroState == LineupRecommendHeroState.NoActivate || heroState == LineupRecommendHeroState.CanActivate);
        txtMoney.SetActive(heroState == LineupRecommendHeroState.NoActivate || heroState == LineupRecommendHeroState.CanActivate);
        imgRed.SetActive(heroState == LineupRecommendHeroState.CanActivate);
        imgMoney.SetIconWithMoneyType(moneyType);
        imgMoney.gray = heroState == LineupRecommendHeroState.NoActivate;
        txtMoney.text = moneyNeedCnt.ToString();
        txtMoney.color = heroState == LineupRecommendHeroState.NoActivate ? colMoneyNoActivate : colMoneyCanActivate;
        btnClick.SetListener(() =>
        {
            if (heroState == LineupRecommendHeroState.CanActivate)
            {
                manager.SendGetReward(recommendID, index);
            }
            else
            {
                HeroUIManager.Instance.selectForPreviewHeroID = heroConfig.HeroID;
                UIManager.Instance.OpenWindow<HeroBestWin>();
            }
        });
    }
}
Main/System/LineupRecommend/LineupRecommendItem.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e23320880bdf6fd40a654bf05ee2a9c6
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/LineupRecommend/LineupRecommendManager.cs
New file
@@ -0,0 +1,328 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using UnityEngine;
public enum LineupRecommendHeroState
{
    NoActivate = 0,             //0 - 未激活
    CanActivate = 1,            // 1 - 可激活
    ActivateAndHave = 2,        // 2 - 已获得
    ActivateButNoHave = 3,      // 3 - 未获得
}
public class LineupRecommendManager : GameSystemManager<LineupRecommendManager>
{
    Dictionary<int, uint> haveDict = new Dictionary<int, uint>();
    public event Action OnUpdateLineupRecommendInfoEvent;
    public override void Init()
    {
        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent += OnBeforePlayerDataInitializeEvent;
        DTC0403_tagPlayerLoginLoadOK.playerLoginOkEvent += OnPlayerLoginOk;
        HeroManager.Instance.onHeroChangeEvent += OnHeroChangeEvent;
        HeroManager.Instance.onHeroDeleteEvent += OnHeroDeleteEvent;
        HeroUIManager.Instance.OnHeroCollectEvent += OnHeroCollectEvent;
        FuncOpen.Instance.OnFuncStateChangeEvent += OnFuncStateChangeEvent;
    }
    public override void Release()
    {
        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent -= OnBeforePlayerDataInitializeEvent;
        DTC0403_tagPlayerLoginLoadOK.playerLoginOkEvent -= OnPlayerLoginOk;
        HeroManager.Instance.onHeroChangeEvent -= OnHeroChangeEvent;
        HeroManager.Instance.onHeroDeleteEvent -= OnHeroDeleteEvent;
        HeroUIManager.Instance.OnHeroCollectEvent -= OnHeroCollectEvent;
        FuncOpen.Instance.OnFuncStateChangeEvent -= OnFuncStateChangeEvent;
    }
    private void OnFuncStateChangeEvent(int obj)
    {
        if (obj != funcId)
            return;
        UpdateRedPoint();
    }
    private void OnPlayerLoginOk()
    {
        UpdateRedPoint();
    }
    private void OnHeroCollectEvent()
    {
        UpdateRedPoint();
    }
    private void OnHeroDeleteEvent(int obj)
    {
        UpdateRedPoint();
    }
    private void OnHeroChangeEvent(HeroInfo heroInfo)
    {
        UpdateRedPoint();
    }
    private void OnBeforePlayerDataInitializeEvent()
    {
        haveDict.Clear();
    }
    // 哪些id是展开的
    List<int> onList = new List<int>();
    public event Action OnUpdateSwitchOnOrOffEvent;
    public void ClearOnList()
    {
        onList.Clear();
    }
    public bool IsOn(int id)
    {
        return onList.Contains(id);
    }
    public void SetOn(int id, bool isOn)
    {
        if (isOn)
        {
            if (!onList.Contains(id))
            {
                onList.Add(id);
                OnUpdateSwitchOnOrOffEvent?.Invoke();
            }
        }
        else
        {
            onList.Remove(id);
            OnUpdateSwitchOnOrOffEvent?.Invoke();
        }
    }
    List<int> sortShowList = null;
    public List<int> GetSortShowList()
    {
        if (sortShowList.IsNullOrEmpty())
        {
            sortShowList = LineupRecommendConfig.GetKeys();
            sortShowList.Sort();
        }
        return sortShowList;
    }
    public bool TryGetMoneyInfo(int RecommendID, int index, out int moneyType, out int moneyNeedCnt)
    {
        moneyType = 0;
        moneyNeedCnt = 0;
        if (!TryGetHeroConfigByIndex(RecommendID, index, out HeroConfig config))
            return false;
        int quality = config.Quality;
        if (!HeroQualityConfig.HasKey(quality))
            return false;
        HeroQualityConfig heroQualityConfig = HeroQualityConfig.Get(quality);
        int[] recommendAwardMoney = heroQualityConfig.RecommendAwardMoney;
        if (recommendAwardMoney.IsNullOrEmpty() || recommendAwardMoney.Length < 2)
            return false;
        moneyType = recommendAwardMoney[0];
        moneyNeedCnt = recommendAwardMoney[1];
        return true;
    }
    public bool TryGetHeroSkinConfig(int heroID, out HeroSkinConfig skinConfig)
    {
        skinConfig = null;
        if (!HeroConfig.HasKey(heroID))
            return false;
        HeroConfig heroConfig = HeroConfig.Get(heroID);
        int[] skinIDList = heroConfig.SkinIDList;
        if (skinIDList.IsNullOrEmpty())
            return false;
        int skinID = skinIDList[0];
        if (!HeroSkinConfig.HasKey(skinID))
            return false;
        skinConfig = HeroSkinConfig.Get(skinID);
        return true;
    }
    public bool TryGetHaveDictValue(int recommendID, out uint awardState)
    {
        return haveDict.TryGetValue(recommendID, out awardState);
    }
    public bool TryGetHeroIDListByRecommendID(int recommendID, out int[] heroIDArr)
    {
        heroIDArr = null;
        if (!LineupRecommendConfig.HasKey(recommendID))
            return false;
        LineupRecommendConfig config = LineupRecommendConfig.Get(recommendID);
        heroIDArr = config.HeroIDList;
        return true;
    }
    // 推荐武将是否一个也没有
    public bool HasHeroMin(int recommendID)
    {
        if (!TryGetHeroIDListByRecommendID(recommendID, out int[] heroIDArr) || heroIDArr.IsNullOrEmpty())
            return false;
        foreach (var heroID in heroIDArr)
        {
            if (HeroManager.Instance.HasHero(heroID))
                return true;
        }
        return false;
    }
    public void UseTeam(int recommendID)
    {
        if (!LineupRecommendConfig.HasKey(recommendID))
            return;
        LineupRecommendConfig config = LineupRecommendConfig.Get(recommendID);
        int[] heroIDList = config.HeroIDList;
        int[] posIndexList = config.PosIndexList;
        if (heroIDList.IsNullOrEmpty() || posIndexList.IsNullOrEmpty() || heroIDList.Length != posIndexList.Length)
            return;
        bool hasHeroMin = HasHeroMin(recommendID);
        if (!hasHeroMin)
        {
            SysNotifyMgr.Instance.ShowTip("LineupRecommendErr01");
            return;
        }
        TeamBase storyTeam = TeamManager.Instance.GetTeam(TeamType.Story);
        storyTeam.RemoveAllHeroes();
        int currentMaxLineupCount = TeamConst.MaxTeamHeroCount - HeroUIManager.Instance.lockIndexList.Count;
        for (int i = 0; i < heroIDList.Length; i++)
        {
            if (currentMaxLineupCount - storyTeam.GetTeamHeroCount() > 0)
            {
                int heroID = heroIDList[i];
                var hero = HeroManager.Instance.GetHeroByID(heroID);
                if (hero == null)
                    continue;
                storyTeam.AddHero(hero, Mathf.Max(0, posIndexList[i] - 1), true);
            }
        }
        storyTeam.SaveTeam();
    }
    public bool TryGetHeroConfigByIndex(int recommendID, int index, out HeroConfig config)
    {
        config = null;
        if (!TryGetHeroIDListByRecommendID(recommendID, out int[] heroIDArr) || heroIDArr.IsNullOrEmpty())
            return false;
        if (index < 0 || index >= heroIDArr.Length)
            return false;
        int heroID = heroIDArr[index];
        if (!HeroConfig.HasKey(heroID))
            return false;
        config = HeroConfig.Get(heroID);
        return true;
    }
    public LineupRecommendHeroState GetHeroState(int recommendID, int index)
    {
        if (!TryGetHeroConfigByIndex(recommendID, index, out HeroConfig config))
            return LineupRecommendHeroState.NoActivate;
        // heroBookState: 0未获得、1可激活、2常规、3突破升级、4星升级、5已满级
        int heroID = config.HeroID;
        int heroBookState = HeroUIManager.Instance.GetHeroBookState(heroID, config.Quality);
        bool isHaveAward = IsHaveAward(recommendID, index);
        bool isHasHero = HeroManager.Instance.HasHero(heroID);
        // 已获得:推荐武将已领奖 && 仍拥有该武将
        // 未获得:推荐武将已领奖 && 当前没有该武将 (已被消耗)
        if (isHaveAward)
            return isHasHero ? LineupRecommendHeroState.ActivateAndHave : LineupRecommendHeroState.ActivateButNoHave;
        // 可激活:没领取 && 图鉴状态可激活/已激活
        // 未激活:没领取 && 图鉴状态未激活/未获得
        return heroBookState > 0 ? LineupRecommendHeroState.CanActivate : LineupRecommendHeroState.NoActivate;
    }
    public bool IsHaveAward(int recommendID, int index)
    {
        if (TryGetHaveDictValue(recommendID, out uint awardState))
        {
            if (index >= 0 && index < 6)
            {
                uint mask = (uint)(1 << index);
                return (awardState & mask) != 0;
            }
        }
        return false;
    }
    readonly int funcId = 1;//武将
    Redpoint redpoint = new Redpoint(MainRedDot.HeroCardRedpoint, MainRedDot.LineupRecommendRepoint);
    public void UpdateRedPoint()
    {
        redpoint.state = RedPointState.None;
        //武将没开不刷红点
        if (!FuncOpen.Instance.IsFuncOpen(funcId))
            return;
        if (TryGetJumpIndex(out int index))
        {
            redpoint.state = RedPointState.Simple;
        }
    }
    //第一个可领取的武将所在行索引
    public bool TryGetJumpIndex(out int index)
    {
        index = 0;
        List<int> sortShowList = GetSortShowList();
        if (sortShowList.IsNullOrEmpty())
            return false;
        for (int i = 0; i < sortShowList.Count; i++)
        {
            int recommendID = sortShowList[i];
            if (!TryGetHeroIDListByRecommendID(recommendID, out int[] heroIDArr) || heroIDArr.IsNullOrEmpty())
                continue;
            for (int j = 0; j < heroIDArr.Length; j++)
            {
                LineupRecommendHeroState heroState = GetHeroState(recommendID, j);
                if (heroState == LineupRecommendHeroState.CanActivate)
                {
                    index = i;
                    return true;
                }
            }
        }
        return false;
    }
    public void SendGetReward(int recommendID, int index)
    {
        var pack = new CA504_tagCMPlayerGetReward();
        pack.RewardType = 4;
        pack.DataEx = (uint)recommendID;
        string indexStr = index.ToString();
        pack.DataExStr = indexStr;
        pack.DataExStrLen = (byte)indexStr.Length;
        GameNetSystem.Instance.SendInfo(pack);
    }
    public void UpdateLineupRecommendInfo(HB129_tagSCLineupRecommendInfo vNetData)
    {
        if (vNetData == null || vNetData.RecommendList.IsNullOrEmpty())
            return;
        foreach (var v in vNetData.RecommendList)
        {
            haveDict[v.RecommendID] = v.AwardState;
        }
        UpdateRedPoint();
        OnUpdateLineupRecommendInfoEvent?.Invoke();
    }
}
Main/System/LineupRecommend/LineupRecommendManager.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 662b0c20ef6428948bb5984735291ebb
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/LineupRecommend/LineupRecommendWin.cs
New file
@@ -0,0 +1,136 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class LineupRecommendWin : UIBase
{
    [SerializeField] AvatarCell avatarCell;
    [SerializeField] Text txtPlayerName;
    [SerializeField] Text txtFightPoint;
    [SerializeField] OfficialTitleCell officialRankText;
    [SerializeField] ScrollerController scroller;
    LineupRecommendManager manager { get { return LineupRecommendManager.Instance; } }
    protected override void InitComponent()
    {
        base.InitComponent();
        avatarCell.redpoint.redpointId = MainRedDot.PhantasmPavilionRepoint;
        avatarCell.button.SetListener(() =>
        {
            UIManager.Instance.OpenWindow<PlayerProfileWin>();
        });
    }
    protected override void OnPreOpen()
    {
        PlayerDatas.Instance.playerDataRefreshEvent += PlayerDataRefresh;
        scroller.OnRefreshCell += OnRefreshCell;
        scroller.OnGetDynamicSize += OnGetDynamicSize;
        manager.OnUpdateLineupRecommendInfoEvent += OnUpdateLineupRecommendInfoEvent;
        manager.OnUpdateSwitchOnOrOffEvent += OnUpdateSwitchOnOrOffEvent;
        manager.ClearOnList();
        UpdatePlayerInfo();
        scroller.lockType = EnhanceLockType.KeepVertical;
        CreateScoller();
        int index = 0;
        manager.TryGetJumpIndex(out index);
        scroller.JumpIndex(index);
    }
    protected override void OnPreClose()
    {
        PlayerDatas.Instance.playerDataRefreshEvent -= PlayerDataRefresh;
        scroller.OnRefreshCell -= OnRefreshCell;
        scroller.OnGetDynamicSize -= OnGetDynamicSize;
        manager.OnUpdateLineupRecommendInfoEvent -= OnUpdateLineupRecommendInfoEvent;
        manager.OnUpdateSwitchOnOrOffEvent -= OnUpdateSwitchOnOrOffEvent;
    }
    private void OnUpdateSwitchOnOrOffEvent()
    {
        CreateScoller();
    }
    private void OnUpdateLineupRecommendInfoEvent()
    {
        RefreshScoller();
    }
    private void OnRefreshCell(ScrollerDataType type, CellView cell)
    {
        var _cell = cell.GetComponent<LineupRecommendCell>();
        _cell?.Display(cell.index);
    }
    private bool OnGetDynamicSize(ScrollerDataType type, int index, out float height)
    {
        height = 0;
        List<int> sortShowList = manager.GetSortShowList();
        if (index < 0 || index >= sortShowList.Count)
            return false;
        var id = sortShowList[index];
        bool isOn = manager.IsOn(id);
        height = isOn ? 432 : 252;
        return true;
    }
    void PlayerDataRefresh(PlayerDataType type)
    {
        switch (type)
        {
            case PlayerDataType.FightPower:
                txtFightPoint.text = UIHelper.ReplaceLargeArtNum(PlayerDatas.Instance.baseData.FightPower);
                break;
            case PlayerDataType.RealmLevel:
                officialRankText.InitUI(PlayerDatas.Instance.baseData.realmLevel, PlayerDatas.Instance.baseData.TitleID);
                break;
            case PlayerDataType.Face:
            case PlayerDataType.FacePic:
                avatarCell.InitUI(AvatarHelper.GetAvatarModel((int)PlayerDatas.Instance.baseData.PlayerID,
                                                                PlayerDatas.Instance.baseData.face,
                                                                PlayerDatas.Instance.baseData.facePic));
                break;
            case PlayerDataType.ExAttr3:
                officialRankText.InitUI(PlayerDatas.Instance.baseData.realmLevel, PlayerDatas.Instance.baseData.TitleID);
                break;
        }
    }
    void RefreshScoller()
    {
        scroller.m_Scorller.RefreshActiveCellViews();
    }
    void CreateScoller()
    {
        scroller.Refresh();
        var list = manager.GetSortShowList();
        if (!list.IsNullOrEmpty())
        {
            for (int i = 0; i < list.Count; i++)
            {
                scroller.AddCell(ScrollerDataType.Header, i);
            }
        }
        scroller.Restart();
    }
    private void UpdatePlayerInfo()
    {
        // 从玩家数据中获取信息并更新UI
        avatarCell.InitUI(AvatarHelper.GetAvatarModel((int)PlayerDatas.Instance.baseData.PlayerID,
                                                        PlayerDatas.Instance.baseData.face,
                                                        PlayerDatas.Instance.baseData.facePic));
        txtPlayerName.text = PlayerDatas.Instance.baseData.PlayerName;
        txtFightPoint.text = UIHelper.ReplaceLargeArtNum(PlayerDatas.Instance.baseData.FightPower);
        officialRankText.InitUI(PlayerDatas.Instance.baseData.realmLevel, PlayerDatas.Instance.baseData.TitleID);
    }
}
Main/System/LineupRecommend/LineupRecommendWin.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: def9cd8112cd17a48b0d023c0eb20781
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Redpoint/MainRedDot.cs
@@ -130,6 +130,7 @@
    public const int ArenaRepoint = 470; //演武场
    public const int TianziBillboradRepoint = 471; //天子的考验
    public const int PhantasmPavilionRepoint = 472; //幻境阁
    public const int LineupRecommendRepoint = 473; //阵容推荐
    public void Register()
    {