lcy
7 天以前 92722a93e2239070a187c5d4352c39f41b291bae
492 武将登场-客户端
15个文件已修改
118个文件已添加
6170 ■■■■■ 已修改文件
Main/Config/ConfigManager.cs 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/ActBillboardAwardConfig.cs 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/ActBillboardAwardConfig.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/ActHeroAppearArtConfig.cs 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/ActHeroAppearArtConfig.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/ActHeroAppearConfig.cs 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/ActHeroAppearConfig.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/ActHeroAppearSkinArtConfig.cs 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/ActHeroAppearStarConfig.cs 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/ActHeroAppearStarConfig.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/ActSignAwardConfig.cs 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/ActSignAwardConfig.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/TreasureSetConfig.cs 53 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/PartialConfigs/ActBillboardAwardConfig.cs 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/PartialConfigs/ActBillboardAwardConfig.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/PartialConfigs/ActHeroAppearConfig.cs 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/PartialConfigs/ActHeroAppearConfig.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/PartialConfigs/ActHeroAppearStarConfig.cs 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/PartialConfigs/ActHeroAppearStarConfig.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/PartialConfigs/ActSignAwardConfig.cs 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/PartialConfigs/ActSignAwardConfig.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/PartialConfigs/HeroSkinAttrConfig.cs 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/PartialConfigs/TreasureItemLibConfig.cs 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/ClientPack/CAA SaleActivity.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/ClientPack/CAA SaleActivity/CAA01_tagCSActHeroAppearStarHeroSelect.cs 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/ClientPack/CAA SaleActivity/CAA01_tagCSActHeroAppearStarHeroSelect.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/ClientPack/CAA SaleActivity/CAA02_tagCSActHeroAppearCallHeroSelect.cs 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/ClientPack/CAA SaleActivity/CAA02_tagCSActHeroAppearCallHeroSelect.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/DTCFile/ServerPack/HA0_Sys/DTCA009_tagSCGameRecInfo.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA20_tagSCActSignPlayerInfo.cs 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA20_tagSCActSignPlayerInfo.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA21_tagSCActHeroAppearInfo.cs 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA21_tagSCActHeroAppearInfo.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA22_tagSCActHeroAppearPlayerInfo.cs 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA22_tagSCActHeroAppearPlayerInfo.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/DataToCtl/PackageRegedit.cs 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA20_tagSCActSignPlayerInfo.cs 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA20_tagSCActSignPlayerInfo.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA21_tagSCActHeroAppearInfo.cs 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA21_tagSCActHeroAppearInfo.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA22_tagSCActHeroAppearPlayerInfo.cs 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA22_tagSCActHeroAppearPlayerInfo.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Main.cs 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/BillboardRank/RankModel.cs 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/CustomizedGift/CustomizedGiftModel.cs 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HappyXB/HappyXBModel.cs 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/BubbleFloat.cs 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/BubbleFloat.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/GeneralActInfoManager.cs 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/GeneralActInfoManager.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCallBubbleCell.cs 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCallBubbleCell.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCallButton.cs 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCallButton.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCallChangeCell.cs 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCallChangeCell.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCallChangeItem.cs 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCallChangeItem.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCallChangeWin.cs 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCallChangeWin.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCallHistoryCell.cs 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCallHistoryCell.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCallHistoryOutCell.cs 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCallHistoryOutCell.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCallHistoryWin.cs 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCallHistoryWin.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCallRateCell.cs 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCallRateCell.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCallRateHeroCell.cs 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCallRateHeroCell.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCallRateHeroWin.cs 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCallRateHeroWin.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCallRateItem.cs 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCallRateItem.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCallRateWin.cs 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCallRateWin.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCallResultCell.cs 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCallResultCell.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCallResultWin.cs 370 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCallResultWin.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCallWin.cs 321 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCallWin.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCell.cs 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCell.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCheckInCell.cs 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCheckInCell.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCheckInWin.cs 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutCheckInWin.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutGiftCell.cs 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutGiftCell.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutGiftWin.cs 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutGiftWin.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutManager.cs 1017 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutManager.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutPopWin.cs 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutPopWin.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutRankAwardCell.cs 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutRankAwardCell.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutRankCell.cs 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutRankCell.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutRankTop3Cell.cs 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutRankTop3Cell.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutRankWin.cs 175 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutRankWin.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutShopCell.cs 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutShopCell.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutShopLineCell.cs 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutShopLineCell.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutShopWin.cs 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutShopWin.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutSkinAwardCell.cs 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutSkinAwardCell.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutSkinTabCell.cs 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutSkinTabCell.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutSkinWin.cs 215 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutSkinWin.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutStarUpCell.cs 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutStarUpCell.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutStarUpPaidItemCell.cs 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutStarUpPaidItemCell.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutStarUpWin.cs 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutStarUpWin.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutWin.cs 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/HeroDebutWin.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/OperationHeroAppearInfo.cs 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroDebut/OperationHeroAppearInfo.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Main/HomeWin.cs 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/OpenServerActivity/OperationTimeHepler.cs 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Redpoint/MainRedDot.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/UIBase/UIJumpManager.cs 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Utility/EnumHelper.cs 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/ConfigManager.cs
@@ -38,7 +38,13 @@
        // 加载配置文件
        HashSet<Type> configTypes = new HashSet<Type>() {
            typeof(ActBillboardAwardConfig),
            typeof(ActHeroAppearArtConfig),
            typeof(ActHeroAppearConfig),
            typeof(ActHeroAppearSkinArtConfig),
            typeof(ActHeroAppearStarConfig),
            typeof(ActLunhuidianTypeConfig),
            typeof(ActSignAwardConfig),
            typeof(ADAwardConfig),
            typeof(BattleMapConfig),
            typeof(BeautyConfig),
@@ -262,8 +268,20 @@
    public override void Release()
    {
        // 清空 ActBillboardAwardConfig 字典
        ClearConfigDictionary<ActBillboardAwardConfig>();
        // 清空 ActHeroAppearArtConfig 字典
        ClearConfigDictionary<ActHeroAppearArtConfig>();
        // 清空 ActHeroAppearConfig 字典
        ClearConfigDictionary<ActHeroAppearConfig>();
        // 清空 ActHeroAppearSkinArtConfig 字典
        ClearConfigDictionary<ActHeroAppearSkinArtConfig>();
        // 清空 ActHeroAppearStarConfig 字典
        ClearConfigDictionary<ActHeroAppearStarConfig>();
        // 清空 ActLunhuidianTypeConfig 字典
        ClearConfigDictionary<ActLunhuidianTypeConfig>();
        // 清空 ActSignAwardConfig 字典
        ClearConfigDictionary<ActSignAwardConfig>();
        // 清空 ADAwardConfig 字典
        ClearConfigDictionary<ADAwardConfig>();
        // 清空 BattleMapConfig 字典
Main/Config/Configs/ActBillboardAwardConfig.cs
New file
@@ -0,0 +1,53 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2026年3月6日
//--------------------------------------------------------
using System.Collections.Generic;
using System;
using UnityEngine;
using LitJson;
public partial class ActBillboardAwardConfig : ConfigBase<int, ActBillboardAwardConfig>
{
    static ActBillboardAwardConfig()
    {
        // 访问过静态构造函数
        visit = true;
    }
    public int ID;
    public int TemplateID;
    public int RankA;
    public int RankB;
    public float NeedValue;
    public int[][] AwardItemList;
    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 ID);
            int.TryParse(tables[1],out TemplateID);
            int.TryParse(tables[2],out RankA);
            int.TryParse(tables[3],out RankB);
            float.TryParse(tables[4],out NeedValue);
            AwardItemList = JsonMapper.ToObject<int[][]>(tables[5].Replace("(", "[").Replace(")", "]"));
        }
        catch (Exception exception)
        {
            Debug.LogError(exception);
        }
    }
}
Main/Config/Configs/ActBillboardAwardConfig.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9bd0535e10f3bc74bb3ec887f2cb87d2
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Config/Configs/ActHeroAppearArtConfig.cs
New file
@@ -0,0 +1,101 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2026年3月13日
//--------------------------------------------------------
using System.Collections.Generic;
using System;
using UnityEngine;
using LitJson;
public partial class ActHeroAppearArtConfig : ConfigBase<int, ActHeroAppearArtConfig>
{
    static ActHeroAppearArtConfig()
    {
        // 访问过静态构造函数
        visit = true;
    }
    public int HeroID;
    public int[][] HeroNameColor;
    public int[][] CallBubbleItems;
    public string EntryBgImage;
    public string EntryTitleText;
    public string PopBgImage;
    public string PopTitleBgImage;
    public string PopTitleImage;
    public string PopInfoBgImage;
    public int PopInfoBgUIEffectId;
    public string PopInfoText;
    public int[] PopInfoColor;
    public string MainBgImage;
    public string MainTitleImage;
    public int MainSkinID;
    public string StarUpHeroImage;
    public string GiftHeroImage;
    public string RankAwardHeroImage;
    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 HeroID);
            HeroNameColor = JsonMapper.ToObject<int[][]>(tables[1].Replace("(", "[").Replace(")", "]"));
            CallBubbleItems = JsonMapper.ToObject<int[][]>(tables[2].Replace("(", "[").Replace(")", "]"));
            EntryBgImage = tables[3];
            EntryTitleText = tables[4];
            PopBgImage = tables[5];
            PopTitleBgImage = tables[6];
            PopTitleImage = tables[7];
            PopInfoBgImage = tables[8];
            int.TryParse(tables[9],out PopInfoBgUIEffectId);
            PopInfoText = tables[10];
            if (tables[11].Contains("["))
            {
                PopInfoColor = JsonMapper.ToObject<int[]>(tables[11]);
            }
            else
            {
                string[] PopInfoColorStringArray = tables[11].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
                PopInfoColor = new int[PopInfoColorStringArray.Length];
                for (int i=0;i<PopInfoColorStringArray.Length;i++)
                {
                     int.TryParse(PopInfoColorStringArray[i],out PopInfoColor[i]);
                }
            }
            MainBgImage = tables[12];
            MainTitleImage = tables[13];
            int.TryParse(tables[14],out MainSkinID);
            StarUpHeroImage = tables[15];
            GiftHeroImage = tables[16];
            RankAwardHeroImage = tables[17];
        }
        catch (Exception exception)
        {
            Debug.LogError(exception);
        }
    }
}
Main/Config/Configs/ActHeroAppearArtConfig.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bde3ad9e23ce4ed4480784d86e068190
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Config/Configs/ActHeroAppearConfig.cs
New file
@@ -0,0 +1,104 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2026年3月9日
//--------------------------------------------------------
using System.Collections.Generic;
using System;
using UnityEngine;
using LitJson;
public partial class ActHeroAppearConfig : ConfigBase<int, ActHeroAppearConfig>
{
    static ActHeroAppearConfig()
    {
        // 访问过静态构造函数
        visit = true;
    }
    public int CfgID;
    public int[] ActHeroIDList;
    public int ActTreasureType;
    public int StarGiftTempID;
    public int[] SkinCTGIDList;
    public int[] GiftCTGIDList;
    public int GiftShopType;
    public int ExShopType;
    public int ExShopCostItemID;
    public int SignTempID;
    public int BillTempID;
    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 CfgID);
            if (tables[1].Contains("["))
            {
                ActHeroIDList = JsonMapper.ToObject<int[]>(tables[1]);
            }
            else
            {
                string[] ActHeroIDListStringArray = tables[1].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
                ActHeroIDList = new int[ActHeroIDListStringArray.Length];
                for (int i=0;i<ActHeroIDListStringArray.Length;i++)
                {
                     int.TryParse(ActHeroIDListStringArray[i],out ActHeroIDList[i]);
                }
            }
            int.TryParse(tables[2],out ActTreasureType);
            int.TryParse(tables[3],out StarGiftTempID);
            if (tables[4].Contains("["))
            {
                SkinCTGIDList = JsonMapper.ToObject<int[]>(tables[4]);
            }
            else
            {
                string[] SkinCTGIDListStringArray = tables[4].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
                SkinCTGIDList = new int[SkinCTGIDListStringArray.Length];
                for (int i=0;i<SkinCTGIDListStringArray.Length;i++)
                {
                     int.TryParse(SkinCTGIDListStringArray[i],out SkinCTGIDList[i]);
                }
            }
            if (tables[5].Contains("["))
            {
                GiftCTGIDList = JsonMapper.ToObject<int[]>(tables[5]);
            }
            else
            {
                string[] GiftCTGIDListStringArray = tables[5].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
                GiftCTGIDList = new int[GiftCTGIDListStringArray.Length];
                for (int i=0;i<GiftCTGIDListStringArray.Length;i++)
                {
                     int.TryParse(GiftCTGIDListStringArray[i],out GiftCTGIDList[i]);
                }
            }
            int.TryParse(tables[6],out GiftShopType);
            int.TryParse(tables[7],out ExShopType);
            int.TryParse(tables[8],out ExShopCostItemID);
            int.TryParse(tables[9],out SignTempID);
            int.TryParse(tables[10],out BillTempID);
        }
        catch (Exception exception)
        {
            Debug.LogError(exception);
        }
    }
}
Main/Config/Configs/ActHeroAppearConfig.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1b5b7653c8be0c24790efdb595f1c96e
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Config/Configs/ActHeroAppearSkinArtConfig.cs
New file
@@ -0,0 +1,56 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2026年3月11日
//--------------------------------------------------------
using System.Collections.Generic;
using System;
using UnityEngine;
using LitJson;
public partial class ActHeroAppearSkinArtConfig : ConfigBase<int, ActHeroAppearSkinArtConfig>
{
    static ActHeroAppearSkinArtConfig()
    {
        // 访问过静态构造函数
        visit = true;
    }
    public int SkinID;
    public string MainSkinBuyBgImage;
    public string BGImage;
    public string HeroNameImage;
    public string SkinInfoImage;
    public string AwardBGImage;
    public string TabInfoImage;
    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 SkinID);
            MainSkinBuyBgImage = tables[1];
            BGImage = tables[2];
            HeroNameImage = tables[3];
            SkinInfoImage = tables[4];
            AwardBGImage = tables[5];
            TabInfoImage = tables[6];
        }
        catch (Exception exception)
        {
            Debug.LogError(exception);
        }
    }
}
Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Config/Configs/ActHeroAppearStarConfig.cs
New file
@@ -0,0 +1,56 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2026年3月2日
//--------------------------------------------------------
using System.Collections.Generic;
using System;
using UnityEngine;
using LitJson;
public partial class ActHeroAppearStarConfig : ConfigBase<int, ActHeroAppearStarConfig>
{
    static ActHeroAppearStarConfig()
    {
        // 访问过静态构造函数
        visit = true;
    }
    public int ID;
    public int StarTempID;
    public int NeedStar;
    public int AwardIndex;
    public int[][] FreeAwardItemList;
    public int StarGiftCTGID;
    public string HeroGiftItemInfo;
    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 ID);
            int.TryParse(tables[1],out StarTempID);
            int.TryParse(tables[2],out NeedStar);
            int.TryParse(tables[3],out AwardIndex);
            FreeAwardItemList = JsonMapper.ToObject<int[][]>(tables[4].Replace("(", "[").Replace(")", "]"));
            int.TryParse(tables[5],out StarGiftCTGID);
            HeroGiftItemInfo = tables[6];
        }
        catch (Exception exception)
        {
            Debug.LogError(exception);
        }
    }
}
Main/Config/Configs/ActHeroAppearStarConfig.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b4cb144f745e63f4e911c2c4085b36e9
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Config/Configs/ActSignAwardConfig.cs
New file
@@ -0,0 +1,47 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2026年2月28日
//--------------------------------------------------------
using System.Collections.Generic;
using System;
using UnityEngine;
using LitJson;
public partial class ActSignAwardConfig : ConfigBase<int, ActSignAwardConfig>
{
    static ActSignAwardConfig()
    {
        // 访问过静态构造函数
        visit = true;
    }
    public int ID;
    public int TemplateID;
    public int DayNum;
    public int[][] SignAwardItemList;
    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 ID);
            int.TryParse(tables[1],out TemplateID);
            int.TryParse(tables[2],out DayNum);
            SignAwardItemList = JsonMapper.ToObject<int[][]>(tables[3].Replace("(", "[").Replace(")", "]"));
        }
        catch (Exception exception)
        {
            Debug.LogError(exception);
        }
    }
}
Main/Config/Configs/ActSignAwardConfig.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8af4002ac6b45894d8f80435a2310fc1
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Config/Configs/TreasureSetConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2026年2月26日
//    [  Date ]:           2026年3月5日
//--------------------------------------------------------
using System.Collections.Generic;
@@ -19,6 +19,7 @@
    public int TreasureType;
    public int[] CheckPackList;
    public int DailyMaxCount;
    public int DailyMaxCountMoney;
    public int DailyFreeCount;
    public int[] TreasureCountList;
    public int CostItemID;
