lcy
2026-04-17 9388a25ed33fe004b6e5e6e4730e4f67715d1864
492 武将登场 高级战令
6个文件已修改
12个文件已添加
1074 ■■■■■ 已修改文件
Main/Config/Configs/ActHeroAppearConfig.cs 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/BattlePass/BattlePassManager.cs 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCallWin.cs 27 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutManager.cs 407 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutWin.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutZhanLingCell.cs 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutZhanLingCell.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutZhanLingPreviewCell.cs 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutZhanLingPreviewCell.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutZhanLingPreviewHCell.cs 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutZhanLingPreviewHCell.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutZhanLingPreviewHWin.cs 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutZhanLingPreviewHWin.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutZhanLingPreviewWin.cs 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutZhanLingPreviewWin.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutZhanLingWin.cs 151 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutZhanLingWin.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/UIBase/UIJumpManager.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/ActHeroAppearConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           Thursday, March 26, 2026
//    [  Date ]:           Thursday, April 16, 2026
//--------------------------------------------------------
using System.Collections.Generic;
@@ -20,6 +20,7 @@
    public int ActNum;
    public int[] ActHeroIDList;
    public int ActTreasureType;
    public int ActZhanlingType;
    public int StarGiftTempID;
    public int[] SkinCTGIDList;
    public int[] GiftCTGIDList;
@@ -59,15 +60,17 @@
            int.TryParse(tables[3],out ActTreasureType); 
            int.TryParse(tables[4],out StarGiftTempID);
            int.TryParse(tables[4],out ActZhanlingType);
            if (tables[5].Contains("["))
            int.TryParse(tables[5],out StarGiftTempID);
            if (tables[6].Contains("["))
            {
                SkinCTGIDList = JsonMapper.ToObject<int[]>(tables[5]);
                SkinCTGIDList = JsonMapper.ToObject<int[]>(tables[6]);
            }
            else
            {
                string[] SkinCTGIDListStringArray = tables[5].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
                string[] SkinCTGIDListStringArray = tables[6].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
                SkinCTGIDList = new int[SkinCTGIDListStringArray.Length];
                for (int i=0;i<SkinCTGIDListStringArray.Length;i++)
                {
@@ -75,13 +78,13 @@
                }
            }
            if (tables[6].Contains("["))
            if (tables[7].Contains("["))
            {
                GiftCTGIDList = JsonMapper.ToObject<int[]>(tables[6]);
                GiftCTGIDList = JsonMapper.ToObject<int[]>(tables[7]);
            }
            else
            {
                string[] GiftCTGIDListStringArray = tables[6].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
                string[] GiftCTGIDListStringArray = tables[7].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
                GiftCTGIDList = new int[GiftCTGIDListStringArray.Length];
                for (int i=0;i<GiftCTGIDListStringArray.Length;i++)
                {
@@ -89,15 +92,15 @@
                }
            }
            int.TryParse(tables[7],out GiftShopType);
            int.TryParse(tables[8],out GiftShopType);
            int.TryParse(tables[8],out ExShopType);
            int.TryParse(tables[9],out ExShopType);
            int.TryParse(tables[9],out ExShopCostItemID);
            int.TryParse(tables[10],out ExShopCostItemID);
            int.TryParse(tables[10],out SignTempID);
            int.TryParse(tables[11],out SignTempID);
            int.TryParse(tables[11],out BillTempID);
            int.TryParse(tables[12],out BillTempID);
        }
        catch (Exception exception)
        {
Main/System/BattlePass/BattlePassManager.cs
@@ -133,11 +133,17 @@
                    UpdateWeekRedPoint();
                    break;
                }
        }
        if (HeroDebutManager.IsZhanLingType(type))
        {
            HeroDebutManager.Instance.UpdateRedpoint();
        }
    }
    #endregion
    //是否有任何奖励可以领取
    public bool HasAnyAward(int type, int totalValue)
@@ -370,7 +376,14 @@
        }
        return 0;
        // 处理ZhanLing类型(从HeroDebutManager获取缓存的ZhanLingType列表)
        if (HeroDebutManager.IsZhanLingType(_type))
        {
            return HeroDebutManager.GetZhanLingValueByType(_type);
        }
        return 0;
    }
}
Main/System/HeroDebut/HeroDebutCallWin.cs
@@ -44,6 +44,7 @@
    [SerializeField] UIHeroController lhController;
    [SerializeField] UIHeroController uiHeroController;
    [SerializeField] HeroDebutCallBubbleCell[] bubbleCell;
    [SerializeField] RichText richText;
    [SerializeField] float modleSize = 1f;
    HeroDebutManager manager => HeroDebutManager.Instance;
@@ -263,8 +264,10 @@
        xbButton10.Display(config.ActTreasureType, 1);
        resMoneyCallCntText.text = Language.Get("HeroDebut24", Mathf.Max(treasureSetConfig.DailyMaxCountMoney - xbTypeInfo.treasureCountTodayGold, 0));
        var needCount = GetNextXBCountForBigAward(treasureType);
        nextBigAwardCntText.text = Language.Get("HeroDebut08", needCount.ToString());
        int buyState = manager.GetZhanLingBuyState();
        bool isBuyPaidH = buyState == 2 || buyState == 3;
        var needCount = manager.GetNextXBCountForBigAward(treasureType) - (isBuyPaidH ? manager.subVulue : 0);
        nextBigAwardCntText.text = Language.Get("HeroDebut08", needCount <= 0 ? 1 : needCount);
        heroQualityText.text = Language.Get($"heroCallQaulity{heroConfig.Quality}");
        manager.SetheroQaulityColor(heroQualityText, heroConfig.Quality);
