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.metacopy 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.metacopy 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.metacopy 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.metacopy 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.metacopy 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.metacopy 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.metacopy 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.metacopy 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; //首充