@@ -66,15 +67,17 @@
            int.TryParse(tables[2],out DailyMaxCount); 
            int.TryParse(tables[3],out DailyFreeCount);
            int.TryParse(tables[3],out DailyMaxCountMoney);
            if (tables[4].Contains("["))
            int.TryParse(tables[4],out DailyFreeCount);
            if (tables[5].Contains("["))
            {
                TreasureCountList = JsonMapper.ToObject<int[]>(tables[4]);
                TreasureCountList = JsonMapper.ToObject<int[]>(tables[5]);
            }
            else
            {
                string[] TreasureCountListStringArray = tables[4].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
                string[] TreasureCountListStringArray = tables[5].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
                TreasureCountList = new int[TreasureCountListStringArray.Length];
                for (int i=0;i<TreasureCountListStringArray.Length;i++)
                {
@@ -82,15 +85,15 @@
                }
            }
            int.TryParse(tables[5],out CostItemID);
            int.TryParse(tables[6],out CostItemID);
            if (tables[6].Contains("["))
            if (tables[7].Contains("["))
            {
                CostItemCountList = JsonMapper.ToObject<int[]>(tables[6]);
                CostItemCountList = JsonMapper.ToObject<int[]>(tables[7]);
            }
            else
            {
                string[] CostItemCountListStringArray = tables[6].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
                string[] CostItemCountListStringArray = tables[7].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
                CostItemCountList = new int[CostItemCountListStringArray.Length];
                for (int i=0;i<CostItemCountListStringArray.Length;i++)
                {
@@ -98,15 +101,15 @@
                }
            }
            int.TryParse(tables[7],out CostMoneyType);
            int.TryParse(tables[8],out CostMoneyType);
            if (tables[8].Contains("["))
            if (tables[9].Contains("["))
            {
                CostMoneyList = JsonMapper.ToObject<int[]>(tables[8]);
                CostMoneyList = JsonMapper.ToObject<int[]>(tables[9]);
            }
            else
            {
                string[] CostMoneyListStringArray = tables[8].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
                string[] CostMoneyListStringArray = tables[9].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
                CostMoneyList = new int[CostMoneyListStringArray.Length];
                for (int i=0;i<CostMoneyListStringArray.Length;i++)
                {
@@ -114,29 +117,29 @@
                }
            }
            int.TryParse(tables[9],out EnsureCount);
            int.TryParse(tables[10],out EnsureCount);
            int.TryParse(tables[10],out OnceLucky);
            int.TryParse(tables[11],out OnceLucky);
            int.TryParse(tables[11],out LuckyGridNum);
            int.TryParse(tables[12],out LuckyGridNum);
            GridNumMaxLimitInfo = ConfigParse.ParseIntDict(tables[12]);
            GridNumMaxLimitInfo = ConfigParse.ParseIntDict(tables[13]);
            int.TryParse(tables[13],out AwardMoneyType);
            int.TryParse(tables[14],out AwardMoneyType);
            int.TryParse(tables[14],out AwardMoneyValue);
            int.TryParse(tables[15],out AwardMoneyValue);
            int.TryParse(tables[15],out WishOpen);
            int.TryParse(tables[16],out WishOpen);
            int.TryParse(tables[16],out WishReset);
            int.TryParse(tables[17],out WishReset);
            WishLibSelect = ConfigParse.ParseIntDict(tables[17]);
            WishLibSelect = ConfigParse.ParseIntDict(tables[18]);
            WishLibPubFreeCnt = ConfigParse.ParseIntDict(tables[18]);
            WishLibPubFreeCnt = ConfigParse.ParseIntDict(tables[19]);
            WishLibCard = ConfigParse.ParseIntDict(tables[19]);
            WishLibCard = ConfigParse.ParseIntDict(tables[20]);
            ProbabilityDisplay = tables[20];
            ProbabilityDisplay = tables[21];
        }
        catch (Exception exception)
        {
Main/Config/PartialConfigs/ActBillboardAwardConfig.cs
New file
@@ -0,0 +1,77 @@
using System.Collections.Generic;
using UnityEngine;
public partial class ActBillboardAwardConfig : ConfigBase<int, ActBillboardAwardConfig>
{
    // 模板编号: 名次A :配置ID
    private static Dictionary<int, Dictionary<int, int>> infoDict = new Dictionary<int, Dictionary<int, int>>();
    // 模板编号 名次A
    private static Dictionary<int, List<int>> sortDict = new Dictionary<int, List<int>>();
    protected override void OnConfigParseCompleted()
    {
        if (!infoDict.TryGetValue(TemplateID, out var dict))
        {
            dict = new Dictionary<int, int>();
            infoDict[TemplateID] = dict;
        }
        dict[RankA] = ID;
    }
    private static void LoadSortList()
    {
        if (!sortDict.IsNullOrEmpty()) return;
        foreach (var kvp in infoDict)
        {
            int templateID = kvp.Key;
            List<int> list = new List<int>(kvp.Value.Keys);
            list.Sort();
            sortDict[templateID] = list;
        }
    }
    public static List<int> GetRankASortList(int templateID)
    {
        LoadSortList();
        sortDict.TryGetValue(templateID, out var list);
        return list;
    }
    public static Dictionary<int, int> GetTemplateIDDict(int templateID)
    {
        infoDict.TryGetValue(templateID, out var dict);
        return dict;
    }
    public static int GetID(int templateID, int rankA)
    {
        var dict = GetTemplateIDDict(templateID);
        if (dict == null) return 0;
        dict.TryGetValue(rankA, out var id);
        return id;
    }
    public static ActBillboardAwardConfig GetConfig(int templateID, int rankA)
    {
        int id = GetID(templateID, rankA);
        return Get(id);
    }
    public static float GetTop3MinCalNeedValue(int templateID)
    {
        var list = GetRankASortList(templateID);
        float res = float.MaxValue;
        foreach (var rankA in list)
        {
            if (rankA > 3) continue;
            var config = GetConfig(templateID, rankA);
            if (config == null) continue;
            res = Mathf.Min(res, config.NeedValue);
        }
        return res == float.MaxValue ? 0 : res;
    }
}
Main/Config/PartialConfigs/ActBillboardAwardConfig.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 337f905faa5a7bf44a09646897bd603f
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Config/PartialConfigs/ActHeroAppearConfig.cs
New file
@@ -0,0 +1,18 @@
using System.Collections.Generic;
public partial class ActHeroAppearConfig : ConfigBase<int, ActHeroAppearConfig>
{
    private static List<int> actTreasureTypeList;
    public static List<int> GetActTreasureTypeList()
    {
        if (actTreasureTypeList == null)
        {
            actTreasureTypeList = new();
            foreach (var item in GetValues())
            {
                if (!actTreasureTypeList.Contains(item.ActTreasureType))
                    actTreasureTypeList.Add(item.ActTreasureType);
            }
        }
        return actTreasureTypeList;
    }
}
Main/Config/PartialConfigs/ActHeroAppearConfig.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c556397a9ff351e4e8895e33b7e19209
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Config/PartialConfigs/ActHeroAppearStarConfig.cs
New file
@@ -0,0 +1,58 @@
using System.Collections.Generic;
public partial class ActHeroAppearStarConfig : ConfigBase<int, ActHeroAppearStarConfig>
{
    // 升星礼包模版ID: 奖励记录索引 :配置ID
    private static Dictionary<int, Dictionary<int, int>> infoDict = new();
    // 升星礼包模版ID List<奖励记录索引>
    private static Dictionary<int, List<int>> sortDict = new();
    protected override void OnConfigParseCompleted()
    {
        if (!infoDict.TryGetValue(StarTempID, out var dict))
        {
            dict = new Dictionary<int, int>();
            infoDict[StarTempID] = dict;
        }
        dict[AwardIndex] = ID;
    }
    private static void LoadSortList()
    {
        if (!sortDict.IsNullOrEmpty()) return;
        foreach (var kvp in infoDict)
        {
            int starTempID = kvp.Key;
            List<int> list = new List<int>(kvp.Value.Keys);
            list.Sort();
            sortDict[starTempID] = list;
        }
    }
    public static List<int> GetAwardIndexSortList(int starTempID)
    {
        LoadSortList();
        sortDict.TryGetValue(starTempID, out var list);
        return list;
    }
    public static Dictionary<int, int> GetAwardIndexDict(int starTempID)
    {
        infoDict.TryGetValue(starTempID, out var dict);
        return dict;
    }
    public static int GetID(int starTempID, int awardIndex)
    {
        var dict = GetAwardIndexDict(starTempID);
        if (dict == null) return 0;
        dict.TryGetValue(awardIndex, out var id);
        return id;
    }
    public static ActHeroAppearStarConfig GetConfig(int starTempID, int awardIndex)
    {
        int id = GetID(starTempID, awardIndex);
        return Get(id);
    }
}
Main/Config/PartialConfigs/ActHeroAppearStarConfig.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dfb28fa9e267ad64d8164e33078a9cdd
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Config/PartialConfigs/ActSignAwardConfig.cs
New file
@@ -0,0 +1,57 @@
using System.Collections.Generic;
public partial class ActSignAwardConfig : ConfigBase<int, ActSignAwardConfig>
{
    // 模板编号: 第X天从1开始 :配置ID
    private static Dictionary<int, Dictionary<int, int>> infoDict = new Dictionary<int, Dictionary<int, int>>();
    // 模板编号 第X天从1开始
    private static Dictionary<int, List<int>> sortDict = new Dictionary<int, List<int>>();
    protected override void OnConfigParseCompleted()
    {
        if (!infoDict.TryGetValue(TemplateID, out var dict))
        {
            dict = new Dictionary<int, int>();
            infoDict[TemplateID] = dict;
        }
        dict[DayNum] = ID;
    }
    private static void LoadSortList()
    {
        if (!sortDict.IsNullOrEmpty()) return;
        foreach (var kvp in infoDict)
        {
            int templateID = kvp.Key;
            List<int> list = new List<int>(kvp.Value.Keys);
            list.Sort();
            sortDict[templateID] = list;
        }
    }
    public static List<int> GetDayNumSortList(int templateID)
    {
        LoadSortList();
        sortDict.TryGetValue(templateID, out var list);
        return list;
    }
    public static Dictionary<int, int> GetTemplateIDDict(int templateID)
    {
        infoDict.TryGetValue(templateID, out var dict);
        return dict;
    }
    public static int GetID(int templateID, int dayNum)
    {
        var dict = GetTemplateIDDict(templateID);
        if (dict == null) return 0;
        dict.TryGetValue(dayNum, out var id);
        return id;
    }
    public static ActSignAwardConfig GetConfig(int templateID, int dayNum)
    {
        int id = GetID(templateID, dayNum);
        return Get(id);
    }
}
Main/Config/PartialConfigs/ActSignAwardConfig.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8c89fb14eface4d409c9bc91038a9102
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Config/PartialConfigs/HeroSkinAttrConfig.cs
@@ -1,18 +1,32 @@
using System.Collections.Generic;
using System.Collections.Generic;
public partial class HeroSkinAttrConfig : ConfigBase<int, HeroSkinAttrConfig>
{
    public static List<int> itemIdList = new List<int>();
    protected override void OnConfigParseCompleted()
    {
        itemIdList.Add(NeedItemID);
    }
    /// <summary>
    /// 通过物品ID获取皮肤ID
    /// </summary>
    static Dictionary<int, int> itemDict = new();
    public static bool TryGetSkinIDByItemID(int itemID, out int skinID)
    {
        if (itemDict.IsNullOrEmpty())
        {
            foreach (var config in GetValues())
            {
                if (itemDict == null)
                    itemDict = new Dictionary<int, int>();
                itemDict[config.NeedItemID] = config.SkinID;
            }
        }
        return itemDict.TryGetValue(itemID, out skinID);
    }
}
Main/Config/PartialConfigs/TreasureItemLibConfig.cs
@@ -6,7 +6,9 @@
{
    private static Dictionary<int, List<int>> resultDict = new Dictionary<int, List<int>>();
    private static Dictionary<int, List<int>> resultWishIDDict = new Dictionary<int, List<int>>();
    protected override void OnConfigParseCompleted()
    private static Dictionary<int, Dictionary<int, int>> infoDict = new Dictionary<int, Dictionary<int, int>>();
    protected override void OnConfigParseCompleted()
    {
        if (!resultDict.ContainsKey(LibID))
        {
@@ -25,6 +27,12 @@
        {
            resultWishIDDict[LibID].Add(ID);
        }
        if (!infoDict.ContainsKey(LibID))
        {
            infoDict[LibID] = new Dictionary<int, int>();
        }
        infoDict[LibID][ItemID] = ID;
    }
@@ -37,4 +45,10 @@
    {
        return resultWishIDDict[libID];
    }
    public static bool TryGetID(int libID, int itemID, out int id)
    {
        id = 0;
        return infoDict.TryGetValue(libID, out var dict) && dict.TryGetValue(itemID, out id);
    }
}
Main/Core/NetworkPackage/ClientPack/CAA SaleActivity.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 81b74fbdb1ec9d743a0ea4b15fb5a97f
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Core/NetworkPackage/ClientPack/CAA SaleActivity/CAA01_tagCSActHeroAppearStarHeroSelect.cs
New file
@@ -0,0 +1,20 @@
using UnityEngine;
using System.Collections;
// AA 01 武将登场升星武将选择 #tagCSActHeroAppearStarHeroSelect
public class CAA01_tagCSActHeroAppearStarHeroSelect : GameNetPackBasic {
    public byte ActNum;    // 活动编号
    public byte StarHeroIndex;    // 升星计划选择的武将ID索引
    public CAA01_tagCSActHeroAppearStarHeroSelect () {
        combineCmd = (ushort)0x03FE;
        _cmd = (ushort)0xAA01;
    }
    public override void WriteToBytes () {
        WriteBytes (ActNum, NetDataType.BYTE);
        WriteBytes (StarHeroIndex, NetDataType.BYTE);
    }
}
Main/Core/NetworkPackage/ClientPack/CAA SaleActivity/CAA01_tagCSActHeroAppearStarHeroSelect.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4baab55a896f759449a3958baf35b816
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Core/NetworkPackage/ClientPack/CAA SaleActivity/CAA02_tagCSActHeroAppearCallHeroSelect.cs
New file
@@ -0,0 +1,20 @@
using UnityEngine;
using System.Collections;
// AA 02 武将登场招募武将选择 #tagCSActHeroAppearCallHeroSelect
public class CAA02_tagCSActHeroAppearCallHeroSelect : GameNetPackBasic {
    public byte ActNum;    // 活动编号
    public byte CallHeroIndex;    // 招募选择的武将ID索引
    public CAA02_tagCSActHeroAppearCallHeroSelect () {
        combineCmd = (ushort)0x03FE;
        _cmd = (ushort)0xAA02;
    }
    public override void WriteToBytes () {
        WriteBytes (ActNum, NetDataType.BYTE);
        WriteBytes (CallHeroIndex, NetDataType.BYTE);
    }
}
Main/Core/NetworkPackage/ClientPack/CAA SaleActivity/CAA02_tagCSActHeroAppearCallHeroSelect.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4be187b44e045a841b23e6587bce5044
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Core/NetworkPackage/DTCFile/ServerPack/HA0_Sys/DTCA009_tagSCGameRecInfo.cs
@@ -8,5 +8,6 @@
        base.Done(vNetPack);
        HA009_tagSCGameRecInfo vNetData = vNetPack as HA009_tagSCGameRecInfo;
        ArenaManager.Instance.UpdateGameRecInfo(vNetData);
        HeroDebutManager.Instance.UpdateGameRecInfo(vNetData);
    }
}
Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA20_tagSCActSignPlayerInfo.cs
New file
@@ -0,0 +1,14 @@
using UnityEngine;
using System.Collections;
// AA 20 活动签到奖励信息 #tagSCActSignPlayerInfo
public class DTCAA20_tagSCActSignPlayerInfo : DtcBasic
{
    public override void Done(GameNetPackBasic vNetPack)
    {
        base.Done(vNetPack);
        HAA20_tagSCActSignPlayerInfo vNetData = vNetPack as HAA20_tagSCActSignPlayerInfo;
        GeneralActInfoManager.Instance.UpdateActSignPlayerInfo(vNetData);
    }
}
Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA20_tagSCActSignPlayerInfo.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d4a0cca060961b44bb617c44b0d8a319
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA21_tagSCActHeroAppearInfo.cs
New file
@@ -0,0 +1,12 @@
using UnityEngine;
using System.Collections;
// AA 21 武将登场活动信息 #tagSCActHeroAppearInfo
public class DTCAA21_tagSCActHeroAppearInfo : DtcBasic {
    public override void Done(GameNetPackBasic vNetPack) {
        base.Done(vNetPack);
        HAA21_tagSCActHeroAppearInfo vNetData = vNetPack as HAA21_tagSCActHeroAppearInfo;
        OperationTimeHepler.Instance.UpdateActHeroAppearInfo(vNetData);
    }
}
Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA21_tagSCActHeroAppearInfo.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 95268094788bf524795c5eb9affc17ac
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA22_tagSCActHeroAppearPlayerInfo.cs
New file
@@ -0,0 +1,14 @@
using UnityEngine;
using System.Collections;
// AA 22 武将登场活动玩家信息 #tagSCActHeroAppearPlayerInfo
public class DTCAA22_tagSCActHeroAppearPlayerInfo : DtcBasic
{
    public override void Done(GameNetPackBasic vNetPack)
    {
        base.Done(vNetPack);
        HAA22_tagSCActHeroAppearPlayerInfo vNetData = vNetPack as HAA22_tagSCActHeroAppearPlayerInfo;
        HeroDebutManager.Instance.UpdateHeroAppearPlayerInfo(vNetData);
    }
}
Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA22_tagSCActHeroAppearPlayerInfo.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0358d952d0e98b349b417901b9f1c7f2
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Core/NetworkPackage/DataToCtl/PackageRegedit.cs
@@ -156,6 +156,9 @@
        Register(typeof(HA124_tagMCPlayerInfo), typeof(DTCA124_tagMCPlayerInfo));
        Register(typeof(HA106_tagMCCoinToGoldReport), typeof(DTCA106_tagMCCoinToGoldReport));
        Register(typeof(HA30C_tagMCPlayerRewardGetRecord), typeof(DTCA30C_tagMCPlayerRewardGetRecord));
        Register(typeof(HAA20_tagSCActSignPlayerInfo), typeof(DTCAA20_tagSCActSignPlayerInfo));
        Register(typeof(HAA21_tagSCActHeroAppearInfo), typeof(DTCAA21_tagSCActHeroAppearInfo));
        Register(typeof(HAA22_tagSCActHeroAppearPlayerInfo), typeof(DTCAA22_tagSCActHeroAppearPlayerInfo));
    }
    //主工程注册封包
Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA20_tagSCActSignPlayerInfo.cs
New file
@@ -0,0 +1,21 @@
using UnityEngine;
using System.Collections;
// AA 20 活动签到奖励信息 #tagSCActSignPlayerInfo
public class HAA20_tagSCActSignPlayerInfo : GameNetPackBasic {
    public byte ActType;    // 活动类型
    public byte ActNum;    // 活动编号
    public uint SignAward;    // 奖励领取记录,按天对应二进制位记录是否已领取
    public HAA20_tagSCActSignPlayerInfo () {
        _cmd = (ushort)0xAA20;
    }
    public override void ReadFromBytes (byte[] vBytes) {
        TransBytes (out ActType, vBytes, NetDataType.BYTE);
        TransBytes (out ActNum, vBytes, NetDataType.BYTE);
        TransBytes (out SignAward, vBytes, NetDataType.DWORD);
    }
}
Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA20_tagSCActSignPlayerInfo.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fda0c7a713e37ea409e3af9e2f896e6a
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA21_tagSCActHeroAppearInfo.cs
New file
@@ -0,0 +1,25 @@
using UnityEngine;
using System.Collections;
// AA 21 武将登场活动信息 #tagSCActHeroAppearInfo
public class HAA21_tagSCActHeroAppearInfo : GameNetPackBasic {
    public byte ActType;    // 活动类型,用于关联活动相关模块用,如签到、任务等
    public byte ActNum;    // 活动编号
    public string StartDate;    // 开始日期 y-m-d
    public string EndtDate;    // 结束日期 y-m-d
    public ushort CfgID;    // 活动时间表配置ID
    public HAA21_tagSCActHeroAppearInfo () {
        _cmd = (ushort)0xAA21;
    }
    public override void ReadFromBytes (byte[] vBytes) {
        TransBytes (out ActType, vBytes, NetDataType.BYTE);
        TransBytes (out ActNum, vBytes, NetDataType.BYTE);
        TransBytes (out StartDate, vBytes, NetDataType.Chars, 10);
        TransBytes (out EndtDate, vBytes, NetDataType.Chars, 10);
        TransBytes (out CfgID, vBytes, NetDataType.WORD);
    }
}
Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA21_tagSCActHeroAppearInfo.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f19899a717605364295e38a213b7883a
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA22_tagSCActHeroAppearPlayerInfo.cs
New file
@@ -0,0 +1,23 @@
using UnityEngine;
using System.Collections;
// AA 22 武将登场活动玩家信息 #tagSCActHeroAppearPlayerInfo
public class HAA22_tagSCActHeroAppearPlayerInfo : GameNetPackBasic {
    public byte ActNum;    // 活动编号
    public byte StarHeroIndex;    // 升星计划选择的武将ID索引
    public uint StarFreeAward;    // 升星计划免费奖励记录,按奖励记录索引二进制位运算记录是否已领取
    public byte CallHeroIndex;    // 招募选择的武将ID索引
    public HAA22_tagSCActHeroAppearPlayerInfo () {
        _cmd = (ushort)0xAA22;
    }
    public override void ReadFromBytes (byte[] vBytes) {
        TransBytes (out ActNum, vBytes, NetDataType.BYTE);
        TransBytes (out StarHeroIndex, vBytes, NetDataType.BYTE);
        TransBytes (out StarFreeAward, vBytes, NetDataType.DWORD);
        TransBytes (out CallHeroIndex, vBytes, NetDataType.BYTE);
    }
}
Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA22_tagSCActHeroAppearPlayerInfo.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2b1c2aa4b20f3d84896cc03b007884ec
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Main.cs
@@ -108,6 +108,8 @@
        managers.Add(SettingDataManager.Instance);
        managers.Add(TimeRushManager.Instance);
        managers.Add(SmallFuncManager.Instance);
        managers.Add(HeroDebutManager.Instance);
        managers.Add(GeneralActInfoManager.Instance);
        foreach (var manager in managers)
        {
Main/System/BillboardRank/RankModel.cs
@@ -187,10 +187,11 @@
    public void ReceiveRankPagePackage(HA130_tagMCViewBillboardRet package)
    {
        int rankType = package.Type;
        //部分跨服排行榜同一个榜存在分组分区的情况 //赛区3位+赛季3位+排行榜类型3位
        if (rankType == 165)    //CrossServerOneVsOneRewardModel.rankType
        //榜单类型6-武将登场招募榜 支持不同的ActNum同时开放活动,榜单数据独立
        if (rankType == 6)
        {
            rankType = (int)package.GroupValue1 * 1000000 + (int)package.GroupValue2 * 1000 + rankType;
            rankType = (int)package.GroupValue1 * 1000 + rankType;
        }
        if (!m_RankPageDatas.ContainsKey(rankType))
Main/System/CustomizedGift/CustomizedGiftModel.cs
@@ -3,7 +3,7 @@
//自选礼包的活动
public class CustomizedGiftModel  : GameSystemManager<CustomizedGiftModel>, IOpenServerActivity
public class CustomizedGiftModel : GameSystemManager<CustomizedGiftModel>, IOpenServerActivity
{
    public event Action<int> onStateUpdate;
    public Redpoint enRedPoint = new Redpoint(MainRedDot.CustomizedGiftRedpoint);
@@ -13,8 +13,10 @@
    private int GiftAwardRecord; //领取状态
    public const int activityType = (int)OpenServerActivityCenter.ActivityType.AT_DateActivity;
    public const int activityID = (int)NewDayActivityID.CustomizedGiftWin;
    public static OperationType operaType = OperationType.CustomizedGift;
    public const int activityID = 99999;
    //public const int activityID = (int)NewDayActivityID.CustomizedGiftWin;
    public static OperationType operaType = (OperationType)99999999;
    //public static OperationType operaType = OperationType.CustomizedGift;
    public int actNum; //对应界面
    public event Action UpdateRechargeGiftActEvent;
Main/System/HappyXB/HappyXBModel.cs
@@ -18,11 +18,11 @@
    {
        get
        {
            #if UNITY_EDITOR
#if UNITY_EDITOR
            if (Time.time - xbLastTime > 1)
            #else
#else
            if (Time.time - xbLastTime > 10)
            #endif
#endif
            {
                m_IsWaitServerXB = false;
                return m_IsWaitServerXB;
@@ -36,7 +36,7 @@
            m_IsWaitServerXB = value;
            xbLastTime = Time.time;
        }
    }
    }
    private Dictionary<int, XBTypeInfo> xbTypeInfoDict = new Dictionary<int, XBTypeInfo>(); //抽奖状态相关的 服务器记录
    public int lhQuality;
@@ -134,7 +134,7 @@
    public int addXBScoreType { get; private set; } //寻宝积分货币类型
    public int addXBLuckValue { get; private set; }
    public int addXBAddItemID { get; private set; } // 本次寻宝额外赠送的物品ID
    public long addItemCount { get; private set; }   // 本次寻宝额外赠送的物品ID个数
    public long addXBItemCount { get; private set; }   // 本次寻宝额外赠送的物品ID个数
    public Dictionary<int, XBGetItem> xbResultDict { get; private set; } = new Dictionary<int, XBGetItem>(); //奖品顺序:奖品
    public void GetServerXBResult(HA350_tagMCTreasureResult result)
    {
@@ -144,7 +144,7 @@
        addXBScoreType = result.AddMoneyType;
        addXBLuckValue = result.AddTreasureLuck;
        addXBAddItemID = (int)result.AddItemID;
        addItemCount = result.AddItemCount;
        addXBItemCount = result.AddItemCount;
        JsonData resultData = JsonMapper.ToObject(result.TreasureResult);
        if (resultData.IsArray)
        {
@@ -183,11 +183,19 @@
                UIManager.Instance.OpenWindow<HeroCallResultWin>();
            }
        }
        if (ActHeroAppearConfig.GetActTreasureTypeList().Contains(type))
        {
            if (!UIManager.Instance.IsOpened<HeroDebutCallResultWin>())
            {
                UIManager.Instance.OpenWindow<HeroDebutCallResultWin>();
            }
        }
    }
    public int GetCountInResult(int itemID)
    {
    {
        int count = 0;
        if (xbResultDict != null && xbResultDict.Count > 0)
        {
@@ -208,7 +216,7 @@
        xbResultDict.Clear();
    }
    public void GetServerXBInfo(HA351_tagMCTreasureInfo info)
    {
        for (int i = 0; i < info.InfoCount; i++)
@@ -270,7 +278,7 @@
                    int cnt = info.TreasuerInfoList[i].GridLimitCntList[j].GridCnt;
                    xbTypeInfoDict[info.TreasuerInfoList[i].TreasureType].gridLimitCntDict[num] = cnt;
                }
                xbTypeInfoDict[info.TreasuerInfoList[i].TreasureType].wishCntDict.Clear();
                for (int j = 0; j < info.TreasuerInfoList[i].WishLibCnt; j++)
                {
@@ -318,7 +326,7 @@
    public void SendXBQuest(int type, int index, int costType)
    {
        if (isXBCoolTime) return;
        isXBCoolTime = true;
        CA568_tagCMRequestTreasure treasure = new CA568_tagCMRequestTreasure();
        treasure.TreasureType = (byte)type;
@@ -511,7 +519,7 @@
        {
            return typeInfo.freeCountToday;
        }
        return 0;
    }
@@ -618,12 +626,12 @@
                needMoney = funcSet.CostMoneyList[0] * (needToolCnt - toolCnt);
            }
            else
            {
            {
                //全部不足的按多次价格算 可能配置了折扣
                needMoney = funcSet.CostMoneyList[1];
            }
        }
        return false;
    }
@@ -635,7 +643,7 @@
    }
    public int GetCostItemID(int type)
    {
    {
        var funcSet = TreasureSetConfig.Get(type);
        if (funcSet == null) return 0;
        return funcSet.CostItemID;
@@ -654,7 +662,7 @@
    public Redpoint bestXB10Red = new Redpoint(HappyXB_RedKey, XBHeroCall10_RedKey);
    public Redpoint bestXBScoreRed = new Redpoint(HappyXB_RedKey, XBHeroCallScore_RedKey);
    private void UpdateFuncState(int funcId)
    {
@@ -678,7 +686,7 @@
            return;
        }
    }
    void OnDayEvent()
@@ -705,12 +713,12 @@
        if (IsHaveFreeXB((int)HappXBTitle.HeroCallAdvanced))
        {
            bestXBFreeRed.state = PlayerDatas.Instance.baseData.realmLevel >= 1 ?RedPointState.GetReward : RedPointState.Simple;
            bestXBFreeRed.state = PlayerDatas.Instance.baseData.realmLevel >= 1 ? RedPointState.GetReward : RedPointState.Simple;
        }
        if (IsHaveManyXBToolEx((int)HappXBTitle.HeroCallAdvanced, out int xbtoolCnt, out int needtoolCnt, out int needMoney))
        {
            bestXB10Red.state = PlayerDatas.Instance.baseData.realmLevel >= 1 ?RedPointState.GetReward : RedPointState.Simple;
            bestXB10Red.state = PlayerDatas.Instance.baseData.realmLevel >= 1 ? RedPointState.GetReward : RedPointState.Simple;
            return;
        }
@@ -718,8 +726,8 @@
        if ((InvestModel.Instance.IsInvested(InvestModel.monthCardType)
        || GetXBInfoByType((int)HappXBTitle.HeroCallScore)?.treasureCount == 0)
        && UIHelper.GetMoneyCnt(51) >= TreasureSetConfig.Get((int)HappXBTitle.HeroCallScore).CostMoneyList[0])
        {
            bestXBScoreRed.state = PlayerDatas.Instance.baseData.realmLevel >= 1 ?RedPointState.GetReward : RedPointState.Simple;
        {
            bestXBScoreRed.state = PlayerDatas.Instance.baseData.realmLevel >= 1 ? RedPointState.GetReward : RedPointState.Simple;
        }
    }
@@ -735,7 +743,7 @@
        return itemIDListTemp.Distinct().ToList();
    }
    #endregion
}
Main/System/HeroDebut.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 03399e82bce6baf41b535b50baffa026
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/BubbleFloat.cs
New file
@@ -0,0 +1,76 @@
using UnityEngine;
using DG.Tweening;
public class BubbleFloat : MonoBehaviour
{
    [Header("浮动范围设置")]
    [SerializeField] private float minY = -20f; // 相对于初始位置的最低偏移
    [SerializeField] private float maxY = 20f;  // 相对于初始位置的最高偏移
    [Header("动画设置")]
    [SerializeField] private float duration = 2f;    // 单程时间
    [SerializeField] private Ease easeType = Ease.InOutSine;
    [SerializeField] private bool useRandomDelay = true; // 是否开启随机延迟
    private Vector3 initialPosition;
    private Tween floatTween;
    private void Awake()
    {
        // 记录 UI 挂载时的原始本地坐标
        initialPosition = transform.localPosition;
    }
    private void OnEnable()
    {
        RestartAnimation();
    }
    private void RestartAnimation()
    {
        KillTween();
        // 1. 确保回到初始参考点
        transform.localPosition = initialPosition;
        float startY = initialPosition.y + minY;
        float endY = initialPosition.y + maxY;
        // 2. 先设置初始位置(起始点)
        transform.localPosition = new Vector3(initialPosition.x, startY, initialPosition.z);
        // 3. 创建动画并记录
        // 注意:我们将动画赋值给变量,并强制立即执行
        floatTween = transform.DOLocalMoveY(endY, duration)
            .SetEase(easeType)
            .SetLoops(-1, LoopType.Yoyo)
            .SetUpdate(true);
        if (useRandomDelay)
        {
            // 关键修正:先让动画计算出初始状态,再跳转进度
            // 否则在创建的第一帧,动画系统可能还没意识到它需要移动
            float randomTime = Random.Range(0f, duration * 2f);
            floatTween.Goto(randomTime, true); // true 表示立即执行回调和位移
        }
    }
    private void OnDisable()
    {
        KillTween();
    }
    private void OnDestroy()
    {
        KillTween();
    }
    private void KillTween()
    {
        if (floatTween != null)
        {
            floatTween.Kill();
            floatTween = null;
        }
    }
}
Main/System/HeroDebut/BubbleFloat.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 92816cc4164e9414583e6b905e94a15e
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/GeneralActInfoManager.cs
New file
@@ -0,0 +1,69 @@
using System;
using System.Collections.Generic;
//活动通用信息
public class GeneralActInfoManager : GameSystemManager<GeneralActInfoManager>
{
    public override void Init()
    {
        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEventOnRelogin += OnBeforePlayerDataInitializeEventOnRelogin;
    }
    public override void Release()
    {
        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEventOnRelogin -= OnBeforePlayerDataInitializeEventOnRelogin;
    }
    private void OnBeforePlayerDataInitializeEventOnRelogin()
    {
        actSignInfos.Clear();
    }
    #region 活动通用模版 活动签到奖励
    public Dictionary<int, Dictionary<int, uint>> actSignInfos = new();
    public event Action<int, int> OnUpdateActSignInfosEvent;
    public void UpdateActSignPlayerInfo(HAA20_tagSCActSignPlayerInfo vNetData)
    {
        if (vNetData == null) return;
        if (!actSignInfos.TryGetValue(vNetData.ActType, out var actNumDict))
        {
            actNumDict = new Dictionary<int, uint>();
            actSignInfos[vNetData.ActType] = actNumDict;
        }
        actNumDict[vNetData.ActNum] = vNetData.SignAward;
        OnUpdateActSignInfosEvent?.Invoke(vNetData.ActType, vNetData.ActNum);
    }
    public bool TryGetSignAward(int actType, int actNum, out uint reward)
    {
        reward = 0;
        if (!actSignInfos.TryGetValue(actType, out var actNumDict)) return false;
        if (!actNumDict.TryGetValue(actNum, out reward)) return false;
        return true;
    }
    public bool IsDaySigned(int actType, int actNum, int dayNum)
    {
        if (dayNum < 1 || dayNum > 32) return false;
        if (!TryGetSignAward(actType, actNum, out uint signAward)) return false;
        return ((signAward >> dayNum) & 1u) == 1u;
    }
    // 活动如果有搭配签到,一般在活动包中会有ActType信息,如AA21封包中的ActType
    public void SendGetSignReward(int actType, int actNum)
    {
        string actTypeStr = actType.ToString();
        var pack = new CA504_tagCMPlayerGetReward
        {
            RewardType = 70,
            DataEx = (uint)actNum,
            DataExStr = actTypeStr,
            DataExStrLen = (byte)actTypeStr.Length
        };
        GameNetSystem.Instance.SendInfo(pack);
    }
    #endregion
}
Main/System/HeroDebut/GeneralActInfoManager.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0f04cdfa27c19304fa145ce589958767
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutCallBubbleCell.cs
New file
@@ -0,0 +1,23 @@
using UnityEngine;
public class HeroDebutCallBubbleCell : MonoBehaviour
{
    [SerializeField] ButtonEx clickButton;
    [SerializeField] ImageEx bgImage;
    [SerializeField] ImageEx iconImage;
    [SerializeField] TextEx countText;
    public void Display(int itemID, int count)
    {
        var config = ItemConfig.Get(itemID);
        if (config == null) return;
        bgImage.SetSprite($"HeroDebutCallBubbleBG{config.ItemColor}");
        iconImage.SetItemSprite(itemID);
        iconImage.SetNativeSize();
        countText.text = count.ToString();
        clickButton.SetListener(() => ItemTipUtility.Show(itemID));
    }
}
Main/System/HeroDebut/HeroDebutCallBubbleCell.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c470779b736bf5144ab6d68c3989aac3
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutCallButton.cs
New file
@@ -0,0 +1,89 @@
using UnityEngine;
public class HeroDebutCallButton : MonoBehaviour
{
    [SerializeField] ButtonEx clickButton;
    [SerializeField] TextEx callText;
    [SerializeField] TextEx needText;
    [SerializeField] ImageEx needImage;
    HeroDebutManager manager => HeroDebutManager.Instance;
    HappyXBModel xbManager => HappyXBModel.Instance;
    int index;
    int type;
    int needCostItemCnt;
    long hasItemCnt;
    int needCostMoneyCnt;
    long moneyCount;
    public void Display(int treasureType, int index)
    {
        this.index = index;
        type = treasureType;
        var treasureSetConfig = TreasureSetConfig.Get(treasureType);
        if (treasureSetConfig == null) return;
        if (treasureSetConfig.TreasureCountList == null || treasureSetConfig.TreasureCountList.Length <= index) return;
        if (treasureSetConfig.CostItemCountList == null || treasureSetConfig.CostItemCountList.Length <= index) return;
        if (treasureSetConfig.CostMoneyList == null || treasureSetConfig.CostMoneyList.Length <= index) return;
        XBTypeInfo info = xbManager.GetXBInfoByType(treasureType);
        if (info == null) return;
        int treasureCnt = treasureSetConfig.TreasureCountList[index];
        callText.text = Language.Get("HeroDebut23", treasureCnt);
        int dailyMaxCountMoney = treasureSetConfig.DailyMaxCountMoney;
        int nowMoneyCnt = info.treasureCountTodayGold;
        needCostMoneyCnt = treasureSetConfig.CostMoneyList[index];
        moneyCount = UIHelper.GetMoneyCnt(treasureSetConfig.CostMoneyType);
        needCostItemCnt = treasureSetConfig.CostItemCountList[index];
        hasItemCnt = PackManager.Instance.GetItemCountByID(PackType.Item, treasureSetConfig.CostItemID);
        // 物品不足 && 没超货币招募次数上限 &&  货币足够
        if (hasItemCnt < needCostItemCnt &&
            nowMoneyCnt + treasureCnt <= dailyMaxCountMoney &&
            moneyCount >= needCostMoneyCnt)
        {
            DisplayByMoney(treasureSetConfig.CostMoneyType, needCostMoneyCnt);
            return;
        }
        DisplayByItem(treasureSetConfig.CostItemID, treasureCnt);
    }
    void DisplayByMoney(int moneyType, long moneyCnt)
    {
        needText.text = Language.Get("L1100", RichTextMsgReplaceConfig.GetRichReplace("MONEY", moneyType), UIHelper.AppendColor(moneyCount < moneyCnt ? TextColType.Red : TextColType.LightGreen, moneyCnt.ToString()));
        needImage.SetIconWithMoneyType(moneyType);
        clickButton.SetListener(() =>
        {
            HeroUIManager.Instance.selectCallType = (HappXBTitle)type;
            HeroUIManager.Instance.selectCallIndex = index;
            HappyXBModel.Instance.SendXBQuest(type, index, 0);
        });
    }
    void DisplayByItem(int itemID, int count)
    {
        ItemConfig itemConfig = ItemConfig.Get(itemID);
        if (itemConfig == null) return;
        bool isEnough = hasItemCnt >= needCostItemCnt;
        needText.text = Language.Get("L1100", itemConfig.ItemName, UIHelper.AppendColor(!isEnough ? TextColType.Red : TextColType.LightGreen, count.ToString()));
        needImage.SetItemSprite(itemID);
        clickButton.SetListener(() =>
        {
            if (!isEnough)
            {
                ItemTipUtility.Show(itemID, true);
                return;
            }
            HeroUIManager.Instance.selectCallType = (HappXBTitle)type;
            HeroUIManager.Instance.selectCallIndex = index;
            HappyXBModel.Instance.SendXBQuest(type, index, 2);
        });
    }
}
Main/System/HeroDebut/HeroDebutCallButton.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ddb737f7cca716044ac755290a7029fe
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutCallChangeCell.cs
New file
@@ -0,0 +1,33 @@
using UnityEngine;
public class HeroDebutCallChangeCell : CellView
{
    [SerializeField] HeroDebutCallChangeItem[] items;
    HeroDebutManager manager => HeroDebutManager.Instance;
    public void Display(int rowIndex)
    {
        var act = manager.GetOperationHeroAppearInfo();
        if (act == null) return;
        var config = ActHeroAppearConfig.Get(act.CfgID);
        if (config == null) return;
        var heroArr = config.ActHeroIDList;
        if (heroArr.IsNullOrEmpty()) return;
        for (int i = 0; i < items.Length; i++)
        {
            int index = rowIndex * HeroDebutCallChangeWin.rowCountMax + i;
            if (index < heroArr.Length)
            {
                items[i].SetActive(true);
                items[i].Display(index, heroArr, act.CfgID);
            }
            else
            {
                items[i].SetActive(false);
            }
        }
    }
}
Main/System/HeroDebut/HeroDebutCallChangeCell.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ece47d072ae8d0e4a8912feed21f3e59
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutCallChangeItem.cs
New file
@@ -0,0 +1,41 @@
using UnityEngine;
using UnityEngine.UI;
public class HeroDebutCallChangeItem : MonoBehaviour
{
    [SerializeField] HeroHeadBaseCell heroHeadBaseCell;
    [SerializeField] Image jobImg;
    [SerializeField] Text nameText;
    [SerializeField] Transform select;
    HeroDebutManager manager => HeroDebutManager.Instance;
    HeroConfig heroConfig;
    int index;
    public void Display(int index, int[] heroIds, int cfgId)
    {
        this.index = index;
        if (heroIds?.Length <= index) return;
        int heroId = heroIds[index];
        heroConfig = HeroConfig.Get(heroId);
        if (heroConfig == null) return;
        int skinID = manager.GetDefaultSkinID(heroId);
        var heroSkinConfig = HeroSkinConfig.Get(skinID);
        if (heroSkinConfig == null) return;
        heroHeadBaseCell.Init(heroConfig.HeroID, skinID, 0, 0, 0, OnClick);
        nameText.text = heroConfig.Name;
        jobImg.SetSprite(HeroUIManager.Instance.GetJobIconName(heroConfig.Class));
        bool isChoose = manager.nowCallChooseHeroID == heroId;
        select?.SetActive(isChoose);
    }
    public void OnClick()
    {
        if (heroConfig == null) return;
        manager.nowCallChooseHeroID = heroConfig.HeroID;
    }
}
Main/System/HeroDebut/HeroDebutCallChangeItem.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f6ce4f60b45922447b708afaa5d49213
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutCallChangeWin.cs
New file
@@ -0,0 +1,100 @@
using UnityEngine;
public class HeroDebutCallChangeWin : UIBase
{
    [SerializeField] ScrollerController scroller;
    [SerializeField] ButtonEx closeButton;
    [SerializeField] ButtonEx okButton;
    [SerializeField] ButtonEx previewButton;
    [SerializeField] UIHeroController uiHeroController;
    public const int rowCountMax = 4;
    HeroDebutManager manager => HeroDebutManager.Instance;
    protected override void InitComponent()
    {
        closeButton.SetListener(CloseWindow);
        okButton.SetListener(() =>
        {
            var act = manager.GetOperationHeroAppearInfo();
            if (act == null) return;
            int index = manager.GetHeroIdIndex(act.CfgID, manager.nowCallChooseHeroID);
            if (index < 0) return;
            if (manager.GetCurrentDisplayCallHeroId() == manager.nowCallChooseHeroID)
            {
                SysNotifyMgr.Instance.ShowTip("HeroDebut01");
                return;
            }
            manager.SnedHeroAppearCallHeroSelect(manager.actNum, index);
            CloseWindow();
        });
        previewButton.SetListener(() =>
        {
            HeroUIManager.Instance.selectForPreviewHeroID = manager.nowCallChooseHeroID;
            UIManager.Instance.OpenWindow<HeroBestWin>();
        });
    }
    protected override void OnPreOpen()
    {
        scroller.OnRefreshCell += OnRefreshCell;
        manager.OnNowCallChooseHeroIDChangeEvent += OnNowCallChooseHeroIDChangeEvent;
        manager.nowCallChooseHeroID = manager.GetCurrentDisplayCallHeroId();
        Display();
        CreateScroller();
    }
    protected override void OnPreClose()
    {
        scroller.OnRefreshCell -= OnRefreshCell;
        manager.OnNowCallChooseHeroIDChangeEvent -= OnNowCallChooseHeroIDChangeEvent;
    }
    private void OnNowCallChooseHeroIDChangeEvent()
    {
        Display();
        scroller.m_Scorller.RefreshActiveCellViews();
    }
    void OnRefreshCell(ScrollerDataType type, CellView cell)
    {
        var _cell = cell as HeroDebutCallChangeCell;
        _cell.Display(cell.index);
    }
    void CreateScroller()
    {
        var act = manager.GetOperationHeroAppearInfo();
        if (act == null) return;
        var config = ActHeroAppearConfig.Get(act.CfgID);
        if (config == null) return;
        var arr = config.ActHeroIDList;
        if (arr.IsNullOrEmpty()) return;
        scroller.Refresh();
        int rowCount = (int)Mathf.Ceil((float)arr.Length / rowCountMax);
        for (int i = 0; i < rowCount; i++)
        {
            scroller.AddCell(ScrollerDataType.Header, i);
        }
        scroller.Restart();
    }
    void Display()
    {
        var act = manager.GetOperationHeroAppearInfo();
        if (act == null) return;
        int skinID = manager.GetDefaultSkinID(manager.nowCallChooseHeroID);
        var skinConfig = HeroSkinConfig.Get(skinID);
        if (skinConfig == null) return;
        uiHeroController.Create(skinID, 1);
    }
}
Main/System/HeroDebut/HeroDebutCallChangeWin.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a286c50b901fce241bb3783575297797
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutCallHistoryCell.cs
New file
@@ -0,0 +1,42 @@
using System.Collections.Generic;
using UnityEngine;
public class HeroDebutCallHistoryCell : CellView
{
    [SerializeField] Color nameColor;
    [SerializeField] TextEx infoText;
    public virtual void Display(int index, List<HeroDebutGameRec> list)
    {
        if (list?.Count <= index) return;
        var rec = list[index];
        var itemconfig = ItemConfig.Get(rec.ItemID);
        if (itemconfig == null) return;
        //150 整个武将
        if (itemconfig.Type == 150)
        {
            HeroConfig heroConfig = HeroConfig.Get(rec.ItemID);
            if (heroConfig == null) return;
            int quality = heroConfig.Quality;
            infoText.text = Language.Get("HeroDebut29",
                UIHelper.AppendColor(nameColor, rec.PlayerName),
                UIHelper.AppendColor(UIHelper.GetUIColorByFunc(quality), Language.Get(StringUtility.Concat("CommonQuality", quality.ToString()))),
                UIHelper.AppendColor(UIHelper.GetUIColorByFunc(quality), heroConfig.Name.ToString())
            );
        }
        else
        {
            int quality = itemconfig.ItemColor;
            infoText.text = Language.Get("HeroDebut30",
                UIHelper.AppendColor(nameColor, rec.PlayerName),
                UIHelper.AppendColor(UIHelper.GetUIColorByFunc(quality), itemconfig.ItemName.ToString()),
                rec.ItemCount.ToString()
            );
        }
    }
}
Main/System/HeroDebut/HeroDebutCallHistoryCell.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f47885b4668b2db4d8ff505bb9b07800
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutCallHistoryOutCell.cs
New file
@@ -0,0 +1,17 @@
using System.Collections.Generic;
using UnityEngine;
public class HeroDebutCallHistoryOutCell : HeroDebutCallHistoryCell
{
    [SerializeField] ButtonEx clickButton;
    [SerializeField] CanvasGroup canvasGroup;
    float[] alphas = new float[4] { 0.45f, 0.60f, 0.80f, 1f };
    public override void Display(int index, List<HeroDebutGameRec> list)
    {
        base.Display(index, list);
        clickButton.SetListener(() => UIManager.Instance.OpenWindow<HeroDebutCallHistoryWin>());
        float alpha = alphas[index];
        canvasGroup.alpha = alpha;
    }
}
Main/System/HeroDebut/HeroDebutCallHistoryOutCell.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 56e7d3092a51a944e9a737346fb5e09c
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutCallHistoryWin.cs
New file
@@ -0,0 +1,57 @@
using System.Collections.Generic;
using UnityEngine;
public class HeroDebutCallHistoryWin : UIBase
{
    [SerializeField] ScrollerController scroller;
    [SerializeField] RectTransform noRect;
    HeroDebutManager manager => HeroDebutManager.Instance;
    protected override void OnPreOpen()
    {
        scroller.lockType = EnhanceLockType.LockVerticalBottom;
        scroller.OnRefreshCell += OnRefreshCell;
        manager.OnUpdateGameRecInfo += OnUpdateGameRecInfo;
        CreateScroller();
    }
    protected override void OnPreClose()
    {
        scroller.OnRefreshCell -= OnRefreshCell;
        manager.OnUpdateGameRecInfo -= OnUpdateGameRecInfo;
    }
    private void OnUpdateGameRecInfo()
    {
        scroller.m_Scorller.RefreshActiveCellViews();
    }
    void OnRefreshCell(ScrollerDataType type, CellView cell)
    {
        var _cell = cell as HeroDebutCallHistoryCell;
        _cell.Display(cell.index, list);
    }
    public List<HeroDebutGameRec> list;
    void CreateScroller()
    {
        list = manager.GetGameRecList();
        if (list == null)
        {
            noRect.SetActive(true);
            scroller.SetActive(false);
            return;
        }
        noRect.SetActive(false);
        scroller.SetActive(true);
        scroller.Refresh();
        for (int i = 0; i < list.Count; i++)
        {
            scroller.AddCell(ScrollerDataType.Header, i);
        }
        scroller.Restart();
    }
}
Main/System/HeroDebut/HeroDebutCallHistoryWin.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 72b89a64567af334e93d6d6e601aa62c
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutCallRateCell.cs
New file
@@ -0,0 +1,28 @@
using System.Collections.Generic;
using UnityEngine;
public class HeroDebutCallRateCell : CellView
{
    [SerializeField] HeroDebutCallRateItem[] items;
    HeroDebutManager manager => HeroDebutManager.Instance;
    public void Display(int rowIndex, Dictionary<int, int> gridRateDict, List<int> gridList, XBGetItemConfig xbConfig)
    {
        if (gridList == null) return;
        for (int i = 0; i < items.Length; i++)
        {
            int index = rowIndex * HeroDebutCallChangeWin.rowCountMax + i;
            if (index < gridList.Count)
            {
                items[i].SetActive(true);
                items[i].Display(index, gridRateDict, gridList, xbConfig);
            }
            else
            {
                items[i].SetActive(false);
            }
        }
    }
}
Main/System/HeroDebut/HeroDebutCallRateCell.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a80d3abc6fbb27e42b345110ed2ebe66
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutCallRateHeroCell.cs
New file
@@ -0,0 +1,28 @@
using System.Collections.Generic;
using UnityEngine;
public class HeroDebutCallRateHeroCell : CellView
{
    [SerializeField] ItemCell[] itemCells;
    public void Display(int rowIndex, List<Item> dataList)
    {
        if (dataList == null) return;
        for (int i = 0; i < itemCells.Length; i++)
        {
            int dataIndex = rowIndex * HeroDebutCallRateHeroWin.rowCountMax + i;
            if (dataIndex < dataList.Count)
            {
                itemCells[i].SetActive(true);
                itemCells[i].Init(new ItemCellModel(dataList[dataIndex].id, true, dataList[dataIndex].countEx));
                itemCells[i].button.SetListener(() => ItemTipUtility.Show(dataList[dataIndex].id));
            }
            else
            {
                itemCells[i].SetActive(false);
            }
        }
    }
}
Main/System/HeroDebut/HeroDebutCallRateHeroCell.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: aa92522c2542a584586c1992c24395f3
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutCallRateHeroWin.cs
New file
@@ -0,0 +1,119 @@
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using UnityEngine;
public class HeroDebutCallRateHeroWin : UIBase
{
    [SerializeField] RectTransform rectTransform;
    [SerializeField] RectTransform arrowImage;
    [SerializeField] RectTransform arrowUpImage;
    [SerializeField] ScrollerController scroller;
    public static Vector3 worldPos; //世界坐标系位置
    public static bool isDownShow = false;  // 是否向下显示
    public static List<Item> dataList;
    public const int rowCountMax = 4;
    protected override void OnPreOpen()
    {
        scroller.OnRefreshCell += OnRefreshCell;
        rectTransform.position = new Vector3(100, 100, 100);   //初始化时,屏幕范围外
        arrowImage.SetActive(!isDownShow);
        arrowUpImage.SetActive(isDownShow);
        CreateScroller();
    }
    protected override void OnPreClose()
    {
        isDownShow = false;
        scroller.OnRefreshCell -= OnRefreshCell;
    }
    void OnRefreshCell(ScrollerDataType type, CellView cell)
    {
        var _cell = cell as HeroDebutCallRateHeroCell;
        _cell.Display(cell.index, dataList);
    }
    void CreateScroller()
    {
        if (dataList == null || dataList.Count == 0) return;
        scroller.Refresh();
        int rowCount = Mathf.CeilToInt((float)dataList.Count / rowCountMax);
        for (int i = 0; i < rowCount; i++)
        {
            scroller.AddCell(ScrollerDataType.Header, i);
        }
        scroller.Restart();
    }
    protected override void OnOpen()
    {
        UpdatePos().Forget();
    }
    async UniTask UpdatePos()
    {
        await UniTask.DelayFrame(3);
        // 限制在屏幕范围内
        Vector3[] corners = new Vector3[4];
        rectTransform.GetWorldCorners(corners);
        float minY = corners[0].y;
        float maxY = corners[0].y;
        for (int i = 1; i < corners.Length; i++)
        {
            if (corners[i].y < minY) minY = corners[i].y;
            if (corners[i].y > maxY) maxY = corners[i].y;
        }
        float screenHeight = maxY - minY;
        Vector2 adjustedPos = new Vector2(worldPos.x, worldPos.y + (!isDownShow ? screenHeight * 0.5f : -screenHeight * 0.5f));
        Vector2 screenAdjustedPos = CameraManager.uiCamera.WorldToScreenPoint(adjustedPos);
        var rectWidth = rectTransform.rect.width * Screen.width / canvasScaler.referenceResolution.x;
        screenAdjustedPos.x = Mathf.Clamp(screenAdjustedPos.x, rectWidth * 0.5f, Screen.width - rectWidth * 0.5f);
        screenAdjustedPos.y = Mathf.Clamp(screenAdjustedPos.y, rectTransform.rect.height * 0.5f, Screen.height - rectTransform.rect.height * 0.5f - 15);
        adjustedPos = CameraManager.uiCamera.ScreenToWorldPoint(screenAdjustedPos);
        rectTransform.position = adjustedPos;
        if (!isDownShow)
        {
            rectTransform.localPosition = new Vector3(rectTransform.localPosition.x, rectTransform.localPosition.y + 15, rectTransform.localPosition.z);
        }
        else
        {
            rectTransform.localPosition = new Vector3(rectTransform.localPosition.x, rectTransform.localPosition.y - 15, rectTransform.localPosition.z);
        }
        rectTransform.GetWorldCorners(corners);
        float minX = corners[0].x;
        float maxX = corners[0].x;
        for (int i = 1; i < corners.Length; i++)
        {
            if (corners[i].x < minX) minX = corners[i].x;
            if (corners[i].x > maxX) maxX = corners[i].x;
        }
        //显示arrowImage 的x轴上的位置,和worldPos同步,但不超过minX 和 maxX范围
        if (!isDownShow)
        {
            Vector3 arrowImagePosition = arrowImage.position;
            arrowImagePosition.x = Mathf.Clamp(worldPos.x, minX, maxX);
            arrowImage.position = arrowImagePosition;
        }
        else
        {
            Vector3 arrowUpImagePosition = arrowUpImage.position;
            arrowUpImagePosition.x = Mathf.Clamp(worldPos.x, minX, maxX);
            arrowUpImage.position = arrowUpImagePosition;
        }
    }
}
Main/System/HeroDebut/HeroDebutCallRateHeroWin.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8f25ce44e5dc223458403a88dfba4c42
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutCallRateItem.cs
New file
@@ -0,0 +1,115 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class HeroDebutCallRateItem : MonoBehaviour
{
    [SerializeField] ButtonEx libButton;
    [SerializeField] ItemCell itemCell;
    [SerializeField] Text rateText;
    HeroDebutManager manager => HeroDebutManager.Instance;
    public void Display(int index, Dictionary<int, int> gridRateDict, List<int> gridList, XBGetItemConfig xbConfig)
    {
        if (gridList?.Count <= index || gridRateDict?.Count != gridList?.Count || xbConfig == null) return;
        if (xbConfig?.GridItemInfo == null || xbConfig?.GridLibInfo == null) return;
        if (manager.xbGridArr == null) return;
        int grid = gridList[index];
        int rate = gridRateDict[grid];
        rateText.text = Language.Get("TimingGift02", (double)rate / (double)100.0);
        SetItemCell(grid, xbConfig.GridItemInfo, xbConfig.GridLibInfo, manager.xbGridArr);
    }
    private void SetItemCell(int grid, Dictionary<int, int[]> gridItemInfo, Dictionary<int, int> gridLibInfo, int[] xbGridArr)
    {
        libButton.SetActive(false);
        itemCell.SetActive(false);
        if (gridItemInfo.TryGetValue(grid, out var itemInfo))
        {
            itemCell.SetActive(true);
            itemCell.Init(new ItemCellModel(itemInfo[0], true, itemInfo[1]));
            itemCell.button.SetListener(() => ItemTipUtility.Show(itemInfo[0]));
            return;
        }
        if (!gridLibInfo.TryGetValue(grid, out var libID)) return;
        var list = TreasureItemLibConfig.GetItemIDList(libID);
        if (list == null) return;
        if (xbGridArr == null) return;
        if (xbGridArr.Contains(grid))
        {
            int heroID = manager.GetCurrentDisplayCallHeroId();
            if (!TryGetHeroItemInfo(heroID, libID, list, out int itemID, out int itemCount)) return;
            itemCell.SetActive(true);
            itemCell.Init(new ItemCellModel(itemID, true, itemCount));
            itemCell.button.SetListener(() => ItemTipUtility.Show(itemID));
        }
        else
        {
            libButton.SetActive(true);
            libButton.SetListener(() =>
            {
                HeroDebutCallRateHeroWin.worldPos = libButton.transform.position;
                HeroDebutCallRateHeroWin.dataList = GetLibItemList(libID, list);
                HeroDebutCallRateHeroWin.isDownShow = true;
                UIManager.Instance.OpenWindow<HeroDebutCallRateHeroWin>();
            });
        }
    }
    public List<Item> GetLibItemList(int libID, List<int> itemList)
    {
        List<Item> res = new();
        for (int i = 0; i < itemList.Count; i++)
        {
            int itemID = itemList[i];
            var config = ItemConfig.Get(itemID);
            if (config == null) continue;
            if (!TreasureItemLibConfig.TryGetID(libID, itemID, out int id)) continue;
            var treasureItemLibConfig = TreasureItemLibConfig.Get(id);
            if (treasureItemLibConfig == null) continue;
            res.Add(new Item(itemID, treasureItemLibConfig.ItemCount));
        }
        return res;
    }
    public bool TryGetHeroItemInfo(int heroID, int libID, List<int> itemList, out int itemID, out int itemCount)
    {
        itemID = 0;
        itemCount = 0;
        if (itemList == null) return false;
        for (int i = 0; i < itemList.Count; i++)
        {
            itemID = itemList[i];
            var config = ItemConfig.Get(itemID);
            if (config == null) continue;
            if (!TreasureItemLibConfig.TryGetID(libID, itemID, out int id)) continue;
            var treasureItemLibConfig = TreasureItemLibConfig.Get(id);
            if (treasureItemLibConfig == null) continue;
            //本体
            if (config.Type == 150)
            {
                if (heroID == itemID)
                {
                    itemCount = treasureItemLibConfig.ItemCount;
                    return true;
                }
            }
            else if (config.Type == 151)
            {
                if (heroID == config.EffectValueA1)
                {
                    itemCount = treasureItemLibConfig.ItemCount;
                    return true;
                }
            }
        }
        return false;
    }
}
Main/System/HeroDebut/HeroDebutCallRateItem.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7741319acfce9754caec83e02f18d8b8
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutCallRateWin.cs
New file
@@ -0,0 +1,83 @@
using System.Collections.Generic;
using UnityEngine;
public class HeroDebutCallRateWin : UIBase
{
    [SerializeField] ScrollerController scroller;
    public const int rowCountMax = 4;
    HeroDebutManager manager => HeroDebutManager.Instance;
    protected override void OnPreOpen()
    {
        scroller.OnRefreshCell += OnRefreshCell;
        CreateScroller();
    }
    protected override void OnPreClose()
    {
        scroller.OnRefreshCell -= OnRefreshCell;
    }
    void OnRefreshCell(ScrollerDataType type, CellView cell)
    {
        var _cell = cell as HeroDebutCallRateCell;
        _cell.Display(cell.index, gridRateDict, gridList, xbConfig);
    }
    Dictionary<int, int> gridRateDict;
    List<int> gridList;
    XBGetItemConfig xbConfig;
    void CreateScroller()
    {
        var act = manager.GetOperationHeroAppearInfo();
        if (act == null) return;
        var config = ActHeroAppearConfig.Get(act.CfgID);
        if (config == null) return;
        xbConfig = HappyXBModel.Instance.GetXBItemConfigByType(config.ActTreasureType);
        if (xbConfig == null || xbConfig.GridItemRateList1 == null) return;
        gridRateDict = GetGridRateDict(xbConfig.GridItemRateList1);
        if (gridRateDict == null) return;
        gridList = GetSortedGridList();
        if (gridList == null) return;
        scroller.Refresh();
        int rowCount = (int)Mathf.Ceil((float)gridList.Count / rowCountMax);
        for (int i = 0; i < rowCount; i++)
        {
            scroller.AddCell(ScrollerDataType.Header, i);
        }
        scroller.Restart();
    }
    //<格子,万分率>
    public Dictionary<int, int> GetGridRateDict(int[][] gridItemRateList1)
    {
        Dictionary<int, int> res = new();
        for (int i = 0; i < gridItemRateList1.Length; i++)
        {
            res[gridItemRateList1[i][1]] = i == 0 ?
                gridItemRateList1[i][0] :
                gridItemRateList1[i][0] - gridItemRateList1[i - 1][0];
        }
        return res;
    }
    public List<int> GetSortedGridList()
    {
        if (gridRateDict == null || gridRateDict.Count == 0) return null;
        List<int> sortedGrids = new List<int>(gridRateDict.Keys);
        sortedGrids.Sort();
        // sortedGrids.Sort((a, b) =>
        // {
        //     int rateA = gridRateDict[a];
        //     int rateB = gridRateDict[b];
        //     return rateA.CompareTo(rateB);
        // });
        return sortedGrids;
    }
}
Main/System/HeroDebut/HeroDebutCallRateWin.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8dc5b2c9b2441074594900b46d1abea5
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutCallResultCell.cs
New file
@@ -0,0 +1,104 @@
using UnityEngine;
using DG.Tweening;
public class HeroDebutCallResultCell : MonoBehaviour
{
    [SerializeField] public ItemCell itemCell;
    [SerializeField] UIEffectPlayer orbBaseEffect;    // 初始状态特效
    [SerializeField] UIEffectPlayer orbBoomEffect;    // 爆发瞬间特效
    [SerializeField] UIEffectPlayer orbQualityEffect; // 品质底色特效
    [SerializeField] UIEffectPlayer flowEffect;       // 最终流光特效
    [HideInInspector] public Vector3 originalLocalPos;
    void Awake()
    {
        // 记录初始本地坐标,用于发牌动画的归位
        originalLocalPos = transform.localPosition;
    }
    /// <summary>
    /// 初始化格子数据
    /// </summary>
    public void DisplayItemCell(int itemID, int count)
    {
        itemCell.Init(new ItemCellModel(itemID, true, count));
        itemCell.button.SetListener(() => ItemTipUtility.Show(itemID));
    }
    /// <summary>
    /// 重置所有 UI 元素和特效至初始状态
    /// </summary>
    public void ResetState()
    {
        itemCell.gameObject.SetActive(false);
        orbBaseEffect.SetActive(false);
        orbBoomEffect.SetActive(false);
        orbQualityEffect.SetActive(false);
        flowEffect.SetActive(false);
    }
    /// <summary>
    /// 阶段 1:播放初始引导光点(飞行阶段)
    /// </summary>
    public void PlayInitialOrb()
    {
        orbBaseEffect.SetActive(true);
        orbBoomEffect.SetActive(false);
        orbQualityEffect.SetActive(false);
        orbBaseEffect.Play(4); // 播放索引为4的通用飞行效
    }
    /// <summary>
    /// 阶段 2 & 3:执行爆开、显色、翻牌、展示流光的组合序列
    /// </summary>
    /// <param name="qualityIndex">品质底色特效索引</param>
    /// <param name="flowQualityIndex">最终流光特效索引</param>
    /// <returns>返回 Sequence 方便外部进行 Stagger(交错)排列</returns>
    public Tween PlayExplosionFadeAndFlipReveal(int qualityIndex, int flowQualityIndex)
    {
        Sequence seq = DOTween.Sequence();
        // [0.0s] 切换特效:关闭飞行态,触发爆发态
        seq.InsertCallback(0f, () =>
        {
            orbBaseEffect.SetActive(false);
            orbBoomEffect.SetActive(true);
            orbBoomEffect.Play(3);
        });
        // [0.2s] 展示品质基色
        seq.InsertCallback(0.2f, () =>
        {
            orbQualityEffect.transform.localScale = Vector3.zero;
            orbQualityEffect.SetActive(true);
            orbQualityEffect.Play(qualityIndex);
        });
        // 品质光团由小变大的回弹动画
        seq.Insert(0.2f, orbQualityEffect.transform.DOScale(Vector3.one, 0.2f).SetEase(Ease.OutBack));
        // [0.8s] 准备翻牌:激活 ItemCell 并设置 90 度侧向,准备旋转
        seq.InsertCallback(0.8f, () =>
        {
            itemCell.gameObject.SetActive(true);
            itemCell.transform.localEulerAngles = new Vector3(0, 90f, 0);
        });
        // [0.8s] 翻转动作(耗时 0.3s):从 90 度旋转回 0 度
        seq.Insert(0.8f, itemCell.transform.DOLocalRotate(Vector3.zero, 0.3f, RotateMode.Fast).SetEase(Ease.OutSine));
        // [1.1s] 序列完结:清理临时特效,激活持久流光
        seq.InsertCallback(1.1f, () =>
        {
            orbBoomEffect.SetActive(false);
            orbQualityEffect.SetActive(false);
            flowEffect.SetActive(true);
            flowEffect.Play(flowQualityIndex);
        });
        return seq;
    }
}
Main/System/HeroDebut/HeroDebutCallResultCell.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 05657965f47d7c34b8cc628132fa967f
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutCallResultWin.cs
New file
@@ -0,0 +1,370 @@
using UnityEngine;
using DG.Tweening;
using System.Collections.Generic;
public class HeroDebutCallResultWin : UIBase
{
    [SerializeField] Transform moneyRect;
    [SerializeField] OwnItemCell ownItemCell;
    [SerializeField] ItemCell presentItemCell;         // 抽卡获得的赠送道具
    [SerializeField] RectTransform oneRect;             // 单抽容器中心点
    [SerializeField] HeroDebutCallResultCell oneCell;   // 单抽单元格
    [SerializeField] RectTransform tenRect;             // 十连容器
    [SerializeField] HeroDebutCallResultCell[] tenCell; // 十连单元格数组
    [SerializeField] UIEffectPlayer firstEffect;        // 开屏初始特效
    [SerializeField] HeroDebutCallButton callButton;    // 再次抽取按钮
    [SerializeField] ButtonEx okButton;                 // 确定返回按钮
    HeroDebutManager manager => HeroDebutManager.Instance;
    HappyXBModel xbManager => HappyXBModel.Instance;
    bool isSkip;            // 是否跳过动画
    int treasureType;       // 抽卡宝库类型
    bool isOne = false;     // 是否为单抽模式
    private Sequence animSeq; // 主动画序列
    protected override void InitComponent()
    {
        okButton.SetListener(CloseWindow);
    }
    protected override void OnPreOpen()
    {
        animSeq?.Kill();
        var act = manager.GetOperationHeroAppearInfo();
        if (act == null) return;
        var config = ActHeroAppearConfig.Get(act.CfgID);
        if (config == null) return;
        treasureType = config.ActTreasureType;
        // 根据配置和时间戳加载用户的是否跳过动画设置
        isSkip = manager.LoadCallSkipData(config.CfgID, act.startDate, act.endDate);
        // 绑定数据刷新回调
        HappyXBModel.Instance.RefreshXBResultAct += RefreshXBResultAct;
        HappyXBModel.Instance.RefreshXBTypeInfoAct += OnRefreshXBTypeInfoAct;
        var treasureSetConfig = TreasureSetConfig.Get(config.ActTreasureType);
        if (treasureSetConfig == null) return;
        ownItemCell.itemID = treasureSetConfig.CostItemID;
        RefreshXBResultAct();
    }
    protected override void OnPreClose()
    {
        animSeq?.Kill();
        // 解绑回调,防止内存泄漏
        HappyXBModel.Instance.RefreshXBResultAct -= RefreshXBResultAct;
        HappyXBModel.Instance.RefreshXBTypeInfoAct -= OnRefreshXBTypeInfoAct;
    }
    /// <summary>
    /// 刷新抽卡结果界面
    /// </summary>
    void RefreshXBResultAct()
    {
        isOne = HeroUIManager.Instance.selectCallIndex == 0;
        // 初始化顶部赠送物品
        int itemId = xbManager.addXBAddItemID;
        long count = xbManager.addXBItemCount;
        presentItemCell.Init(new ItemCellModel(itemId, true, count));
        presentItemCell.button.SetListener(() => ItemTipUtility.Show(itemId));
        // 根据单抽或十连填充物品数据
        if (isOne)
        {
            if (!xbManager.xbResultDict.IsNullOrEmpty())
            {
                oneCell.DisplayItemCell(xbManager.xbResultDict[0].itemId, xbManager.xbResultDict[0].count);
            }
        }
        else
        {
            for (int i = 0; i < tenCell.Length; i++)
            {
                if (i < xbManager.xbResultDict?.Count)
                {
                    tenCell[i].DisplayItemCell(xbManager.xbResultDict[i].itemId, xbManager.xbResultDict[i].count);
                }
            }
        }
        callButton.Display(treasureType, HeroUIManager.Instance.selectCallIndex);
        if (isSkip)
        {
            // 模式:跳过动画,直接显示最终状态
            firstEffect.SetActive(false);
            ShowImmediate();
        }
        else
        {
            // 模式:播放完整展示动画
            PrepareAnimation();
            firstEffect.SetActive(true);
            firstEffect.Play(0);
            // 预留 1.1s 的开屏动效时间后,开始播放发牌/翻牌序列
            PlayResultAnimation(1.1f);
        }
    }
    private void OnRefreshXBTypeInfoAct() { RefreshXBResultAct(); }
    /// <summary>
    /// 静态显示(无动画直接展示结果)
    /// </summary>
    private void ShowImmediate()
    {
        animSeq?.Kill();
        oneRect.SetActive(isOne);
        tenRect.SetActive(!isOne);
        ownItemCell.SetActive(true);
        moneyRect.SetActive(true);
        presentItemCell.SetActive(true);
        callButton.SetActive(true);
        okButton.SetActive(true);
        if (isOne)
        {
            oneCell.SetActive(true);
            oneCell.ResetState();
            oneCell.itemCell.SetActive(true);
        }
        else
        {
            for (int i = 0; i < tenCell.Length; i++)
            {
                if (i < xbManager.xbResultDict?.Count)
                {
                    tenCell[i].SetActive(true);
                    tenCell[i].transform.localPosition = tenCell[i].originalLocalPos;
                    tenCell[i].ResetState();
                    tenCell[i].itemCell.SetActive(true);
                }
                else
                {
                    tenCell[i].SetActive(false);
                }
            }
        }
    }
    /// <summary>
    /// 动画前置准备(隐藏元素并重置坐标)
    /// </summary>
    private void PrepareAnimation()
    {
        oneRect.SetActive(isOne);
        tenRect.SetActive(!isOne);
        ownItemCell.SetActive(false);
        moneyRect.SetActive(false);
        presentItemCell.SetActive(false);
        callButton.SetActive(false);
        okButton.SetActive(false);
        if (isOne)
        {
            oneCell.SetActive(true);
            oneCell.ResetState();
        }
        else
        {
            for (int i = 0; i < tenCell.Length; i++)
            {
                if (i < xbManager.xbResultDict?.Count)
                {
                    tenCell[i].SetActive(true);
                    tenCell[i].ResetState();
                    tenCell[i].transform.localPosition = tenCell[i].originalLocalPos;
                }
                else
                {
                    tenCell[i].SetActive(false);
                }
            }
        }
    }
    /// <summary>
    /// 核心逻辑:编排结果展示动画时间轴
    /// </summary>
    private void PlayResultAnimation(float startDelay = 0f)
    {
        animSeq?.Kill();
        animSeq = DOTween.Sequence();
        if (isOne)
        {
            // ==================== 单抽动画逻辑 ====================
            float timelineCursor = startDelay;
            // 1. 播放中心光团
            animSeq.InsertCallback(timelineCursor, () => oneCell.PlayInitialOrb());
            // 预留短暂的展示时间
            float finishShowTime = 0.12f;
            timelineCursor += finishShowTime;
            // 2. 触发爆开与翻牌组合动画
            int itemId = xbManager.xbResultDict[0].itemId;
            int quality = GetOrbQuality(itemId);
            int flowQuality = GetFlowQuality(itemId);
            animSeq.Insert(timelineCursor, oneCell.PlayExplosionFadeAndFlipReveal(quality, flowQuality));
            // 推进游标至组合动画结束(1.1s基础时长 + 0.3s缓冲)
            timelineCursor += 1.4f;
            // 3. 弹出底部 UI
            animSeq.InsertCallback(timelineCursor, ShowBottomUI);
        }
        else
        {
            // ==================== 十连动画逻辑 ====================
            int count = xbManager.xbResultDict.Count;
            float staggerInterval = 0.1f; // 发牌间隔
            float moveDuration = 0.12f;    // 飞行时间
            float timelineCursor = startDelay;
            // 1. 依次从中心点向目标位置发射光团(发牌阶段)
            for (int i = 0; i < count; i++)
            {
                var cell = tenCell[i];
                cell.transform.position = oneRect.position; // 起始于中心
                float delay = timelineCursor + i * staggerInterval;
                animSeq.InsertCallback(delay, () => cell.PlayInitialOrb());
                animSeq.Insert(delay, cell.transform.DOLocalMove(cell.originalLocalPos, moveDuration).SetEase(Ease.OutCubic));
            }
            // 计算所有卡牌完成飞行的时刻
            float finishFlyingTime = ((count - 1) * staggerInterval) + moveDuration;
            timelineCursor += finishFlyingTime;
            // 2. 依次触发爆开翻牌动画(展示阶段)
            for (int i = 0; i < count; i++)
            {
                int itemId = xbManager.xbResultDict[i].itemId;
                int quality = GetOrbQuality(itemId);
                int flowQuality = GetFlowQuality(itemId);
                animSeq.Insert(timelineCursor + i * staggerInterval, tenCell[i].PlayExplosionFadeAndFlipReveal(quality, flowQuality));
            }
            // 计算全部卡牌翻转完成的时间点并加入缓冲
            float finalFlipDuration = 1.1f + ((count - 1) * staggerInterval) + 0.3f;
            timelineCursor += finalFlipDuration;
            // 3. 弹出底部 UI
            animSeq.InsertCallback(timelineCursor, ShowBottomUI);
        }
    }
    /// <summary>
    /// 展示底部操作按钮,并检查是否触发武将立绘
    /// </summary>
    private void ShowBottomUI()
    {
        ownItemCell.SetActive(true);
        moneyRect.SetActive(true);
        presentItemCell.SetActive(true);
        callButton.SetActive(true);
        okButton.SetActive(true);
        presentItemCell.transform.localScale = Vector3.zero;
        callButton.transform.localScale = Vector3.zero;
        okButton.transform.localScale = Vector3.zero;
        Sequence bottomSeq = DOTween.Sequence();
        bottomSeq.Append(presentItemCell.transform.DOScale(Vector3.one, 0.3f).SetEase(Ease.OutBack));
        bottomSeq.Join(callButton.transform.DOScale(Vector3.one, 0.3f).SetEase(Ease.OutBack));
        bottomSeq.Join(okButton.transform.DOScale(Vector3.one, 0.3f).SetEase(Ease.OutBack));
        bottomSeq.OnComplete(() =>
        {
            if (!isSkip)
            {
                CheckAndShowHeroLH();
            }
        });
        animSeq.Append(bottomSeq);
    }
    /// <summary>
    /// 检测并展示高品质武将立绘(弹窗展示)
    /// </summary>
    private void CheckAndShowHeroLH()
    {
        // 清理缓存列表
        ItemLogicUtility.Instance.poplhHeroIdList.Clear();
        List<int> uniqueHeroIds = new List<int>();
        int count = xbManager.xbResultDict.Count;
        for (int i = 0; i < count; i++)
        {
            int itemId = xbManager.xbResultDict[i].itemId;
            // 仅对 HeroConfig 中存在的完整武将进行处理
            if (HeroConfig.HasKey(itemId))
            {
                // 仅展示高于设定品质的武将
                if (HeroConfig.Get(itemId).Quality < HappyXBModel.Instance.lhQuality) continue;
                if (!uniqueHeroIds.Contains(itemId))
                {
                    uniqueHeroIds.Add(itemId);
                }
            }
        }
        // 如果存在符合条件的武将,打开大图展示界面
        if (uniqueHeroIds.Count > 0)
        {
            ItemLogicUtility.Instance.poplhHeroIdList = uniqueHeroIds;
            if (!UIManager.Instance.IsOpenedInList<HeroShowLHWin>())
            {
                UIManager.Instance.OpenWindow<HeroShowLHWin>();
            }
        }
    }
    // --- 辅助方法:映射配置品质到特效索引 ---
    private int GetOrbQuality(int itemId)
    {
        int qualityLevel = ItemConfig.Get(itemId).ItemColor;
        switch (qualityLevel)
        {
            case 2: return 5; // 紫色
            case 3: return 2; // 黄色
            case 4: return 0; // 橙色
            case 5: return 1; // 红色
            default: return 0;
        }
    }
    private int GetFlowQuality(int itemId)
    {
        int qualityLevel = ItemConfig.Get(itemId).ItemColor;
        switch (qualityLevel)
        {
            case 2: return 3; // 紫色
            case 3: return 2; // 黄色
            case 4: return 0; // 橙色
            case 5: return 1; // 红色
            default: return 0;
        }
    }
}
Main/System/HeroDebut/HeroDebutCallResultWin.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6ffc73cd38a0318498657bf4ae3312a4
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutCallWin.cs
New file
@@ -0,0 +1,321 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;
public class HeroDebutCallWin : UIBase
{
    [SerializeField] RectTransform changeRect;
    [SerializeField] UIEffectPlayer changeUIEffect;
    [SerializeField] OwnItemCell ownItemCell;
    [SerializeField] ButtonEx closeBtn;
    [SerializeField] Toggle skipToggle;
    [SerializeField] HeroDebutCallButton xbButton1;
    [SerializeField] HeroDebutCallButton xbButton10;
    [SerializeField] TextEx resMoneyCallCntText;
    [SerializeField] GradientText nextBigAwardCntText;
    [SerializeField] GradientText heroQualityText;
    [SerializeField] GradientText heroNameText;
    [SerializeField] TextEx timeText;
    [SerializeField] TextEx nameText;
    [SerializeField] TextEx descText;
    [SerializeField] ImageEx countryImage;
    [SerializeField] ImageEx jobImage;
    [SerializeField] ButtonEx changeHeroButton;//更换英雄
    [SerializeField] ButtonEx previewButton;//满级预览
    [SerializeField] ButtonEx closeButton;
    [SerializeField] ButtonEx shopButton; // 兑换商店
    [SerializeField] RedpointBehaviour shopRedpoint;
    [SerializeField] ButtonEx giftButton; // 皇权礼包
    [SerializeField] RedpointBehaviour giftRedpoint;
    [SerializeField] ButtonEx rankButton;
    [SerializeField] TextEx[] top3NameText;
    [SerializeField] TextEx rankTipText;
    [SerializeField] ButtonEx rateButton;
    [SerializeField] ScrollerController scroller;
    [SerializeField] UIHeroController lhController;
    [SerializeField] UIHeroController uiHeroController;
    [SerializeField] HeroDebutCallBubbleCell[] bubbleCell;
    [SerializeField] float modleSize = 1f;
    HeroDebutManager manager => HeroDebutManager.Instance;
    protected override void InitComponent()
    {
        closeButton.SetListener(CloseWindow);
        shopButton.SetListener(() => UIManager.Instance.OpenWindow<HeroDebutShopWin>());
        giftButton.SetListener(() => UIManager.Instance.OpenWindow<HeroDebutGiftWin>());
        changeHeroButton.SetListener(() => UIManager.Instance.OpenWindow<HeroDebutCallChangeWin>());
        rankButton.SetListener(() => UIManager.Instance.OpenWindow<HeroDebutRankWin>());
        rateButton.SetListener(() => UIManager.Instance.OpenWindow<HeroDebutCallRateWin>());
        previewButton.SetListener(OnClickPreview);
        skipToggle.AddListener((value) =>
        {
            manager.SaveCallSkipData(config.CfgID, act.startDate, act.endDate, value);
        });
    }
    protected override void OnPreOpen()
    {
        scroller.lockType = EnhanceLockType.LockVerticalBottom;
        RankModel.Instance.ResetQueryParam();
        RankModel.Instance.QueryRankByPage(manager.sendRankType, watchID: (int)PlayerDatas.Instance.baseData.PlayerID, groupValue1: manager.actNum);
        HappyXBModel.Instance.RefreshXBTypeInfoAct += OnRefreshXBTypeInfoAct;
        GlobalTimeEvent.Instance.secondEvent += OnSecondEvent;
        RankModel.Instance.onRankRefresh += OnRankRefresh;
        PlayerDatas.Instance.playerDataRefreshEvent += PlayerDataRefresh;
        PackManager.Instance.RefreshItemEvent += RefreshItemEvent;
        scroller.OnRefreshCell += OnRefreshCell;
        manager.OnUpdateGameRecInfo += OnUpdateGameRecInfo;
        manager.OnUpdateHeroAppearPlayerInfoEvent += OnUpdateHeroAppearPlayerInfoEvent;
        if (manager.isSendFirst)
        {
            act = manager.GetOperationHeroAppearInfo();
            if (act == null) return;
            config = ActHeroAppearConfig.Get(act.CfgID);
            if (config == null) return;
            int treasureType = config.ActTreasureType;
            manager.SendViewGameRecPack(treasureType);
        }
        InitRedpoint();
        CreateScroller();
        Display();
    }
    protected override void OnPreClose()
    {
        HappyXBModel.Instance.RefreshXBTypeInfoAct -= OnRefreshXBTypeInfoAct;
        GlobalTimeEvent.Instance.secondEvent -= OnSecondEvent;
        RankModel.Instance.onRankRefresh -= OnRankRefresh;
        PlayerDatas.Instance.playerDataRefreshEvent -= PlayerDataRefresh;
        PackManager.Instance.RefreshItemEvent -= RefreshItemEvent;
        scroller.OnRefreshCell -= OnRefreshCell;
        manager.OnUpdateGameRecInfo -= OnUpdateGameRecInfo;
        manager.OnUpdateHeroAppearPlayerInfoEvent -= OnUpdateHeroAppearPlayerInfoEvent;
    }
    // 1. 在类中声明一个全局的 Sequence 变量,用于统一管控动画
    private Sequence heroAnimSeq;
    private void OnUpdateHeroAppearPlayerInfoEvent(int actNum)
    {
        changeRect.SetActive(false);
        // 2. 彻底杀死之前的 Sequence,防止快速连点造成内部 Tween 复用错乱
        if (heroAnimSeq != null)
        {
            heroAnimSeq.Kill();
            heroAnimSeq = null;
        }
        // 刷新界面数据和英雄模型(这里面会调用 lhController.Create)
        Display();
        Transform targetTrans = lhController.transform;
        // 停止 Transform 上可能残留的单独动画
        targetTrans.DOKill();
        int heroID = manager.GetCurrentDisplayCallHeroId();
        int skinID = manager.GetDefaultSkinID(heroID);
        var skinConfig = HeroSkinConfig.Get(skinID);
        float baseScaleValue = 1f; // 默认缩放
        // 检查是否有配置专属的立绘缩放参数(TachieParam[2])
        if (skinConfig != null && skinConfig.TachieParam != null && skinConfig.TachieParam.Length == 4)
        {
            baseScaleValue = skinConfig.TachieParam[2];
        }
        Vector3 baseScale = Vector3.one * baseScaleValue;
        // 【强制复位!】解决 UIHeroController 内部 return 导致的缩放未复位问题
        targetTrans.localScale = baseScale;
        // 获取或添加 CanvasGroup 用于透明度控制
        CanvasGroup cg = lhController.GetComponent<CanvasGroup>();
        if (cg == null) cg = lhController.gameObject.AddComponent<CanvasGroup>();
        cg.DOKill();
        cg.alpha = 0.8f;
        changeUIEffect.Play();
        // 4. 创建新的 Sequence 并赋值给成员变量
        heroAnimSeq = DOTween.Sequence();
        // 缩放动画基于正确的 baseScale 进行计算(变大1.1倍后再还原)
        heroAnimSeq.Append(targetTrans.DOScale(baseScale * 1.1f, 0.3f).SetEase(Ease.OutQuad));
        heroAnimSeq.Append(targetTrans.DOScale(baseScale, 0.3f).SetEase(Ease.InQuad));
        // 透明度
        heroAnimSeq.Join(cg.DOFade(1f, 0.3f).SetEase(Ease.Linear));
        // 动画完成后显示 changeRect,并清空引用
        heroAnimSeq.OnComplete(() =>
        {
            changeRect.SetActive(true);
            heroAnimSeq = null;
        });
    }
    private void OnUpdateGameRecInfo()
    {
        CreateScroller();
    }
    public void RefreshItemEvent(PackType packType, int index, int itemID)
    {
        if (packType != PackType.Item && treasureSetConfig?.CostItemID != itemID) return;
        Display();
    }
    private void PlayerDataRefresh(PlayerDataType type)
    {
        if (type != PlayerDataType.Gold) return;
        Display();
    }
    private void OnRankRefresh(int type)
    {
        if (type != manager.sendRankType) return;
        ShowTop3();
    }
    private void OnSecondEvent()
    {
        manager.GetActTimeStr(timeText);
    }
    private void OnRefreshXBTypeInfoAct()
    {
        Display();
    }
    public void InitRedpoint()
    {
        shopRedpoint.redpointId = manager.GetRedPointId(HeroDebutRedPointType.Shop);
        giftRedpoint.redpointId = manager.GetRedPointId(HeroDebutRedPointType.Gift);
    }
    private void OnClickPreview()
    {
        if (heroConfig == null) return;
        HeroUIManager.Instance.selectForPreviewHeroID = heroConfig.HeroID;
        UIManager.Instance.OpenWindow<HeroBestWin>();
    }
    OperationHeroAppearInfo act;
    ActHeroAppearConfig config;
    HeroConfig heroConfig;
    TreasureSetConfig treasureSetConfig;
    XBTypeInfo xbTypeInfo;
    private void Display()
    {
        act = manager.GetOperationHeroAppearInfo();
        if (act == null) return;
        config = ActHeroAppearConfig.Get(act.CfgID);
        if (config == null) return;
        int heroID = manager.GetCurrentDisplayCallHeroId();
        heroConfig = HeroConfig.Get(heroID);
        if (heroConfig == null) return;
        int skinID = manager.GetDefaultSkinID(heroID);
        var skinConfig = HeroSkinConfig.Get(skinID);
        if (skinConfig == null) return;
        var artConfig = ActHeroAppearArtConfig.Get(heroID);
        if (artConfig == null || artConfig.CallBubbleItems == null) return;
        int treasureType = config.ActTreasureType;
        treasureSetConfig = TreasureSetConfig.Get(treasureType);
        if (treasureSetConfig == null) return;
        xbTypeInfo = HappyXBModel.Instance.GetXBInfoByType(treasureType);
        if (xbTypeInfo == null) return;
        lhController.Create(skinID, 1, motionName: "", isLh: true);
        uiHeroController.Create(skinID, modleSize);
        uiHeroController.transform.localScale = new Vector3(modleSize, modleSize, modleSize);
        ownItemCell.itemID = treasureSetConfig.CostItemID;
        skipToggle.isOn = manager.LoadCallSkipData(config.CfgID, act.startDate, act.endDate);
        xbButton1.Display(config.ActTreasureType, 0);
        xbButton10.Display(config.ActTreasureType, 1);
        resMoneyCallCntText.text = Language.Get("HeroDebut24", Mathf.Max(treasureSetConfig.DailyMaxCountMoney - xbTypeInfo.treasureCountTodayGold, 0));
        var needCount = HappyXBModel.Instance.GetNextXBCountForBigAward(treasureType, out var qualityList);
        nextBigAwardCntText.text = needCount.ToString();
        heroQualityText.text = Language.Get($"heroCallQaulity{heroConfig.Quality}");
        manager.SetheroQaulityColor(heroQualityText, heroConfig.Quality);
        nameText.text = heroConfig.Name;
        nameText.color = UIHelper.GetUIColorByFunc(heroConfig.Quality);
        descText.text = heroConfig.Desc;
        countryImage.SetSprite(HeroUIManager.Instance.GetCountryIconName(heroConfig.Country));
        jobImage.SetSprite(HeroUIManager.Instance.GetJobIconName(heroConfig.Class));
        heroNameText.text = heroConfig.Name;
        manager.SetGradientTextColor(heroNameText, artConfig.HeroNameColor);
        for (int i = 0; i < bubbleCell.Length; i++)
        {
            if (i < artConfig.CallBubbleItems.Length)
            {
                bubbleCell[i].SetActive(true);
                bubbleCell[i].Display(artConfig.CallBubbleItems[i][0], artConfig.CallBubbleItems[i][1]);
            }
            else
            {
                bubbleCell[i].SetActive(false);
            }
        }
        ShowTop3();
        OnSecondEvent();
    }
    void ShowTop3()
    {
        for (int i = 0; i < top3NameText.Length; i++)
        {
            var rankData = RankModel.Instance.GetRankDataByRank(manager.loadRankType, i + 1);
            top3NameText[i].text = rankData == null ? Language.Get("L1124") : rankData.name1;
        }
        int billTempID = config.BillTempID;
        rankTipText.text = Language.Get("HeroDebut27", ActBillboardAwardConfig.GetTop3MinCalNeedValue(billTempID));
    }
    public List<HeroDebutGameRec> list;
    void OnRefreshCell(ScrollerDataType type, CellView cell)
    {
        var _cell = cell as HeroDebutCallHistoryOutCell;
        _cell.Display(cell.index, list);
    }
    void CreateScroller()
    {
        list = manager.GetLastFourRecords();
        scroller.Refresh();
        if (list != null)
        {
            for (int i = 0; i < list.Count; i++)
            {
                scroller.AddCell(ScrollerDataType.Header, i);
            }
        }
        scroller.Restart();
    }
}
Main/System/HeroDebut/HeroDebutCallWin.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d2e10a7ad06305c4dbd67d43b5343202
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutCell.cs
New file
@@ -0,0 +1,31 @@
using UnityEngine;
public class HeroDebutCell : MonoBehaviour
{
    [SerializeField] ButtonEx clickButton;
    [SerializeField] ImageEx bgImage;
    [SerializeField] ImageEx heroImage;
    [SerializeField] GradientText titleText;
    HeroDebutManager manager => HeroDebutManager.Instance;
    public void Display()
    {
        clickButton.SetListener(() =>
        {
            UIManager.Instance.OpenWindow<HeroDebutWin>();
        });
        int heroID = manager.GetCurrentDisplayCallHeroId();
        var artConfig = ActHeroAppearArtConfig.Get(heroID);
        if (artConfig == null) return;
        int skinID = manager.GetDefaultSkinID(heroID);
        var skinConfig = HeroSkinConfig.Get(skinID);
        if (skinConfig == null) return;
        bgImage.SetSprite(artConfig.EntryBgImage);
        manager.SetHeroSquareIcon(heroImage, skinConfig.SquareIcon);
        titleText.text = artConfig.EntryTitleText;
    }
}
Main/System/HeroDebut/HeroDebutCell.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2d56020c6e8624a4d9451d33aca7ef47
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutCheckInCell.cs
New file
@@ -0,0 +1,60 @@
using UnityEngine;
public class HeroDebutCheckInCell : MonoBehaviour
{
    [SerializeField] ButtonEx clickButton;
    [SerializeField] ImageEx bgImage;
    [SerializeField] TextEx dayText;
    [SerializeField] TextEx itemNameText;
    [SerializeField] ItemCell itemCell;
    [SerializeField] UIEffectPlayer uiEffectPlayer;
    [SerializeField] Transform imgMask;
    HeroDebutManager manager => HeroDebutManager.Instance;
    private int currentItemId;
    private int currentState;
    public void Display(int templateID, int dayNum)
    {
        uiEffectPlayer.Stop();
        var config = ActSignAwardConfig.GetConfig(templateID, dayNum);
        if (config == null) return;
        if (config.SignAwardItemList.IsNullOrEmpty()) return;
        currentItemId = config.SignAwardItemList[0][0];
        int count = config.SignAwardItemList[0][1];
        var itemConfig = ItemConfig.Get(currentItemId);
        if (itemConfig == null) return;
        currentState = manager.GetCheckInState(dayNum);
        imgMask.SetActive(currentState == 2);
        bgImage.SetSprite(currentState == 1 ? "HeroDebutCheckInDayBG1" : "HeroDebutCheckInDayBG2");
        if (currentState == 1)
        {
            uiEffectPlayer.Play();
        }
        dayText.text = Language.Get($"SignDay{dayNum}");
        itemNameText.text = itemConfig.ItemName;
        itemCell.Init(new ItemCellModel(currentItemId, false, count));
        itemCell.button.AddListener(OnItemClicked);
        clickButton.SetListener(() => manager.SendGetCheckInReward());
    }
    private void OnItemClicked()
    {
        if (currentState == 1)
        {
            manager.SendGetCheckInReward();
        }
        else
        {
            ItemTipUtility.Show(currentItemId);
        }
    }
}
Main/System/HeroDebut/HeroDebutCheckInCell.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f2adf3253dbe5a7429ed0a362a3c5c53
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutCheckInWin.cs
New file
@@ -0,0 +1,79 @@
using UnityEngine;
public class HeroDebutCheckInWin : UIBase
{
    [SerializeField] ImageEx bgImage;
    [SerializeField] UIHeroController rolelhShow;
    [SerializeField] TextEx timeText;
    [SerializeField] ButtonEx closeButton;
    [SerializeField] HeroDebutCheckInCell[] cells;
    HeroDebutManager manager => HeroDebutManager.Instance;
    protected override void InitComponent()
    {
        closeButton.SetListener(CloseWindow);
    }
    protected override void OnPreOpen()
    {
        GeneralActInfoManager.Instance.OnUpdateActSignInfosEvent += OnUpdateActSignInfosEvent;
        TimeMgr.Instance.OnDayEvent += OnDayEvent;
        GlobalTimeEvent.Instance.secondEvent += OnSecondEvent;
        Display();
    }
    protected override void OnPreClose()
    {
        GeneralActInfoManager.Instance.OnUpdateActSignInfosEvent -= OnUpdateActSignInfosEvent;
        TimeMgr.Instance.OnDayEvent -= OnDayEvent;
        GlobalTimeEvent.Instance.secondEvent -= OnSecondEvent;
    }
    private void OnDayEvent()
    {
        Display();
    }
    private void OnUpdateActSignInfosEvent(int arg1, int arg2)
    {
        Display();
    }
    private void OnSecondEvent()
    {
        manager.GetActTimeStr(timeText);
    }
    private void Display()
    {
        int heroID = manager.GetCurrentDisplayCallHeroId();
        var artConfig = ActHeroAppearArtConfig.Get(heroID);
        if (artConfig == null) return;
        var heroConfig = HeroConfig.Get(heroID);
        if (heroConfig == null) return;
        int skinID = manager.GetDefaultSkinID(heroID);
        var act = manager.GetOperationHeroAppearInfo();
        if (act == null) return;
        var config = ActHeroAppearConfig.Get(act.CfgID);
        if (config == null) return;
        int templateID = config.SignTempID;
        var list = ActSignAwardConfig.GetDayNumSortList(templateID);
        if (list == null) return;
        for (int i = 0; i < cells.Length; i++)
        {
            if (i < list.Count)
            {
                cells[i].SetActive(true);
                cells[i].Display(templateID, list[i]);
            }
            else
            {
                cells[i].SetActive(false);
            }
        }
        rolelhShow.Create(skinID, 1, motionName: "", isLh: true);
        OnSecondEvent();
    }
}
Main/System/HeroDebut/HeroDebutCheckInWin.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ac084043fc15fba478af2e039db46fbe
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutGiftCell.cs
New file
@@ -0,0 +1,128 @@
using System.Collections.Generic;
using UnityEngine;
public class HeroDebutGiftCell : MonoBehaviour
{
    [SerializeField] ItemCell[] itemCells;
    [SerializeField] TextEx titleText;
    [SerializeField] ButtonEx buyButton;
    [SerializeField] ImageEx buyImage;
    [SerializeField] TextEx buyText;
    [SerializeField] TextEx buyText1;
    [SerializeField] ImageEx moneyIconImage;
    [SerializeField] TextEx limitCountText;
    [SerializeField] ImageEx redImage;
    HeroDebutManager manager => HeroDebutManager.Instance;
    StoreModel storeModel => StoreModel.Instance;
    public void Display(int index, List<HeroDebutGiftItem> giftItems)
    {
        if (giftItems.IsNullOrEmpty() || index < 0 || index >= giftItems.Count) return;
        HeroDebutGiftItem item = giftItems[index];
        if (item.type == 0)
        {
            DisplayStore(item.id);
            return;
        }
        DisplayCTG(item.id);
    }
    private void DisplayCTG(int ctgId)
    {
        redImage.SetActive(false);
        buyText.SetActive(true);
        buyText1.SetActive(false);
        moneyIconImage.SetActive(false);
        if (!RechargeManager.Instance.TryGetOrderInfo(ctgId, out var orderConfig)) return;
        if (!RechargeManager.Instance.TryGetRechargeCount(ctgId, out var rechargeCount)) return;
        if (!CTGConfig.HasKey(ctgId)) return;
        if (!RechargeManager.Instance.TryGetRechargeItem(ctgId, out var rechargeItemList)) return;
        CTGConfig config = CTGConfig.Get(ctgId);
        bool isCanBuy = manager.IsNoSellOutCTGID(ctgId);
        titleText.text = config.Title;
        buyImage.SetSprite(isCanBuy ? "DailySpecialsBuy1" : "DailySpecialsBuy2");
        buyText.text = !isCanBuy ? Language.Get("storename11") : Language.Get("PayMoneyNum", UIHelper.GetMoneyFormat(orderConfig.PayRMBNum));
        limitCountText.SetActive(true);
        limitCountText.text = Language.Get("TimeRush07", UIHelper.AppendColor(rechargeCount.totalCount >= config.TotalBuyCount ? TextColType.Red : TextColType.LightGreen, Mathf.Max(0, config.TotalBuyCount - rechargeCount.totalCount).ToString()));
        buyButton.interactable = isCanBuy;
        buyButton.SetListener(() =>
        {
            RechargeManager.Instance.CTG(ctgId);
        });
        for (int i = 0; i < itemCells.Length; i++)
        {
            var itemBaisc = itemCells[i];
            if (i < rechargeItemList.Count)
            {
                var itemInfo = rechargeItemList[i];
                itemBaisc.SetActive(true);
                itemBaisc.Init(new ItemCellModel((int)itemInfo.id, false, itemInfo.countEx));
                itemBaisc.button.AddListener(() =>
                {
                    ItemTipUtility.Show((int)itemInfo.id);
                });
            }
            else
            {
                itemBaisc.SetActive(false);
            }
        }
    }
    private void DisplayStore(int id)
    {
        if (!StoreConfig.HasKey(id)) return;
        StoreConfig storeConfig = StoreConfig.Get(id);
        int remainNum;
        storeModel.TryGetIsSellOut(storeConfig, out remainNum);
        bool isFree = manager.IsFreeShop(id);
        titleText.text = storeConfig.Name;
        limitCountText.SetActive(!isFree);
        limitCountText.text = Language.Get("TimeRush08", UIHelper.AppendColor(remainNum == 0 ? TextColType.Red : TextColType.LightGreen, Mathf.Max(0, remainNum).ToString(), true));
        bool isCanBuy = manager.IsNoSellOutShopID(id);
        redImage.SetActive(isFree && isCanBuy);
        buyText.SetActive(isFree || !isCanBuy);
        buyText.text = isFree ? Language.Get("L1127") : Language.Get("storename11");
        buyText1.SetActive(!isFree && isCanBuy);
        buyText1.text = UIHelper.GetMoneyFormat(storeConfig.MoneyNum);
        moneyIconImage.SetActive(!isFree && isCanBuy);
        moneyIconImage.SetIconWithMoneyType(1);
        buyImage.SetSprite(isCanBuy ? "DailySpecialsBuy1" : "DailySpecialsBuy2");
        buyButton.interactable = isCanBuy;
        buyButton.SetListener(() =>
        {
            storeModel.SendBuyShopItemWithPopCheck(storeConfig, 1, (int)BuyStoreItemCheckType.ActGift);
        });
        var items = storeModel.GetShopItemlistByIndex(storeConfig);
        for (int i = 0; i < itemCells.Length; i++)
        {
            var itemBaisc = itemCells[i];
            if (i < items.Count)
            {
                var itemInfo = items[i];
                itemBaisc.SetActive(true);
                itemBaisc.Init(new ItemCellModel(itemInfo.itemId, false, itemInfo.count));
                itemBaisc.button.AddListener(() =>
                {
                    ItemTipUtility.Show(itemInfo.itemId);
                });
            }
            else
            {
                itemBaisc.SetActive(false);
            }
        }
    }
}
Main/System/HeroDebut/HeroDebutGiftCell.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3c4c10ba84995ee49925ec3512064f3c
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutGiftWin.cs
New file
@@ -0,0 +1,82 @@
using System.Collections.Generic;
using UnityEngine;
public class HeroDebutGiftWin : UIBase
{
    [SerializeField] ButtonEx closeButton;
    [SerializeField] ImageEx heroImage;
    [SerializeField] ScrollerController scroller;
    [SerializeField] TextEx timeText;
    HeroDebutManager manager => HeroDebutManager.Instance;
    StoreModel storeModel => StoreModel.Instance;
    protected override void InitComponent()
    {
        closeButton.SetListener(CloseWindow);
    }
    protected override void OnPreOpen()
    {
        scroller.OnRefreshCell += OnRefreshCell;
        GlobalTimeEvent.Instance.secondEvent += OnSecondEvent;
        RechargeManager.Instance.rechargeCountEvent += OnRechargeCountEvent;
        storeModel.RefreshBuyShopLimitEvent += RefreshBuyShopLimitEvent;
        int heroID = manager.GetCurrentDisplayCallHeroId();
        var artConfig = ActHeroAppearArtConfig.Get(heroID);
        if (artConfig == null) return;
        heroImage.SetSprite(artConfig.GiftHeroImage);
        heroImage.SetNativeSize();
        OnSecondEvent();
        CreateGiftScroller();
    }
    protected override void OnPreClose()
    {
        scroller.OnRefreshCell -= OnRefreshCell;
        GlobalTimeEvent.Instance.secondEvent -= OnSecondEvent;
        RechargeManager.Instance.rechargeCountEvent -= OnRechargeCountEvent;
        storeModel.RefreshBuyShopLimitEvent -= RefreshBuyShopLimitEvent;
    }
    private void OnRefreshCell(ScrollerDataType type, CellView cell)
    {
        var _cell = cell.GetComponent<HeroDebutGiftCell>();
        _cell?.Display(cell.index, giftItems);
    }
    private void OnSecondEvent()
    {
        manager.GetActTimeStr(timeText);
    }
    private void OnRechargeCountEvent(int obj)
    {
        RefreshAll();
    }
    private void RefreshBuyShopLimitEvent()
    {
        RefreshAll();
    }
    List<HeroDebutGiftItem> giftItems;
    private void CreateGiftScroller()
    {
        giftItems = manager.GetGiftItemList(true);
        scroller.Refresh();
        if (!giftItems.IsNullOrEmpty())
        {
            for (int i = 0; i < giftItems.Count; i++)
            {
                scroller.AddCell(ScrollerDataType.Header, i);
            }
        }
        scroller.Restart();
    }
    void RefreshAll()
    {
        scroller.m_Scorller.RefreshActiveCellViews();
    }
}
Main/System/HeroDebut/HeroDebutGiftWin.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a8fd1e3fe78ecf540bd5ff1360a746d7
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutManager.cs
New file
@@ -0,0 +1,1017 @@
using System;
using System.Collections.Generic;
using System.Linq;
using LitJson;
using UnityEngine;
public class HeroDebutManager : GameSystemManager<HeroDebutManager>, IOpenServerActivity
{
    public int[] xbGridArr;
    public Dictionary<int, int[][]> heroQaulityColor;
    public override void Init()
    {
        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEventOnRelogin += OnBeforePlayerDataInitializeEventOnRelogin;
        DTC0403_tagPlayerLoginLoadOK.playerLoginOkEvent += OnPlayerLoginOk;
        FuncOpen.Instance.OnFuncStateChangeEvent += OnFuncStateChangeEvent;
        OperationTimeHepler.Instance.operationTimeUpdateEvent += OperationTimeUpdateEvent;
        OperationTimeHepler.Instance.operationStartEvent += OperationStartEvent;
        OperationTimeHepler.Instance.operationEndEvent += OperationEndEvent;
        OperationTimeHepler.Instance.operationAdvanceEvent += OperationAdvanceEvent;
        StoreModel.Instance.RefreshBuyShopLimitEvent += RefreshBuyShopLimitEvent;
        GeneralActInfoManager.Instance.OnUpdateActSignInfosEvent += OnUpdateActSignInfosEvent;
        HeroManager.Instance.onHeroChangeEvent += OnHeroChangeEvent;
        TimeMgr.Instance.OnDayEvent += OnDayEvent;
        var config = FuncConfigConfig.Get("HeroAppear");
        xbGridArr = JsonMapper.ToObject<int[]>(config.Numerical1);
        heroQaulityColor = ConfigParse.ParseIntArray2Dict(config.Numerical2);
        InitRedPointId();
    }
    public void SetheroQaulityColor(GradientText text, int qaulity)
    {
        if (!heroQaulityColor.TryGetValue(qaulity, out var colors)) return;
        if (colors?.Length < 2) return;
        text.SetVerticalGradient(ParseColor32(colors[0]), ParseColor32(colors[1]));
    }
    public override void Release()
    {
        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEventOnRelogin -= OnBeforePlayerDataInitializeEventOnRelogin;
        DTC0403_tagPlayerLoginLoadOK.playerLoginOkEvent -= OnPlayerLoginOk;
        FuncOpen.Instance.OnFuncStateChangeEvent -= OnFuncStateChangeEvent;
        OperationTimeHepler.Instance.operationTimeUpdateEvent -= OperationTimeUpdateEvent;
        OperationTimeHepler.Instance.operationStartEvent -= OperationStartEvent;
        OperationTimeHepler.Instance.operationEndEvent -= OperationEndEvent;
        OperationTimeHepler.Instance.operationAdvanceEvent -= OperationAdvanceEvent;
        StoreModel.Instance.RefreshBuyShopLimitEvent -= RefreshBuyShopLimitEvent;
        GeneralActInfoManager.Instance.OnUpdateActSignInfosEvent -= OnUpdateActSignInfosEvent;
        HeroManager.Instance.onHeroChangeEvent -= OnHeroChangeEvent;
        TimeMgr.Instance.OnDayEvent -= OnDayEvent;
    }
    private void OnDayEvent()
    {
        UpdateRedpoint();
    }
    private void OnHeroChangeEvent(HeroInfo info)
    {
        UpdateRedpoint();
    }
    private void OnUpdateActSignInfosEvent(int arg1, int arg2)
    {
        UpdateRedpoint();
    }
    private void RefreshBuyShopLimitEvent()
    {
        UpdateRedpoint();
    }
    private void OnBeforePlayerDataInitializeEventOnRelogin()
    {
        isSendFirst = true;
        starHeroIndexDict.Clear();
        starFreeAwardDict.Clear();
        callHeroIndexDict.Clear();
    }
    private void OnPlayerLoginOk()
    {
        TryPopWin();
    }
    private void OnFuncStateChangeEvent(int obj)
    {
        if (obj != (int)FuncOpenEnum.HeroDebut)
            return;
        TryPopWin();
    }
    public readonly int sendRankType = 6;
    public int loadRankType => actNum * 1000 + sendRankType;
    public const int activityType = (int)OpenServerActivityCenter.ActivityType.AT_DateActivity;
    public const int activityID = (int)NewDayActivityID.HeroDebutAct;
    public static OperationType operaType = OperationType.HeroDebut;
    public Redpoint redPoint = new Redpoint(MainRedDot.HeroDebutRepoint);
    public bool IsOpen => OperationTimeHepler.Instance.SatisfyOpenCondition(operaType);
    public bool IsAdvance => OperationTimeHepler.Instance.SatisfyAdvanceCondition(operaType);
    public bool priorityOpen => redPoint.state == RedPointState.Simple;
    public readonly int actNum = 10;
    public event Action<int> onStateUpdate;
    private void OperationTimeUpdateEvent(OperationType type)
    {
        if (type == operaType)
        {
            if (UIManager.Instance.IsOpened<HeroDebutPopWin>())
                UIManager.Instance.CloseWindow<HeroDebutPopWin>();
            if (UIManager.Instance.IsOpened<HeroDebutWin>())
                UIManager.Instance.CloseWindow<HeroDebutWin>();
            UpdateRedpoint();
        }
    }
    private void OperationStartEvent(OperationType type, int state)
    {
        if (type == operaType && state == 0)
        {
            onStateUpdate?.Invoke(activityID);
            TryPopWin();
            UpdateRedpoint();
        }
    }
    private void OperationEndEvent(OperationType type, int state)
    {
        if (type == operaType)
        {
            onStateUpdate?.Invoke(activityID);
            if (UIManager.Instance.IsOpened<HeroDebutPopWin>())
                UIManager.Instance.CloseWindow<HeroDebutPopWin>();
            if (UIManager.Instance.IsOpened<HeroDebutWin>())
                UIManager.Instance.CloseWindow<HeroDebutWin>();
            UpdateRedpoint();
        }
    }
    private void OperationAdvanceEvent(OperationType type)
    {
        if (type == operaType)
        {
            onStateUpdate?.Invoke(activityID);
            UpdateRedpoint();
        }
    }
    public OperationHeroAppearInfo GetOperationHeroAppearInfo()
    {
        OperationTimeHepler.Instance.TryGetOperation(operaType, out OperationHeroAppearInfo act);
        return act;
    }
    public void SetHeroSquareIcon(ImageEx image, string name)
    {
        var sprite = UILoader.LoadSprite("HeroHead", name);
        if (sprite != null)
        {
            image.overrideSprite = sprite;
            return;
        }
        image.SetSprite("herohead_default");
    }
    public void GetActTimeStr(TextEx timeText, string key = "TimeRush05")
    {
        var act = GetOperationHeroAppearInfo();
        if (act == null)
        {
            timeText.text = Language.Get("OSActivity6");
            return;
        }
        timeText.text = Language.Get(key, TimeUtility.SecondsToShortDHMS(act.GetResetSurplusTime()));
    }
    public void SetGradientTextColor(GradientText text, int[][] colors)
    {
        if (colors?.Length < 4) return;
        text.topLeftColor = ParseColor32(colors[0]);
        text.topRightColor = ParseColor32(colors[1]);
        text.bottomLeftColor = ParseColor32(colors[2]);
        text.bottomRightColor = ParseColor32(colors[3]);
        text.SetVerticesDirty();
    }
    public Color32 ParseColor32(int[] colorArr)
    {
        return new Color32()
        {
            r = (byte)(colorArr.Length > 0 ? colorArr[0] : 0),
            g = (byte)(colorArr.Length > 1 ? colorArr[1] : 0),
            b = (byte)(colorArr.Length > 2 ? colorArr[2] : 0),
            a = (byte)(colorArr.Length > 3 ? colorArr[3] : 255),
        };
    }
    public int GetDefaultSkinID(int heroID)
    {
        HeroConfig heroConfig = HeroConfig.Get(heroID);
        if (heroConfig == null || heroConfig.SkinIDList.IsNullOrEmpty()) return 0;
        return heroConfig.SkinIDList[0];
    }
    public bool IsHeroDebutOpen()
    {
        if (!IsOpen) return false;
        if (!FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.HeroDebut)) return false;
        return true;
    }
    public int GetHeroIdIndex(int cfgID, int heroID)
    {
        var config = ActHeroAppearConfig.Get(cfgID);
        if (config == null) return 0;
        var heroArr = config.ActHeroIDList;
        if (heroArr.IsNullOrEmpty()) return 0;
        int index = Array.IndexOf(heroArr, heroID);
        return index;
    }
    public event Action OnNowCallChooseHeroIDChangeEvent;
    private int m_heroAppearActNum = 0;
    public int nowCallChooseHeroID
    {
        get { return m_heroAppearActNum; }
        set
        {
            if (m_heroAppearActNum == value) return;
            m_heroAppearActNum = value;
            OnNowCallChooseHeroIDChangeEvent?.Invoke();
        }
    }
    public event Action<int> OnUpdateHeroAppearPlayerInfoEvent;
    public void UpdateHeroAppearPlayerInfo(HAA22_tagSCActHeroAppearPlayerInfo vNetData)
    {
        if (vNetData == null) return;
        int actNum = vNetData.ActNum;
        starHeroIndexDict[actNum] = vNetData.StarHeroIndex;
        callHeroIndexDict[actNum] = vNetData.CallHeroIndex;
        if (!starFreeAwardDict.TryGetValue(actNum, out var dict))
        {
            dict = new Dictionary<int, uint>();
            starFreeAwardDict[actNum] = dict;
        }
        dict[vNetData.StarHeroIndex] = vNetData.StarFreeAward;
        UpdateRedpoint();
        OnUpdateHeroAppearPlayerInfoEvent?.Invoke(actNum);
    }
    public void SendHeroAppearStarHeroSelect(int actNum, int starHeroIndex)
    {
        var pack = new CAA01_tagCSActHeroAppearStarHeroSelect();
        pack.ActNum = (byte)actNum;                 // 活动编号
        pack.StarHeroIndex = (byte)starHeroIndex;   // 升星计划选择的武将ID索引
        GameNetSystem.Instance.SendInfo(pack);
    }
    public void SnedHeroAppearCallHeroSelect(int actNum, int callHeroIndex)
    {
        var pack = new CAA02_tagCSActHeroAppearCallHeroSelect();
        pack.ActNum = (byte)actNum;                 // 活动编号
        pack.CallHeroIndex = (byte)callHeroIndex;   // 招募选择的武将ID索引
        GameNetSystem.Instance.SendInfo(pack);
    }
    public void SendGetStarReward()
    {
        var pack = new CA504_tagCMPlayerGetReward();
        pack.RewardType = 10;
        pack.DataEx = (uint)actNum;
        GameNetSystem.Instance.SendInfo(pack);
    }
    #region 红点
    public int GetRedPointId(HeroDebutRedPointType type)
    {
        return MainRedDot.HeroDebutRepoint * 10 + (int)type;
    }
    public Redpoint checkInRedpoint;
    public Redpoint starUpRedpoint;
    public Redpoint shopRedpoint;
    public Redpoint giftRedpoint;
    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));
    }
    public void UpdateRedpoint()
    {
        redPoint.state = RedPointState.None;
        checkInRedpoint.state = RedPointState.None;
        starUpRedpoint.state = RedPointState.None;
        shopRedpoint.state = RedPointState.None;
        giftRedpoint.state = RedPointState.None;
        if (!IsHeroDebutOpen()) return;
        if (HasCheckInCanHave()) //签到赠礼
        {
            checkInRedpoint.state = RedPointState.Simple;
        }
        if (HasStarUpCanHave())//星级提升
        {
            starUpRedpoint.state = RedPointState.Simple;
        }
        //兑换商店每天0点显示红点,点击进入一次界面后消失
        if (!IsShopVisitedToday) //兑换商店
        {
            shopRedpoint.state = RedPointState.Simple;
        }
        if (HasGiftCanHave())//皇权礼包
        {
            giftRedpoint.state = RedPointState.Simple;
        }
    }
    #endregion
    #region 拍脸界面
    public bool IsTodayPop
    {
        get
        {
            int lastPopTime = LoadPopTimeData();
            int todayStartTime = TimeUtility.GetTodayStartTick();
            return lastPopTime < todayStartTime;
        }
    }
    private string PopTimeDataKey { get { return $"HeroDebutManager_PopTimeData_{PlayerDatas.Instance.PlayerId}"; } }
    private int LoadPopTimeData()
    {
        return LocalSave.GetInt(PopTimeDataKey);
    }
    public void SavePopTimeData()
    {
        LocalSave.SetInt(PopTimeDataKey, TimeUtility.AllSeconds);
    }
    private void TryPopWin()
    {
        if (!IsHeroDebutOpen()) return;
        if (!IsTodayPop) return;
        if (UIManager.Instance.IsOpened<HeroDebutPopWin>()) return;
        if (UIManager.Instance.IsOpened<HeroDebutWin>()) return;
        PopupWindowsProcessor.Instance.Add("HeroDebutPopWin");
    }
    #endregion
    #region 签到
    private int GetNowDayNum()
    {
        var act = GetOperationHeroAppearInfo();
        if (act == null) return 0;
        int dayNum = act.IndexOfDays(TimeUtility.ServerNow);
        return dayNum < 0 ? 0 : dayNum + 1;
    }
    private bool IsCheckInGridUnlock(int gridDayNum)
    {
        int nowDayNum = GetNowDayNum();
        if (nowDayNum <= 0) return false;
        return nowDayNum >= gridDayNum;
    }
    /// <summary>
    /// 0-未解锁 1-可签 2-已签
    /// </summary>
    public int GetCheckInState(int gridDayNum)
    {
        var act = GetOperationHeroAppearInfo();
        if (act == null) return 0;
        int actType = act.ActType;
        if (GeneralActInfoManager.Instance.IsDaySigned(actType, actNum, gridDayNum)) return 2;
        if (IsCheckInGridUnlock(gridDayNum)) return 1;
        return 0;
    }
    public void SendGetCheckInReward()
    {
        var act = GetOperationHeroAppearInfo();
        if (act == null) return;
        int actType = act.ActType;
        GeneralActInfoManager.Instance.SendGetSignReward(actType, actNum);
    }
    public bool HasCheckInCanHave()
    {
        var act = GetOperationHeroAppearInfo();
        if (act == null) return false;
        var config = ActHeroAppearConfig.Get(act.CfgID);
        if (config == null) return false;
        int templateID = config.SignTempID;
        var list = ActSignAwardConfig.GetDayNumSortList(templateID);
        if (list == null) return false;
        for (int i = 0; i < list.Count; i++)
        {
            int dayNum = list[i];
            int state = GetCheckInState(dayNum);
            if (state == 1) return true;
        }
        return false;
    }
    #endregion
    #region 升星计划
    //<活动编号,升星计划选择的武将ID索引>
    public Dictionary<int, int> starHeroIndexDict = new();
    //<活动编号,<升星计划选择的武将ID索引,升星计划免费奖励记录>>
    public Dictionary<int, Dictionary<int, uint>> starFreeAwardDict = new();
    /// <summary>
    /// 当前升星计划选中的武将ID
    /// </summary>
    public int GetCurrentDisplayStarUpHeroId()
    {
        var act = GetOperationHeroAppearInfo();
        if (act == null) return 0;
        if (!starHeroIndexDict.TryGetValue(actNum, out int index)) return 0;
        var config = ActHeroAppearConfig.Get(act.CfgID);
        if (config == null || config.ActHeroIDList?.Length <= index) return 0;
        return config.ActHeroIDList[index];
    }
    private Dictionary<int, Dictionary<int, int[][]>> showHeroGiftItemInfoDict = new();
    public bool TryGetStarUpAwardArr(int id, int heroID, out int[][] arr)
    {
        arr = null;
        var config = ActHeroAppearStarConfig.Get(id);
        if (config == null) return false;
        var ctgConfig = CTGConfig.Get(config.StarGiftCTGID);
        if (ctgConfig == null) return false;
        if (!showHeroGiftItemInfoDict.TryGetValue(id, out var dict))
        {
            dict = new Dictionary<int, int[][]>();
            showHeroGiftItemInfoDict[id] = dict;
        }
        if (!dict.TryGetValue(heroID, out arr))
        {
            // 如果缓存里没有当前武将的数据,才进行解析
            var giftdict = ConfigParse.ParseIntArray2Dict(config.HeroGiftItemInfo);
            int[][] ctgArray = ctgConfig.GainItemList;
            foreach (var kvp in giftdict)
            {
                int hId = kvp.Key;
                int[][] hGift = kvp.Value ?? Array.Empty<int[]>();
                dict[hId] = hGift.Concat(ctgArray).ToArray();
            }
            // 如果遍历完发现配表里根本没有这个 heroID
            if (!dict.TryGetValue(heroID, out arr))
            {
                arr = ctgArray;
                dict[heroID] = arr;
            }
        }
        return true;
    }
    /// <summary>
    /// 0 - 未解锁 1 - 可领取 2 - 已领取
    /// </summary>
    public int GetStarUpFreeState(int id)
    {
        var config = ActHeroAppearStarConfig.Get(id);
        if (config == null) return 0;
        int heroId = GetCurrentDisplayStarUpHeroId();
        var heroConfig = HeroConfig.Get(heroId);
        if (heroConfig == null) return 0;
        if (!starHeroIndexDict.TryGetValue(actNum, out int index)) return 0;
        if (IsStarUpFreeHave(index, config.AwardIndex)) return 2;
        if (IsHeroStarCntOk(heroConfig.HeroID, config.NeedStar)) return 1;
        return 0;
    }
    private bool IsStarUpFreeHave(int starHeroIndex, int awardIndex)
    {
        if (!starFreeAwardDict.TryGetValue(actNum, out var dict)) return false;
        if (!dict.TryGetValue(starHeroIndex, out uint freeAward)) return false;
        return ((freeAward >> awardIndex) & 1u) == 1u;
    }
    public bool IsHeroStarCntOk(int heroId, int needStar)
    {
        return GetNowHeroMaxStarCnt(heroId) >= needStar;
    }
    public int GetNowHeroMaxStarCnt(int heroId)
    {
        int res = 0;
        foreach (var item in HeroManager.Instance.GetHeroList())
        {
            if (item == null) continue;
            if (item.heroId == heroId)
            {
                if (res < item.heroStar)
                    res = item.heroStar;
            }
        }
        return res;
    }
    public bool TryGetStarUpStateIndex(int starGiftTempID, int tarState, out int index)
    {
        index = 0;
        var list = ActHeroAppearStarConfig.GetAwardIndexSortList(starGiftTempID);
        if (list == null) return false;
        for (int i = 0; i < list.Count; i++)
        {
            var awardIndex = list[i];
            var config = ActHeroAppearStarConfig.GetConfig(starGiftTempID, awardIndex);
            if (config == null) continue;
            int state = GetStarUpFreeState(config.ID);
            if (state == tarState)
            {
                index = i;
                return true;
            }
        }
        return false;
    }
    public int GetStarUpJumpIndex(int starGiftTempID)
    {
        // 优先查找可领取的奖励
        if (TryGetStarUpStateIndex(starGiftTempID, 1, out int index)) return index;
        // 若没有可领取的,则查找未达到条件的奖励
        if (TryGetStarUpStateIndex(starGiftTempID, 0, out index)) return index;
        // 都没有
        return 0;
    }
    public bool HasStarUpCanHave()
    {
        var act = GetOperationHeroAppearInfo();
        if (act == null) return false;
        var config = ActHeroAppearConfig.Get(act.CfgID);
        if (config == null) return false;
        int starGiftTempID = config.StarGiftTempID;
        return TryGetStarUpStateIndex(starGiftTempID, 1, out _);
    }
    #endregion
    #region 兑换商店
    private string ShopVisitTimeDataKey { get { return $"HeroDebutManager_ShopVisitTime_{PlayerDatas.Instance.PlayerId}"; } }
    private int LoadShopVisitTimeData()
    {
        return LocalSave.GetInt(ShopVisitTimeDataKey);
    }
    public void SaveShopVisitTimeData()
    {
        LocalSave.SetInt(ShopVisitTimeDataKey, TimeUtility.AllSeconds);
    }
    public bool IsShopVisitedToday
    {
        get
        {
            int lastVisitTime = LoadShopVisitTimeData();
            int todayStartTime = TimeUtility.GetTodayStartTick();
            return lastVisitTime >= todayStartTime;
        }
    }
    #endregion
    #region 皇权礼包
    //没售罄
    public bool IsNoSellOutCTGID(int ctgID)
    {
        CTGConfig config = CTGConfig.Get(ctgID);
        if (config == null) return false;
        if (!RechargeManager.Instance.TryGetRechargeCount(ctgID, out var rechargeCount)) return false;
        return rechargeCount.totalCount < config.TotalBuyCount;
    }
    // 免费商品
    public bool IsFreeShop(int shopID)
    {
        StoreConfig config = StoreConfig.Get(shopID);
        if (config == null) return false;
        return config.MoneyNum == 0;
    }
    //没售罄
    public bool IsNoSellOutShopID(int shopID)
    {
        StoreConfig config = StoreConfig.Get(shopID);
        if (config == null) return false;
        StoreModel.Instance.TryGetIsSellOut(config, out int remainNum);
        return remainNum > 0;
    }
    public List<HeroDebutGiftItem> GetGiftItemList(bool isSort = false)
    {
        var act = GetOperationHeroAppearInfo();
        if (act == null) return null;
        var config = ActHeroAppearConfig.Get(act.CfgID);
        if (config == null) return null;
        List<HeroDebutGiftItem> res = new List<HeroDebutGiftItem>();
        var list = StoreModel.Instance.storeTypeDict[config.GiftShopType];
        if (!list.IsNullOrEmpty())
        {
            for (int i = 0; i < list.Count; i++)
            {
                var item = list[i];
                if (item.storeConfig == null)
                    continue;
                res.Add(new HeroDebutGiftItem
                {
                    type = 0,
                    id = item.storeConfig.ID,
                });
            }
        }
        if (config.GiftCTGIDList != null)
        {
            for (int i = 0; i < config.GiftCTGIDList.Length; i++)
            {
                var item = config.GiftCTGIDList[i];
                res.Add(new HeroDebutGiftItem
                {
                    type = 1,
                    id = item,
                });
            }
        }
        if (isSort)
        {
            res = res.OrderBy(item =>
            {
                bool isCanBuy = item.type == 0 ? IsNoSellOutShopID(item.id) : IsNoSellOutCTGID(item.id);
                return !isCanBuy;
            })
            .ThenBy(item => item.type)
            .ThenBy(item => item.id)
            .ToList();
        }
        return res;
    }
    public bool HasGiftCanHave()
    {
        var list = GetGiftItemList(false);
        if (list.IsNullOrEmpty())
            return false;
        for (int i = 0; i < list.Count; i++)
        {
            var item = list[i];
            if (item.type == 0)
            {
                bool isFree = IsFreeShop(item.id);
                bool isCanBuy = IsNoSellOutShopID(item.id);
                if (isFree && isCanBuy)
                    return true;
            }
        }
        return false;
    }
    #endregion
    #region 招募
    public int ToInt(OperationDate date)
    {
        return date.year * 10000 + date.month * 100 + date.day;
    }
    private string GetCallSkipKey(int cfgID, OperationDate startDate, OperationDate endDate)
    {
        return string.Concat("HeroDebutManager_CallSkip_", cfgID, ToInt(startDate), ToInt(endDate), PlayerDatas.Instance.PlayerId);
    }
    public bool LoadCallSkipData(int cfgID, OperationDate startDate, OperationDate endDate)
    {
        return LocalSave.GetBool(GetCallSkipKey(cfgID, startDate, endDate));
    }
    public void SaveCallSkipData(int cfgID, OperationDate startDate, OperationDate endDate, bool value)
    {
        LocalSave.SetBool(GetCallSkipKey(cfgID, startDate, endDate), value);
    }
    //<活动编号,招募选择的武将ID索引>
    public Dictionary<int, int> callHeroIndexDict = new();
    /// <summary>
    /// 当前招募选中的武将ID
    /// </summary>
    public int GetCurrentDisplayCallHeroId()
    {
        var act = GetOperationHeroAppearInfo();
        if (act == null) return 0;
        if (!callHeroIndexDict.TryGetValue(actNum, out int index)) return 0;
        var config = ActHeroAppearConfig.Get(act.CfgID);
        if (config == null || config.ActHeroIDList?.Length <= index) return 0;
        return config.ActHeroIDList[index];
    }
    #endregion
    #region 时装特卖
    public event Action OnCurrentChooseSkinIDChangeEevent;
    private int m_currentChooseSkinID = 0;
    public int currentChooseSkinID
    {
        get
        {
            return m_currentChooseSkinID;
        }
        set
        {
            if (m_currentChooseSkinID == value) return;
            m_currentChooseSkinID = value;
            OnCurrentChooseSkinIDChangeEevent?.Invoke();
        }
    }
    /// <summary>
    /// 通过skinID获取对应的heroID
    /// </summary>
    private int GetHeroIDBySkinID(int skinID)
    {
        foreach (var heroConfig in HeroConfig.GetValues())
        {
            if (heroConfig.SkinIDList != null && heroConfig.SkinIDList.Contains(skinID))
            {
                return heroConfig.HeroID;
            }
        }
        return 0;
    }
    /// <summary>
    /// 获取skinID在HeroConfig.SkinIDList中的索引
    /// </summary>
    private int GetSkinIndexInHeroConfig(int heroID, int skinID)
    {
        var heroConfig = HeroConfig.Get(heroID);
        if (heroConfig?.SkinIDList == null) return int.MaxValue;
        for (int i = 0; i < heroConfig.SkinIDList.Length; i++)
        {
            if (heroConfig.SkinIDList[i] == skinID)
                return i;
        }
        return int.MaxValue;
    }
    //<skinID,ctgID>
    Dictionary<int, int> ctgDict = new();
    public int GetCtgIDBySkinID(int skinID)
    {
        if (ctgDict.IsNullOrEmpty())
        {
            GetSkinIDToCtgIDDict();
        }
        int ctgID;
        ctgDict.TryGetValue(skinID, out ctgID);
        return ctgID;
    }
    Dictionary<int, int> GetSkinIDToCtgIDDict()
    {
        if (!ctgDict.IsNullOrEmpty())
        {
            return ctgDict;
        }
        foreach (var config in ActHeroAppearConfig.GetValues())
        {
            if (config == null || config.SkinCTGIDList == null) return null;
            for (int i = 0; i < config.SkinCTGIDList.Length; i++)
            {
                var ctgID = config.SkinCTGIDList[i];
                var ctgConfig = CTGConfig.Get(ctgID);
                if (ctgConfig == null || ctgConfig.GainItemList == null) continue;
                for (int j = 0; j < ctgConfig.GainItemList.Length; j++)
                {
                    var itemID = ctgConfig.GainItemList[j][0];
                    var itemConfig = ItemConfig.Get(itemID);
                    if (itemConfig == null) continue;
                    if (!HeroSkinAttrConfig.TryGetSkinIDByItemID(itemID, out var skinID)) continue;
                    if (ctgDict.ContainsKey(skinID)) continue;
                    ctgDict[skinID] = ctgID;
                }
            }
        }
        return ctgDict;
    }
    public List<int> GetSkinIDList(int cfgID, int heroID, int mainSkinID)
    {
        var config = ActHeroAppearConfig.Get(cfgID);
        if (config == null || config.SkinCTGIDList == null) return null;
        var res = new List<int>();
        for (int i = 0; i < config.SkinCTGIDList.Length; i++)
        {
            var ctgID = config.SkinCTGIDList[i];
            var ctgConfig = CTGConfig.Get(ctgID);
            if (ctgConfig == null || ctgConfig.GainItemList == null) continue;
            for (int j = 0; j < ctgConfig.GainItemList.Length; j++)
            {
                var itemID = ctgConfig.GainItemList[j][0];
                var itemConfig = ItemConfig.Get(itemID);
                if (itemConfig == null) continue;
                if (!HeroSkinAttrConfig.TryGetSkinIDByItemID(itemID, out var skinID)) continue;
                if (res.Contains(skinID)) continue;
                res.Add(skinID);
            }
        }
        // 自定义排序
        res.Sort((a, b) =>
        {
            // 1. 判断是否是传入heroID的皮肤,优先排前面
            int heroIDA = GetHeroIDBySkinID(a);
            int heroIDB = GetHeroIDBySkinID(b);
            bool isPriorityA = (heroIDA == heroID);
            bool isPriorityB = (heroIDB == heroID);
            if (isPriorityA != isPriorityB)
                return isPriorityA ? -1 : 1;
            // 2. 相同武将的多个皮肤连续挨在一起
            if (heroIDA != heroIDB)
                return heroIDA.CompareTo(heroIDB);
            // 3. 如果heroid相同,和MainSkinID相同的排在最前面
            if (a == mainSkinID) return -1;
            if (b == mainSkinID) return 1;
            // 4. 其他按SkinIDList索引排序
            int indexA = GetSkinIndexInHeroConfig(heroIDA, a);
            int indexB = GetSkinIndexInHeroConfig(heroIDB, b);
            return indexA.CompareTo(indexB);
        });
        return res;
    }
    #endregion
    #region 获奖记录
    public static readonly int RecordType = 311;
    public void SendViewGameRecPack(int treasureType)
    {
        CA008_tagCSViewGameRec pack = new CA008_tagCSViewGameRec();
        pack.RecType = (ushort)RecordType;
        pack.RecID = (uint)treasureType;
        GameNetSystem.Instance.SendInfo(pack);
    }
    public bool isSendFirst = true;
    List<HeroDebutGameRec> gameRecDict = new();
    public List<HeroDebutGameRec> GetGameRecList()
    {
        return gameRecDict;
    }
    public List<HeroDebutGameRec> GetLastFourRecords()
    {
        if (gameRecDict == null || gameRecDict.Count == 0) return new List<HeroDebutGameRec>();
        int count = gameRecDict.Count;
        int takeCount = Math.Min(4, count);
        return gameRecDict.GetRange(count - takeCount, takeCount);
    }
    public event Action OnUpdateGameRecInfo;
    public void UpdateGameRecInfo(HA009_tagSCGameRecInfo vNetData)
    {
        var act = GetOperationHeroAppearInfo();
        if (act == null) return;
        var config = ActHeroAppearConfig.Get(act.CfgID);
        if (config == null) return;
        int treasureType = config.ActTreasureType;
        if (vNetData.RecType != RecordType || treasureType != (int)vNetData.RecID) return;
        if (vNetData.RecList.IsNullOrEmpty()) return;
        if (isSendFirst)
        {
            gameRecDict.Clear();
        }
        foreach (var rec in vNetData.RecList)
        {
            try
            {
                var playerName = JsonMapper.ToObject(rec.UserData)["Name"].ToString();
                var arenaGameRec = new HeroDebutGameRec
                {
                    Time = (int)rec.Time,
                    ItemID = (int)rec.Value1,
                    ItemCount = rec.Value2,
                    PlayerID = (int)rec.Value3,
                    ServerID = (int)rec.Value4,
                    PlayerName = playerName,
                };
                gameRecDict.Add(arenaGameRec);
            }
            catch (Exception ex)
            {
                Debug.LogError($"JSON解析错误: {ex.Message}, UserData: {rec.UserData}");
                continue;
            }
        }
        if (isSendFirst)
        {
            isSendFirst = !isSendFirst;
            gameRecDict.Sort((x, y) => x.Time.CompareTo(y.Time));
        }
        OnUpdateGameRecInfo?.Invoke();
    }
    #endregion
}
public class HeroDebutGiftItem
{
    public int type;//0 商店id 1 充值id
    public int id;
}
public enum HeroDebutRedPointType
{
    CheckIn = 1,
    StarUp = 2,
    Shop = 3,
    Gift = 4,
}
public class HeroDebutGameRec
{
    public int Time;
    public int ItemID;
    public long ItemCount;
    public int PlayerID;
    public int ServerID;
    public string PlayerName;
}
Main/System/HeroDebut/HeroDebutManager.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f5c5e5d4f591d88438fe2de638524e94
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutPopWin.cs
New file
@@ -0,0 +1,96 @@
using UnityEngine;
using UnityEngine.UI;
public class HeroDebutPopWin : UIBase
{
    [SerializeField] ImageEx bgImage;
    [SerializeField] UIHeroController rolelhShow;
    [SerializeField] ImageEx qaulityBgImage;
    [SerializeField] ImageEx qaulityImage;
    [SerializeField] ButtonEx goButton;
    [SerializeField] ImageEx titleBgImage;
    [SerializeField] ImageEx titleImage;
    [SerializeField] ImageEx infoBgImage;
    [SerializeField] UIEffectPlayer uiEffectPlayer;
    [SerializeField] TextEx infoText;
    [SerializeField] TextEx timeText;
    [SerializeField] Toggle todayPopToggle;
    [SerializeField] ButtonEx closeButton;
    HeroDebutManager manager => HeroDebutManager.Instance;
    protected override void InitComponent()
    {
        closeButton.SetListener(CloseWindow);
        goButton.SetListener(() =>
        {
            UIManager.Instance.CloseWindow<HeroDebutPopWin>();
            if (!UIManager.Instance.IsOpened<HeroDebutWin>())
                UIManager.Instance.OpenWindow<HeroDebutWin>();
        });
        todayPopToggle.AddListener((bool value) =>
        {
            if (value)
                manager.SavePopTimeData();
        });
    }
    protected override void OnPreOpen()
    {
        GlobalTimeEvent.Instance.secondEvent += OnSecondEvent;
        Display();
    }
    protected override void OnPreClose()
    {
        GlobalTimeEvent.Instance.secondEvent -= OnSecondEvent;
    }
    private void OnSecondEvent()
    {
        manager.GetActTimeStr(timeText, "HeroDebutPop02");
    }
    private void Display()
    {
        uiEffectPlayer.Stop();
        todayPopToggle.isOn = !manager.IsTodayPop;
        int heroID = manager.GetCurrentDisplayCallHeroId();
        var artConfig = ActHeroAppearArtConfig.Get(heroID);
        if (artConfig == null) return;
        var heroConfig = HeroConfig.Get(heroID);
        if (heroConfig == null) return;
        int skinID = manager.GetDefaultSkinID(heroID);
        var skinConfig = HeroSkinConfig.Get(skinID);
        if (skinConfig == null) return;
        uiEffectPlayer.effectId = artConfig.PopInfoBgUIEffectId;
        uiEffectPlayer.Play();
        bgImage.SetSprite(artConfig.PopBgImage);
        bgImage.SetNativeSize();
        qaulityBgImage.SetSprite($"HeroDebutPopQaulityBG{heroConfig.Quality}");
        qaulityBgImage.SetNativeSize();
        qaulityImage.SetSprite($"HeroDebutPopQaulity{heroConfig.Quality}");
        qaulityImage.SetNativeSize();
        titleBgImage.SetSprite(artConfig.PopTitleBgImage);
        titleBgImage.SetNativeSize();
        titleImage.SetSprite(artConfig.PopTitleImage);
        titleImage.SetNativeSize();
        infoBgImage.SetSprite(artConfig.PopInfoBgImage);
        infoBgImage.SetNativeSize();
        infoText.text = artConfig.PopInfoText;
        infoText.color = manager.ParseColor32(artConfig.PopInfoColor);
        rolelhShow.Create(skinID, 1, motionName: "", isLh: true);
        OnSecondEvent();
    }
}
Main/System/HeroDebut/HeroDebutPopWin.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 24ad8ea9f5a40274bad405fecb092325
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutRankAwardCell.cs
New file
@@ -0,0 +1,45 @@
using UnityEngine;
public class HeroDebutRankAwardCell : CellView
{
    [SerializeField] ImageEx imgRank;
    [SerializeField] TextEx txtRank;
    [SerializeField] ItemCell[] itemCells;
    public void Display(int rankA, int templateID)
    {
        var config = ActBillboardAwardConfig.GetConfig(templateID, rankA);
        if (config == null) return;
        if (rankA <= 3)
        {
            imgRank.SetActive(true);
            txtRank.SetActive(false);
            imgRank.SetSprite(StringUtility.Concat("Rank", rankA.ToString()));
            txtRank.text = rankA.ToString();
        }
        else
        {
            imgRank.SetActive(false);
            txtRank.SetActive(true);
            txtRank.text = Language.Get("Arena15", rankA, config.RankB);
        }
        int[][] rewardArr = config.AwardItemList;
        for (int i = 0; i < itemCells.Length; i++)
        {
            var itemCell = itemCells[i];
            if (!rewardArr.IsNullOrEmpty() && i < rewardArr.Length)
            {
                int itemCellIndex = i;
                itemCell.SetActive(true);
                itemCell.Init(new ItemCellModel(rewardArr[i][0], true, rewardArr[i][1]));
                itemCell.button.SetListener(() => ItemTipUtility.Show(rewardArr[itemCellIndex][0], true));
            }
            else
            {
                itemCell.SetActive(false);
            }
        }
    }
}
Main/System/HeroDebut/HeroDebutRankAwardCell.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3afacd7889426a94db84c1bc905ca6f2
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutRankCell.cs
New file
@@ -0,0 +1,76 @@
using UnityEngine;
using UnityEngine.UI;
public class HeroDebutRankCell : MonoBehaviour
{
    [SerializeField] AvatarCell avatarCell;
    [SerializeField] Text rankText;
    [SerializeField] Text rankValueText;    //排名比较内容
    [SerializeField] Text nameText;
    [SerializeField] OfficialTitleCell officialTitleCell;
    [SerializeField] Button queryPlayerBtn; //后续添加点击查看玩家详情
    HeroDebutManager manager => HeroDebutManager.Instance;
    // rank 为0 代表玩家自己
    public void Display(int rankType, int rank, string valueFormat)
    {
        var act = manager.GetOperationHeroAppearInfo();
        if (act == null) return;
        var config = ActHeroAppearConfig.Get(act.CfgID);
        if (config == null) return;
        int billTempID = config.BillTempID;
        var awardConfig = ActBillboardAwardConfig.GetConfig(billTempID, rank);
        RankData rankData = null;
        int viewPlayerId = (int)PlayerDatas.Instance.baseData.PlayerID;
        if (rank != 0)
        {
            rankData = RankModel.Instance.GetRankDataByRank(rankType, rank);
        }
        else
        {
            rankData = RankModel.Instance.GetMyRank(rankType);
            if (rankData == null)
            {
                //取玩家自己的数据
                avatarCell.InitUI(AvatarHelper.GetAvatarModel((int)PlayerDatas.Instance.baseData.PlayerID,
                                                PlayerDatas.Instance.baseData.face,
                                                PlayerDatas.Instance.baseData.facePic));
                rankText.text = Language.Get("L1045");
                rankValueText.text = awardConfig == null || awardConfig.NeedValue == 0 ? "0" : Language.Get("HeroDebut27", awardConfig.NeedValue);
                nameText.text = PlayerDatas.Instance.baseData.PlayerName;
                officialTitleCell.InitUI(PlayerDatas.Instance.baseData.realmLevel, PlayerDatas.Instance.baseData.TitleID);
                return;
            }
            rank = rankData.rank;
        }
        if (rankData == null)
        {
            officialTitleCell.SetActive(false);
            avatarCell.SetActive(false);
            nameText.text = Language.Get("L1124");
            rankValueText.text = awardConfig == null || awardConfig.NeedValue == 0 ? "0" : Language.Get("HeroDebut27", awardConfig.NeedValue);
        }
        else
        {
            officialTitleCell.SetActive(true);
            officialTitleCell.InitUI((int)rankData.value1, (int)rankData.value2);
            avatarCell.SetActive(true);
            avatarCell.InitUI(AvatarHelper.GetAvatarModel((int)rankData.id, (int)rankData.value3, (int)rankData.value4));
            viewPlayerId = (int)rankData.id;
            nameText.text = rankData.name1;
            rankValueText.text = string.Format(valueFormat, UIHelper.ReplaceLargeNum(rankData.cmpValue));
        }
        rankText.text = rank.ToString();
        if (queryPlayerBtn != null)
        {
            queryPlayerBtn.AddListener(() =>
            {
                AvatarHelper.TryViewOtherPlayerInfo(viewPlayerId);
            });
        }
    }
}
Main/System/HeroDebut/HeroDebutRankCell.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fbdf6f5d48d9a404ba6e0f542c629ca5
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutRankTop3Cell.cs
New file
@@ -0,0 +1,47 @@
using UnityEngine;
using UnityEngine.UI;
public class HeroDebutRankTop3Cell : MonoBehaviour
{
    //[SerializeField] Model 显示NPC 武将模型
    [SerializeField] Text rankValueText;    //排名比较内容
    [SerializeField] Text nameText;
    [SerializeField] OfficialTitleCell officialTitleCell;
    [SerializeField] Button queryPlayerBtn; //后续添加点击查看玩家详情
    [SerializeField] HorseController model;
    HeroDebutManager manager => HeroDebutManager.Instance;
    public void Display(int rankType, int rank, string valueFormat = "{0}")
    {
        var act = manager.GetOperationHeroAppearInfo();
        if (act == null) return;
        var config = ActHeroAppearConfig.Get(act.CfgID);
        if (config == null) return;
        int billTempID = config.BillTempID;
        var awardConfig = ActBillboardAwardConfig.GetConfig(billTempID, rank);
        var rankData = RankModel.Instance.GetRankDataByRank(rankType, rank);
        if (rankData == null)
        {
            rankValueText.text = awardConfig == null || awardConfig.NeedValue == 0 ? "0" : Language.Get("HeroDebut27", awardConfig.NeedValue);
            nameText.text = Language.Get("L1124");
            officialTitleCell.SetActive(false);
            model.SetActive(false);
            return;
        }
        officialTitleCell.SetActive(true);
        rankValueText.text = string.Format(valueFormat, UIHelper.ReplaceLargeNum(rankData.cmpValue));
        nameText.text = rankData.name1;
        officialTitleCell.InitUI((int)rankData.value1, (int)rankData.value2);
        model.SetActive(true);
        model.Create(HorseManager.Instance.GetOtherPlayerHorseSkinID((int)rankData.value6), (int)rankData.value5, rank == 1 ? 1f : 0.8f);
        queryPlayerBtn.SetListener(() =>
        {
            AvatarHelper.TryViewOtherPlayerInfo((int)rankData.id);
        });
    }
}
Main/System/HeroDebut/HeroDebutRankTop3Cell.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4c2c1678330ae2942ad512bb4b5dd76c
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutRankWin.cs
New file
@@ -0,0 +1,175 @@
using System.Collections.Generic;
using UnityEngine;
public class HeroDebutRankWin : FunctionsBaseWin
{
    [SerializeField] ButtonEx btnClose;
    [SerializeField] RectTransform rankRect;
    [SerializeField] RectTransform awardRect;
    [SerializeField] TextEx timeText;
    [Header("排行")]
    [SerializeField] ScrollerController rankScroller;
    [SerializeField] List<HeroDebutRankTop3Cell> playerTop3Cells;
    [SerializeField] HeroDebutRankCell myRankCell;
    [HideInInspector] public string valueFormat = "{0}";
    [Header("奖励")]
    // [SerializeField] TextEx txtCountdown;
    [SerializeField] ScrollerController awardScroller;
    [SerializeField] ImageEx heroImage;
    [SerializeField] TextEx myRankNumText;
    [SerializeField] TextEx myCallCntText;
    [SerializeField] TextEx timeText1;
    HeroDebutManager manager => HeroDebutManager.Instance;
    protected override void InitComponent()
    {
        base.InitComponent();
        btnClose.SetListener(CloseWindow);
    }
    protected override void OnPreOpen()
    {
        base.OnPreOpen();
        RankModel.Instance.ResetQueryParam();
        RankModel.Instance.QueryRankByPage(manager.sendRankType, watchID: (int)PlayerDatas.Instance.baseData.PlayerID, groupValue1: manager.actNum);
        RankModel.Instance.onRankRefresh += OnRankRefresh;
        GlobalTimeEvent.Instance.secondEvent += OnSecondEvent;
        rankScroller.OnRefreshCell += OnRefreshCell;
        awardScroller.OnRefreshCell += OnRefreshAwardCell;
        Display();
    }
    protected override void OnPreClose()
    {
        base.OnPreClose();
        RankModel.Instance.onRankRefresh -= OnRankRefresh;
        GlobalTimeEvent.Instance.secondEvent -= OnSecondEvent;
        rankScroller.OnRefreshCell -= OnRefreshCell;
        awardScroller.OnRefreshCell -= OnRefreshAwardCell;
    }
    void OnRankRefresh(int type)
    {
        RankRefresh();
    }
    void RankRefresh()
    {
        ShowTop3();
        rankScroller.m_Scorller.RefreshActiveCellViews();
        DisplayMyRank();
        DisplayAwardMyRank();
    }
    void CreateRankScroller()
    {
        rankScroller.Refresh();
        var cnt = RankModel.Instance.GetRankShowMaxCnt(manager.sendRankType);
        for (int i = 3; i < cnt; i++)
        {
            rankScroller.AddCell(ScrollerDataType.Header, i);
        }
        rankScroller.Restart();
    }
    void OnRefreshCell(ScrollerDataType type, CellView cell)
    {
        var _cell = cell.GetComponent<HeroDebutRankCell>();
        _cell.Display(manager.loadRankType, cell.index + 1, valueFormat);
        RankModel.Instance.ListenRankPage(manager.sendRankType, cell.index, groupValue1: manager.actNum);
    }
    private void OnSecondEvent()
    {
        manager.GetActTimeStr(timeText);
        manager.GetActTimeStr(timeText1);
    }
    protected override void OpenSubUIByTabIndex()
    {
        rankRect.SetActive(functionOrder == 0);
        awardRect.SetActive(functionOrder == 1);
        Display();
    }
    public void Display()
    {
        int heroID = manager.GetCurrentDisplayCallHeroId();
        var artConfig = ActHeroAppearArtConfig.Get(heroID);
        if (artConfig == null) return;
        if (functionOrder == 0)
        {
            ShowTop3();
            CreateRankScroller();
            DisplayMyRank();
        }
        else
        {
            CreateAwardScroller();
            heroImage.SetSprite(artConfig.RankAwardHeroImage);
            heroImage.SetNativeSize();
            DisplayAwardMyRank();
        }
        OnSecondEvent();
    }
    private void DisplayMyRank()
    {
        myRankCell.Display(manager.loadRankType, 0, valueFormat);
    }
    void ShowTop3()
    {
        for (int i = 0; i < playerTop3Cells.Count; i++)
        {
            playerTop3Cells[i].Display(manager.loadRankType, i + 1);
        }
    }
    void DisplayAwardMyRank()
    {
        RankData rankData = RankModel.Instance.GetMyRank(manager.loadRankType);
        if (rankData == null)
        {
            myRankNumText.text = Language.Get("L1045");
            myCallCntText.text = "0";
            return;
        }
        myRankNumText.text = Language.Get("WarlordPavilion12", rankData.rank);
        myCallCntText.text = string.Format(valueFormat, UIHelper.ReplaceLargeNum(rankData.cmpValue));
    }
    int billTempID;
    private void CreateAwardScroller()
    {
        var act = manager.GetOperationHeroAppearInfo();
        if (act == null) return;
        var config = ActHeroAppearConfig.Get(act.CfgID);
        if (config == null) return;
        billTempID = config.BillTempID;
        var list = ActBillboardAwardConfig.GetRankASortList(billTempID);
        if (list == null) return;
        awardScroller.Refresh();
        for (int i = 0; i < list.Count; i++)
        {
            awardScroller.AddCell(ScrollerDataType.Header, list[i]);
        }
        awardScroller.Restart();
    }
    private void OnRefreshAwardCell(ScrollerDataType type, CellView cell)
    {
        var _cell = cell.GetComponent<HeroDebutRankAwardCell>();
        _cell?.Display(cell.index, billTempID);
    }
}
Main/System/HeroDebut/HeroDebutRankWin.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a81d546baaf89554eb10f8deaa384226
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutShopCell.cs
New file
@@ -0,0 +1,134 @@
using UnityEngine;
using UnityEngine.UI;
public class HeroDebutShopCell : MonoBehaviour
{
    [SerializeField] Transform saleRect;
    [SerializeField] Text saleText;
    [SerializeField] Text itemName;
    [SerializeField] ItemCell itemCell;
    [SerializeField] Text limitText;
    [SerializeField] Text lockTip;
    [SerializeField] Transform priceRect;
    [SerializeField] Image priceIcon;
    [SerializeField] Text priceText;
    [SerializeField] Transform priceRect1;//居中位置的价格
    [SerializeField] Image priceIcon1;
    [SerializeField] Text priceText1;
    [SerializeField] Transform salePriceRect;
    [SerializeField] Text salePriceText;
    [SerializeField] Button buyButton;
    [SerializeField] Image freeRedPoint;
    [SerializeField] Text freeText;
    [SerializeField] Image exclusiveImage;//专属
    [SerializeField] Image sellOutImage;//售罄
    HeroDebutManager manager => HeroDebutManager.Instance;
    public void Display(int index)
    {
        var act = manager.GetOperationHeroAppearInfo();
        if (act == null) return;
        var config = ActHeroAppearConfig.Get(act.CfgID);
        if (config == null) return;
        if (!StoreModel.Instance.storeTypeDict.TryGetValue(config.ExShopType, out var list)) return;
        var storeData = list[index];
        int shopID = storeData.shopId;
        var itemID = storeData.storeConfig.ItemID;
        var itemCount = storeData.storeConfig.ItemCnt;
        exclusiveImage.SetActive(storeData.storeConfig.IsExclusive == 1);
        itemCell.Init(new ItemCellModel(itemID, false, itemCount));
        itemCell.button.AddListener(() =>
        {
            ItemTipUtility.Show(itemID);
        });
        var itemConfig = ItemConfig.Get(itemID);
        itemName.text = itemConfig.ItemName;
        //折扣
        if (storeData.storeConfig.MoneyOriginal != 0)
        {
            saleRect.SetActive(true);
            saleText.text = Language.Get("storename5", (storeData.storeConfig.MoneyNum * 10 / (float)storeData.storeConfig.MoneyOriginal).ToString("0.#"));
        }
        else
        {
            saleRect.SetActive(false);
        }
        var buyCnt = StoreModel.Instance.GetShopLimitBuyCount(shopID);
        string limitStr = "";
        if (storeData.storeConfig.MoneyNum == 0)
        {
            //免费
            limitStr = "";
        }
        else if (storeData.storeConfig.ResetType == 0)
        {
            //限购
            limitStr = storeData.storeConfig.LimitCnt > 0 ? Language.Get("storename8", storeData.storeConfig.LimitCnt - buyCnt, storeData.storeConfig.LimitCnt) : "";
        }
        else if (storeData.storeConfig.ResetType == 1)
        {
            //每日限购
            limitStr = Language.Get("storename6", storeData.storeConfig.LimitCnt - buyCnt, storeData.storeConfig.LimitCnt);
        }
        else if (storeData.storeConfig.ResetType == 2)
        {
            //每周限购
            limitStr = Language.Get("storename7", storeData.storeConfig.LimitCnt - buyCnt, storeData.storeConfig.LimitCnt);
        }
        limitText.text = buyCnt >= storeData.storeConfig.LimitCnt ? UIHelper.AppendColor(TextColType.Gray, limitStr) : limitStr;
        buyButton.AddListener(() => { BuyGoods(shopID); });
        //0可购买 1已售罄 2免费 3未解锁
        var state = StoreModel.Instance.GetShopIDState(shopID);
        sellOutImage.SetActive(state == 1);
        freeRedPoint.SetActive(state == 2);
        lockTip.text = state == 2 ? Language.Get("storename10", storeData.storeConfig.UnlockValue) : string.Empty;
        priceRect.SetActive(state != 2 && storeData.storeConfig.MoneyOriginal != 0);
        priceRect1.SetActive(state != 2 && storeData.storeConfig.MoneyOriginal == 0);
        freeText.SetActive(state == 2);
        salePriceRect.SetActive(state != 2 && storeData.storeConfig.MoneyOriginal != 0);
        priceText.text = storeData.storeConfig.MoneyNum.ToString();
        priceText1.text = storeData.storeConfig.MoneyNum.ToString();
        if (storeData.storeConfig.MoneyType <= 0)
        {
            priceIcon.SetItemSprite(storeData.storeConfig.CostItemID);
            priceIcon1.SetItemSprite(storeData.storeConfig.CostItemID);
        }
        else
        {
            priceIcon.SetIconWithMoneyType(storeData.storeConfig.MoneyType);
            priceIcon1.SetIconWithMoneyType(storeData.storeConfig.MoneyType);
        }
        salePriceText.text = storeData.storeConfig.MoneyOriginal.ToString();
    }
    void BuyGoods(int shopID)
    {
        var state = StoreModel.Instance.GetShopIDState(shopID);
        if (state == 1) return;
        if (state == 2)
        {
            StoreModel.Instance.SendBuyShopItem(StoreConfig.Get(shopID), 1);
        }
        else
        {
            StoreModel.Instance.buyShopID = shopID;
            UIManager.Instance.OpenWindow<BuyItemWin>();
        }
    }
}
Main/System/HeroDebut/HeroDebutShopCell.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 868584e8775d70b45a260329d5666b60
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutShopLineCell.cs
New file
@@ -0,0 +1,30 @@
using UnityEngine;
public class HeroDebutShopLineCell : CellView
{
    [SerializeField] HeroDebutShopCell[] storeCells;
    HeroDebutManager manager => HeroDebutManager.Instance;
    public void Display(int index)
    {
        var act = manager.GetOperationHeroAppearInfo();
        if (act == null) return;
        var config = ActHeroAppearConfig.Get(act.CfgID);
        if (config == null) return;
        if (!StoreModel.Instance.storeTypeDict.TryGetValue(config.ExShopType, out var list)) return;
        for (int i = 0; i < storeCells.Length; i++)
        {
            if (index + i < list.Count)
            {
                storeCells[i].SetActive(true);
                storeCells[i].Display(index + i);
            }
            else
            {
                storeCells[i].SetActive(false);
            }
        }
    }
}
Main/System/HeroDebut/HeroDebutShopLineCell.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 13317ad05161a4047992bc2ea9471602
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutShopWin.cs
New file
@@ -0,0 +1,80 @@
using UnityEngine;
public class HeroDebutShopWin : UIBase
{
    [SerializeField] OwnItemCell ownItemCell;
    [SerializeField] ButtonEx closeButton;
    [SerializeField] TextEx timeText;
    [SerializeField] ScrollerController scroller;
    HeroDebutManager manager => HeroDebutManager.Instance;
    protected override void InitComponent()
    {
        closeButton.SetListener(CloseWindow);
    }
    protected override void OnPreOpen()
    {
        scroller.OnRefreshCell += OnRefreshCell;
        StoreModel.Instance.RefreshShopEvent += CreateScroller;
        StoreModel.Instance.RefreshBuyShopLimitEvent += CreateScroller;
        GlobalTimeEvent.Instance.secondEvent += OnSecondEvent;
        if (!manager.IsShopVisitedToday)
        {
            HeroDebutManager.Instance.SaveShopVisitTimeData();
            manager.UpdateRedpoint();
        }
        var act = manager.GetOperationHeroAppearInfo();
        if (act == null) return;
        var config = ActHeroAppearConfig.Get(act.CfgID);
        if (config == null) return;
        ownItemCell.itemID = config.ExShopCostItemID;
        CreateScroller();
        OnSecondEvent();
    }
    protected override void OnPreClose()
    {
        scroller.OnRefreshCell -= OnRefreshCell;
        StoreModel.Instance.RefreshShopEvent -= CreateScroller;
        StoreModel.Instance.RefreshBuyShopLimitEvent -= CreateScroller;
        GlobalTimeEvent.Instance.secondEvent -= OnSecondEvent;
        StoreModel.Instance.selectStoreFuncType = StoreFunc.Normal;
    }
    void OnRefreshCell(ScrollerDataType type, CellView cell)
    {
        var _cell = cell as HeroDebutShopLineCell;
        _cell.Display(cell.index);
    }
    private void OnSecondEvent()
    {
        manager.GetActTimeStr(timeText);
    }
    void CreateScroller()
    {
        var act = manager.GetOperationHeroAppearInfo();
        if (act == null) return;
        var config = ActHeroAppearConfig.Get(act.CfgID);
        if (config == null) return;
        if (!StoreModel.Instance.storeTypeDict.TryGetValue(config.ExShopType, out var list)) return;
        scroller.Refresh();
        for (int i = 0; i < list.Count; i++)
        {
            if (i % 3 == 0)
            {
                scroller.AddCell(ScrollerDataType.Header, i);
            }
        }
        scroller.Restart();
        scroller.lockType = EnhanceLockType.KeepVertical;
    }
}
Main/System/HeroDebut/HeroDebutShopWin.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 473e6aff97f65f44db8f1810ecf7a0f1
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutSkinAwardCell.cs
New file
@@ -0,0 +1,18 @@
using UnityEngine;
public class HeroDebutSkinAwardCell : CellView
{
    [SerializeField] ItemCell itemCell;
    public void Display(int index, int[][] arr)
    {
        if (arr == null || arr.Length <= index) return;
        int itemID = arr[index][0];
        long itemCount = arr[index][1];
        itemCell.Init(new ItemCellModel(itemID, false, itemCount));
        itemCell.button.AddListener(() =>
        {
            ItemTipUtility.Show(itemID);
        });
    }
}
Main/System/HeroDebut/HeroDebutSkinAwardCell.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 31cefbc704fb50d4f863263aafa70814
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutSkinTabCell.cs
New file
@@ -0,0 +1,28 @@
using System.Collections.Generic;
using UnityEngine;
public class HeroDebutSkinTabCell : CellView
{
    [SerializeField] ImageEx tabBgImage;
    [SerializeField] ButtonEx tabButton;
    [SerializeField] RectTransform chooseRect;
    [SerializeField] RectTransform maskRect;
    HeroDebutManager manager => HeroDebutManager.Instance;
    public void Display(int index, List<int> list)
    {
        if (list?.Count <= index) return;
        var skinID = list[index];
        var skinArtConfig = ActHeroAppearSkinArtConfig.Get(skinID);
        if (skinArtConfig == null) return;
        tabBgImage.SetSprite(skinArtConfig.TabInfoImage);
        tabBgImage.SetNativeSize();
        maskRect.SetActive(manager.currentChooseSkinID != skinID);
        chooseRect.SetActive(manager.currentChooseSkinID == skinID);
        tabButton.SetListener(() =>
        {
            manager.currentChooseSkinID = skinID;
        });
    }
}
Main/System/HeroDebut/HeroDebutSkinTabCell.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: de6e158685024444f9af2711cb4bce26
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutSkinWin.cs
New file
@@ -0,0 +1,215 @@
using System.Collections.Generic;
using UnityEngine;
public class HeroDebutSkinWin : UIBase
{
    [SerializeField] ImageEx bgImage;
    [SerializeField] ImageEx heroNameImage;
    [SerializeField] ImageEx skinInfoImage;
    [SerializeField] ImageEx awardBgImage;
    [SerializeField] TextEx timeText;
    [SerializeField] ButtonEx buyButton;
    [SerializeField] ImageEx buyImage;
    [SerializeField] ImageEx countryImage;
    [SerializeField] TextEx buyText;
    [SerializeField] ButtonEx closeButton;
    [SerializeField] UIHeroController uiHeroController;
    [SerializeField] UIHeroController lhController;
    [SerializeField] ScrollerController awardScroller;
    [SerializeField] ScrollerController tabScroller;
    [SerializeField] Color numColor;
    [SerializeField] TextEx[] wearAttrText;
    [SerializeField] TextEx[] roleAttrText;
    [SerializeField] ButtonEx infoButton;
    HeroDebutManager manager => HeroDebutManager.Instance;
    protected override void InitComponent()
    {
        closeButton.SetListener(CloseWindow);
        infoButton.SetListener(() => UIManager.Instance.OpenWindow<HeroBestBaseWin>(1));
    }
    protected override void OnPreOpen()
    {
        GlobalTimeEvent.Instance.secondEvent += OnSecondEvent;
        RechargeManager.Instance.rechargeCountEvent += OnRechargeCountEvent;
        awardScroller.OnRefreshCell += OnRefreshAwardCell;
        tabScroller.OnRefreshCell += OnRefreshTabCell;
        manager.OnCurrentChooseSkinIDChangeEevent += OnCurrentChooseSkinIDChange;
        CreateTabScroller();
        Display();
    }
    protected override void OnPreClose()
    {
        GlobalTimeEvent.Instance.secondEvent -= OnSecondEvent;
        RechargeManager.Instance.rechargeCountEvent -= OnRechargeCountEvent;
        awardScroller.OnRefreshCell -= OnRefreshAwardCell;
        tabScroller.OnRefreshCell -= OnRefreshTabCell;
        manager.OnCurrentChooseSkinIDChangeEevent -= OnCurrentChooseSkinIDChange;
    }
    private void OnCurrentChooseSkinIDChange()
    {
        tabScroller.m_Scorller.RefreshActiveCellViews();
        Display();
    }
    void OnRefreshTabCell(ScrollerDataType type, CellView cell)
    {
        var _cell = cell as HeroDebutSkinTabCell;
        _cell.Display(cell.index, skinIDList);
    }
    List<int> skinIDList;
    void CreateTabScroller()
    {
        var act = manager.GetOperationHeroAppearInfo();
        if (act == null) return;
        var config = ActHeroAppearConfig.Get(act.CfgID);
        if (config == null) return;
        int heroID = manager.GetCurrentDisplayCallHeroId();
        var artConfig = ActHeroAppearArtConfig.Get(heroID);
        if (artConfig == null) return;
        skinIDList = manager.GetSkinIDList(act.CfgID, heroID, artConfig.MainSkinID);
        if (skinIDList.IsNullOrEmpty()) return;
        manager.currentChooseSkinID = skinIDList[0];
        tabScroller.Refresh();
        for (int i = 0; i < skinIDList.Count; i++)
        {
            tabScroller.AddCell(ScrollerDataType.Header, i);
        }
        tabScroller.Restart();
    }
    int[][] arr = null;
    void OnRefreshAwardCell(ScrollerDataType type, CellView cell)
    {
        var _cell = cell as HeroDebutSkinAwardCell;
        _cell.Display(cell.index, arr);
    }
    void CreateAwardScroller(int[][] arr)
    {
        this.arr = arr;
        awardScroller.Refresh();
        if (arr != null)
        {
            for (int i = 0; i < arr.Length; i++)
            {
                awardScroller.AddCell(ScrollerDataType.Header, i);
            }
        }
        awardScroller.Restart();
    }
    private void OnSecondEvent()
    {
        manager.GetActTimeStr(timeText);
    }
    private void OnRechargeCountEvent(int obj)
    {
        Display();
    }
    public void Display()
    {
        var act = manager.GetOperationHeroAppearInfo();
        if (act == null) return;
        var config = ActHeroAppearConfig.Get(act.CfgID);
        if (config == null) return;
        int heroID = manager.GetCurrentDisplayCallHeroId();
        var artConfig = ActHeroAppearArtConfig.Get(heroID);
        if (artConfig == null) return;
        var heroConfig = HeroConfig.Get(heroID);
        if (heroConfig == null) return;
        int skinID = manager.currentChooseSkinID;
        var skinArtConfig = ActHeroAppearSkinArtConfig.Get(skinID);
        if (skinArtConfig == null) return;
        var heroSkinAttrConfig = HeroSkinAttrConfig.Get(skinID);
        if (heroSkinAttrConfig == null) return;
        if (heroSkinAttrConfig.WearAttrIDList == null) return;
        if (heroSkinAttrConfig.WearAttrValueList == null) return;
        if (heroSkinAttrConfig.RoleAttrIDList == null) return;
        if (heroSkinAttrConfig.RoleAttrValueList == null) return;
        var skinIDList = manager.GetSkinIDList(act.CfgID, heroID, skinID);
        if (skinIDList.IsNullOrEmpty()) return;
        int ctgId = manager.GetCtgIDBySkinID(skinID);
        var ctgConfig = CTGConfig.Get(ctgId);
        if (ctgConfig == null) return;
        if (!RechargeManager.Instance.TryGetOrderInfo(ctgId, out var orderConfig)) return;
        if (!RechargeManager.Instance.TryGetRechargeCount(ctgId, out var rechargeCount)) return;
        if (!RechargeManager.Instance.TryGetRechargeItem(ctgId, out var rechargeItemList)) return;
        bgImage.SetSprite(skinArtConfig.BGImage);
        bgImage.SetNativeSize();
        heroNameImage.SetSprite(skinArtConfig.HeroNameImage);
        heroNameImage.SetNativeSize();
        skinInfoImage.SetSprite(skinArtConfig.SkinInfoImage);
        skinInfoImage.SetNativeSize();
        awardBgImage.SetSprite(skinArtConfig.AwardBGImage);
        awardBgImage.SetNativeSize();
        uiHeroController.Create(skinID, 1);
        lhController.Create(skinID, 1, motionName: "", isLh: true);
        countryImage.SetSprite(HeroUIManager.Instance.GetCountryIconName(heroConfig.Country));
        OnSecondEvent();
        CreateAwardScroller(ctgConfig.GainItemList);
        bool isCanBuy = manager.IsNoSellOutCTGID(ctgId);
        //buyImage.gray = !isCanBuy;
        buyText.text = !isCanBuy ? Language.Get("storename11") : Language.Get("PayMoneyNum", UIHelper.GetMoneyFormat(orderConfig.PayRMBNum));
        buyButton.interactable = isCanBuy;
        buyButton.SetListener(() =>
        {
            RechargeManager.Instance.CTG(ctgId);
        });
        for (int i = 0; i < wearAttrText.Length; i++)
            SetAttrInfo(0, i, heroSkinAttrConfig, wearAttrText[i]);
        for (int i = 0; i < roleAttrText.Length; i++)
            SetAttrInfo(1, i, heroSkinAttrConfig, roleAttrText[i]);
    }
    // type 0 穿戴属性值 1 主公属性
    public void SetAttrInfo(int type, int index, HeroSkinAttrConfig heroSkinAttrConfig, TextEx info)
    {
        if (heroSkinAttrConfig == null) return;
        int[] arrID = type == 0 ? heroSkinAttrConfig.WearAttrIDList : heroSkinAttrConfig.RoleAttrIDList;
        int[] arrValue = type == 0 ? heroSkinAttrConfig.WearAttrValueList : heroSkinAttrConfig.RoleAttrValueList;
        if (arrID?.Length <= index || arrValue?.Length <= index)
        {
            info.text = string.Empty;
            return;
        }
        info.text = GetFullDescription(arrID[index], arrValue[index]);
    }
    string GetFullDescription(int id, long value)
    {
        var config = PlayerPropertyConfig.Get(id);
        if (config == null) return string.Empty;
        return Language.Get("HeroDebut33", config.ShowName, PlayerPropertyConfig.GetValueDescription(id, value));
    }
}
Main/System/HeroDebut/HeroDebutSkinWin.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6330e8f4c656dd34ab077262bf052ca5
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutStarUpCell.cs
New file
@@ -0,0 +1,122 @@
using System.Linq;
using UnityEngine;
public class HeroDebutStarUpCell : CellView
{
    [SerializeField] ItemCell freeAwardItemCell;
    [SerializeField] Transform freeAwardHaveTransform;//已领取
    [SerializeField] Transform freeAwardCanHaveTransform;//可领取
    [SerializeField] Transform upProcssBGTransform;
    [SerializeField] Transform upProcessTransform;
    [SerializeField] Transform downProcssBGTransform;
    [SerializeField] Transform downProcessTransform;
    [SerializeField] TextEx starCntText;
    [SerializeField] TextEx limitText;
    [SerializeField] ButtonEx buyButton;
    [SerializeField] ImageEx buyImage;
    [SerializeField] TextEx buyText;
    [SerializeField] ScrollerController scroller;
    HeroDebutManager manager => HeroDebutManager.Instance;
    int id;
    public void Display(int id, CellView cell)
    {
        this.id = id;
        int heroID = cell.info.Value.infoInt1;
        bool isFrist = cell.info.Value.infoInt2 == 1;
        bool isEnd = cell.info.Value.infoInt3 == 1;
        var config = ActHeroAppearStarConfig.Get(id);
        if (config == null) return;
        var heroConfig = HeroConfig.Get(heroID);
        if (heroConfig == null) return;
        if (config.FreeAwardItemList.IsNullOrEmpty()) return;
        int ctgId = config.StarGiftCTGID;
        int awardIndex = config.AwardIndex;
        if (!manager.TryGetStarUpAwardArr(id, heroID, out int[][] list)) return;
        if (!RechargeManager.Instance.TryGetOrderInfo(ctgId, out var orderConfig)) return;
        if (!RechargeManager.Instance.TryGetRechargeCount(ctgId, out var rechargeCount)) return;
        if (!RechargeManager.Instance.TryGetRechargeItem(ctgId, out var rechargeItemList)) return;
        CTGConfig ctgConfig = CTGConfig.Get(ctgId);
        if (ctgConfig == null) return;
        int state = manager.GetStarUpFreeState(id);//0 - 未解锁 1 - 可领取 2 - 已领取
        freeAwardHaveTransform.SetActive(state == 2);
        freeAwardCanHaveTransform.SetActive(state == 1);
        bool isNoSellOut = manager.IsNoSellOutCTGID(ctgId);
        buyButton.interactable = state != 0 && isNoSellOut;
        buyButton.SetListener(() =>
        {
            if (isNoSellOut && state != 0)
            {
                RechargeManager.Instance.CTG(ctgId);
            }
        });
        //buyImage.gray = state == 0 || !isNoSellOut;
        buyText.text = !isNoSellOut ? Language.Get("storename11") : Language.Get("PayMoneyNum", UIHelper.GetMoneyFormat(orderConfig.PayRMBNum));
        limitText.text = Language.Get("TimeRush08", UIHelper.AppendColor(rechargeCount.totalCount >= ctgConfig.TotalBuyCount ? TextColType.Red : TextColType.DarkGreen, $"{rechargeCount.totalCount}/{ctgConfig.TotalBuyCount}"));
        bool isHeroStarOk = manager.IsHeroStarCntOk(heroConfig.HeroID, config.NeedStar);
        upProcssBGTransform.SetActive(!isFrist);
        downProcssBGTransform.SetActive(!isEnd);
        upProcessTransform.SetActive(isHeroStarOk);
        downProcessTransform.SetActive(isHeroStarOk);
        CreateScroller(list);
        int[] arr = config.FreeAwardItemList.First();
        int itemID = arr[0];
        int itemCount = arr[1];
        freeAwardItemCell.SetActive(true);
        freeAwardItemCell.Init(new ItemCellModel(itemID, false, itemCount));
        freeAwardItemCell.button.AddListener(() =>
        {
            if (state == 1)
            {
                manager.SendGetStarReward();
            }
            else
            {
                ItemTipUtility.Show(itemID);
            }
        });
        starCntText.text = Language.Get("HeroDebut20", config.NeedStar);
    }
    private void CreateScroller(int[][] list)
    {
        if (list == null) return;
        var config = ActHeroAppearStarConfig.Get(id);
        if (config == null) return;
        scroller.OnRefreshCell += OnRefreshCell;
        scroller.Refresh();
        for (int i = 0; i < list.Length; i++)
        {
            var item = list[i];
            var itemID = item[0];
            var itemCount = item[1];
            CellInfo cellInfo = new()
            {
                infoInt1 = itemID,
                infoInt2 = itemCount,
                infoInt3 = manager.IsNoSellOutCTGID(config.StarGiftCTGID) ? 1 : 0,
            };
            scroller.AddCell(ScrollerDataType.Header, i, cellInfo);
        }
        scroller.Restart();
        scroller.OnRefreshCell -= OnRefreshCell;
    }
    private void OnRefreshCell(ScrollerDataType type, CellView cell)
    {
        var _cell = cell.GetComponent<HeroDebutStarUpPaidItemCell>();
        _cell?.Display(cell.index, cell);
    }
}
Main/System/HeroDebut/HeroDebutStarUpCell.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 74da6ff1c960d3a409be13a89136573d
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutStarUpPaidItemCell.cs
New file
@@ -0,0 +1,17 @@
using UnityEngine;
public class HeroDebutStarUpPaidItemCell : CellView
{
    [SerializeField] ItemCell itemCell;
    [SerializeField] Transform soldOutTransform;
    public void Display(int index, CellView cell)
    {
        int itemID = cell.info.Value.infoInt1;
        int count = cell.info.Value.infoInt2;
        bool isSoldOut = cell.info.Value.infoInt3 == 0;
        soldOutTransform.SetActive(isSoldOut);
        itemCell.SetActive(true);
        itemCell.Init(new ItemCellModel((int)itemID, false, count));
        itemCell.button.AddListener(() => ItemTipUtility.Show(itemID));
    }
}
Main/System/HeroDebut/HeroDebutStarUpPaidItemCell.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2ba8d299ce307054c8e3b9e6608dffd5
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutStarUpWin.cs
New file
@@ -0,0 +1,121 @@
using UnityEngine;
public class HeroDebutStarUpWin : UIBase
{
    [SerializeField] GradientText heroNameText;
    [SerializeField] TextEx timeText;
    [SerializeField] ImageEx heroImage;
    [SerializeField] ButtonEx goCallButton;
    [SerializeField] ButtonEx goInfoButton;
    [SerializeField] ButtonEx closeButton;
    [SerializeField] ScrollerController scroller;
    HeroDebutManager manager => HeroDebutManager.Instance;
    protected override void InitComponent()
    {
        closeButton.SetListener(CloseWindow);
        goCallButton.SetListener(() =>
        {
            UIManager.Instance.CloseWindow<HeroDebutStarUpWin>();
            UIManager.Instance.OpenWindow<HeroDebutCallWin>();
        });
        goInfoButton.SetListener(() =>
        {
            if (heroConfig == null) return;
            UIManager.Instance.CloseWindow<HeroDebutStarUpWin>();
            HeroUIManager.Instance.selectForPreviewHeroID = heroConfig.HeroID;
            UIManager.Instance.OpenWindow<HeroBestWin>();
        });
    }
    protected override void OnPreOpen()
    {
        scroller.OnRefreshCell += OnRefreshCell;
        GlobalTimeEvent.Instance.secondEvent += OnSecondEvent;
        RechargeManager.Instance.rechargeCountEvent += OnRechargeCountEvent;
        manager.OnUpdateHeroAppearPlayerInfoEvent += OnUpdateHeroAppearPlayerInfoEvent;
        Display();
    }
    protected override void OnPreClose()
    {
        scroller.OnRefreshCell -= OnRefreshCell;
        GlobalTimeEvent.Instance.secondEvent -= OnSecondEvent;
        RechargeManager.Instance.rechargeCountEvent -= OnRechargeCountEvent;
        manager.OnUpdateHeroAppearPlayerInfoEvent -= OnUpdateHeroAppearPlayerInfoEvent;
    }
    private void OnUpdateHeroAppearPlayerInfoEvent(int obj)
    {
        scroller.m_Scorller.RefreshActiveCellViews();
    }
    private void OnRefreshCell(ScrollerDataType type, CellView cell)
    {
        var _cell = cell.GetComponent<HeroDebutStarUpCell>();
        _cell?.Display(cell.index, cell);
    }
    private void OnSecondEvent()
    {
        manager.GetActTimeStr(timeText);
    }
    private void OnRechargeCountEvent(int obj)
    {
        scroller.m_Scorller.RefreshActiveCellViews();
    }
    HeroConfig heroConfig;
    private void Display()
    {
        int heroID = manager.GetCurrentDisplayStarUpHeroId();
        heroConfig = HeroConfig.Get(heroID);
        if (heroConfig == null) return;
        var artConfig = ActHeroAppearArtConfig.Get(heroID);
        if (artConfig == null) return;
        var act = manager.GetOperationHeroAppearInfo();
        if (act == null) return;
        var config = ActHeroAppearConfig.Get(act.CfgID);
        if (config == null) return;
        heroNameText.text = heroConfig.Name;
        manager.SetGradientTextColor(heroNameText, artConfig.HeroNameColor);
        heroImage.SetSprite(artConfig.StarUpHeroImage);
        heroImage.SetNativeSize();
        CreateScroller(config, heroConfig);
    }
    private void CreateScroller(ActHeroAppearConfig appearConfig, HeroConfig heroConfig)
    {
        if (appearConfig == null || heroConfig == null) return;
        int starGiftTempID = appearConfig.StarGiftTempID;
        var list = ActHeroAppearStarConfig.GetAwardIndexSortList(starGiftTempID);
        if (list == null) return;
        scroller.Refresh();
        for (int i = 0; i < list.Count; i++)
        {
            var awardIndex = list[i];
            var config = ActHeroAppearStarConfig.GetConfig(starGiftTempID, awardIndex);
            if (config == null) continue;
            CellInfo cellInfo = new()
            {
                infoInt1 = heroConfig.HeroID,
                infoInt2 = i == 0 ? 1 : 0,
                infoInt3 = i == list.Count - 1 ? 1 : 0
            };
            scroller.AddCell(ScrollerDataType.Header, config.ID, cellInfo);
        }
        scroller.Restart();
        scroller.JumpIndex(manager.GetStarUpJumpIndex(starGiftTempID));
    }
}
Main/System/HeroDebut/HeroDebutStarUpWin.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1093406ae678d4843b4b41a662287bb9
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/HeroDebutWin.cs
New file
@@ -0,0 +1,115 @@
using System;
using UnityEngine;
using UnityEngine.UI;
public class HeroDebutWin : UIBase
{
    [SerializeField] RectTransform activeRect;
    [SerializeField] RectTransform moveRect;
    [SerializeField] RectTransform startRect;
    [SerializeField] RectTransform endRect;
    [SerializeField] ImageEx bgImage;
    [SerializeField] ImageEx titleImage;
    [SerializeField] TextEx timeText;
    [SerializeField] ButtonEx animationButton;
    [SerializeField] ButtonEx checkInButton; // 签到赠礼
    [SerializeField] RedpointBehaviour checkInRedpoint;
    [SerializeField] ButtonEx starUpButton; // 升星计划
    [SerializeField] RedpointBehaviour starUpRedpoint;
    [SerializeField] ButtonEx shopButton; // 兑换商店
    [SerializeField] RedpointBehaviour shopRedpoint;
    [SerializeField] ImageEx skinImage;
    [SerializeField] ButtonEx skinButton; // 时装特卖
    [SerializeField] ButtonEx giftButton; // 皇权礼包
    [SerializeField] RedpointBehaviour giftRedpoint;
    [SerializeField] ButtonEx callButton; // 皇权招募
    [SerializeField] UIHeroController uiHeroController;
    [SerializeField] UIHeroController lhController;
    [SerializeField] Image callRedImage;
    [SerializeField] ButtonEx closeButton;
    [SerializeField] float modleSize = 0.8f;
    HeroDebutManager manager => HeroDebutManager.Instance;
    protected override void InitComponent()
    {
        closeButton.SetListener(() => UIManager.Instance.CloseWindow<HeroDebutWin>());
        checkInButton.SetListener(() => UIManager.Instance.OpenWindow<HeroDebutCheckInWin>());
        starUpButton.SetListener(() => UIManager.Instance.OpenWindow<HeroDebutStarUpWin>());
        shopButton.SetListener(() => UIManager.Instance.OpenWindow<HeroDebutShopWin>());
        skinButton.SetListener(() => UIManager.Instance.OpenWindow<HeroDebutSkinWin>());
        giftButton.SetListener(() => UIManager.Instance.OpenWindow<HeroDebutGiftWin>());
        callButton.SetListener(() => UIManager.Instance.OpenWindow<HeroDebutCallWin>());
    }
    protected override void OnPreOpen()
    {
        InitRedpoint();
        GlobalTimeEvent.Instance.secondEvent += OnSecondEvent;
        RechargeManager.Instance.rechargeCountEvent += OnRechargeCountEvent;
        StoreModel.Instance.RefreshBuyShopLimitEvent += Display;
        manager.OnUpdateHeroAppearPlayerInfoEvent += OnUpdateHeroAppearPlayerInfoEvent;
        Display();
    }
    protected override void OnPreClose()
    {
        GlobalTimeEvent.Instance.secondEvent -= OnSecondEvent;
        RechargeManager.Instance.rechargeCountEvent -= OnRechargeCountEvent;
        StoreModel.Instance.RefreshBuyShopLimitEvent -= Display;
        manager.OnUpdateHeroAppearPlayerInfoEvent -= OnUpdateHeroAppearPlayerInfoEvent;
    }
    private void OnUpdateHeroAppearPlayerInfoEvent(int obj)
    {
        Display();
    }
    private void OnRechargeCountEvent(int obj)
    {
        Display();
    }
    public void InitRedpoint()
    {
        checkInRedpoint.redpointId = manager.GetRedPointId(HeroDebutRedPointType.CheckIn);
        starUpRedpoint.redpointId = manager.GetRedPointId(HeroDebutRedPointType.StarUp);
        shopRedpoint.redpointId = manager.GetRedPointId(HeroDebutRedPointType.Shop);
        giftRedpoint.redpointId = manager.GetRedPointId(HeroDebutRedPointType.Gift);
    }
    private void Display()
    {
        int heroID = manager.GetCurrentDisplayCallHeroId();
        var artConfig = ActHeroAppearArtConfig.Get(heroID);
        if (artConfig == null) return;
        int skinID = manager.GetDefaultSkinID(heroID);
        var skinConfig = HeroSkinConfig.Get(skinID);
        if (skinConfig == null) return;
        var skinArtConfig = ActHeroAppearSkinArtConfig.Get(artConfig.MainSkinID);
        if (skinArtConfig == null) return;
        uiHeroController.Create(skinID, modleSize);
        uiHeroController.transform.localScale = new Vector3(-modleSize, modleSize, modleSize);
        lhController.Create(skinID, 1, motionName: "", isLh: true);
        callRedImage.SetActive(!manager.IsShopVisitedToday || manager.HasGiftCanHave());
        bgImage.SetSprite(artConfig.MainBgImage);
        bgImage.SetNativeSize();
        titleImage.SetSprite(artConfig.MainTitleImage);
        titleImage.SetNativeSize();
        skinImage.SetSprite(skinArtConfig.MainSkinBuyBgImage);
        OnSecondEvent();
    }
    private void OnSecondEvent()
    {
        manager.GetActTimeStr(timeText);
    }
}
Main/System/HeroDebut/HeroDebutWin.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ef7895a8e56d7424d9f3bc87d12e997e
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroDebut/OperationHeroAppearInfo.cs
New file
@@ -0,0 +1,21 @@

