lcy
2 天以前 e19bcaa7ced9d17f7dae4672ae0c41710e178a60
218 子 【付费内容】首充 / 【付费内容】首充-客户端
9个文件已修改
1个文件已删除
8 文件已复制
10个文件已添加
1 文件已重命名
1765 ■■■■■ 已修改文件
Main/Component/UI/Common/PopupWindowsProcessor.cs 161 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Component/UI/Common/PopupWindowsProcessor.cs.meta 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/ConfigManager.cs 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/AppointItemConfig.cs 50 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/FirstChargeConfig.cs 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/FirstChargeConfig.cs.meta 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/PartialConfigs/FirstChargeConfig.cs 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/PartialConfigs/FirstChargeConfig.cs.meta 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA02_tagMCFirstGoldInfo.cs 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA02_tagSCFirstChargeInfo.cs 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA02_tagSCFirstChargeInfo.cs.meta 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/DataToCtl/PackageRegedit.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA02_tagSCFirstChargeInfo.cs 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA02_tagSCFirstChargeInfo.cs.meta 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Main.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Equip/EquipTipWin.cs 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/FirstCharge.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/FirstCharge/FirstChargeDayAward.cs 224 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/FirstCharge/FirstChargeDayAward.cs.meta 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/FirstCharge/FirstChargeHeroInfoWin.cs 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/FirstCharge/FirstChargeHeroInfoWin.cs.meta 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/FirstCharge/FirstChargeManager.cs 522 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/FirstCharge/FirstChargeManager.cs.meta 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/FirstCharge/FirstChargeWin.cs 308 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/FirstCharge/FirstChargeWin.cs.meta 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/ItemTip/ItemTipUtility.cs 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Main/HomeWin.cs 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Recharge/RechargeManager.cs 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Redpoint/MainRedDot.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Component/UI/Common/PopupWindowsProcessor.cs
New file
@@ -0,0 +1,161 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 弹窗处理器 - 负责管理游戏中的弹窗队列,按顺序显示弹窗窗口
/// 避免多个窗口同时弹出造成界面混乱
/// </summary>
public class PopupWindowsProcessor : SingletonMonobehaviour<PopupWindowsProcessor>
{
    // 弹窗队列,存储待处理的弹窗请求
    List<PopupWindow> popupWindowQueue = new List<PopupWindow>();
    // 当前正在显示的弹窗
    PopupWindow currentWindow;
    // 上次弹窗时间,用于控制弹窗之间的间隔
    float lastTime = 0; //上次弹窗时间
    /// <summary>
    /// 添加一个弹窗到处理队列
    /// </summary>
    /// <param name="name">窗口名称</param>
    /// <param name="functionId">功能ID,用于指定窗口的具体功能或显示模式</param>
    public void Add(string name, int functionId = 0)
    {
        var popupWindow = new PopupWindow()
        {
            window = name,
            functionId = functionId,
        };
        if (popupWindowQueue.Contains(popupWindow))
        {
            popupWindowQueue.Remove(popupWindow);
        }
        popupWindowQueue.Add(popupWindow);
    }
    /// <summary>
    /// 从处理队列中移除指定的弹窗
    /// </summary>
    /// <param name="name">窗口名称</param>
    /// <param name="functionId">功能ID</param>
    public void Remove(string name, int functionId = 0)
    {
        var popupWindow = new PopupWindow()
        {
            window = name,
            functionId = functionId,
        };
        if (popupWindowQueue.Contains(popupWindow))
        {
            popupWindowQueue.Remove(popupWindow);
        }
    }
    /// <summary>
    /// LateUpdate中处理弹窗队列,确保在所有其他逻辑处理完毕后才显示弹窗
    /// </summary>
    private void LateUpdate()
    {
        //打开窗口需要时间,不然会导致队列中的窗口全部同时打开
        if (Time.realtimeSinceStartup - lastTime < 1)
            return;
        // 检查玩家是否完成登录加载
        if (!DTC0403_tagPlayerLoginLoadOK.finishedLogin)
            return;
        // 检查是否进入游戏主场景
        if (StageManager.Instance.currentStage != StageName.Game)
        {
            return;
        }
        // 检查是否在新手引导中
        // 注意:NewBieCenter在当前代码库中不存在,暂时注释掉相关检查
        // if (NewBieCenter.Instance.inGuiding)
        // {
        //     return;
        // }
        if (popupWindowQueue.Count == 0)
        {
            return;
        }
        // 检查是否正在显示Loading窗口
        if (UIManager.Instance.IsOpened<LoadingWin>())
            return;
        // 检查是否存在全屏或遮罩窗口
        // 注意:ExistAnyFullScreenOrMaskWin方法在当前UIManager中不存在,暂时注释掉相关检查
        // if (UIManager.Instance.ExistAnyFullScreenOrMaskWin())
        //     return;
        if (currentWindow.window != null)
        {
            //判断上一个推送是否关闭
            UIBase ui = UIManager.Instance.GetUI(currentWindow.window);
            if (ui != null && ui.IsActive())
                return;
            currentWindow = popupWindowQueue[0];
            popupWindowQueue.RemoveAt(0);
            UIManager.Instance.OpenWindow(currentWindow.window, currentWindow.functionId);
            Debug.LogFormat("推送窗口 " + currentWindow.window);
        }
        else
        {
            currentWindow = popupWindowQueue[0];
            popupWindowQueue.RemoveAt(0);
            UIManager.Instance.OpenWindow(currentWindow.window, currentWindow.functionId);
            Debug.LogFormat("推送窗口 " + currentWindow.window);
        }
        lastTime = Time.realtimeSinceStartup;
    }
    /// <summary>
    /// 弹窗结构体,用于表示一个待处理的弹窗请求
    /// 包含窗口名称和功能ID,通过这两个字段可以唯一标识一个弹窗请求
    /// </summary>
    public struct PopupWindow
    {
        // 窗口名称
        public string window;
        // 功能ID,用于指定窗口的具体功能或显示模式
        public int functionId;
        public static bool operator ==(PopupWindow lhs, PopupWindow rhs)
        {
            return lhs.window == rhs.window && lhs.functionId == rhs.functionId;
        }
        public static bool operator !=(PopupWindow lhs, PopupWindow rhs)
        {
            return lhs.window != rhs.window || lhs.functionId != rhs.functionId;
        }
        // 添加GetHashCode和Equals方法以确保结构体可以正确比较
        public override bool Equals(object obj)
        {
            if (obj is PopupWindow)
            {
                PopupWindow other = (PopupWindow)obj;
                return this.window == other.window && this.functionId == other.functionId;
            }
            return false;
        }
        public override int GetHashCode()
        {
            return window.GetHashCode() ^ functionId.GetHashCode();
        }
    }
}
Main/Component/UI/Common/PopupWindowsProcessor.cs.meta
copy from Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA02_tagMCFirstGoldInfo.cs.meta copy to Main/Component/UI/Common/PopupWindowsProcessor.cs.meta
File was copied from Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA02_tagMCFirstGoldInfo.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 56da7e3109f052e46860b1ed27323ab4
guid: 63a256d5f4c621d4c9d01ad4d1771d13
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
Main/Config/ConfigManager.cs
@@ -44,6 +44,7 @@
            typeof(DirtyWordConfig),
            typeof(FaceConfig),
            typeof(FightPowerRatioConfig),
            typeof(FirstChargeConfig),
            typeof(GoldRushCampConfig),
            typeof(GoldRushItemConfig),
            typeof(GoldRushWorkerConfig),
@@ -229,6 +230,8 @@
        ClearConfigDictionary<FaceConfig>();
        // 清空 FightPowerRatioConfig 字典
        ClearConfigDictionary<FightPowerRatioConfig>();
        // 清空 FirstChargeConfig 字典
        ClearConfigDictionary<FirstChargeConfig>();
        // 清空 GoldRushCampConfig 字典
        ClearConfigDictionary<GoldRushCampConfig>();
        // 清空 GoldRushItemConfig 字典
Main/Config/Configs/AppointItemConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年8月5日
//    [  Date ]:           Tuesday, October 7, 2025
//--------------------------------------------------------
using System.Collections.Generic;
@@ -17,6 +17,10 @@
    }
    public int ID;
    public int CancelUseLimit;
    public int ItemLV;
    public int[] BaseAttrID;
    public int[] BaseAttrValue;
    public int[] LegendAttrID;
    public int[] LegendAttrValue;