@@ -291,28 +294,14 @@
            }
        }
        // 购买了高级战令(玄级)时隐藏richText
        richText.SetActive(!isBuyPaidH);
        ShowTop3();
        OnSecondEvent();
    }
    public int GetNextXBCountForBigAward(int type)
    {
        XBTypeInfo typeInfo = HappyXBModel.Instance.GetXBInfoByType(type);
        if (typeInfo == null) return 0;
        var xbConfig = HappyXBModel.Instance.GetXBItemConfigByType(type);
        var luckList = xbConfig.LuckyItemRateInfo.Keys.ToList();
        luckList.Sort();
        for (int i = 0; i < luckList.Count; i++)
        {
            var luckyValue = typeInfo.luckValue;
            if (luckyValue < luckList[i])
            {
                return luckList[i] - luckyValue;
            }
        }
        return 0;
    }
    void ShowTop3()
    {
        for (int i = 0; i < top3NameText.Length; i++)
Main/System/HeroDebut/HeroDebutManager.cs
@@ -1,14 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Codice.Client.BaseCommands.Import;
using LitJson;
using UnityEngine;
public class HeroDebutManager : GameSystemManager<HeroDebutManager>, IOpenServerActivity
{
    // 缓存的ZhanLingType列表(从ActHeroAppearConfig获取,后续不变)
    private static List<int> zhanLingTypeList = null;
    public int[] xbGridArr;
    public Dictionary<int, int[][]> heroQaulityColor;
    public int[][] seeArr;
    public int subVulue;
    public override void Init()
    {
        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEventOnRelogin += OnBeforePlayerDataInitializeEventOnRelogin;
@@ -28,8 +33,11 @@
        xbGridArr = JsonMapper.ToObject<int[]>(config.Numerical1);
        heroQaulityColor = ConfigParse.ParseIntArray2Dict(config.Numerical2);
        seeArr = JsonMapper.ToObject<int[][]>(config.Numerical3);
        subVulue = int.Parse(config.Numerical4);
        InitRedPointId();
        BattlePassManager.Instance.BattlePassDataUpdateEvent += OnBattlePassDataUpdate;
    }
    public void SetheroQaulityColor(GradientText text, int qaulity)
@@ -52,6 +60,8 @@
        GeneralActInfoManager.Instance.OnUpdateActSignInfosEvent -= OnUpdateActSignInfosEvent;
        HeroManager.Instance.onHeroChangeEvent -= OnHeroChangeEvent;
        TimeMgr.Instance.OnDayEvent -= OnDayEvent;
        BattlePassManager.Instance.BattlePassDataUpdateEvent -= OnBattlePassDataUpdate;
    }
    private void OnDayEvent()
@@ -124,8 +134,8 @@
    {
        if (type == operaType && state == 0)
        {
            gameRecDict.Clear();
            isSendFirst = true;
            gameRecDict.Clear();
            isSendFirst = true;
            onStateUpdate?.Invoke(activityID);
            TryPopWin();
            UpdateRedpoint();
@@ -297,12 +307,14 @@
    public Redpoint starUpRedpoint;
    public Redpoint shopRedpoint;
    public Redpoint giftRedpoint;
    public Redpoint zhanLingRedpoint;
    public void InitRedPointId()
    {
        checkInRedpoint ??= new Redpoint(MainRedDot.HeroDebutRepoint, GetRedPointId(HeroDebutRedPointType.CheckIn));
        starUpRedpoint ??= new Redpoint(MainRedDot.HeroDebutRepoint, GetRedPointId(HeroDebutRedPointType.StarUp));
        shopRedpoint ??= new Redpoint(MainRedDot.HeroDebutRepoint, GetRedPointId(HeroDebutRedPointType.Shop));
        giftRedpoint ??= new Redpoint(MainRedDot.HeroDebutRepoint, GetRedPointId(HeroDebutRedPointType.Gift));
        zhanLingRedpoint ??= new Redpoint(MainRedDot.HeroDebutRepoint, GetRedPointId(HeroDebutRedPointType.ZhanLing));
    }
    public void UpdateRedpoint()
@@ -312,6 +324,7 @@
        starUpRedpoint.state = RedPointState.None;
        shopRedpoint.state = RedPointState.None;
        giftRedpoint.state = RedPointState.None;
        zhanLingRedpoint.state = RedPointState.None;
        if (!IsHeroDebutOpen()) return;
@@ -334,6 +347,11 @@
        if (HasGiftCanHave())//皇权礼包
        {
            giftRedpoint.state = RedPointState.Simple;
        }
        if (HasZhanLingCanHave())//战令
        {
            zhanLingRedpoint.state = RedPointState.Simple;
        }
    }
    #endregion
@@ -754,7 +772,43 @@
        return config.ActHeroIDList[callHeroIndex];
    }
    public int GetLuckValueAward(int type)
    {
        XBTypeInfo typeInfo = HappyXBModel.Instance.GetXBInfoByType(type);
        if (typeInfo == null) return 0;
        var xbConfig = HappyXBModel.Instance.GetXBItemConfigByType(type);
        var luckList = xbConfig.LuckyItemRateInfo.Keys.ToList();
        luckList.Sort();
        for (int i = 0; i < luckList.Count; i++)
        {
            var luckyValue = typeInfo.luckValue;
            if (luckyValue < luckList[i])
            {
                return luckList[i];
            }
        }
        return 0;
    }
    public int GetNextXBCountForBigAward(int type)
    {
        XBTypeInfo typeInfo = HappyXBModel.Instance.GetXBInfoByType(type);
        if (typeInfo == null) return 0;
        var xbConfig = HappyXBModel.Instance.GetXBItemConfigByType(type);
        var luckList = xbConfig.LuckyItemRateInfo.Keys.ToList();
        luckList.Sort();
        for (int i = 0; i < luckList.Count; i++)
        {
            var luckyValue = typeInfo.luckValue;
            if (luckyValue < luckList[i])
            {
                return luckList[i] - luckyValue;
            }
        }
        return 0;
    }
    #endregion
    #region 时装特卖
@@ -931,6 +985,354 @@
    #endregion
    #region 战令
    /// <summary>
    /// 武将登场战令类型(从配置实时获取)
    /// </summary>
    public int ZhanLingType => GetCurrentZhanLingType();
    /// <summary>
    /// 获取当前战令类型
    /// </summary>
    private int GetCurrentZhanLingType()
    {
        var act = GetOperationHeroAppearInfo();
        if (act == null)
            return 0;
        var config = ActHeroAppearConfig.Get(act.CfgID);
        return config?.ActZhanlingType ?? 0;
    }
    /// <summary>
    /// 武将登场战令功能ID
    /// </summary>
    public const int ZhanLingFuncId = 63;
    /// <summary>
    /// 战令数据更新事件
    /// </summary>
    public event Action OnZhanLingUpdateEvent;
    private void OnBattlePassDataUpdate(int type)
    {
        if (type == ZhanLingType)
        {
            OnZhanLingUpdateEvent?.Invoke();
        }
    }
    /// <summary>
    /// 获取武将登场战令的当前进度值
    /// </summary>
    public int GetZhanLingValue()
    {
        var data = BattlePassManager.Instance.GetBattlePassData(ZhanLingType);
        return data != null ? (int)data.value1 : 0;
    }
    /// <summary>
    /// 判断指定类型是否为ZhanLing类型(缓存查询)
    /// </summary>
    public static bool IsZhanLingType(int type)
    {
        if (zhanLingTypeList == null)
        {
            zhanLingTypeList = ActHeroAppearConfig.GetValues()
                .Select(x => x.ActZhanlingType)
                .Where(x => x > 0)
                .Distinct()
                .ToList();
        }
        return zhanLingTypeList.Contains(type);
    }
    /// <summary>
    /// 获取指定ZhanLing类型的进度值
    /// </summary>
    public static int GetZhanLingValueByType(int zhanLingType)
    {
        var data = BattlePassManager.Instance.GetBattlePassData(zhanLingType);
        return data != null ? (int)data.value1 : 0;
    }
    /// <summary>
    /// 判断武将登场战令的指定等级是否达成
    /// </summary>
    public bool IsZhanLingNeedValueOk(int needValue)
    {
        return GetZhanLingValue() >= needValue;
    }
    /// <summary>
    /// 获取武将登场战令的购买状态
    /// 0 没购买进阶和玄级 1 购买了进阶没买玄级 2 购买了玄级没买进阶 3 购买了进阶和玄级
    /// </summary>
    public int GetZhanLingBuyState()
    {
        var data = BattlePassManager.Instance.GetBattlePassData(ZhanLingType);
        if (data == null)
            return 0;
        bool isBuyPaid = data.isActivite > 0;
        bool isBuyPaidH = data.isActiviteH > 0;
        if (isBuyPaid && isBuyPaidH)
            return 3;
        if (isBuyPaid)
            return 1;
        if (isBuyPaidH)
            return 2;
        return 0;
    }
    /// <summary>
    /// 是否有可领取的战令奖励
    /// </summary>
    public bool HasZhanLingCanHave()
    {
        var data = BattlePassManager.Instance.GetBattlePassData(ZhanLingType);
        if (data == null)
            return false;
        var dict = ZhanlingConfig.GetTypeToIDDict(ZhanLingType);
        if (dict.IsNullOrEmpty())
            return false;
        int buyState = GetZhanLingBuyState();
        bool isBuyPaid = buyState == 1 || buyState == 3;
        bool isBuyPaidH = buyState == 2 || buyState == 3;
        foreach (var kvp in dict)
        {
            int needValue = kvp.Key;
            // 检查免费奖励
            int freeState = GetZhanLingFreeGiftState(needValue);
            if (freeState == 1)
                return true;
            // 检查普通奖励(需要已购买进阶)
            if (isBuyPaid)
            {
                int paidState = GetZhanLingPaidGiftState(needValue);
                if (paidState == 1)
                    return true;
            }
            // 检查高级奖励(需要已购买玄级)
            if (isBuyPaidH)
            {
                int paidHState = GetZhanLingPaidGiftHState(needValue);
                if (paidHState == 1)
                    return true;
            }
        }
        return false;
    }
    /// <summary>
    /// 获取武将登场战令免费奖励状态
    /// 0 不能领 1 未领取 2 已领取
    /// </summary>
    public int GetZhanLingFreeGiftState(int needValue)
    {
        var data = BattlePassManager.Instance.GetBattlePassData(ZhanLingType);
        if (data == null)
            return 0;
        var totalValue = BattlePassManager.Instance.GetTotalValue(ZhanLingType);
        return BattlePassManager.Instance.GetBPCellAwardState(data, totalValue, needValue, 0);
    }
    /// <summary>
    /// 获取武将登场战令普通奖励状态
    /// 0 不能领 1 未领取 2 已领取
    /// </summary>
    public int GetZhanLingPaidGiftState(int needValue)
    {
        var data = BattlePassManager.Instance.GetBattlePassData(ZhanLingType);
        if (data == null)
            return 0;
        var totalValue = BattlePassManager.Instance.GetTotalValue(ZhanLingType);
        return BattlePassManager.Instance.GetBPCellAwardState(data, totalValue, needValue, 1);
    }
    /// <summary>
    /// 获取武将登场战令高级奖励状态
    /// 0 不能领 1 未领取 2 已领取
    /// </summary>
    public int GetZhanLingPaidGiftHState(int needValue)
    {
        var data = BattlePassManager.Instance.GetBattlePassData(ZhanLingType);
        if (data == null)
            return 0;
        var totalValue = BattlePassManager.Instance.GetTotalValue(ZhanLingType);
        return BattlePassManager.Instance.GetBPCellAwardState(data, totalValue, needValue, 2);
    }
    /// <summary>
    /// 一键领取武将登场战令所有可领取奖励
    /// </summary>
    public void HaveAllZhanLingGift()
    {
        var data = BattlePassManager.Instance.GetBattlePassData(ZhanLingType);
        if (data == null)
            return;
        if (PackManager.Instance.GetEmptyGridCount(PackType.Item) < 1)
        {
            SysNotifyMgr.Instance.ShowTip("GeRen_lhs_202580");
            return;
        }
        var totalValue = BattlePassManager.Instance.GetTotalValue(ZhanLingType);
        BattlePassManager.Instance.GetAllAward(data, ZhanLingType, totalValue);
    }
    #endregion
    #region 战令预览购买
    /// <summary>
    /// 当前预览的战令类型
    /// </summary>
    public int previewZhanLingType { get; private set; }
    /// <summary>
    /// 当前预览的礼包类型 1 普通战令礼包 2 高级战令礼包
    /// </summary>
    public int previewGiftType { get; private set; }
    /// <summary>
    /// 显示战令购买预览界面
    /// </summary>
    public void ShowZhanLingHBuy(int zhanLingType, int showGiftType)
    {
        previewZhanLingType = zhanLingType;
        previewGiftType = showGiftType;
        if (showGiftType == 1)
        {
            UIManager.Instance.OpenWindow<HeroDebutZhanLingPreviewWin>();
        }
        else if (showGiftType == 2)
        {
            UIManager.Instance.OpenWindow<HeroDebutZhanLingPreviewHWin>();
        }
    }
    /// <summary>
    /// 获取当前预览类型的充值ID
    /// </summary>
    public int GetPreviewCtgID()
    {
        int ctgid = 0;
        if (previewGiftType == 1)
        {
            ctgid = BattlePassManager.Instance.GetCTGIDByType(previewZhanLingType);
        }
        else if (previewGiftType == 2)
        {
            // 高级战令使用 Numerical3
            var config = FuncConfigConfig.Get("Zhanling");
            if (config != null)
            {
                var dict = ConfigParse.ParseIntArrayDict(config.Numerical3);
                if (dict.TryGetValue(previewZhanLingType, out var arr) && arr.Length > 0)
                {
                    ctgid = arr[0];
                }
            }
        }
        return ctgid;
    }
    /// <summary>
    /// 获取购买后所有等级的奖励
    /// </summary>
    /// <param name="maxCountPerSlot">每个相同的itemid每个格子最大同时显示的数量</param>
    public List<Item> GetPreviewGiftAllItem(int maxCountPerSlot = 20)
    {
        List<int> collectList = new List<int>();
        var dict = ZhanlingConfig.GetTypeToIDDict(previewZhanLingType);
        if (dict.IsNullOrEmpty())
            return new List<Item>();
        var arr = dict.Keys.ToArray();
        for (int i = 0; i < arr.Length; i++)
        {
            int needValue = arr[i];
            int zhanLingId = dict[needValue];
            collectList.Add(zhanLingId);
        }
        return CollectPreviewItems(collectList, maxCountPerSlot);
    }
    private List<Item> CollectPreviewItems(List<int> collectList, int maxCountPerSlot)
    {
        Dictionary<int, int> resultDict = new Dictionary<int, int>();
        for (int i = 0; i < collectList.Count; i++)
        {
            int zhanLingId = collectList[i];
            int[][] itemArr = GetPreviewItemArr(zhanLingId, previewGiftType);
            if (itemArr.IsNullOrEmpty())
                continue;
            for (int j = 0; j < itemArr.Length; j++)
            {
                int itemID = itemArr[j][0];
                int count = itemArr[j][1];
                if (resultDict.ContainsKey(itemID))
                    resultDict[itemID] += count;
                else
                    resultDict[itemID] = count;
            }
        }
        List<Item> result = GetItemListByDict(resultDict, maxCountPerSlot);
        result.Sort(CmpPreviewItem);
        return result;
    }
    private int[][] GetPreviewItemArr(int zhanLingId, int showGiftType)
    {
        var config = ZhanlingConfig.Get(zhanLingId);
        if (config == null)
            return new int[][] { };
        if (showGiftType == 1)
            return config.ZLRewardItemList;
        if (showGiftType == 2)
            return config.ZLRewardItemListH;
        return new int[][] { };
    }
    private List<Item> GetItemListByDict(Dictionary<int, int> dict, int maxCountPerSlot)
    {
        List<Item> result = new List<Item>();
        var arr = dict.Keys.ToArray();
        for (int i = 0; i < arr.Length; i++)
        {
            int itemID = arr[i];
            int count = dict[itemID];
            // 根据maxCountPerSlot拆分数量,每个Item最多显示maxCountPerSlot个
            int slotCount = Mathf.CeilToInt((float)count / maxCountPerSlot);
            for (int s = 0; s < slotCount; s++)
            {
                int itemCount = Mathf.Min(maxCountPerSlot, count - s * maxCountPerSlot);
                result.Add(new Item(itemID, itemCount));
            }
        }
        return result;
    }
    private int CmpPreviewItem(Item a, Item b)
    {
        int quality1 = ItemConfig.Get(a.id).ItemColor;
        int quality2 = ItemConfig.Get(b.id).ItemColor;
        if (quality1 != quality2)
            return quality2.CompareTo(quality1);
        return a.countEx.CompareTo(b.countEx);
    }
    #endregion
    #region 获奖记录
    public static readonly int RecordType = 311;
@@ -1019,6 +1421,7 @@
    StarUp = 2,
    Shop = 3,
    Gift = 4,
    ZhanLing = 5,
}
public class HeroDebutGameRec
Main/System/HeroDebut/HeroDebutWin.cs
@@ -28,6 +28,8 @@
    [SerializeField] UIHeroController lhController;
    [SerializeField] Image callRedImage;
    [SerializeField] ButtonEx closeButton;
    [SerializeField] ButtonEx zhanlingBtn;
    [SerializeField] RedpointBehaviour zhanlingRedpoint;
    [SerializeField] float modleSize = 0.8f;
    HeroDebutManager manager => HeroDebutManager.Instance;
    protected override void InitComponent()