//英雄登场(武将登场)
public class OperationHeroAppearInfo : OperationBase
{
    public int ActType; // 活动类型,用于关联活动相关模块用,如签到、任务等
    public int CfgID;   // 活动时间表配置ID
    public override string ToDisplayTime()
    {
        var textBuilder = OperationTimeHepler.textBuilder;
        textBuilder.Length = 0;
        textBuilder.Append(startDate.ToDisplay());
        if (startDate != endDate)
        {
            textBuilder.Append("—");
            textBuilder.Append(endDate.ToDisplay());
        }
        return textBuilder.ToString();
    }
}
Main/System/HeroDebut/OperationHeroAppearInfo.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2c27b7bd6b1cca749b6b40fcb645785d
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Main/HomeWin.cs
@@ -69,6 +69,7 @@
    [SerializeField] Button osGalaBtn;
    [SerializeField] TimingGiftCell timingGiftCell;
    [SerializeField] TimeRushCell timeRushCell;
    [SerializeField] HeroDebutCell heroDebutCell;
    //坐骑
    [SerializeField] Image horseBGImg;
@@ -272,6 +273,7 @@
        UIManager.Instance.OnOpenWindow += OnOpenWindow;
        TimingGiftManager.Instance.OnShowGiftIdListAddEvent += OnShowGiftIdListAddEvent;
        OpenServerActivityCenter.Instance.openServerActivityStateChange += OpenServerActivityStateChange;
        OperationTimeHepler.Instance.operationTimeUpdateEvent += OnOperationTimeUpdateEvent;
        TryPlayAutoFightBoss();
        Display();
        DisplayFirstChargeBtn();