@@ -32,13 +36,45 @@
        string[] tables = input.Split('\t');
        int.TryParse(tables[0],out ID); 
            if (tables[1].Contains("["))
            int.TryParse(tables[1],out CancelUseLimit);
            int.TryParse(tables[2],out ItemLV);
            if (tables[3].Contains("["))
            {
                LegendAttrID = JsonMapper.ToObject<int[]>(tables[1]);
                BaseAttrID = JsonMapper.ToObject<int[]>(tables[3]);
            }
            else
            {
                string[] LegendAttrIDStringArray = tables[1].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
                string[] BaseAttrIDStringArray = tables[3].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
                BaseAttrID = new int[BaseAttrIDStringArray.Length];
                for (int i=0;i<BaseAttrIDStringArray.Length;i++)
                {
                     int.TryParse(BaseAttrIDStringArray[i],out BaseAttrID[i]);
                }
            }
            if (tables[4].Contains("["))
            {
                BaseAttrValue = JsonMapper.ToObject<int[]>(tables[4]);
            }
            else
            {
                string[] BaseAttrValueStringArray = tables[4].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
                BaseAttrValue = new int[BaseAttrValueStringArray.Length];
                for (int i=0;i<BaseAttrValueStringArray.Length;i++)
                {
                     int.TryParse(BaseAttrValueStringArray[i],out BaseAttrValue[i]);
                }
            }
            if (tables[5].Contains("["))
            {
                LegendAttrID = JsonMapper.ToObject<int[]>(tables[5]);
            }
            else
            {
                string[] LegendAttrIDStringArray = tables[5].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
                LegendAttrID = new int[LegendAttrIDStringArray.Length];
                for (int i=0;i<LegendAttrIDStringArray.Length;i++)
                {
@@ -46,13 +82,13 @@
                }
            }
            if (tables[2].Contains("["))
            if (tables[6].Contains("["))
            {
                LegendAttrValue = JsonMapper.ToObject<int[]>(tables[2]);
                LegendAttrValue = JsonMapper.ToObject<int[]>(tables[6]);
            }
            else
            {
                string[] LegendAttrValueStringArray = tables[2].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
                string[] LegendAttrValueStringArray = tables[6].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
                LegendAttrValue = new int[LegendAttrValueStringArray.Length];
                for (int i=0;i<LegendAttrValueStringArray.Length;i++)
                {
Main/Config/Configs/FirstChargeConfig.cs
New file
@@ -0,0 +1,56 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           Friday, October 3, 2025
//--------------------------------------------------------
using System.Collections.Generic;
using System;
using UnityEngine;
using LitJson;
public partial class FirstChargeConfig : ConfigBase<int, FirstChargeConfig>
{
    static FirstChargeConfig()
    {
        // 访问过静态构造函数
        visit = true;
    }
    public int FirstID;
    public int CTGID;
    public int[][] AwardListDay1;
    public int[][] AwardListDay2;
    public int[][] AwardListDay3;
    public int ExtraRewardTextType;
    public string ExtraRewardTextInfo;
    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 FirstID);
            int.TryParse(tables[1],out CTGID);
            AwardListDay1 = JsonMapper.ToObject<int[][]>(tables[2].Replace("(", "[").Replace(")", "]"));
            AwardListDay2 = JsonMapper.ToObject<int[][]>(tables[3].Replace("(", "[").Replace(")", "]"));
            AwardListDay3 = JsonMapper.ToObject<int[][]>(tables[4].Replace("(", "[").Replace(")", "]"));
            int.TryParse(tables[5],out ExtraRewardTextType);
            ExtraRewardTextInfo = tables[6];
        }
        catch (Exception exception)
        {
            Debug.LogError(exception);
        }
    }
}
Main/Config/Configs/FirstChargeConfig.cs.meta
File was renamed from Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA02_tagMCFirstGoldInfo.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 56da7e3109f052e46860b1ed27323ab4
guid: e32927c96cf6d0240940a74853e29c60
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
Main/Config/PartialConfigs/FirstChargeConfig.cs
New file
@@ -0,0 +1,23 @@
using System.Collections.Generic;
using System.Linq;
public partial class FirstChargeConfig : ConfigBase<int, FirstChargeConfig>
{
    private static Dictionary<int, int> ctgIdTofirstIdDict = new Dictionary<int, int>();
    protected override void OnConfigParseCompleted()
    {
        ctgIdTofirstIdDict[CTGID] = FirstID;
    }
    public static List<int> GetCtgIDList()
    {
        return ctgIdTofirstIdDict.Keys.ToList();
    }
    public static bool TryGetFirstIdByCtgID(int ctgID, out int firstID)
    {
        return ctgIdTofirstIdDict.TryGetValue(ctgID, out firstID);
    }
}
Main/Config/PartialConfigs/FirstChargeConfig.cs.meta
copy from Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA02_tagMCFirstGoldInfo.cs.meta copy to Main/Config/PartialConfigs/FirstChargeConfig.cs.meta
File was copied from Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA02_tagMCFirstGoldInfo.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 56da7e3109f052e46860b1ed27323ab4
guid: ca3bcf278fca3e84da1115d44c2a6067
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA02_tagMCFirstGoldInfo.cs
File was deleted
Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA02_tagSCFirstChargeInfo.cs
New file
@@ -0,0 +1,13 @@
using UnityEngine;
using System.Collections;
// AA 02 首充信息 #tagSCFirstChargeInfo
public class DTCAA02_tagSCFirstChargeInfo : DtcBasic {
    public override void Done(GameNetPackBasic vNetPack)
    {
        base.Done(vNetPack);
        HAA02_tagSCFirstChargeInfo vNetData = vNetPack as HAA02_tagSCFirstChargeInfo;
        FirstChargeManager.Instance.UpdateFirstChargeInfo(vNetData);
    }
}
Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA02_tagSCFirstChargeInfo.cs.meta
copy from Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA02_tagMCFirstGoldInfo.cs.meta copy to Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA02_tagSCFirstChargeInfo.cs.meta
File was copied from Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA02_tagMCFirstGoldInfo.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 56da7e3109f052e46860b1ed27323ab4
guid: 3d6b7a163391b194397c23e92c7b5114
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
Main/Core/NetworkPackage/DataToCtl/PackageRegedit.cs
@@ -54,7 +54,7 @@
        Register(typeof(HA3A1_tagMCModuleFightPowerInfo), typeof(DTCA3A1_tagMCModuleFightPowerInfo));
        Register(typeof(HA110_tagMCCoinToGoldCountInfo), typeof(DTCA110_tagMCCoinToGoldCountInfo));
        Register(typeof(HA008_tagGCPlayerRecInfo), typeof(DTCA008_tagGCPlayerRecInfo));
        Register(typeof(HAA02_tagMCFirstGoldInfo), typeof(DTCAA02_tagMCFirstGoldInfo));
        Register(typeof(HAA02_tagSCFirstChargeInfo), typeof(DTCAA02_tagSCFirstChargeInfo));
        Register(typeof(HAA03_tagMCDailyPackBuyGiftInfo), typeof(DTCAA03_tagMCDailyPackBuyGiftInfo));
        Register(typeof(HA302_tagMCFuncOpenStateList), typeof(DTCA302_tagMCFuncOpenStateList));
        Register(typeof(HA320_tagMCPlayerFBInfoData), typeof(DTCA320_tagMCPlayerFBInfoData));
Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA02_tagSCFirstChargeInfo.cs
New file
@@ -0,0 +1,31 @@
using UnityEngine;
using System.Collections;
// AA 02 首充信息 #tagSCFirstChargeInfo
public class HAA02_tagSCFirstChargeInfo : GameNetPackBasic {
    public byte Count;
    public  tagSCFirstCharge[] FirstChargeList;
    public HAA02_tagSCFirstChargeInfo () {
        _cmd = (ushort)0xAA02;
    }
    public override void ReadFromBytes (byte[] vBytes) {
        TransBytes (out Count, vBytes, NetDataType.BYTE);
        FirstChargeList = new tagSCFirstCharge[Count];
        for (int i = 0; i < Count; i ++) {
            FirstChargeList[i] = new tagSCFirstCharge();
            TransBytes (out FirstChargeList[i].FirstID, vBytes, NetDataType.BYTE);
            TransBytes (out FirstChargeList[i].ChargeTime, vBytes, NetDataType.DWORD);
            TransBytes (out FirstChargeList[i].AwardRecord, vBytes, NetDataType.WORD);
        }
    }
    public class tagSCFirstCharge {
        public byte FirstID;        //首充ID
        public uint ChargeTime;        //充值该首充的时间戳
        public ushort AwardRecord;        //首充奖励领奖记录,按二进制位记录首充第X天是否已领取
    }
}
Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA02_tagSCFirstChargeInfo.cs.meta
copy from Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA02_tagMCFirstGoldInfo.cs.meta copy to Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA02_tagSCFirstChargeInfo.cs.meta
File was copied from Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA02_tagMCFirstGoldInfo.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 56da7e3109f052e46860b1ed27323ab4
guid: 08d11e1da03650e48a3721f84f7b8d9f
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
Main/Main.cs
@@ -82,6 +82,7 @@
        managers.Add(BattleSettlementManager.Instance);
        managers.Add(GoldRushManager.Instance);
        managers.Add(MailManager.Instance);
        managers.Add(FirstChargeManager.Instance);
        
        foreach (var manager in managers)
        {
Main/System/Equip/EquipTipWin.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;
@@ -26,18 +27,46 @@
    [SerializeField] RectTransform bgRect;
    ItemModel equip;
    ItemConfig customEquipItemConfig;
    AppointItemConfig customEquipAppointItemConfig;
    protected override void OnPreOpen()
    {
        equip = PackManager.Instance.GetItemByGuid(ItemTipUtility.mainTipData.guid);
        Display(equip);
        bool isShowCustomEquip = ItemTipUtility.isShowCustomEquip;
        if (isShowCustomEquip)
        {
            int customEquipItemId = ItemTipUtility.customEquipItemId;
            int customEquipAppointItemId = ItemTipUtility.customEquipAppointItemId;
            if (!ItemConfig.HasKey(customEquipItemId))
                return;
            if (!AppointItemConfig.HasKey(customEquipAppointItemId))
                return;
            customEquipItemConfig = ItemConfig.Get(customEquipItemId);
            customEquipAppointItemConfig = AppointItemConfig.Get(customEquipAppointItemId);
            Display(customEquipItemConfig, customEquipAppointItemConfig);
        }
        else
        {
            equip = PackManager.Instance.GetItemByGuid(ItemTipUtility.mainTipData.guid);
            Display(equip);
        }
    }
    protected override void OnOpen()
    {
        //先缩小,这样不会因为间隔帧产生明显的闪烁
        uieffect.transform.localScale = Vector3.zero;
        //特效显示依赖rect的排版,放在下一帧
        RefreshEffect(equip).Forget();
        bool isShowCustomEquip = ItemTipUtility.isShowCustomEquip;
        if (isShowCustomEquip)
        {
            RefreshEffect(customEquipItemConfig).Forget();
        }
        else
        {
            //特效显示依赖rect的排版,放在下一帧
            RefreshEffect(equip).Forget();
        }
    }
    protected override void OnPreClose()
@@ -101,9 +130,64 @@
    }
    public void Display(ItemConfig itemConfig, AppointItemConfig appointItemConfig)
    {
        equipImage.SetOrgSprite(itemConfig.IconKey);
        itemName.text = UIHelper.AppendColor(itemConfig.ItemColor, itemConfig.ItemName, true, 1);
        itemNameOutline.OutlineColor = UIHelper.GetUIOutlineColor(itemConfig.ItemColor);
        qualityName.text = UIHelper.GetQualityNameWithColor(itemConfig.ItemColor, Language.Get("equipQualityFormat"));
        qualityNameOutline.OutlineColor = UIHelper.GetUIOutlineColor(itemConfig.ItemColor);
        placeName.text = EquipModel.Instance.GetEquipPlaceName(itemConfig.EquipPlace);
        lvText.text = Language.Get("EquipExchangeWin7", appointItemConfig.ItemLV);
        bgFlower.color = UIHelper.GetUIColor(itemConfig.ItemColor);
        var baseAttrs = appointItemConfig.BaseAttrID.ToList();
        var baseValues = appointItemConfig.BaseAttrValue.ToList();
        var fightAttrs = appointItemConfig.LegendAttrID.ToList();
        var fightValues = appointItemConfig.LegendAttrValue.ToList();
        for (var i = 0; i < baseAttrNames.Count; i++)
        {
            if (i >= baseAttrs.Count)
            {
                baseAttrNames[i].text = "";
                baseAttrValues[i].text = "";
            }
            else
            {
                baseAttrNames[i].text = PlayerPropertyConfig.Get(baseAttrs[i]).Name;
                baseAttrValues[i].text = PlayerPropertyConfig.GetValueDescription(baseAttrs[i], baseValues[i]);
            }
        }
        if (fightAttrs.IsNullOrEmpty())
        {
            fightAttrGameObj.SetActive(false);
        }
        else
        {
            fightAttrGameObj.SetActive(true);
            for (var i = 0; i < fightAttrNames.Count; i++)
            {
                if (i >= fightAttrs.Count)
                {
                    fightAttrNames[i].SetActive(false);
                }
                else
                {
                    fightAttrNames[i].SetActive(true);
                    fightAttrNames[i].text = PlayerPropertyConfig.Get(fightAttrs[i]).Name;
                    fightAttrValues[i].text = PlayerPropertyConfig.GetValueDescription(fightAttrs[i], fightValues[i]);
                }
            }
        }
    }
    //延迟处理特效大小
    async UniTask RefreshEffect(ItemModel equip)
    {
    {
        await UniTask.DelayFrame(3);
        int effectID = EquipModel.Instance.equipUIEffects[Math.Min(equip.config.ItemColor, EquipModel.Instance.equipUIEffects.Length) - 1];
        if (effectID == 0)
@@ -119,6 +203,24 @@
        }
    }
    //延迟处理特效大小
    async UniTask RefreshEffect(ItemConfig itemConfig)
    {
        await UniTask.DelayFrame(3);
        int effectID = EquipModel.Instance.equipUIEffects[Math.Min(itemConfig.ItemColor, EquipModel.Instance.equipUIEffects.Length) - 1];
        if (effectID == 0)
        {
            uieffect.Stop();
        }
        else
        {
            uieffect.effectId = effectID;
            //计算高度缩放比例 特效显示依赖rect的排版
            uieffect.transform.localScale = new Vector3(0.98f, bgRect.rect.height / uieffect.GetComponent<RectTransform>().rect.height, 1);
            uieffect.Play();
        }
    }
}
Main/System/FirstCharge.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3a4c2bde079b6004a842bd139495b341
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/FirstCharge/FirstChargeDayAward.cs
New file
@@ -0,0 +1,224 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 首充每日奖励显示组件
/// 负责显示首充活动每天的奖励内容和领取状态
/// </summary>
public class FirstChargeDayAward : MonoBehaviour
{
    [SerializeField] ImageEx imgCanHaveBG;          // 可领取背景高亮显示
    [SerializeField] ImageEx imgDay;                // 天数图片
    [SerializeField] TextEx txtDay;                 // 天数文本
    [SerializeField] Transform transCount4;         // 4个奖励物品的容器
    [SerializeField] Transform transCount3;         // 3个奖励物品的容器
    [SerializeField] Transform transCount2;         // 2个奖励物品的容器
    [SerializeField] Transform transCount1;         // 1个奖励物品的容器
    // 各数量级奖励物品显示单元
    [SerializeField] List<ItemCell> itemCellCount4 = new List<ItemCell>();
    [SerializeField] List<ItemCell> itemCellCount3 = new List<ItemCell>();
    [SerializeField] List<ItemCell> itemCellCount2 = new List<ItemCell>();
    [SerializeField] ItemCell itemCellCount1 = new ItemCell();
    // 奖励已领取遮罩图片
    [SerializeField] List<ImageEx> imgHaveCount4 = new List<ImageEx>();
    [SerializeField] List<ImageEx> imgHaveCount3 = new List<ImageEx>();
    [SerializeField] List<ImageEx> imgHaveCount2 = new List<ImageEx>();
    [SerializeField] ImageEx imgHaveCount1 = new ImageEx();
    /// <summary>
    /// 显示指定首充ID和天数的奖励信息
    /// </summary>
    /// <param name="firstId">首充配置ID</param>
    /// <param name="day">第几天(1-3)</param>
    public void Display(int firstId, int day)
    {
        // 获取首充数据
        if (!FirstChargeManager.Instance.TryGetFirstChargeDataByFirstId(firstId, out var firstChargeData))
            return;
        // 获取奖励状态: 0-已领取, 1-不可领取, 2-可领取, 3-未知状态
        int awardState = firstChargeData.GetHaveState(day);
        // 根据状态设置UI显示
        imgCanHaveBG.SetActive(firstChargeData.IsBuy() && awardState == 2);
        txtDay.text = awardState == 0 ? Language.Get("L1129_2") : Language.Get("FirstCharge02", day);
        imgDay.gray = awardState == 0;  // 已领取则置灰天数图标
        // 隐藏所有奖励物品容器
        transCount4.SetActive(false);
        transCount3.SetActive(false);
        transCount2.SetActive(false);
        transCount1.SetActive(false);
        // 检查配置是否存在
        if (!FirstChargeConfig.HasKey(firstId))
            return;
        FirstChargeConfig config = FirstChargeConfig.Get(firstId);
        int[][] awardList = GetAwardListByDay(config, day);
        // 检查奖励列表有效性
        if (awardList == null || awardList.Length <= 0)
        {
            Debug.LogError($"首充表第{day}天奖励没配");
            return;
        }
        if (awardList.Length > 4)
        {
            Debug.LogError($"首充表奖励物品不支持配大于4个");
            return;
        }
        // 根据奖励数量显示对应的UI
        switch (awardList.Length)
        {
            case 1:
                ShowAwardsForCount1(awardList, awardState, firstId);
                break;
            case 2:
                ShowAwardsForCount2(awardList, awardState);
                break;
            case 3:
                ShowAwardsForCount3(awardList, awardState);
                break;
            case 4:
                ShowAwardsForCount4(awardList, awardState);
                break;
        }
    }
    /// <summary>
    /// 根据天数获取对应的奖励列表
    /// </summary>
    /// <param name="config">首充配置</param>
    /// <param name="day">天数</param>
    /// <returns>奖励列表</returns>
    private int[][] GetAwardListByDay(FirstChargeConfig config, int day)
    {
        switch (day)
        {
            case 1:
                return config.AwardListDay1;
            case 2:
                return config.AwardListDay2;
            case 3:
                return config.AwardListDay3;
            default:
                Debug.LogError("FirstChargeItemCellShow传入天数大于3或小于0");
                return null;
        }
    }
    /// <summary>
    /// 显示单个奖励物品
    /// </summary>
    /// <param name="awardList">奖励列表</param>
    /// <param name="awardState">奖励状态</param>
    /// <param name="firstId">首充ID</param>
    private void ShowAwardsForCount1(int[][] awardList, int awardState, int firstId)
    {
        transCount1.SetActive(true);
        itemCellCount1.Init(new ItemCellModel((int)awardList[0][0], true, awardList[0][1]));
        itemCellCount1.button.SetListener(() => HandleItemClick((int)awardList[0][0], awardList[0][2]));
        imgHaveCount1.SetActive(awardState == 0);
    }
    /// <summary>
    /// 显示两个奖励物品
    /// </summary>
    /// <param name="awardList">奖励列表</param>
    /// <param name="awardState">奖励状态</param>
    private void ShowAwardsForCount2(int[][] awardList, int awardState)
    {
        transCount2.SetActive(true);
        ShowAwardsCommonLogic(awardList, awardState, itemCellCount2, imgHaveCount2);
    }
    /// <summary>
    /// 显示三个奖励物品
    /// </summary>
    /// <param name="awardList">奖励列表</param>
    /// <param name="awardState">奖励状态</param>
    private void ShowAwardsForCount3(int[][] awardList, int awardState)
    {
        transCount3.SetActive(true);
        ShowAwardsCommonLogic(awardList, awardState, itemCellCount3, imgHaveCount3);
    }
    /// <summary>
    /// 显示四个奖励物品
    /// </summary>
    /// <param name="awardList">奖励列表</param>
    /// <param name="awardState">奖励状态</param>
    private void ShowAwardsForCount4(int[][] awardList, int awardState)
    {
        transCount4.SetActive(true);
        ShowAwardsCommonLogic(awardList, awardState, itemCellCount4, imgHaveCount4);
    }
    /// <summary>
    /// 统一处理物品点击事件
    /// </summary>
    /// <param name="itemId">物品ID</param>
    private void HandleItemClick(int itemId, int customEquipId)
    {
        if (!ItemConfig.HasKey(itemId))
            return;
        if (ItemConfig.Get(itemId).Type == 150)
        {
            FirstChargeManager.Instance.heroItemID = itemId;
            UIManager.Instance.OpenWindow<FirstChargeHeroInfoWin>();
        }
        else if (ItemConfig.Get(itemId).Type >= 101 &&
                ItemConfig.Get(itemId).Type <= 117 &&
                customEquipId > 0 &&
                AppointItemConfig.HasKey(customEquipId))
        {
            ItemTipUtility.ShowCustomEquip(itemId, customEquipId);
        }
        else
        {
            ItemTipUtility.Show(itemId, true);
        }
    }
    /// <summary>
    /// 通用奖励显示逻辑
    /// </summary>
    /// <param name="awardList">奖励列表</param>
    /// <param name="awardState">奖励状态</param>
    /// <param name="itemCells">物品显示单元列表</param>
    /// <param name="haveImages">已领取遮罩图片列表</param>
    private void ShowAwardsCommonLogic<T>(int[][] awardList, int awardState, List<T> itemCells, List<ImageEx> haveImages) where T : ItemCell
    {
        for (int i = 0; i < awardList.Length; i++)
        {
            // 设置物品显示
            if (i < itemCells.Count)
            {
                int index = i; // Lambda表达式中使用,需要创建局部副本
                itemCells[i].SetActive(true);
                itemCells[i].Init(new ItemCellModel((int)awardList[i][0], true, awardList[i][1]));
                itemCells[i].button.SetListener(() => HandleItemClick((int)awardList[index][0], awardList[index][2]));
            }
            else
            {
                itemCells[i].SetActive(false);
            }
            // 设置已领取遮罩
            if (awardState == 0 && i < haveImages.Count)
            {
                haveImages[i].SetActive(true);
            }
            else if (i < haveImages.Count)
            {
                haveImages[i].SetActive(false);
            }
        }
    }
}
Main/System/FirstCharge/FirstChargeDayAward.cs.meta
copy from Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA02_tagMCFirstGoldInfo.cs.meta copy to Main/System/FirstCharge/FirstChargeDayAward.cs.meta
File was copied from Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA02_tagMCFirstGoldInfo.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 56da7e3109f052e46860b1ed27323ab4
guid: c0aadae3ee9951048aef2bd511ce3d0d
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
Main/System/FirstCharge/FirstChargeHeroInfoWin.cs
New file
@@ -0,0 +1,75 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FirstChargeHeroInfoWin : UIBase
{
    [SerializeField] ItemCell itemCell;
    [SerializeField] TextEx txtName;
    [SerializeField] TextEx txtJob;
    [SerializeField] TextEx txtDesc;
    [SerializeField] RichText txtInherit;   //武将继承描述
    [SerializeField] TextEx[] txtInheritAttr;    //武将会继承的属性
    [SerializeField] RichText txtHeroAddPer; //主公(上阵)加成描述
    [SerializeField] TextEx[] txtHeroAddAttrPer; //主公(上阵)加成
    [SerializeField] SkillBaseCell normalSkillCell;
    [SerializeField] SkillBaseCell angerSkillCell;
    protected override void InitComponent()
    {
        base.InitComponent();
        txtInherit.OnClick = () =>
        {
            SmallTipWin.showText = Language.Get("herocard47");
            SmallTipWin.worldPos = CameraManager.uiCamera.ScreenToWorldPoint(Input.mousePosition);
            UIManager.Instance.OpenWindow<SmallTipWin>();
        };
        txtHeroAddPer.OnClick = () =>
        {
            SmallTipWin.showText = Language.Get("herocard48");
            SmallTipWin.worldPos = CameraManager.uiCamera.ScreenToWorldPoint(Input.mousePosition);
            UIManager.Instance.OpenWindow<SmallTipWin>();
        };
    }
    protected override void OnPreOpen()
    {
        base.OnPreOpen();
        ItemInfo itemInfo = new ItemInfo();
        itemInfo.itemId = FirstChargeManager.Instance.heroItemID;
        HeroInfo heroInfo = new HeroInfo(new ItemModel(PackType.Item, itemInfo));
        txtInheritAttr[0].text = PlayerPropertyConfig.GetFullDescription(new Int2(PlayerPropertyConfig.inheritAttrs[0], heroInfo.heroConfig.AtkInheritPer));
        txtInheritAttr[1].text = PlayerPropertyConfig.GetFullDescription(new Int2(PlayerPropertyConfig.inheritAttrs[1], heroInfo.heroConfig.DefInheritPer));
        txtInheritAttr[2].text = PlayerPropertyConfig.GetFullDescription(new Int2(PlayerPropertyConfig.inheritAttrs[2], heroInfo.heroConfig.HPInheritPer));
        int valuePer = heroInfo.GetOnBattleAddPer();
        for (int i = 0; i < txtHeroAddAttrPer.Length; i++)
        {
            txtHeroAddAttrPer[i].text = PlayerPropertyConfig.GetFullDescription(new Int2(PlayerPropertyConfig.basePerAttrs[i], valuePer));
        }
        normalSkillCell.Init(heroInfo.heroConfig.AtkSkillID, () =>
        {
            UIManager.Instance.OpenWindow<HeroSkillWin>(heroInfo.heroId);
        }, true);
        angerSkillCell.Init(heroInfo.heroConfig.AngerSkillID, () =>
        {
            UIManager.Instance.OpenWindow<HeroSkillWin>(heroInfo.heroId);
        }, true);
        itemCell.Init(new ItemCellModel((int)FirstChargeManager.Instance.heroItemID, true, 1));
        txtName.text = Language.Get("FirstCharge09", Language.Get("CommonQuality" + heroInfo.Quality),heroInfo.heroConfig.Name);
        txtName.color = UIHelper.GetUIColorByFunc(heroInfo.Quality);
        txtJob.text = Language.Get("FirstCharge06",Language.Get(StringUtility.Contact("HeroClass",heroInfo.heroConfig.Class)));
        txtDesc.text = Language.Get("FirstCharge07",heroInfo.heroConfig.Desc);
    }
    protected override void OnPreClose()
    {
        base.OnPreClose();
    }
}
Main/System/FirstCharge/FirstChargeHeroInfoWin.cs.meta
copy from Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA02_tagMCFirstGoldInfo.cs.meta copy to Main/System/FirstCharge/FirstChargeHeroInfoWin.cs.meta
File was copied from Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA02_tagMCFirstGoldInfo.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 56da7e3109f052e46860b1ed27323ab4
guid: b00cabe8422fffb4abb93695a3aeacf0
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
Main/System/FirstCharge/FirstChargeManager.cs
New file
@@ -0,0 +1,522 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class FirstChargeManager : GameSystemManager<FirstChargeManager>
{
    public const int FuncID = 110;
    public int mainItemId { get { return GetMainItemId(); } }
    public int heroItemID;
    public int maxGiftCount
    {
        get
        {
            var list = FirstChargeConfig.GetKeys();
            return list.IsNullOrEmpty() ? 0 : list.Count;
        }
    }
    public int maxDay = 3;
    public Redpoint parentRedpoint = new Redpoint(MainRedDot.FirstChargeRepoint);
    public Dictionary<int, Redpoint> tabRedpointDict = new Dictionary<int, Redpoint>();
    public Dictionary<int, bool> clickTabDict = new Dictionary<int, bool>();
    public Dictionary<int, FirstChargeData> firstChargeInfoDict = new Dictionary<int, FirstChargeData>();
    public event Action OnUpdateFirstChargeInfo;
    public override void Init()
    {
        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent += OnBeforePlayerDataInitializeEvent;
        DTC0403_tagPlayerLoginLoadOK.playerLoginOkEvent += OnPlayerLoginOk;
        RechargeManager.Instance.rechargeCountEvent += OnRechargeCountEvent;
        FuncOpen.Instance.OnFuncStateChangeEvent += OnFuncStateChangeEvent;
    }
    public override void Release()
    {
        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent -= OnBeforePlayerDataInitializeEvent;
        DTC0403_tagPlayerLoginLoadOK.playerLoginOkEvent -= OnPlayerLoginOk;
        RechargeManager.Instance.rechargeCountEvent -= OnRechargeCountEvent;
        FuncOpen.Instance.OnFuncStateChangeEvent -= OnFuncStateChangeEvent;
    }
    private void OnFuncStateChangeEvent(int obj)
    {
        if (FuncID == obj)
        {
            string key = $"FirstCharge_FirstTime_{FuncID}_{PlayerDatas.Instance.baseData.PlayerID}";
            if (!LocalSave.HasKey(key))
            {
                // 第一次开启功能
                LocalSave.SetBool(key, true);
                PopupWindowsProcessor.Instance.Add("FirstChargeWin");
            }
        }
    }
    public void InitClickTabDict()
    {
        var list = FirstChargeConfig.GetKeys();
        if (!list.IsNullOrEmpty())
        {
            for (int i = 0; i < list.Count; i++)
            {
                int firstId = list[i];
                clickTabDict[firstId] = false;
            }
        }
    }
    public bool GetClickTabState(int fristId)
    {
        return clickTabDict.ContainsKey(fristId) && clickTabDict[fristId];
    }
    public void SetClickTabState(int fristId)
    {
        clickTabDict[fristId] = true;
        UpdateRedPoint();
    }
    public void InitRedPoint()
    {
        var list = FirstChargeConfig.GetKeys();
        if (!list.IsNullOrEmpty())
        {
            for (int i = 0; i < list.Count; i++)
            {
                int firstId = list[i];
                int redpointId = GetRedpointIdByFirstId(firstId);
                tabRedpointDict[firstId] = new Redpoint(MainRedDot.FirstChargeRepoint, redpointId);
            }
        }
    }
    public int GetRedpointIdByFirstId(int firstId)
    {
        return MainRedDot.FirstChargeRepoint * 10000 + firstId;
    }
    private void OnRechargeCountEvent(int obj)
    {
        var list = FirstChargeConfig.GetCtgIDList();
        if (!list.IsNullOrEmpty() && list.Contains(obj))
        {
            UpdateRedPoint();
        }
    }
    public void OnBeforePlayerDataInitializeEvent()
    {
        firstChargeInfoDict.Clear();
    }
    public void OnPlayerLoginOk()
    {
        InitClickTabDict();
        InitRedPoint();
        if (FuncOpen.Instance.IsFuncOpen(FuncID)&& TryGetUnBuyFirstId(out int firstId))
        {
            PopupWindowsProcessor.Instance.Add("FirstChargeWin");
        }
    }
    public bool TryGetFirstChargeDataByFirstId(int firstId, out FirstChargeData firstChargeData)
    {
        return firstChargeInfoDict.TryGetValue(firstId, out firstChargeData);
    }
    public bool TryGetUnBuyFirstId(out int firstId)
    {
        firstId = 0;
        var firstChargeList = FirstChargeConfig.GetKeys();
        if (firstChargeList != null)
        {
            firstChargeList.Sort();
            foreach (int item in firstChargeList)
            {
                if (TryGetFirstChargeDataByFirstId(item, out FirstChargeData data))
                {
                    if (data.IsUnlock() && !data.IsBuy())
                    {
                        firstId = item;
                        return true;
                    }
                }
            }
        }
        return false;
    }
    /// <summary>
    /// 根据标签页索引获取对应的首充ID
    /// </summary>
    /// <param name="tabIndex">标签页索引,从0开始</param>
    /// <returns>对应的首充ID,从1开始</returns>
    public int GetFirstIDByTabIndex(int tabIndex)
    {
        return tabIndex + 1;
    }
    /// <summary>
    /// 根据首充ID获取对应的标签页索引
    /// </summary>
    /// <param name="firstId">首充ID,从1开始</param>
    /// <returns>对应的标签页索引,从0开始</returns>
    public int GetTabIndexByFirstID(int firstId)
    {
        return Math.Max(firstId - 1, 0);
    }
    public int GetLastFirstIDByTabIndex(int tabIndex)
    {
        return GetFirstIDByTabIndex(tabIndex == 0 ? tabIndex : tabIndex - 1);
    }
    public int GetNextFirstIDByTabIndex(int tabIndex)
    {
        return GetFirstIDByTabIndex(tabIndex >= maxGiftCount - 1 ? maxGiftCount - 1 : tabIndex + 1);
    }
    public int GetLastFirstIDByFirstID(int firstId)
    {
        int tabIndex = GetTabIndexByFirstID(firstId);
        return GetLastFirstIDByTabIndex(tabIndex);
    }
    public int GetNextFirstIDByFirstID(int firstId)
    {
        int tabIndex = GetTabIndexByFirstID(firstId);
        return GetNextFirstIDByTabIndex(tabIndex);
    }
    public bool TryGetFirstChargeConfigByFirstID(int firstId, out FirstChargeConfig firstChargeConfig)
    {
        firstChargeConfig = null;
        if (!FirstChargeConfig.HasKey(firstId))
            return false;
        firstChargeConfig = FirstChargeConfig.Get(firstId);
        return true;
    }
    public bool TryGetOrderInfoConfigByFirstID(int firstId, out OrderInfoConfig orderInfoConfig)
    {
        orderInfoConfig = null;
        if (!TryGetFirstChargeConfigByFirstID(firstId, out FirstChargeConfig firstChargeConfig))
            return false;
        int ctgId = firstChargeConfig.CTGID;
        return RechargeManager.Instance.TryGetOrderInfo(ctgId, out orderInfoConfig);
    }
    public bool TryGetCTGConfigByFirstID(int firstId, out CTGConfig ctgConfig)
    {
        ctgConfig = null;
        if (!TryGetFirstChargeConfigByFirstID(firstId, out FirstChargeConfig firstChargeConfig))
            return false;
        int ctgId = firstChargeConfig.CTGID;
        if (!CTGConfig.HasKey(ctgId))
            return false;
        ctgConfig = CTGConfig.Get(ctgId);
        return true;
    }
    public int GetMainItemId()
    {
        var list = FirstChargeConfig.GetKeys();
        list.Sort();
        var config = FirstChargeConfig.Get(list[0]);
        for (int i = 0; i < config.AwardListDay1.Length; i++)
        {
            int itemId = config.AwardListDay1[i][0];
            if (!ItemConfig.HasKey(itemId))
                continue;
            if (ItemConfig.Get(itemId).Type == 150)
            {
                return itemId;
            }
        }
        return 0;
    }
    public void UpdateFirstChargeInfo(HAA02_tagSCFirstChargeInfo vNetData)
    {
        if (vNetData.FirstChargeList.IsNullOrEmpty())
            return;
        foreach (var chargeInfo in vNetData.FirstChargeList)
        {
            int firstID = chargeInfo.FirstID;
            if (!firstChargeInfoDict.TryGetValue(firstID, out var firstChargeData))
            {
                firstChargeData = new FirstChargeData();
                firstChargeInfoDict[firstID] = firstChargeData;
            }
            firstChargeData.FirstID = firstID;
            firstChargeData.ChargeTime = chargeInfo.ChargeTime;
            firstChargeData.AwardRecord = chargeInfo.AwardRecord;
        }
        // 检查是否所有奖励都已领取,如果是,则记录当前服务器时间到本地
        CheckAndSaveAllRewardsClaimedTime();
        UpdateRedPoint();
        OnUpdateFirstChargeInfo?.Invoke();
    }
    /// <summary>
    /// 检查是否所有首充奖励都已领取,如果是,则将当前服务器时间保存到本地
    /// </summary>
    private void CheckAndSaveAllRewardsClaimedTime()
    {
        // 检查是否所有奖励都已领取
        if (IsAllFirstChargeRewardsClaimed())
        {
            // 生成一个唯一的键来存储时间
            string key = $"FirstCharge_AllRewardsClaimed_Time_{PlayerDatas.Instance.baseData.PlayerID}";
            // 将当前服务器时间保存到本地
            LocalSave.SetString(key, TimeUtility.ServerNow.Ticks.ToString());
        }
    }
    public void UpdateRedPoint()
    {
        // 重置所有红点状态
        parentRedpoint.state = RedPointState.None;
        foreach (var redpoint in tabRedpointDict.Values)
        {
            redpoint.state = RedPointState.None;
        }
        var firstChargeList = FirstChargeConfig.GetKeys();
        if (firstChargeList.IsNullOrEmpty())
            return;
        firstChargeList.Sort();
        foreach (int firstId in firstChargeList)
        {
            if (!tabRedpointDict.ContainsKey(firstId))
                continue;
            var redpoint = tabRedpointDict[firstId];
            if (TryGetFirstChargeDataByFirstId(firstId, out var firstChargeData))
            {
                if (firstChargeData.IsBuy())
                {
                    for (int day = 1; day <= maxDay; day++)
                    {
                        int awardState = firstChargeData.GetHaveState(day);
                        // 2: 可领取
                        if (awardState == 2)
                        {
                            redpoint.state = RedPointState.Simple;
                            break;
                        }
                    }
                }
                else
                {
                    bool clickTabState = GetClickTabState(firstId);
                    if (firstChargeData.IsUnlock() && !clickTabState)
                    {
                        redpoint.state = RedPointState.Simple;
                    }
                }
            }
        }
    }
    /// <summary>
    /// 发送领取首充奖励请求
    /// </summary>
    /// <param name="day">要领取的奖励是第x天的, 从1开始</param>
    /// <param name="firstID">首充表的ID</param>
    public void SendGetReward(int day, int firstID)
    {
        var pack = new CA504_tagCMPlayerGetReward();
        pack.RewardType = 8;
        pack.DataEx = (uint)day;//第x天,1代表第1天
        string firstIdStr = firstID.ToString();//领取哪个首充ID,对应首充表的ID
        pack.DataExStr = firstIdStr;
        pack.DataExStrLen = (byte)firstIdStr.Length;
        GameNetSystem.Instance.SendInfo(pack);
    }
    /// <summary>
    /// 自动领取玩家可以领取的所有首充奖励
    /// </summary>
    /// <param name="firstID">首充表的ID</param>
    public void AutoClaimAllRewards(int firstID)
    {
        if (!TryGetFirstChargeDataByFirstId(firstID, out var firstChargeData))
            return;
        if (!firstChargeData.IsBuy())
            return;
        // 获取当前是购买后的第几天
        int currentDay = firstChargeData.GetNowBuyDay();
        // 遍历从第1天到当前天数的所有奖励
        for (int day = 1; day <= maxDay; day++)
        {
            // 检查奖励状态,只有状态为已购买没领取才发送领取请求
            if (day <= currentDay && firstChargeData.GetHaveState(day) == 2)//0: 已领取 1: 不可领取 2: 可领取
            {
                SendGetReward(day, firstID);
            }
        }
    }
    // 检查是否所有首充奖励都已经领取
    public bool IsAllFirstChargeRewardsClaimed()
    {
        // 获取所有首充配置ID
        var firstChargeIds = FirstChargeConfig.GetKeys();
        if (firstChargeIds == null || firstChargeIds.Count == 0)
            return false;
        foreach (var firstId in firstChargeIds)
        {
            // 尝试获取首充数据
            if (!TryGetFirstChargeDataByFirstId(firstId, out var firstChargeData))
                return false;
            // 检查是否购买
            if (!firstChargeData.IsBuy())
                return false;
            // 检查是否所有奖励都已领取
            if (!firstChargeData.IsAllHave())
                return false;
        }
        // 所有首充档位都已购买且所有奖励都已领取
        // 检查是否已经过了第二天0点
        return true;
    }
    // 检查是否已经过了所有奖励领取完毕后的第二天0点
    public bool IsNextDayAfterAllClaimed()
    {
        // 生成一个唯一的键来获取时间
        string key = $"FirstCharge_AllRewardsClaimed_Time_{PlayerDatas.Instance.baseData.PlayerID}";
        // 检查是否存在记录的时间戳
        if (!LocalSave.HasKey(key))
            return false;
        // 获取记录的时间戳
        string timeString = LocalSave.GetString(key);
        if (string.IsNullOrEmpty(timeString))
            return false;
        // 解析时间戳
        if (!long.TryParse(timeString, out long ticks))
            return false;
        // 将时间戳转换为DateTime
        DateTime allRewardsClaimedTime = new DateTime(ticks);
        // 计算第二天0点的时间
        DateTime nextDayStart = allRewardsClaimedTime.Date.AddDays(1);
        // 判断当前服务器时间是否已经过了第二天0点
        DateTime serverNow = TimeUtility.ServerNow;
        return serverNow >= nextDayStart;
    }
}
public class FirstChargeData
{
    public int FirstID;        //首充ID
    public uint ChargeTime;        //充值该首充的时间戳
    public ushort AwardRecord;        //首充奖励领奖记录,按二进制位记录首充第X天是否已领取(第1天对应第1位)
    public bool IsUnlock()
    {
        int tabIndex = FirstChargeManager.Instance.GetTabIndexByFirstID(FirstID);
        if (tabIndex == 0)
            return true;
        int lastFirstID = FirstChargeManager.Instance.GetLastFirstIDByTabIndex(tabIndex);
        FirstChargeData firstChargeDataNow;
        if (!FirstChargeManager.Instance.TryGetFirstChargeDataByFirstId(lastFirstID, out firstChargeDataNow))
            return false;
        return firstChargeDataNow.IsBuy();
    }
    public bool IsBuy()
    {
        return ChargeTime > 0;
    }
    /// <summary>
    /// 检查指定天的奖励是否已领取
    /// </summary>
    /// <param name="day">天数,从1开始</param>
    public bool IsHave(int day)
    {
        bool res = (AwardRecord & (1 << day)) != 0;
        return res;
    }
    public bool IsAllHave()
    {
        int maxGiftCount = FirstChargeManager.Instance.maxGiftCount;
        for (int i = 1; i <= maxGiftCount; i++)
        {
            if (!IsHave(i))
                return false;
        }
        return true;
    }
   // ... existing code ...
    /// <summary>
    /// 获取当前时间是购买这档充值礼包的第几天
    /// 购买的当天算作第一天,第二天0点后算第二天,以此类推
    /// </summary>
    /// <returns>第几天</returns>
    public int GetNowBuyDay()
    {
        DateTime serverNow = TimeUtility.ServerNow;
        DateTime chargeTime = TimeUtility.GetTime(ChargeTime);
        DateTime chargeDate = chargeTime.Date;
        DateTime serverDate = serverNow.Date;
        // 计算从充值日期到当前日期的完整天数
        // 购买的当天算第一天,第二天0点后算第二天
        TimeSpan timeSpan = serverDate - chargeDate;
        int days = (int)timeSpan.TotalDays + 1; // +1 因为当天算第一天
        int maxDay = FirstChargeManager.Instance.maxDay;
        return Mathf.Min(maxDay, Mathf.Max(1, days));
    }
    public bool HasNextDay()
    {
        int currentDay = GetNowBuyDay();
        int maxDay = FirstChargeManager.Instance.maxDay;
        return currentDay < maxDay;
    }
    /// <summary>
    /// 获得指定天的领取详细状态
    /// </summary>
    /// <param name="day">天数,从1开始</param>
    //0: 已领取 1: 不可领取 2: 可领取
    public int GetHaveState(int day)
    {
        if (IsHave(day))
            return 0;
        int currentDay = GetNowBuyDay();
        // 检查是否可以领取(购买这档充值礼包的第一天后才可领取)
        return day <= currentDay ? 2 : 1;
    }
    /// <summary>
    /// 返回显示距离第二天0点解锁奖励剩余时间
    /// </summary>
    /// <returns>剩余时间字符串,格式:小时:分钟:秒钟</returns>
    public string GetNextDayUnlockRemainingTime()
    {
        if (!IsBuy())
            return string.Empty;
        DateTime serverNow = TimeUtility.ServerNow;
        DateTime nextDayStart = serverNow.Date.AddDays(1);
        TimeSpan remainingTime = nextDayStart - serverNow;
        int remainingSeconds = (int)remainingTime.TotalSeconds;
        return TimeUtility.SecondsToHMS(remainingSeconds);
    }
}
Main/System/FirstCharge/FirstChargeManager.cs.meta
copy from Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA02_tagMCFirstGoldInfo.cs.meta copy to Main/System/FirstCharge/FirstChargeManager.cs.meta
File was copied from Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA02_tagMCFirstGoldInfo.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 56da7e3109f052e46860b1ed27323ab4
guid: b013edce05d6415418c0b0edbf55af71
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
Main/System/FirstCharge/FirstChargeWin.cs
New file
@@ -0,0 +1,308 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using UnityEngine;
public class FirstChargeWin : FunctionsBaseWin
{
    [Header("标签页")]
    [SerializeField] TextEx[] txtTabTitles;
    [SerializeField] ButtonEx[] btnTabs;
    [SerializeField] RedpointBehaviour[] rpTabs;
    [Header("主物品")]
    [SerializeField] TextEx txtName;
    [SerializeField] TextEx txtDesc;
    [SerializeField] ImageEx imgCountry;
    [SerializeField] ImageEx imgJob;
    [SerializeField] UIHeroController roleLhModel;    //展示英雄立绘
    [SerializeField] ButtonEx btnPreviewHero;
    [Header("额外道具宣传文字")]
    [SerializeField] ImageEx imgExtraRewardText;
    [SerializeField] TextEx txtExtraRewardText;
    [Header("奖励物品")]
    [SerializeField] FirstChargeDayAward[] days;
    [Header("性价比文字")]
    [SerializeField] TextEx txtPercentage;
    [Header("购买和领取")]
    [SerializeField] ImageEx imgHave;
    [SerializeField] ImageEx imgNoHave;
    [SerializeField] ImageEx imgRed;
    [SerializeField] TextEx txtHave;
    [SerializeField] ButtonEx btnHave;
    [SerializeField] TextEx txtBuy;
    [SerializeField] ButtonEx btnBuy;
    FirstChargeManager model { get { return FirstChargeManager.Instance; } }
    protected override void InitComponent()
    {
        base.InitComponent();
        btnHave.SetListener(OnClickHaveButton);
        btnBuy.SetListener(OnClickBuyButton);
        btnPreviewHero.SetListener(OnClickPreviewHero);
    }
    protected override void OnPreOpen()
    {
        base.OnPreOpen();
        InitRedPoint();
        functionOrder = GetDefaultTabIndex();
        tabButtons[functionOrder].SelectBtn(true);
        int firstId = model.GetFirstIDByTabIndex(functionOrder);
        model.SetClickTabState(firstId);
        model.OnUpdateFirstChargeInfo += OnUpdateFirstChargeInfo;
        GlobalTimeEvent.Instance.secondEvent += OnSecondEvent;
        DisplayMainItem();
        Display();
    }
    protected override void OnPreClose()
    {
        base.OnPreClose();
        model.OnUpdateFirstChargeInfo -= OnUpdateFirstChargeInfo;
        GlobalTimeEvent.Instance.secondEvent -= OnSecondEvent;
    }
    private void OnSecondEvent()
    {
        int firstId = model.GetFirstIDByTabIndex(functionOrder);
        if (!model.TryGetFirstChargeDataByFirstId(firstId, out var firstChargeData))
            return;
        if (!firstChargeData.IsUnlock())
            return;
        if (!firstChargeData.IsBuy())
            return;
        DisplayButton(firstId);
    }
    protected override void OpenSubUIByTabIndex()
    {
        int firstId = model.GetFirstIDByTabIndex(functionOrder);
        model.SetClickTabState(firstId);
        Display();
    }
    private void OnUpdateFirstChargeInfo()
    {
        Display();
    }
    private void OnClickBuyButton()
    {
        int firstId = model.GetFirstIDByTabIndex(functionOrder);
        if (!model.TryGetFirstChargeConfigByFirstID(firstId, out FirstChargeConfig firstChargeConfig))
            return;
        RechargeManager.Instance.CTG(firstChargeConfig.CTGID);
    }
    private void OnClickHaveButton()
    {
        int firstId = model.GetFirstIDByTabIndex(functionOrder);
        model.AutoClaimAllRewards(firstId);
    }
    private void OnClickPreviewHero()
    {
        HeroUIManager.Instance.selectForPreviewHeroID = model.mainItemId;
        UIManager.Instance.OpenWindow<HeroBestWin>();
    }
    private void InitRedPoint()
    {
        for (int i = 0; i < rpTabs.Length; i++)
        {
            int firstID = model.GetFirstIDByTabIndex(i);
            int redpointId = model.GetRedpointIdByFirstId(firstID);
            rpTabs[i].redpointId = redpointId;
        }
    }
    private int GetDefaultTabIndex()
    {
        List<int> unlockedAndBoughtAndClaimable = new List<int>();      // 已解锁已购买可领取
        List<int> unlockedAndNotBought = new List<int>();               // 已解锁未购买
        List<int> unlockedAndBoughtAndNotClaimed = new List<int>();     // 已解锁已购买未领取
        var firstChargeList = FirstChargeConfig.GetKeys();
        if (firstChargeList != null)
        {
            firstChargeList.Sort();
            foreach (int firstId in firstChargeList)
            {
                if (!model.TryGetFirstChargeDataByFirstId(firstId, out FirstChargeData firstChargeData))
                    continue;
                if (!firstChargeData.IsUnlock())
                    continue;
                if (firstChargeData.IsBuy())
                {
                    bool hasClaimable = false;
                    bool hasUnclaimed = false;
                    for (int day = 1; day <= model.maxDay; day++)
                    {
                        int awardState = firstChargeData.GetHaveState(day);
                        if (awardState == 2) // 可领取
                        {
                            hasClaimable = true;
                            break;
                        }
                        else if (awardState == 1) // 未到领取时间
                        {
                            hasUnclaimed = true;
                        }
                    }
                    if (hasClaimable)
                    {
                        unlockedAndBoughtAndClaimable.Add(firstId);
                    }
                    else if (hasUnclaimed)
                    {
                        unlockedAndBoughtAndNotClaimed.Add(firstId);
                    }
                }
                else
                {
                    // 未购买
                    unlockedAndNotBought.Add(firstId);
                }
            }
            // 按照优先级返回
            if (unlockedAndBoughtAndClaimable.Count > 0)
            {
                return model.GetTabIndexByFirstID(unlockedAndBoughtAndClaimable[0]);
            }
            else if (unlockedAndNotBought.Count > 0)
            {
                return model.GetTabIndexByFirstID(unlockedAndNotBought[0]);
            }
            else if (unlockedAndBoughtAndNotClaimed.Count > 0)
            {
                return model.GetTabIndexByFirstID(unlockedAndBoughtAndNotClaimed[0]);
            }
        }
        return 0;
    }
    private void Display()
    {
        int firstId = model.GetFirstIDByTabIndex(functionOrder);
        DisplayTab();
        DisplayExtraRewardText(firstId);
        DisplayAward(firstId);
        DisplayPercentage(firstId);
        DisplayButton(firstId);
    }
    public void DisplayMainItem()
    {
        ItemInfo itemInfo = new ItemInfo();
        itemInfo.itemId = FirstChargeManager.Instance.mainItemId;
        HeroInfo heroInfo = new HeroInfo(new ItemModel(PackType.Item, itemInfo));
        txtName.text = heroInfo.heroConfig.Name;
        txtName.color = UIHelper.GetUIColorByFunc(heroInfo.Quality);
        txtDesc.text = heroInfo.heroConfig.Desc;
        imgCountry.SetSprite(HeroUIManager.Instance.GetCountryIconName(heroInfo.heroConfig.Country));
        imgJob.SetSprite(HeroUIManager.Instance.GetJobIconName(heroInfo.heroConfig.Class));
        roleLhModel.Create(heroInfo.SkinID, 0.6f, motionName: "", isLh: true);
        roleLhModel.transform.localScale = new Vector3(0.6f, 0.6f, 0.6f);
    }
    public void DisplayAward(int firstId)
    {
        for (int i = 0; i < days.Length; i++)
        {
            days[i].Display(firstId, i + 1);
        }
    }
    public void DisplayExtraRewardText(int firstId)
    {
        if (!model.TryGetFirstChargeConfigByFirstID(firstId, out var config))
            return;
        int extraRewardTextType = config.ExtraRewardTextType;
        if (extraRewardTextType < 0 || extraRewardTextType > 1)
            return;
        if (extraRewardTextType == 0)
        {
            if (!IconConfig.HasKey(config.ExtraRewardTextInfo))
                return;
            imgExtraRewardText.SetActive(true);
            txtExtraRewardText.SetActive(false);
            imgExtraRewardText.SetSprite(config.ExtraRewardTextInfo);
        }
        else
        {
            if (!LanguageConfig.HasKey(config.ExtraRewardTextInfo))
                return;
            imgExtraRewardText.SetActive(false);
            txtExtraRewardText.SetActive(true);
            txtExtraRewardText.text = Language.Get(config.ExtraRewardTextInfo);
        }
    }
    public void DisplayTab()
    {
        for (int i = 0; i < btnTabs.Length; i++)
        {
            int firstID = model.GetFirstIDByTabIndex(i);
            FirstChargeData firstChargeData;
            if (!model.TryGetFirstChargeDataByFirstId(firstID, out firstChargeData))
                continue;
            btnTabs[i].SetActive(firstChargeData.IsUnlock());
            OrderInfoConfig orderInfoConfig;
            if (model.TryGetOrderInfoConfigByFirstID(firstID, out orderInfoConfig))
            {
                txtTabTitles[i].text = Language.Get("PayMoneyNum", orderInfoConfig.PayRMBNum);
            }
        }
    }
    public void DisplayPercentage(int firstId)
    {
        if (!model.TryGetCTGConfigByFirstID(firstId, out CTGConfig ctgConfig))
            return;
        txtPercentage.text = Language.Get("FirstCharge03", model.maxDay, ctgConfig.Percentage);
    }
    public void DisplayButton(int firstId)
    {
        if (!model.TryGetFirstChargeDataByFirstId(firstId, out var firstChargeData))
            return;
        if (!model.TryGetOrderInfoConfigByFirstID(firstId, out OrderInfoConfig orderInfo))
            return;
        //购买
        bool isBuy = firstChargeData.IsBuy();
        btnBuy.SetActive(!isBuy);
        btnHave.SetActive(isBuy);
        txtBuy.text = Language.Get("PayMoneyNum", orderInfo.PayRMBNum);
        //领取
        int day = firstChargeData.GetNowBuyDay();
        //0: 已领取 1: 不可领取 2: 可领取
        int awardState = firstChargeData.GetHaveState(day);
        bool isAllHave = firstChargeData.IsAllHave();
        btnHave.interactable = awardState == 2;
        imgNoHave.SetActive(awardState != 2);
        imgHave.SetActive(awardState == 2);
        imgRed.SetActive(awardState == 2);
        if (awardState == 2)
        {
            txtHave.text = Language.Get("Mail09");
        }
        else if (awardState == 1 || (awardState == 0 && !isAllHave))
        {
            txtHave.text = firstChargeData.GetNextDayUnlockRemainingTime();
        }
        else
        {
            txtHave.text = Language.Get("FirstCharge04");
        }
    }
}
Main/System/FirstCharge/FirstChargeWin.cs.meta
copy from Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA02_tagMCFirstGoldInfo.cs.meta copy to Main/System/FirstCharge/FirstChargeWin.cs.meta
File was copied from Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA02_tagMCFirstGoldInfo.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 56da7e3109f052e46860b1ed27323ab4
guid: 3d259a77e6813334b92edc4ce7bb2111
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
Main/System/ItemTip/ItemTipUtility.cs
@@ -305,30 +305,30 @@
        switch (tipType)
            {
                case TipType.Equip:
                    // WindowCenter.Instance.Open<EquipTipWin>();
                    break;
        {
            case TipType.Equip:
                // WindowCenter.Instance.Open<EquipTipWin>();
                break;
                // case TipType.PetMount:
                //      WindowCenter.Instance.Open<PetMountTipWin>();
                //     break;
            // case TipType.PetMount:
            //      WindowCenter.Instance.Open<PetMountTipWin>();
            //     break;
                case TipType.BoxItem:
                    UIManager.Instance.OpenWindow<BoxItemWin>();
                    break;
                case TipType.BoxChooseItem:
                    UIManager.Instance.OpenWindow<ChooseItemsWin>();
                    break;
                case TipType.TreasurePavilion:
                    // TreasurePavilionModel.Instance.selectGubao = config.EffectValueA1;
                    // TreasurePavilionModel.Instance.showTipFromPiece = config.ID;
                    // WindowCenter.Instance.OpenIL<TreasurePavilionTipWin>();
                    break;
                default:
                    UIManager.Instance.OpenWindow<ItemTipWin>();
                    break;
            }
            case TipType.BoxItem:
                UIManager.Instance.OpenWindow<BoxItemWin>();
                break;
            case TipType.BoxChooseItem:
                UIManager.Instance.OpenWindow<ChooseItemsWin>();
                break;
            case TipType.TreasurePavilion:
                // TreasurePavilionModel.Instance.selectGubao = config.EffectValueA1;
                // TreasurePavilionModel.Instance.showTipFromPiece = config.ID;
                // WindowCenter.Instance.OpenIL<TreasurePavilionTipWin>();
                break;
            default:
                UIManager.Instance.OpenWindow<ItemTipWin>();
                break;
        }
    }
    public static void Show(string guid, bool operatable = true)
