Files
ft/Client/Assets/Scripts/UI/OfferStoryChain/OfferStoryChainManager.cs
2026-06-29 21:18:33 +08:00

302 lines
9.9 KiB
C#

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<PlayerItemData>();
public static void InitEvent(cfg.FishingEvent e)
{
var manager = GContext.container.Resolve<Manager>();
if (manager == null)
{
GContext.container.Register<Manager>().AsSingleton();
manager = GContext.container.Resolve<Manager>();
}
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<PlayerData>().PriceLv;
_roundCount = 0;
}
public void InitTest()
{
_eventId = 114514;
_progress = 0;
_redirectId = 92101001;
_vipOnTrigger = GContext.container.Resolve<PlayerData>().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<Tables>();
private int _redirectId;
private EventOfferStoryChain TableMain => _tables.TbEventOfferStoryChain[_redirectId];
private TbEventPackManager TablePacks => _tables.TbEventPackManager;
private List<int> GetPackIdList()
{
var vip = Mathf.Clamp(_vipOnTrigger, 0, TableMain.VipOfferList.Count - 1);
return TableMain.VipOfferList[vip];
}
private List<Pack> GetPackList(int packId)
{
return TablePacks[packId].VIPPackList[0].Select(p => _tables.TbPack[p]).ToList();
}
/// <summary>
/// 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.
/// </summary>
/// <returns></returns>
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<ItemData> GrantReward(int dropId)
{
var rewards = _playerItemData.AddItemByDropLureInflation(null, dropId, null);
MoveToNextSlotAndTryGrantFinalReward();
return rewards;
}
public async System.Threading.Tasks.Task<(bool res, List<ItemData> 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<PlayerShopData>()
.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 { }
}