@@ -279,7 +281,7 @@
        timingGiftCell.InitUI();
        DisplayTimeRush();
        DisplayHeroDebut();
        DelayPlayMusic().Forget();
    }
@@ -309,13 +311,24 @@
        UIManager.Instance.OnOpenWindow -= OnOpenWindow;
        TimingGiftManager.Instance.OnShowGiftIdListAddEvent -= OnShowGiftIdListAddEvent;
        OpenServerActivityCenter.Instance.openServerActivityStateChange -= OpenServerActivityStateChange;
        OperationTimeHepler.Instance.operationTimeUpdateEvent -= OnOperationTimeUpdateEvent;
        //  关闭的时候把战斗界面也给关了 虽然是在外面开的
        UIManager.Instance.CloseWindow<BattleWin>();
    }
    private void OnOperationTimeUpdateEvent(OperationType type)
    {
        if (type == OperationType.HeroDebut)
        {
            DisplayHeroDebut();
        }
    }
    private void OpenServerActivityStateChange()
    {
        DisplayTimeRush();
        DisplayHeroDebut();
    }
    private void OnShowGiftIdListAddEvent()
@@ -810,6 +823,10 @@
        {
            DisplayTimeRush();
        }
        else if (funcId == (int)FuncOpenEnum.HeroDebut)
        {
            DisplayHeroDebut();
        }
    }
    private void OnUpdateFirstChargeInfo()