@@ -386,6 +386,7 @@
        switch (tipType)
        {
            case TipType.Equip:
                isShowCustomEquip = false;
                UIManager.Instance.OpenWindow<EquipTipWin>();
                break;
            // case TipType.PetMount:
@@ -408,6 +409,16 @@
        }
    }
    public static bool isShowCustomEquip = false;
    public static int customEquipItemId;
    public static int customEquipAppointItemId;
    public static void ShowCustomEquip(int itemId, int appointItemId)
    {
        customEquipItemId = itemId;
        customEquipAppointItemId = appointItemId;
        isShowCustomEquip = true;
        UIManager.Instance.OpenWindow<EquipTipWin>();
    }
    // public static void ShowCustomEquip(CustomEquipInfo info)
@@ -417,7 +428,7 @@
    //     WindowCenter.Instance.Open<EquipTipWin>();
    // }
    // static TipData CreateNormalEquipData(string guid)
    // {
@@ -765,8 +776,8 @@
        };
    }
    // public static void Operate(ItemOperateType type, string guid)
    // {
    //     switch (type)
@@ -1377,7 +1388,7 @@
    //     var data = new StrengthenProperty();
    //     var strengthenLevel = strengthenModel.GetStrengthLevel(level, place);
    //     var type = EquipStrengthModel.GetEquipStrengthType(place);
    //     var maxStrengthenLevel = strengthenModel.GetEquipLevelMax(type, level);
