using System.Text; using GameCore; using cfg; using asap.core; using System.Collections.Generic; using UnityEngine; using System.Linq; namespace OfferStoryChain { public class Manager { #region RedPoint public bool DoNeedRedPoint { get { var packIdList = GetPackIdList(); if (_roundCount >= packIdList.Count) return false; var packList = GetPackList(packIdList[_roundCount]); if (_progress < 0 || _progress >= packList.Count) return false; return packList[_progress].IAPID == 0; } } public const string RedPointKey = "offerstorychain"; #endregion #region DataStorage private int _eventId, _progress, _vipOnTrigger, _roundCount; public int EventId => _eventId; public int Progress => _progress; public int VipLevel => _vipOnTrigger; public int RoundCount => _roundCount; public bool IsActive { get { (var startTime, var endTime) = FtUtils.GetEventTimeLimit(_eventId); var isWithinTime = ZZTimeHelper.UtcNow() >= startTime && ZZTimeHelper.UtcNow() <= endTime; var isOnGoing = _roundCount < GetMaxRoundCount(); return isWithinTime && isOnGoing; } } private const string PlayFabKey = "OfferStoryChain"; private PlayerItemData _playerItemData => GContext.container.Resolve(); public static void InitEvent(cfg.FishingEvent e) { var manager = GContext.container.Resolve(); if (manager == null) { GContext.container.Register().AsSingleton(); manager = GContext.container.Resolve(); } var loadRes = manager.Load(); if (!loadRes || manager.EventId != e.ID) { manager.Init(e.ID); manager.Save(); } UITypes.OfferStoryChainPanel.SetType(manager.GetUiAddressableUrl()); } public void Init(int eventId) { _eventId = eventId; _progress = 0; _redirectId = _tables.TbFishingEvent[_eventId].RedirectID; _vipOnTrigger = GContext.container.Resolve().PriceLv; _roundCount = 0; } public void InitTest() { _eventId = 114514; _progress = 0; _redirectId = 92101001; _vipOnTrigger = GContext.container.Resolve().PriceLv; _roundCount = 0; } public bool Load() { var s = PlayFabMgr.Instance.GetLocalData(PlayFabKey); if (string.IsNullOrEmpty(s)) { Debug.LogWarning("[OfferStoryChain] No pf data found."); return false; } var parts = s.Split(','); if (parts.Length != 4) { Debug.LogWarning($"[OfferStoryChain] String format error. Expect 4, but got {parts.Length}"); return false; } if (!int.TryParse(parts[0], out int eventId) || !int.TryParse(parts[1], out int progress) || !int.TryParse(parts[2], out int vipLevel) || !int.TryParse(parts[3], out int roundCount)) { Debug.LogWarning($"[OfferStoryChain] Parsing error."); return false; } _eventId = eventId; _progress = progress; _vipOnTrigger = vipLevel; _redirectId = _tables.TbFishingEvent[_eventId].RedirectID; _roundCount = roundCount; return true; } public void Save() { var sb = new StringBuilder(); sb.AppendFormat("{0},{1},{2},{3}", _eventId, _progress, _vipOnTrigger, _roundCount); PlayFabMgr.Instance.UpdateUserDataValue(PlayFabKey, sb.ToString()); } public void Reset() { _progress = 0; _roundCount = 0; Save(); } #endregion #region Table Content private readonly Tables _tables = GContext.container.Resolve(); private int _redirectId; private EventOfferStoryChain TableMain => _tables.TbEventOfferStoryChain[_redirectId]; private TbEventPackManager TablePacks => _tables.TbEventPackManager; private List GetPackIdList() { var vip = Mathf.Clamp(_vipOnTrigger, 0, TableMain.VipOfferList.Count - 1); return TableMain.VipOfferList[vip]; } private List GetPackList(int packId) { return TablePacks[packId].VIPPackList[0].Select(p => _tables.TbPack[p]).ToList(); } /// /// Max progress in one round. /// Progress more than this will either trigger next round or end this game. /// -1 because the last pack is the final reward. /// /// public int GetMaxProgressInRound() { return GetPackList(GetPackIdList()[0]).Count - 1; } private int GetMaxRoundCount() { var vip = Mathf.Clamp(_vipOnTrigger, 0, TableMain.VipOfferList.Count - 1); return TableMain.VipOfferList[vip].Count; } public int GetFinalRewardDropId(int roundCount) { roundCount = Mathf.Clamp(roundCount, 0, GetMaxRoundCount() - 1); var packIdList = GetPackIdList(); var packList = GetPackList(packIdList[roundCount]); return packList[^1].DropID; } public ScrollerItemViewData[] GetScrollerSlotDataArray(int roundCount) { var packIdList = GetPackIdList(); var packList = GetPackList(packIdList[roundCount]); return Enumerable.Range(0, GetMaxProgressInRound()) .Select(i => new ScrollerItemViewData { Index = i, EventId = _eventId, DropId = packList[i].DropID, IapId = packList[i].IAPID, State = GetStateFromIndex(i) }) .ToArray(); } #endregion #region System private OfferStoryChain.ScrollerItemViewState GetStateFromIndex(int idx) { if (idx < _progress) return OfferStoryChain.ScrollerItemViewState.Bought; if (idx == _progress) return OfferStoryChain.ScrollerItemViewState.Available; return OfferStoryChain.ScrollerItemViewState.Locked; } public IEventAggregator EventAggregator = new EventAggregator(); public MainPanelData GetMainPanelData() { var res = new MainPanelData(); res.Progress = _progress; res.Reward = _playerItemData.GetItemDataByDropIdLureInflation(null, GetFinalRewardDropId(_roundCount))[0]; res.ScrollerItemViewDataList = GetScrollerSlotDataArray(_roundCount); res.SpineBaseName = TableMain.Spine; return res; } public List GrantReward(int dropId) { var rewards = _playerItemData.AddItemByDropLureInflation(null, dropId, null); MoveToNextSlotAndTryGrantFinalReward(); return rewards; } public async System.Threading.Tasks.Task<(bool res, List rewards)> GrantReward(int dropId, IAPItemList iapItemList, int eventId) { var rewards = _playerItemData.GetItemDataByDropIdLureInflation(null, dropId); var shopBuyTypeData = new ShopBuyTypeData { type = ShopBuyType.EventPack, ID = eventId }; bool res = await GContext.container.Resolve() .OnBuy(dropId, shopBuyTypeData, iapItemList, rewards); return (res, rewards); } public void MoveToNextSlotAndTryGrantFinalReward() { Debug.Log($"[OfferStoryChain] Move to next slot. Current Progress: {_progress}"); _progress++; if (_progress >= GetMaxProgressInRound()) { var finalRewardDropId = GetFinalRewardDropId(_roundCount); _playerItemData.AddItemByDropLureInflation(null, finalRewardDropId, null, false); _progress = 0; _roundCount++; } Save(); } #endregion #region UI Data public TimerContext GetTimerData() { var res = new TimerContext(); (res.StartTime, res.ExpiryTime) = FtUtils.GetEventTimeLimit(_eventId); return res; } public string GetEntrancIconUrl() { return TableMain.Icon; } public string GetUiAddressableUrl() { return TableMain.Addressable; } #endregion } public class ScrollerItemViewData { // public ItemData[] ItemDataList { get; set; } // public string TextPrice { get; set; } public int Index { get; set; } public int EventId { get; set; } public int DropId { get; set; } public int IapId { get; set; } // public string TextDiscount { get; set; } public ScrollerItemViewState State { get; set; } } public enum ScrollerItemViewState { Bought, Locked, Available } public class MainPanelData { public int Progress { get; set; } public ItemData Reward { get; set; } public ScrollerItemViewData[] ScrollerItemViewDataList { get; set; } public string SpineBaseName { get; set; } // public System.DateTime StartTime { get; set; } // public System.DateTime EndTime { get; set; } } public class OfferStoryChainCloseEvent { } }