@@ -874,6 +891,15 @@
            return;
        timeRushCell.InitUI();
    }
    void DisplayHeroDebut()
    {
        bool isOpen = HeroDebutManager.Instance.IsHeroDebutOpen();
        heroDebutCell.SetActive(isOpen);
        if (!isOpen)
            return;
        heroDebutCell.Display();
    }
}
Main/System/OpenServerActivity/OperationTimeHepler.cs
@@ -461,6 +461,40 @@
        }
    }
    public void UpdateActHeroAppearInfo(HAA21_tagSCActHeroAppearInfo package)
    {
        var opreationType = OperationType.HeroDebut;
        switch (package.ActNum)
        {
            case 10:
                opreationType = OperationType.HeroDebut;
                break;
            // case 11:
            //     opreationType = OperationType.HeroBack;
            //     break;
        }
        if (string.IsNullOrEmpty(package.StartDate) || string.IsNullOrEmpty(package.EndtDate))
        {
            ForceStopOperation(opreationType);
            return;
        }
        if (!operationDict.TryGetValue(opreationType, out OperationBase operationBase))
        {
            operationBase = new OperationHeroAppearInfo();
            operationDict.Add(opreationType, operationBase);
        }
        OperationHeroAppearInfo operation = operationBase as OperationHeroAppearInfo;
        operation.Reset();
        operation.startDate = ParseOperationDate(package.StartDate);
        operation.endDate = ParseOperationDate(package.EndtDate);
        operation.ActType = package.ActType;
        operation.CfgID = package.CfgID;
        operationTimeUpdateEvent?.Invoke(opreationType);
    }
    // public void UpdateActYunShiInfo(HAA87_tagMCActYunshiInfo package)
    // {
    //     Operation operationType = Operation.default48;