@@ -1514,7 +1525,7 @@
        return skillInfo;
    }
    private static SkillInfo GetSkillInfo(int itemId, CustomEquipInfo info)
    {
@@ -1556,7 +1567,7 @@
    //     return skillInfo;
    // }
    // private static GetWay GetGetWay(int itemId)
    // {
@@ -1593,8 +1604,8 @@
    //     return getWay;
    // }
    private static List<ItemOperateType> GetGoodOperates(int goodId)
    {
@@ -1642,7 +1653,7 @@
    {
        var boxType = ChestsAwardConfig.GetBoxType(itemId);
        if (boxType == 1)
        {
        {
            return TipType.BoxItem;
        }
        else if (boxType == 2)
@@ -1681,7 +1692,7 @@
    }
    [System.Diagnostics.Conditional("UNITY_EDITOR")]
Main/System/Main/HomeWin.cs
@@ -1,3 +1,4 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
@@ -53,6 +54,7 @@
    //其他功能入口
    [SerializeField] Button monthCardBtn;
    [SerializeField] Button FirstChargeBtn;
    /// <summary>
    /// 初始化组件
@@ -83,6 +85,11 @@
            InvestModel.Instance.BuyInvest(InvestModel.monthCardType);
        });
        FirstChargeBtn.AddListener(() =>
        {
            UIManager.Instance.OpenWindow<FirstChargeWin>();
        });
        blessLVBtn.AddListener(() =>
        {
            UIManager.Instance.OpenWindow<BlessLVWin>();
@@ -92,7 +99,7 @@
        {
            UIManager.Instance.OpenWindow<MailWin>();
        });
        officialUpBtn.AddListener(() =>
        {
            if (RealmConfig.GetKeys().Count <= PlayerDatas.Instance.baseData.realmLevel)
@@ -128,7 +135,12 @@
        AutoFightModel.Instance.OnFightEvent += ChangeMode;
        TeamManager.Instance.OnTeamChange += DisplayCard;
        UIManager.Instance.OnCloseWindow += OnCloseWindow;
        FuncOpen.Instance.OnFuncStateChangeEvent += OnFuncStateChange;
        FirstChargeManager.Instance.OnUpdateFirstChargeInfo += OnUpdateFirstChargeInfo;
        GlobalTimeEvent.Instance.secondEvent += OnSecondEvent;
        Display();
        DisplayFirstChargeBtn();
        // var battleWin = UIManager.Instance.OpenWindow<BattleWin>();
        // battleWin.SetBattleField(BattleManager.Instance.storyBattleField);
    }
@@ -144,6 +156,9 @@
        AutoFightModel.Instance.OnFightEvent -= ChangeMode;
        TeamManager.Instance.OnTeamChange -= DisplayCard;
        UIManager.Instance.OnCloseWindow -= OnCloseWindow;
        FuncOpen.Instance.OnFuncStateChangeEvent -= OnFuncStateChange;
        FirstChargeManager.Instance.OnUpdateFirstChargeInfo -= OnUpdateFirstChargeInfo;
        GlobalTimeEvent.Instance.secondEvent -= OnSecondEvent;
        //  关闭的时候把战斗界面也给关了 虽然是在外面开的
        UIManager.Instance.CloseWindow<BattleWin>();
@@ -174,7 +189,7 @@
                break;
            case PlayerDataType.LV:
                if (lastLV != PlayerDatas.Instance.baseData.LV)
                {
                {
                    lastLV = PlayerDatas.Instance.baseData.LV;
                    lvUPEffect.Play();
                }
@@ -375,11 +390,44 @@
    }
    void GotoRest()
    {
    {
        if (BattleManager.Instance.storyBattleField != null &&
            BattleManager.Instance.storyBattleField.GetBattleMode() != BattleMode.Stop)
        {
            BattleManager.Instance.storyBattleField.HaveRest();
        }
    }
    private void DisplayFirstChargeBtn()
    {
        bool isFirstChargeFuncOpen = FuncOpen.Instance.IsFuncOpen(FirstChargeManager.FuncID);
        if (FirstChargeManager.Instance.IsAllFirstChargeRewardsClaimed() &&
        FirstChargeManager.Instance.IsNextDayAfterAllClaimed())
        {
            FirstChargeBtn.SetActive(false);
        }
        else
        {
            FirstChargeBtn.SetActive(isFirstChargeFuncOpen);
        }
    }
    private void OnFuncStateChange(int funcId)
    {
        if (funcId == FirstChargeManager.FuncID)
        {
            DisplayFirstChargeBtn();
        }
    }
    private void OnUpdateFirstChargeInfo()
    {
        DisplayFirstChargeBtn();
    }
    private void OnSecondEvent()
    {
        DisplayFirstChargeBtn();
    }
}
Main/System/Recharge/RechargeManager.cs
@@ -674,13 +674,13 @@
        return 0;
    }
    public void UpdateFirstChargeReward(HAA02_tagMCFirstGoldInfo package)
    {
        FirstGoldServerDay = package.FirstGoldServerDay;
        firstChargeRewardGet = package.FirstGoldRewardState;
        UpdateFirstRechargeRedpoint();
        UpdateRedpoint();
    }
    // public void UpdateFirstChargeReward(HAA02_tagMCFirstGoldInfo package)
    // {
    //     FirstGoldServerDay = package.FirstGoldServerDay;
    //     firstChargeRewardGet = package.FirstGoldRewardState;
    //     UpdateFirstRechargeRedpoint();
    //     UpdateRedpoint();
    // }
    private void UpdateFirstRechargeRedpoint()
    {
Main/System/Redpoint/MainRedDot.cs
@@ -95,7 +95,7 @@
    public const int LianQiRepoint = 465; //仙匠大会
    public const int FairySiegeRepoint = 466; //仙盟攻城战
    public const int MailRepoint = 467; //邮箱
    public const int FirstChargeRepoint = 468; //首充