@@ -39,6 +41,7 @@
        skinButton.SetListener(() => UIManager.Instance.OpenWindow<HeroDebutSkinWin>());
        giftButton.SetListener(() => UIManager.Instance.OpenWindow<HeroDebutGiftWin>());
        callButton.SetListener(() => UIManager.Instance.OpenWindow<HeroDebutCallWin>());
        zhanlingBtn.SetListener(() => UIManager.Instance.OpenWindow<HeroDebutZhanLingWin>());
    }
    protected override void OnPreOpen()
@@ -76,6 +79,7 @@
        starUpRedpoint.redpointId = manager.GetRedPointId(HeroDebutRedPointType.StarUp);
        shopRedpoint.redpointId = manager.GetRedPointId(HeroDebutRedPointType.Shop);
        giftRedpoint.redpointId = manager.GetRedPointId(HeroDebutRedPointType.Gift);
        zhanlingRedpoint.redpointId = manager.GetRedPointId(HeroDebutRedPointType.ZhanLing);
    }
    private void Display()
Main/System/HeroDebut/HeroDebutZhanLingCell.cs
New file
@@ -0,0 +1,121 @@
using System.Linq;
using UnityEngine;
public class HeroDebutZhanLingCell : CellView
{
    [SerializeField] ItemCell freeItemCell;
    [SerializeField] Transform freeGotRect;
    [SerializeField] Transform baseCanGetAwardRect;
    [SerializeField] ItemCell[] paidAwards;
    [SerializeField] Transform[] paidGotRects;
    [SerializeField] Transform[] paidCanGetRects;
    [SerializeField] Transform[] paidLockRects;
    [SerializeField] ItemCell[] paidHAwards;
    [SerializeField] Transform[] paidHGotRects;
    [SerializeField] Transform[] paidHCanGetRects;
    [SerializeField] Transform[] paidHLockRects;
    [SerializeField] Transform upProcssBGRect;
    [SerializeField] Transform upProcessRect;
    [SerializeField] Transform downProcssBGRect;
    [SerializeField] Transform downProcessRect;
    [SerializeField] TextEx txtUnlockLV;
    [SerializeField] Transform mask;
    HeroDebutManager zhanLingModel => HeroDebutManager.Instance;
    public void Display(int needValue)
    {
        var totalValue = BattlePassManager.Instance.GetTotalValue(zhanLingModel.ZhanLingType);
        int zhanlingId = ZhanlingConfig.GetTypeToIDDict(zhanLingModel.ZhanLingType)[needValue];
        int freeState = zhanLingModel.GetZhanLingFreeGiftState(needValue);
        int paidState = zhanLingModel.GetZhanLingPaidGiftState(needValue);
        int paidHState = zhanLingModel.GetZhanLingPaidGiftHState(needValue);
        int buyState = zhanLingModel.GetZhanLingBuyState();
        freeGotRect.SetActive(freeState == 2);
        baseCanGetAwardRect.SetActive(freeState == 1);
        mask.SetActive(freeState == 0);
        for (int i = 0; i < paidAwards.Length; i++)
        {
            bool isBuy = buyState == 1 || buyState == 3;
            paidGotRects[i].SetActive(paidState == 2);
            paidCanGetRects[i].SetActive(paidState == 1 && isBuy);
            paidLockRects[i].SetActive(!isBuy || paidState == 0);
        }
        for (int i = 0; i < paidHAwards.Length; i++)
        {
            bool isBuy = buyState == 2 || buyState == 3;
            paidHGotRects[i].SetActive(paidHState == 2);
            paidHCanGetRects[i].SetActive(paidHState == 1 && isBuy);
            paidHLockRects[i].SetActive(!isBuy || paidHState == 0);
        }
        txtUnlockLV.text = needValue.ToString();
        // 进度条显示逻辑
        var ids = ZhanlingConfig.GetTypeToIDDict(zhanLingModel.ZhanLingType).Values.ToList();
        ids.Sort();
        upProcssBGRect.SetActive(ids[0] != zhanlingId);
        upProcessRect.SetActive(freeState != 0);
        downProcssBGRect.SetActive(ids[ids.Count - 1] != zhanlingId);
        var nextConfig = ZhanlingConfig.Get(zhanlingId + 1);
        downProcessRect.SetActive(nextConfig != null && totalValue >= nextConfig.NeedValue);
        // 展示ItemCell
        var config = ZhanlingConfig.Get(zhanlingId);
        if (config == null)
            return;
        // 免费奖励
        int freeItemId = config.FreeRewardItemList[0][0];
        freeItemCell.Init(new ItemCellModel(freeItemId, false, config.FreeRewardItemList[0][1]));
        freeItemCell.button.onClick.RemoveAllListeners();
        freeItemCell.button.onClick.AddListener(() =>
        {
            if (freeState == 1)
                zhanLingModel.HaveAllZhanLingGift();
            else
                ItemTipUtility.Show(freeItemId);
        });
        // 普通奖励
        for (int i = 0; i < paidAwards.Length; i++)
        {
            if (i >= config.ZLRewardItemList.Length)
                continue;
            int itemId2 = config.ZLRewardItemList[i][0];
            paidAwards[i].Init(new ItemCellModel(itemId2, false, config.ZLRewardItemList[i][1]));
            paidAwards[i].button.onClick.RemoveAllListeners();
            paidAwards[i].button.onClick.AddListener(() =>
            {
                if (buyState == 0 || buyState == 2)
                    zhanLingModel.ShowZhanLingHBuy(zhanLingModel.ZhanLingType, 1);
                else if (paidState == 1)
                    zhanLingModel.HaveAllZhanLingGift();
                else
                    ItemTipUtility.Show(itemId2);
            });
        }
        // 高级奖励
        for (int i = 0; i < paidHAwards.Length; i++)
        {
            if (i >= config.ZLRewardItemListH.Length)
                continue;
            int itemId3 = config.ZLRewardItemListH[i][0];
            paidHAwards[i].Init(new ItemCellModel(itemId3, false, config.ZLRewardItemListH[i][1]));
            paidHAwards[i].button.onClick.RemoveAllListeners();
            paidHAwards[i].button.onClick.AddListener(() =>
            {
                if (buyState == 0 || buyState == 1)
                    zhanLingModel.ShowZhanLingHBuy(zhanLingModel.ZhanLingType, 2);
                else if (paidHState == 1)
                    zhanLingModel.HaveAllZhanLingGift();
                else
                    ItemTipUtility.Show(itemId3);
            });
        }
    }
}
Main/System/HeroDebut/HeroDebutZhanLingCell.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 53ed1e831bb755c4085557d561217459
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutZhanLingPreviewCell.cs
New file
@@ -0,0 +1,35 @@
using UnityEngine;
using System.Collections.Generic;
public class HeroDebutZhanLingPreviewCell : CellView
{
    [SerializeField] ItemCell[] itemCells;
    public const int itemCountPerRow = 5;
    public void Display(int rowIndex, List<Item> items)
    {
        if (items == null)
            return;
        for (int i = 0; i < itemCells.Length; i++)
        {
            int index = rowIndex * itemCountPerRow + i;
            if (index < items.Count)
            {
                itemCells[i].SetActive(true);
                int itemID = items[index].id;
                long count = items[index].countEx;
                itemCells[i].Init(new ItemCellModel(itemID, false, count));
                int clickItemId = itemID;
                itemCells[i].button.AddListener(() =>
                {
                    ItemTipUtility.Show(clickItemId);
                });
            }
            else
            {
                itemCells[i].SetActive(false);
            }
        }
    }
}
Main/System/HeroDebut/HeroDebutZhanLingPreviewCell.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a3cd52709b8e8fc419ae3993e855cbab
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutZhanLingPreviewHCell.cs
New file
@@ -0,0 +1,35 @@
using UnityEngine;
using System.Collections.Generic;
public class HeroDebutZhanLingPreviewHCell : CellView
{
    [SerializeField] ItemCell[] itemCells;
    public const int itemCountPerRow = 5;
    public void Display(int rowIndex, List<Item> items)
    {
        if (items == null)
            return;
        for (int i = 0; i < itemCells.Length; i++)
        {
            int index = rowIndex * itemCountPerRow + i;
            if (index < items.Count)
            {
                itemCells[i].SetActive(true);
                int itemID = items[index].id;
                long count = items[index].countEx;
                itemCells[i].Init(new ItemCellModel(itemID, false, count));
                int clickItemId = itemID;
                itemCells[i].button.AddListener(() =>
                {
                    ItemTipUtility.Show(clickItemId);
                });
            }
            else
            {
                itemCells[i].SetActive(false);
            }
        }
    }
}
Main/System/HeroDebut/HeroDebutZhanLingPreviewHCell.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a426bf3edcc306240b4994629c254691
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutZhanLingPreviewHWin.cs
New file
@@ -0,0 +1,91 @@
using System;
using UnityEngine;
using UnityEngine.UI;
public class HeroDebutZhanLingPreviewHWin : UIBase
{
    [SerializeField] ScrollerController allScroller; //所有等级奖励
    [SerializeField] Button btnClose;
    [SerializeField] Button btnBuy;
    [SerializeField] Text txtBuy;
    [SerializeField] Text txtPercentage;
    [SerializeField] Image imgMoney;
    [SerializeField] Text txtMoney;
    HeroDebutManager model => HeroDebutManager.Instance;
    int ctgID;
    int showCnt = 50;
    protected override void InitComponent()
    {
        btnClose.AddListener(CloseWindow);
        btnBuy.AddListener(OnBuyClick);
    }
    protected override void OnPreOpen()
    {
        allScroller.OnRefreshCell += OnScrollerRefreshAllCell;
        Display();
    }
    protected override void OnPreClose()
    {
        allScroller.OnRefreshCell -= OnScrollerRefreshAllCell;
    }
    void OnBuyClick()
    {
        if (ctgID == 0)
        {
            CloseWindow();
            return;
        }
        RechargeManager.Instance.CTG(ctgID);
        CloseWindow();
    }
    protected override void NextFrameAfterOpen()
    {
        CreateAllScroller();
    }
    private void OnScrollerRefreshAllCell(ScrollerDataType type, CellView cell)
    {
        var _cell = cell as HeroDebutZhanLingPreviewHCell;
        _cell.Display(_cell.index, model.GetPreviewGiftAllItem(showCnt));
    }
    void Display()
    {
        ctgID = model.GetPreviewCtgID();
        var config = CTGConfig.Get(ctgID);
        if (config == null)
        {
            CloseWindow();
            return;
        }
        OrderInfoConfig orderCfg;
        RechargeManager.Instance.TryGetOrderInfo(ctgID, out orderCfg);
        txtPercentage.text = Language.Get("TimingGift02", config.Percentage);
        txtBuy.text = Language.Get("PayMoneyNum", UIHelper.GetMoneyFormat(orderCfg.PayRMBNumOnSale));
        imgMoney.SetIconWithMoneyType(config.MoneyType);
        txtMoney.text = config.GainGold.ToString();
    }
    private void CreateAllScroller()
    {
        var items = model.GetPreviewGiftAllItem(showCnt);
        if (items == null || items.Count == 0)
            return;
        int rowCount = (int)Math.Ceiling((double)items.Count / HeroDebutZhanLingPreviewCell.itemCountPerRow);
        allScroller.Refresh();
        for (int i = 0; i < rowCount; i++)
        {
            allScroller.AddCell(ScrollerDataType.Header, i);
        }
        allScroller.Restart();
    }
}
Main/System/HeroDebut/HeroDebutZhanLingPreviewHWin.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 954d7f3edfe26ed4c91e79c003c82484
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutZhanLingPreviewWin.cs
New file
@@ -0,0 +1,87 @@
using System;
using UnityEngine;
using UnityEngine.UI;
public class HeroDebutZhanLingPreviewWin : UIBase
{
    [SerializeField] ScrollerController allScroller; //所有等级奖励
    [SerializeField] Button btnClose;
    [SerializeField] Button btnBuy;
    [SerializeField] Text txtBuy;
    [SerializeField] Text txtPercentage;
    [SerializeField] Image imgMoney;
    [SerializeField] Text txtMoney;
    HeroDebutManager model => HeroDebutManager.Instance;
    int ctgID;
    int showCnt = 10;
    protected override void OnPreOpen()
    {
        allScroller.OnRefreshCell += OnScrollerRefreshAllCell;
        btnClose.AddListener(CloseWindow);
        btnBuy.AddListener(OnBuyClick);
        Display();
    }
    protected override void OnPreClose()
    {
        allScroller.OnRefreshCell -= OnScrollerRefreshAllCell;
    }
    void OnBuyClick()
    {
        if (ctgID == 0)
        {
            CloseWindow();
            return;
        }
        RechargeManager.Instance.CTG(ctgID);
        CloseWindow();
    }
    protected override void NextFrameAfterOpen()
    {
        CreateAllScroller();
    }
    private void OnScrollerRefreshAllCell(ScrollerDataType type, CellView cell)
    {
        var _cell = cell as HeroDebutZhanLingPreviewCell;
        _cell.Display(_cell.index, model.GetPreviewGiftAllItem(showCnt));
    }
    void Display()
    {
        ctgID = model.GetPreviewCtgID();
        var config = CTGConfig.Get(ctgID);
        if (config == null)
        {
            CloseWindow();
            return;
        }
        OrderInfoConfig orderCfg;
        RechargeManager.Instance.TryGetOrderInfo(ctgID, out orderCfg);
        txtPercentage.text = Language.Get("TimingGift02", config.Percentage);
        txtBuy.text = Language.Get("PayMoneyNum", UIHelper.GetMoneyFormat(orderCfg.PayRMBNumOnSale));
        imgMoney.SetIconWithMoneyType(config.MoneyType);
        txtMoney.text = config.GainGold.ToString();
    }
    private void CreateAllScroller()
    {
        var items = model.GetPreviewGiftAllItem(showCnt);
        if (items == null || items.Count == 0)
            return;
        int rowCount = (int)Math.Ceiling((double)items.Count / HeroDebutZhanLingPreviewCell.itemCountPerRow);
        allScroller.Refresh();
        for (int i = 0; i < rowCount; i++)
        {
            allScroller.AddCell(ScrollerDataType.Header, i);
        }
        allScroller.Restart();
    }
}
Main/System/HeroDebut/HeroDebutZhanLingPreviewWin.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bef022f6fa7c2584bb050ca842bbe368
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutZhanLingWin.cs
New file
@@ -0,0 +1,151 @@
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
// 武将登场战令
public class HeroDebutZhanLingWin : UIBase
{
    [SerializeField] ScrollerController scroller;
    [SerializeField] ButtonEx btnGo;
    [SerializeField] ButtonEx btnPaid;
    [SerializeField] ButtonEx btnPaidH;
    [SerializeField] ImageEx imgPaidLock;
    [SerializeField] ImageEx imgPaidLockH;
    [SerializeField] Text txtNowNeedValue;
    [SerializeField] Text welfarePerText;
    [SerializeField] Text itemNameText;
    [SerializeField] Image adImg;
    [SerializeField] Image adWordImg;
    [SerializeField] Image adHeroImg;
    [SerializeField] Text txtPaidLock;
    [SerializeField] Text txtPaidLockH;
    [SerializeField] Text txtPaidLockBuyed;
    [SerializeField] Text txtPaidLockBuyedH;
    HeroDebutManager zhanLingModel => HeroDebutManager.Instance;
    protected override void InitComponent()
    {
        btnGo.AddListener(OnGoClick);
        btnPaid.AddListener(OnPaidClick);
        btnPaidH.AddListener(OnPaidHClick);
    }
    protected override void OnPreOpen()
    {
        zhanLingModel.OnZhanLingUpdateEvent += OnZhanLingUpdateEvent;
        scroller.OnRefreshCell += OnScrollerRefreshCell;
        ShowStaticUI();
        Initialize();
        Display();
    }
    protected override void OnPreClose()
    {
        zhanLingModel.OnZhanLingUpdateEvent -= OnZhanLingUpdateEvent;
        scroller.OnRefreshCell -= OnScrollerRefreshCell;
    }
    private void Display()
    {
        //0 没购买进阶和玄级 1 购买了进阶没买玄级 2 购买了玄级没买进阶 3 购买了进阶和玄级
        int buyState = zhanLingModel.GetZhanLingBuyState();
        scroller.m_Scorller.RefreshActiveCellViews();
        txtNowNeedValue.text = Language.Get("HeroDebutZhanLing06", zhanLingModel.GetZhanLingValue());
        // imgPaidLock: 未购买进阶(type 1)且未购买玄级(type 2)时显示锁,或已购买玄级但未购买进阶时显示锁
        imgPaidLock.SetActive(buyState == 0 || buyState == 2);
        // imgPaidLockH: 未购买玄级且未购买进阶时显示锁,或已购买进阶但未购买玄级时显示锁
        imgPaidLockH.SetActive(buyState == 0 || buyState == 1);
        txtPaidLock.SetActive(buyState == 0 || buyState == 2);
        txtPaidLockBuyed.SetActive(buyState == 1 || buyState == 3);
        txtPaidLockH.SetActive(buyState == 0 || buyState == 1);
        txtPaidLockBuyedH.SetActive(buyState == 2 || buyState == 3);
    }
    private void OnZhanLingUpdateEvent()
    {
        Display();
        scroller.m_Scorller.RefreshActiveCellViews();
    }
    private void OnScrollerRefreshCell(ScrollerDataType type, CellView cell)
    {
        var _cell = cell as HeroDebutZhanLingCell;
        _cell.Display(_cell.index);
    }
    private void Initialize()
    {
        var cellList = ZhanlingConfig.GetTypeToIDDict(zhanLingModel.ZhanLingType).Keys.ToList();
        scroller.Refresh();
        for (int i = 0; i < cellList.Count; i++)
        {
            scroller.AddCell(ScrollerDataType.Header, cellList[i]);
        }
        scroller.Restart();
        var data = BattlePassManager.Instance.GetBattlePassData(zhanLingModel.ZhanLingType);
        var totalValue = BattlePassManager.Instance.GetTotalValue(zhanLingModel.ZhanLingType);
        scroller.JumpIndex(BattlePassManager.Instance.JumpIndex(data, zhanLingModel.ZhanLingType, totalValue));
    }
    void ShowStaticUI()
    {
        // 获取高级付费(PaidH/玄级)的CTGID和百分比
        var funcConfig = FuncConfigConfig.Get("Zhanling");
        var dict = ConfigParse.ParseIntArrayDict(funcConfig.Numerical3);
        if (dict.TryGetValue(zhanLingModel.ZhanLingType, out var arr) && arr.Length > 0)
        {
            var paidHConfig = CTGConfig.Get(arr[0]);
            welfarePerText.text = paidHConfig.Percentage + "%";
        }
        adWordImg.SetSprite("BattlePassInWord" + zhanLingModel.ZhanLingType);
        adImg.SetSprite("BattlePassInWord" + zhanLingModel.ZhanLingType);
        var act = zhanLingModel.GetOperationHeroAppearInfo();
        if (act == null) return;
        var config = ActHeroAppearConfig.Get(act.CfgID);
        if (config == null) return;
        var needCount = zhanLingModel.GetLuckValueAward(config.ActTreasureType) - zhanLingModel.subVulue;
        itemNameText.text = Language.Get("HeroDebutZhanLing01", needCount);
        int heroID = zhanLingModel.GetCurrentDisplayCallHeroId();
        adImg.SetSprite($"HeroDebutZhanLingBG_{heroID}");
        adWordImg.SetSprite($"HeroDebutZhanLingWord_{heroID}");
        adHeroImg.SetSprite($"HeroDebutZhanLingHero_{heroID}");
    }
    void OnGoClick()
    {
        UIJumpManager.Instance.OpenWindow(14);
    }
    void OnPaidClick()
    {
        int buyState = zhanLingModel.GetZhanLingBuyState();
        // 已购买进阶(type 1)或已购买玄级和进阶(buyState == 3)时不再跳转
        if (buyState == 1 || buyState == 3)
            return;
        zhanLingModel.ShowZhanLingHBuy(zhanLingModel.ZhanLingType, 1);
    }
    void OnPaidHClick()
    {
        int buyState = zhanLingModel.GetZhanLingBuyState();
        // 已购买玄级(type 2)或已购买玄级和进阶(buyState == 3)时不再跳转
        if (buyState == 2 || buyState == 3)
            return;
        zhanLingModel.ShowZhanLingHBuy(zhanLingModel.ZhanLingType, 2);
    }
}
Main/System/HeroDebut/HeroDebutZhanLingWin.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8dd1ef3c24623734dbad0ca6cff2bd48
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/UIBase/UIJumpManager.cs
@@ -64,7 +64,7 @@
        //武将登场相关
        else if (config.WinName == "HeroDebutCallWin" || config.WinName == "HeroDebutSkinWin" ||
                config.WinName == "HeroDebutCheckInWin" || config.WinName == "HeroDebutGiftWin" ||
                config.WinName == "HeroDebutShopWin")
                config.WinName == "HeroDebutShopWin" || config.WinName == "HeroDebutZhanLingWin")
        {
            var heroDebutAct = HeroDebutManager.Instance.GetOperationHeroAppearInfo();
            if (heroDebutAct == null)