@@ -1048,7 +1082,7 @@
public enum OperationType
{
    CustomizedGift,  //自选礼包
    TimeRush,  //日期型活动 - 轮回殿
    TimeRush = 1,  //日期型活动 - 轮回殿
    HeroDebut = 2,  //日期型活动 - 武将登场
    max,
}
Main/System/Redpoint/MainRedDot.cs
@@ -150,6 +150,7 @@
    public const int DailyTehui = 476;//每日特惠
    public const int WarlordPavilionRepoint = 477;//定军阁
    public const int TimeRushRepoint = 478; //轮回殿
    public const int HeroDebutRepoint = 479; //武将登场
    public void Register()
    {
Main/System/UIBase/UIJumpManager.cs
@@ -21,11 +21,20 @@
        {
            return false;
        }
        if (config.FuncID !=0 && !FuncOpen.Instance.IsFuncOpen(config.FuncID, showTip))
        if (config.FuncID != 0 && !FuncOpen.Instance.IsFuncOpen(config.FuncID, showTip))
        {
            return false;
        }
        if (config.ActiveType != 0 && !OperationTimeHepler.Instance.SatisfyOpenCondition((OperationType)config.ActiveType))
        {
            if (showTip)
            {
                SysNotifyMgr.Instance.ShowTip("ActivityNoOpen");
            }
            return false;
        }
        //活动后续补充
        return true;
    }
@@ -51,6 +60,27 @@
                StoreModel.Instance.selectStoreFuncType = (StoreFunc)StoreConfig.Get(StoreModel.Instance.jumpShopID).ShopType;
            }
        }
        else if (config.WinName == "HeroDebutCallWin")
        {
            var heroDebutAct = HeroDebutManager.Instance.GetOperationHeroAppearInfo();
            if (heroDebutAct == null) return;
            ActHeroAppearConfig actHeroAppearConfig = ActHeroAppearConfig.Get(heroDebutAct.CfgID);
            if (actHeroAppearConfig == null) return;
            if (actHeroAppearConfig.ExShopCostItemID != int.Parse(config.Extra))
            {
                SysNotifyMgr.Instance.ShowTip("ActivityNoOpen");
            }
            else
            {
                if (UIManager.Instance.IsOpened<HeroDebutCallWin>())
                {
                    UIManager.Instance.CloseWindow<HeroDebutCallWin>();
                    UIManager.Instance.OpenWindow<HeroDebutCallWin>();
                }
            }
        }
        if (!UIManager.Instance.IsOpened(config.WinName))
        {
Main/Utility/EnumHelper.cs
@@ -850,6 +850,7 @@
    FuncPreset = 56, //流派预设
    TimingGift = 57, //时机礼包
    TimeRush = 58, //限时冲刺
    HeroDebut = 63,//武将登场
}
@@ -1803,8 +1804,8 @@
//OpenServerActivityCenter.ActivityType.AT_Activity2的活动  历史原因不要用100
public enum NewDayActivityID
{
    CustomizedGiftWin = 200, //自选礼包
    TimeRushAct = 201,  //轮回殿(武将冲刺)
    TimeRushAct = 200,  //轮回殿(武将冲刺)
    HeroDebutAct = 201,  //英雄登场活动
}
//仙玉购买的二次确认框类型