备份CatanBuilding瘦身独立工程

This commit is contained in:
JSD\13999
2026-05-26 16:15:54 +08:00
commit 2d0e6a61b7
12001 changed files with 2431925 additions and 0 deletions

View File

@@ -0,0 +1,464 @@
using System.Collections.Generic;
using System;
using cfg;
using GameCore;
using UnityEngine.Assertions;
using asap.core;
using UnityEngine;
using System.Linq;
public class GenericChainPackData<T> : IChainPackData where T : IHasChainPack
{
protected const int SlotCount = 6;
protected List<int> ChainList { get; set; }
protected DateTime ExpireTime { get; set; }
protected Pack[] Packs { get; set; }
public bool IsEndGame => ChainProgress > ChainListCount - SlotCount;
public int ChainListCount => ChainList.Count;
private readonly T _rawData;
public int ChainProgress
{
get
{
return _rawData.GetChainProgress();
}
set
{
_rawData.SetChainProgress(value);
}
}
public int EventId { get; set; }
public TimeSpan RemainingTime => ExpireTime - ZZTimeHelper.UtcNow();
public bool IsChainPackDepleted => ChainProgress >= ChainListCount;
public bool DoNeedPackRedPoint
{
get
{
if (!IsChainPackDepleted && ChainProgress < ChainListCount)
return Packs[ChainProgress].IAPID == 0;
return false;
}
}
private string _redPointKey = "eventcan.pack";
public string RedPointKey => _redPointKey;
public static GenericChainPackData<T> Create(T data, EventChainPackInfo info)
{
return new GenericChainPackData<T>(data, info);
}
private GenericChainPackData(T data, EventChainPackInfo info)
{
EventId = data.EventId;
_rawData = data;
ChainList = info.ChainList;
ExpireTime = info.ExpireTime;
Packs = info.Packs;
_redPointKey = info.RedPointKey;
}
public Pack GetChainPackByChainProgress(int chainProgress)
{
return Packs[chainProgress];
}
public int GetChainProgressBySlotIdx(int slotIdx)
{
int res;
if (ChainProgress > ChainList.Count - SlotCount)
res = ChainList.Count - SlotCount + slotIdx;
else
res = ChainProgress + slotIdx;
Assert.IsTrue(res < ChainList.Count, $"Progress {res} out of range: {ChainListCount}");
return res;
}
public List<ItemData> GetItemsByPackDropId(int dropId)
{
throw new NotImplementedException();
}
public List<int> GetTokenProgressRewardAfterAddingToken(int tokenAdded)
{
throw new NotImplementedException();
}
public void OnBuySuccess()
{
// Debug.Log($"[EventLuckMagic] 2nd: {this.GetHashCode()}");
ChainProgress++;
UploadData();
}
public void UploadData()
{
_rawData.Save();
}
}
[Obsolete]
public abstract class AChainPackData : IChainPackData
{
public AChainPackData() { }
protected const int SlotCount = 6;
protected List<int> ChainList { get; set; }
protected DateTime ExpireTime { get; set; }
protected Pack[] Packs { get; set; }
public bool IsEndGame => ChainProgress > ChainListCount - SlotCount;
public int ChainListCount => ChainList.Count;
public int ChainProgress { get; set; }
public int EventId { get; set; }
public TimeSpan RemainingTime => ExpireTime - ZZTimeHelper.UtcNow();
public bool IsChainPackDepleted => ChainProgress >= ChainListCount;
public bool DoNeedPackRedPoint
{
get
{
if (!IsChainPackDepleted && ChainProgress < ChainListCount)
return Packs[ChainProgress].IAPID == 0;
return false;
}
}
public string RedPointKey => "eventcan.pack";
public AChainPackData(int eventId, int chainProgress)
{
EventId = eventId;
ChainProgress = chainProgress;
}
public Pack GetChainPackByChainProgress(int chainProgress)
{
return Packs[chainProgress];
}
public int GetChainProgressBySlotIdx(int slotIdx)
{
int res;
if (ChainProgress > ChainList.Count - SlotCount)
res = ChainList.Count - SlotCount + slotIdx;
else
res = ChainProgress + slotIdx;
Assert.IsTrue(res < ChainList.Count, $"Progress {res} out of range: {ChainListCount}");
return res;
}
public List<ItemData> GetItemsByPackDropId(int dropId)
{
throw new NotImplementedException();
}
public List<int> GetTokenProgressRewardAfterAddingToken(int tokenAdded)
{
throw new NotImplementedException();
}
public void OnBuySuccess()
{
ChainProgress++;
UploadData();
}
abstract public void UploadData();
}
public interface IChainPackData
{
public bool IsEndGame { get; }
public Pack GetChainPackByChainProgress(int chainProgress);
public int GetChainProgressBySlotIdx(int slotIdx);
public int ChainListCount { get; }
public int ChainProgress { get; set; }
public int EventId { get; }
public List<int> GetTokenProgressRewardAfterAddingToken(int tokenAdded);
public void UploadData();
public TimeSpan RemainingTime { get; }
public bool IsChainPackDepleted { get; }
public void OnBuySuccess();
public bool DoNeedPackRedPoint { get; }
public string RedPointKey { get; }
public List<ItemData> GetItemsByPackDropId(int dropId);
}
public interface IHasChainPack
{
public int EventId { get; }
public void SetChainProgress(int p);
public int GetChainProgress();
public void Save();
}
public class EventChainPackInfo
{
public List<int> ChainList { get; set; }
public DateTime ExpireTime { get; set; }
public Pack[] Packs { get; set; }
public string RedPointKey { get; set; }
}
public interface IProgressChainPackData : IChainPackData
{
public int TokenProgress { get; }
public int GetTokenProgressTargetByIdx(int idx);
public void GetTokenProgressTargetByProgress(int progress, out int targetDisplay, out int scoreDisplay);
public int GetRewardDropByChainProgress(int chainProgress);
public string TokenIconUrl { get; }
public void AddToken(int count);
}
public interface IHasProgressChainPack : IHasChainPack
{
public int PackId { get; }
public void SetTaskProgress(int p);
public int GetTaskProgress();
}
public class GenericChainPackWithProgressData<T> : IProgressChainPackData where T : IHasProgressChainPack
{
private T _rawData;
public int TokenProgress
{
get
{
return _rawData.GetTaskProgress();
}
set
{
_rawData.SetTaskProgress(value);
}
}
public const int SlotCount = 6;
private readonly Tables _tables = GContext.container.Resolve<Tables>();
private readonly TbFishingEvent _fishingEvent = GContext.container.Resolve<Tables>().TbFishingEvent;
private readonly TbEventPackManager _eventPackManager = GContext.container.Resolve<Tables>().TbEventPackManager;
private readonly TbPack _tablePack = GContext.container.Resolve<Tables>().TbPack;
private readonly PlayerItemData _playerItemData = GContext.container.Resolve<PlayerItemData>();
private List<int> MileStoneList => GContext.container.Resolve<Tables>().TbEventPackManager[_rawData.PackId].MilestoneList;
private Pack[] _packs;
protected List<int> ChainList;
private DateTime _expireTime;
private string _redPointKey = "This should be overridden.";
private GenericChainPackWithProgressData(T data, EventChainPackInfo info)
{
EventId = data.EventId;
_rawData = data;
ChainList = info.ChainList;
_expireTime = info.ExpireTime;
_packs = info.Packs;
_redPointKey = info.RedPointKey;
}
public bool DoNeedPackRedPoint
{
get
{
if (!IsChainPackDepleted && ChainProgress < ChainListCount)
return _packs[ChainProgress].IAPID == 0;
return false;
}
}
public string TokenIconUrl
{
get
{
int tokenId = _tables.TbDrop[_tablePack[ChainList[0]].DropID].DropList.DropIDList[0];
var emp = _eventPackManager[_rawData.PackId];
if (emp?.MilestoneItem?.Count >= 2 && tokenId == _eventPackManager[_rawData.PackId].MilestoneItem[0])
tokenId = _eventPackManager[_rawData.PackId].MilestoneItem[1];
return _tables.TbItem[tokenId].Icon;
}
}
public bool IsEndGame => ChainProgress > ChainListCount - SlotCount;
public int ChainListCount => _eventPackManager[_rawData.PackId].VIPPackList[0].Count;
public int ChainProgress
{
get
{
return _rawData.GetChainProgress();
}
set
{
_rawData.SetChainProgress(value);
}
}
public int EventId { get; set; }
public TimeSpan RemainingTime => _expireTime - ZZTimeHelper.UtcNow();
public bool IsChainPackDepleted => ChainProgress >= ChainListCount;
public string RedPointKey => _redPointKey;
public void AddToken(int count)
{
// TODO: Add negative detection?
var c = _rawData.GetChainProgress() + count;
_rawData.SetChainProgress(c);
}
public static GenericChainPackWithProgressData<T> Create(T data, EventChainPackInfo info)
{
return new GenericChainPackWithProgressData<T>(data, info);
}
public Pack GetChainPackByChainProgress(int chainProgress)
{
return _packs[chainProgress];
}
public int GetChainProgressBySlotIdx(int slotIdx)
{
int res;
if (ChainProgress > ChainList.Count - SlotCount)
res = ChainList.Count - SlotCount + slotIdx;
else
res = ChainProgress + slotIdx;
Assert.IsTrue(res < ChainList.Count, $"Progress {res} out of range: {ChainListCount}");
return res;
}
public List<ItemData> GetItemsByPackDropId(int dropId)
{
var res = new List<ItemData>();
if (!_tables.TbDrop.DataMap.TryGetValue(dropId, out var drop))
{
Debug.Log($"Drop id {dropId} not found.");
return res;
}
if (drop.Type != DropType.Probability)
{
Debug.Log($"Unsupported drop type {drop.Type} from drop Id {dropId}.");
return res;
}
try
{
int n = drop.DropList.DropIDList.Count;
for (int i = 0; i < n; i++)
{
var itemId = drop.DropList.DropIDList[i];
var mileStoneItem = _eventPackManager[_rawData.PackId].MilestoneItem;
// if (!mileStoneItem.IsNullOrEmpty() && mileStoneItem.Count >= 2 && itemId == mileStoneItem[0])
if (mileStoneItem != null && mileStoneItem.Count >= 2 && itemId == mileStoneItem[0])
{
itemId = mileStoneItem[1];
}
res.Add(new ItemData(itemId, drop.DropList.DropCountList[i]));
_playerItemData.ItemTransition(res[i]);
}
}
catch (Exception e)
{
Debug.LogError($"[ChainPackW]Invalid drop id {drop}: {e.Message}\n{e.StackTrace}");
return res;
}
return res;
}
public int GetRewardDropByChainProgress(int chainProgress)
{
int i, sum = 0;
// var mileStoneList = _eventPackManager[_data.RedirectId].MilestoneList;
for (i = 0; i < MileStoneList.Count - 1; i++)
{
sum += MileStoneList[i];
if (chainProgress < sum)
break;
}
var mileStoneRewards = _eventPackManager[_rawData.PackId].MilestoneReward;
return mileStoneRewards[i];
}
public List<int> GetTokenProgressRewardAfterAddingToken(int tokenAdded)
{
// Debug.Log($"<color=#f18c0a>Add {tokenAdded}</color>");
int previousTokenProgress = TokenProgress - tokenAdded, i, sum = 0, previousIdx = -1, currentIdx = -1;
for (i = 0; i < MileStoneList.Count; i++)
{
sum += MileStoneList[i];
if (previousIdx == -1 && previousTokenProgress < sum)
previousIdx = i;
if (currentIdx == -1 && TokenProgress < sum)
currentIdx = i;
}
if (currentIdx == -1 && TokenProgress >= sum)
currentIdx = MileStoneList.Count;
if (previousIdx == -1 && previousTokenProgress >= sum)
previousIdx = MileStoneList.Count;
// Debug.Log($"<color=#f18c0a>current:{currentIdx}, previous {previousIdx}</color>");
int count = Math.Max(0, currentIdx - previousIdx);
if (count > 0)
{
var res = _eventPackManager[_rawData.PackId].MilestoneReward.GetRange(previousIdx, count);
return res;
}
return new List<int>();
// Debug.Log($"<color=#f18c0a>Progress Reward Length: {res.Count}, or {count}</color>");
}
public int GetTokenProgressTargetByIdx(int idx)
{
if (idx < MileStoneList.Count) return MileStoneList.GetRange(0, idx + 1).Sum();
Debug.LogError($"Index {idx} is not within the scale of list length {MileStoneList.Count}");
return -1;
}
public void GetTokenProgressTargetByProgress(int progress, out int targetDisplay, out int scoreDisplay)
{
// var mileStoneList = _eventPackManager[_data.RedirectId].MilestoneList;
// Debug.Log($"<color=#f18c0a>VS: {progress}</color>");
int i = 0, accTarget = 0;
while (i < MileStoneList.Count)
{
accTarget += MileStoneList[i];
if (accTarget > progress)
{
targetDisplay = MileStoneList[i];
scoreDisplay = progress - MileStoneList.GetRange(0, i).Sum();
// Debug.Log($"<color=#f18c0a>Within: {scoreDisplay} / {targetDisplay}</color>");
return;
}
i++;
}
targetDisplay = MileStoneList[^1];
scoreDisplay = targetDisplay;
// Debug.Log($"<color=#f18c0a>Out: {scoreDisplay} / {targetDisplay}</color>");
}
public void OnBuySuccess()
{
if (ChainProgress >= ChainListCount)
{
Debug.LogError($"Trying to buy pack no.{ChainProgress} while there are/is only {ChainListCount} packs.");
return;
}
int tokenAdded = _tables.TbDrop[GetChainPackByChainProgress(ChainProgress).DropID].DropList.DropCountList[0];
ChainProgress++;
var dropList = GetTokenProgressRewardAfterAddingToken(tokenAdded);
_playerItemData.AddItemByDropList(dropList, false);
}
public void UploadData()
{
_rawData.Save();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 001a5935e207ebd4abf1f2b1b136c12e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,32 @@
using asap.core;
using GameCore;
using UnityEngine.AddressableAssets;
public class EventLuckMagicAct : AGameAct
{
public static EventLuckMagicSystem System;
public static EventLuckMagicTableContext TableContext;
// public static EventLuckMagicParamsCtrl ParamsCtrl;
public static IEventAggregator EventAggregator = new EventAggregator();
// public static GenericChainPackData<EventLuckMagicModel> ChainPackData;
public const string ActAddressable = "EventLuckMagicAct",
OuterRingBtnKey = "UI_EventLuckMagicPanel_2",
MiddleRingBtnKey = "UI_EventLuckMagicPanel_3",
InnerRingBtnKey = "UI_EventLuckMagicPanel_4";
private const string ParamsCtrlName = "EventLuckMagicParamsCtrl";
private async void Awake()
{
var model = GContext.container.Resolve<EventLuckMagicModel>();
model.ParamsCtrl = (EventLuckMagicParamsCtrl)await Addressables.LoadAssetAsync<object>(ParamsCtrlName).Task;
var panel = await UIManager.Instance.ShowUINotLoading(UITypes.EventLuckMagicPanel);
GContext.container.Resolve<IDeferredRewardStashService>().Reset();
panel.GetComponent<EventLuckMagicMainPanel>().Init(model.SelectionState);
}
protected override void OnDestroy()
{
UIManager.Instance.DestroyUI(UITypes.EventLuckMagicPanel);
// GContext.container.Resolve<IDeferredRewardStashService>().Flush();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ad1ab35416559864ca4537f6747d0c1d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,93 @@
using cfg;
using asap.core;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Assertions;
using TMPro;
using GameCore;
using System.Linq;
public class EventLuckMagicBlockView : MonoBehaviour
{
[SerializeField] private GameObject[] goBackgrounds;
// [SerializeField] private RewardItemNew reward;
[SerializeField] private Image icon, iconNum;
[SerializeField] private GameObject goReceived, goUpperTaskIcon, goLowerTaskIcon, goOuterRingSign, goMiddleRingSign;
[SerializeField] private CardLogoNum iconCard;
[SerializeField] private TMP_Text textNum;
[SerializeField] private Button button;
public void Init(EventLuckMagicBlock data)
{
button.onClick.RemoveAllListeners();
button.onClick.AddListener(() =>
{
GContext.container.Resolve<PlayerItemData>().ShowItemTips(data.Reward.id, button.transform);
});
for (int i = 0; i < goBackgrounds.Length; i++)
{
goBackgrounds[i].SetActive((int)data.BlockType == i);
}
HideAllIcons();
goReceived.SetActive(data.IsTaken);
var res = GContext.container.Resolve<Tables>().TbItem.DataMap.TryGetValue(data.Reward.id, out var item);
Assert.IsTrue(res, $"Item {data.Reward.id} not found in item list.");
var count = data.Reward.count;
if (item.Type == 5)
{
iconCard.gameObject.SetActive(true);
iconCard.Init(item);
return;
}
var itemType = EventLuckMagicAct.TableContext.JudgeItemId(data.Reward.id);
switch (itemType)
{
case EEventLuckMagicItemType.UpperTaskItem:
goUpperTaskIcon.SetActive(true);
return;
case EEventLuckMagicItemType.LowerTaskItem:
goLowerTaskIcon.SetActive(true);
return;
default:
break;
}
if (data.BlockType == EEventLuckMagicBlockType.RoadSign)
{
goOuterRingSign.SetActive(data.ParentRing.RingType == EEventLuckMagicRingType.OuterRing);
goMiddleRingSign.SetActive(data.ParentRing.RingType == EEventLuckMagicRingType.MiddleRing);
return;
}
if (count == 1f)
{
icon.gameObject.SetActive(true);
GContext.container.Resolve<IUIService>().SetImageSprite(icon, item.Icon);
}
else
{
iconNum.gameObject.SetActive(true);
GContext.container.Resolve<IUIService>().SetImageSprite(iconNum, item.Icon);
textNum.text = FtMathUtils.GetNumberString(count);
}
}
public void SetReceived(bool isReceived = true)
{
// if (EventLuckMagicAct.TableContext.IsRewardRoadSign(reward.id, out _, out _))
// goReceived.SetActive(false);
// else
goReceived.SetActive(isReceived);
}
private void HideAllIcons()
{
icon.gameObject.SetActive(false);
iconNum.gameObject.SetActive(false);
iconCard.gameObject.SetActive(false);
goUpperTaskIcon.SetActive(false);
goLowerTaskIcon.SetActive(false);
goOuterRingSign.SetActive(false);
goMiddleRingSign.SetActive(false);
goReceived.SetActive(false);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a266f9c7a619d504eb17083a98c34869
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,710 @@
using System.Linq;
using GameCore;
using UnityEngine;
using System.Collections.Generic;
using UnityEngine.Assertions;
using asap.core;
using game;
using System.Text;
using cfg;
using System;
public class EventLuckMagicModel : IHasChainPack, ILuckyTaskGetData, ILuckyTaskUIGetData
{
private int _eventId, _ticketCount, _chainProgress, _roundCount;
/// <summary>
/// Position of selection GameObject, or null if hidden.
/// </summary>
public Vector2? SelectionState;
private readonly List<EventLuckMagicRing> _rings = new List<EventLuckMagicRing>();
public EventLuckMagicRing CurrentRing { get; set; }
public EventLuckMagicRing OuterRing => _rings[0];
public EventLuckMagicRing MiddleRing => _rings[1];
public EventLuckMagicRing InnerRing => _rings[2];
public EventLuckMagicHigherRingData HigherRingData;
public Dictionary<EEventLuckMagicRingType, EventLuckMagicRing> RingMap;
public int TicketCount => _ticketCount;
public Dictionary<int, int> TaskProgress;
public const int TaskProgressCount = 3;
public bool IsGameDepleted => _rings.All(x => x.IsDepleted);
public bool DoesSkipAnimation = false;
private DateTime _expiryTime, _startTime;
public TimeSpan RemainingTime => _expiryTime - ZZTimeHelper.UtcNow();
public bool IsActive => RemainingTime.TotalSeconds > 0;
public int EventId => _eventId;
public int RoundCount => _roundCount;
public DateTime ExpiryTime => _expiryTime;
public EventLuckMagicParamsCtrl ParamsCtrl;
public void InitNew(int eventId)
{
_eventId = eventId;
_rings.Clear();
EventLuckMagicAct.TableContext.GetRingsInfo(out int[] costs, out int[] roadSignIds);
for (int i = 0; i < costs.Length; i++)
_rings.Add(EventLuckMagicRing.CreateEmpty(costs[i], roadSignIds[i], (EEventLuckMagicRingType)(i + 1)));
EventLuckMagicAct.TableContext.GetBlocksInfo(out var infoList);
RingMap = new Dictionary<EEventLuckMagicRingType, EventLuckMagicRing>()
{
{EEventLuckMagicRingType.OuterRing, OuterRing},
{EEventLuckMagicRingType.MiddleRing, MiddleRing},
{EEventLuckMagicRingType.InnerRing, InnerRing}
};
foreach (var info in infoList)
{
RingMap[info.RingType].AddBlock(new EventLuckMagicBlock(info, RingMap[info.RingType]));
}
RingMap[EEventLuckMagicRingType.OuterRing].ImportBitWiseBlockState(0);
RingMap[EEventLuckMagicRingType.MiddleRing].ImportBitWiseBlockState(0);
RingMap[EEventLuckMagicRingType.InnerRing].ImportBitWiseBlockState(0);
HigherRingData = EventLuckMagicHigherRingData.CreateEmpty();
LinkRings();
_ticketCount = EventLuckMagicAct.TableContext.GetWelcomeGift();
_chainProgress = 0;
TaskProgress = GetTaskProgress();
CurrentRing = _rings.FirstOrDefault(r => !r.IsDepleted) ?? _rings.Last();
SelectionState = null;
DoesSkipAnimation = false;
(_startTime, _expiryTime) = EventLuckMagicAct.TableContext.GetEventStartTimeAndEndTime();
_roundCount = 0;
_taskData?.Dispose();
_dicTasks = new Dictionary<int, int>();
_taskData = new LuckyTaskData(this);
_taskData.InitDicTasks(EventLuckMagicAct.TableContext.GetFirstLuckyTaskIdList());
}
public void Load(EventLuckMagicPlayfabData pfData, EventLuckMagicPlayerPreferenceData ppData)
{
_eventId = pfData.EventId;
EventLuckMagicAct.TableContext.GetRingsInfo(out int[] costs, out int[] roadSignIds);
for (int i = 0; i < costs.Length; i++)
_rings.Add(EventLuckMagicRing.CreateEmpty(costs[i], roadSignIds[i], (EEventLuckMagicRingType)(i + 1)));
EventLuckMagicAct.TableContext.GetBlocksInfo(out var infoList);
RingMap = new Dictionary<EEventLuckMagicRingType, EventLuckMagicRing>()
{
{EEventLuckMagicRingType.OuterRing, OuterRing},
{EEventLuckMagicRingType.MiddleRing, MiddleRing},
{EEventLuckMagicRingType.InnerRing, InnerRing}
};
foreach (var info in infoList)
{
RingMap[info.RingType].AddBlock(new EventLuckMagicBlock(info, RingMap[info.RingType]));
}
RingMap[EEventLuckMagicRingType.OuterRing].ImportBitWiseBlockState(pfData.OuterState);
RingMap[EEventLuckMagicRingType.MiddleRing].ImportBitWiseBlockState(pfData.MiddleState);
RingMap[EEventLuckMagicRingType.InnerRing].ImportBitWiseBlockState(pfData.InnerState);
HigherRingData = EventLuckMagicHigherRingData.Create(RingMap[pfData.HigherRingType], pfData.HigherRingExpireTime.Value);
LinkRings();
_ticketCount = pfData.TicketCount;
_chainProgress = pfData.ChainProgress;
_roundCount = pfData.RoundCount;
TaskProgress = GetTaskProgress();
CurrentRing = _rings.FirstOrDefault(r => !r.IsDepleted) ?? _rings.Last();
ppData ??= EventLuckMagicPlayerPreferenceData.CreateEmpty();
SelectionState = ppData.SelectionPosition;
DoesSkipAnimation = ppData.DoesSkipAnimation;
(_startTime, _expiryTime) = EventLuckMagicAct.TableContext.GetEventStartTimeAndEndTime();
_dicTasks = pfData.DicTasks;
_taskData = new LuckyTaskData(this);
}
public void AddTicket(int num)
{
if (_ticketCount + num < 0)
{
Debug.Log($"[EventLuckMagic] Try to add {num} ticket(s) failed. Having {_ticketCount} ticket(s) now.");
return;
}
_ticketCount += num;
GContext.container.Resolve<FishingEventData>().SaveTransitionData(_eventId, _ticketCount);
ToPfData().Save();
EventLuckMagicAct.EventAggregator.Publish(new EventLuckMagicTicketChange());
}
public void LinkRings()
{
for (int i = 0; i < _rings.Count - 1; i++)
_rings[i].HigherRing = _rings[i + 1];
CurrentRing = _rings.FirstOrDefault(r => !r.IsDepleted);
if (CurrentRing == null)
{
Debug.Log($"[EventLuckMagic] Cannot find any available ring. Seems that all rings are depleted.");
return;
}
var r = CurrentRing;
// The Higher ring of r is the next ring that is not depleted.
while (r != null && r.HigherRing != null)
{
while (r.HigherRing != null && r.HigherRing.IsDepleted)
{
r.HigherRing = r.HigherRing.HigherRing;
}
r = r.HigherRing;
}
}
public void UpdateTaskProgress(int targetId)
{
TaskProgress[targetId]++;
// Debug.Log($"[EventLuckMagic] Task progress of {targetId} is {TaskProgress[targetId]}.");
ToPfData().Save();
}
public bool IsTaskCompleted(int targetId)
{
return TaskProgress[targetId] >= TaskProgressCount;
}
public void Reset()
{
for (int i = 0; i < _rings.Count; i++)
_rings[i].Reset();
HigherRingData.SetEmpty();
LinkRings();
HigherRingData.PointTo(CurrentRing.HigherRing);
HigherRingData.ExpireTime = System.DateTime.MinValue;
TaskProgress = EventLuckMagicAct.TableContext.GetTaskInfo(GContext.container.Resolve<EventLuckMagicModel>().RoundCount)
.Keys.ToDictionary(x => x, x => 0);
CurrentRing = _rings.FirstOrDefault(r => !r.IsDepleted) ?? _rings.Last();
_taskData.InitDicTasks(EventLuckMagicAct.TableContext.GetLastLuckyTaskIdList());
ToPfData().Save();
}
public void SetChainProgress(int p)
{
Debug.Log($"[EventLuckMagic]SetProgress {p}");
_chainProgress = p;
}
public int GetChainProgress()
{
return _chainProgress;
}
public void Save()
{
ToPfData().Save();
}
public EventLuckMagicPlayerPreferenceData ToPpData()
{
return new EventLuckMagicPlayerPreferenceData
{
SelectionPosition = SelectionState,
DoesSkipAnimation = DoesSkipAnimation
};
}
public EventLuckMagicPlayfabData ToPfData()
{
var expireTime = HigherRingData.DoesExist ? HigherRingData.ExpireTime : DateTime.MinValue;
// var expireTime = HigherRingData.DoesExist ? HigherRingData.ExpireTime : ZZTimeHelper.UtcNow().AddSeconds(-1);
var ringType = HigherRingData.DoesExist ? HigherRingData.Ring.RingType : EEventLuckMagicRingType.OuterRing;
return new EventLuckMagicPlayfabData
{
EventId = _eventId,
TicketCount = TicketCount,
ChainProgress = _chainProgress,
InnerState = InnerRing.GetBitWiseBlockState(),
MiddleState = MiddleRing.GetBitWiseBlockState(),
OuterState = OuterRing.GetBitWiseBlockState(),
HigherRingExpireTime = expireTime,
HigherRingType = ringType,
RoundCount = _roundCount,
DicTasks = _dicTasks
};
}
private Dictionary<int, int> GetTaskProgress()
{
var taskInfo = EventLuckMagicAct.TableContext.GetTaskInfo(RoundCount);
var res = taskInfo.ToDictionary(
kv => kv.Key,
kv => _rings.Sum(ring => ring.Blocks.Count(x => x.Reward.id == kv.Key && x.IsTaken))
);
return res;
}
public EventLuckMagicEntranceData ToEntranceData()
{
return new EventLuckMagicEntranceData
{
TicketCount = _ticketCount,
ExpiryTime = _expiryTime,
Icon = EventLuckMagicAct.TableContext.GetIcon(),
StartTime = _startTime,
};
}
public GenericChainPackData<EventLuckMagicModel> ToChainPackData()
{
return GenericChainPackData<EventLuckMagicModel>.Create(
this, EventLuckMagicAct.TableContext.GetChainPackInfo());
}
public void AddRoundCount()
{
_roundCount++;
Save();
}
public void SaveTaskData()
{
ToPfData().Save();
}
#region Lucky Task
private Dictionary<int, int> _dicTasks;
private LuckyTaskData _taskData;
public string LuckyTaskRedPointKey => "eventluckmagic.entrance.luckytask";
public Dictionary<int, int> DicTasks { get => _dicTasks; set => _dicTasks = value; }
public string TaskPanelName => "EventLuckyMagicTaskPopupPanel";
public bool OnGetTaskReward(int id)
{
return _taskData.OnGetTaskReward(id, EventLuckMagicAct.TableContext.GetLastLuckyTaskIdList());
}
public int GetLuckyPackID()
{
return EventLuckMagicAct.TableContext.GetPackId();
}
public void DisposeLuckyTaskSubscription()
{
_taskData.Dispose();
}
#endregion
}
public class EventLuckMagicRing
{
public readonly int Cost, RoadSignId;
public List<EventLuckMagicBlock> Blocks;
public bool IsDepleted => Blocks.All(x => x.IsTaken || EventLuckMagicAct.TableContext.IsRewardRoadSign(x.Reward.id, out _, out _, out _));
public readonly EEventLuckMagicRingType RingType;
public EventLuckMagicRing HigherRing { get; set; }
public int[] CornerIndices = new int[4];
private int BlockCount => Blocks.Count;
public int AvailableBlockCount => Blocks.Count(x => !x.IsTaken);
private EventLuckMagicRing(int cost, int roadSignId, EEventLuckMagicRingType ringType)
{
Blocks = new List<EventLuckMagicBlock>();
Cost = cost;
RoadSignId = roadSignId;
RingType = ringType;
HigherRing = null;
}
public static EventLuckMagicRing CreateEmpty(int cost, int roadSignId, EEventLuckMagicRingType ringType)
{
return new EventLuckMagicRing(cost, roadSignId, ringType);
}
public void AddBlock(EventLuckMagicBlock block)
{
Blocks.Add(block);
}
public void Reset()
{
Blocks.ForEach(x => x.Reset());
}
public void GetLoopAnimationInfo(int targetIdx, int extraLoopCount, out int startIdx, out int totalMovementCount)
{
int idx = 0, gap = BlockCount / 4;
startIdx = 0;
while (idx < BlockCount)
{
idx += gap;
if (GetShortestDistance(idx, targetIdx) > GetShortestDistance(startIdx, targetIdx))
startIdx = idx;
}
totalMovementCount = GetClockWiseDistance(startIdx, targetIdx) + extraLoopCount * BlockCount;
}
private int GetClockWiseDistance(int startIdx, int endIdx)
{
Assert.IsTrue(startIdx >= 0 && startIdx < BlockCount && endIdx >= 0 && endIdx < BlockCount);
return (endIdx - startIdx + BlockCount) % BlockCount;
}
private int GetShortestDistance(int startIdx, int endIdx)
{
int d = Mathf.Abs(startIdx - endIdx);
d = d > BlockCount / 2 ? BlockCount - d : d;
return d;
}
public int GetBitWiseBlockState()
{
var res = 0;
for (int i = 0; i < BlockCount; i++)
{
if (Blocks[i].IsTaken)
res |= 1 << i;
}
return res;
}
public void ImportBitWiseBlockState(int state)
{
for (int i = 0; i < BlockCount; i++)
{
if ((state & (1 << i)) != 0)
Blocks[i].Take();
else
Blocks[i].Reset();
}
}
}
public class EventLuckMagicBlock
{
public int TableId;
public readonly ItemData Reward;
private bool _isTaken;
public bool IsTaken
{
get
{
if (EventLuckMagicAct.TableContext.IsRewardRoadSign(Reward.id, out _, out _, out _))
return ParentRing == null || ParentRing.HigherRing == null || ParentRing.HigherRing.IsDepleted;
return _isTaken;
}
}
private int _weight;
public int Weight
{
get
{
if (EventLuckMagicAct.TableContext.IsRewardRoadSign(Reward.id, out _, out _, out var weightConfig))
{
if (weightConfig.Length != 2)
return _weight;
return ParentRing.AvailableBlockCount <= weightConfig[0] ? weightConfig[1] : _weight;
}
return _weight;
}
set
{
_weight = value;
}
}
public EEventLuckMagicBlockType BlockType;
/// <summary>
/// The ring this block belongs to.
/// </summary>
public EventLuckMagicRing ParentRing { get; }
public EventLuckMagicBlock(EventLuckMagicBlockInfo info, EventLuckMagicRing parentRing)
{
Reward = info.Reward;
Weight = info.Weight;
BlockType = GetBlockType(info.RingType, info.Reward.id);
ParentRing = parentRing;
TableId = info.TableId;
// _isTaken = isTaken;
}
public void Take()
{
_isTaken = true;
}
private static EEventLuckMagicBlockType GetBlockType(EEventLuckMagicRingType ringType, int rewardId)
{
if (EventLuckMagicAct.TableContext.IsRewardRoadSign(ringType, rewardId))
return EEventLuckMagicBlockType.RoadSign;
else
return (EEventLuckMagicBlockType)(ringType - 1);
}
public void Reset()
{
_isTaken = false;
}
}
public class EventLuckMagicHigherRingData
{
public EventLuckMagicRing Ring { get; set; }
public System.DateTime ExpireTime;
public System.TimeSpan RemainingTime => ExpireTime - ZZTimeHelper.UtcNow();
public bool DoesExist => Ring != null && !Ring.IsDepleted && RemainingTime.TotalSeconds > 0;
private EventLuckMagicHigherRingData() { }
public void PointTo(EventLuckMagicRing ring)
{
Ring = ring;
}
public void Activate(int expireDuration)
{
ExpireTime = ZZTimeHelper.UtcNow().AddSeconds(expireDuration);
}
public void SetEmpty()
{
Ring = null;
ExpireTime = ZZTimeHelper.UtcNow().AddSeconds(-5);
}
public static EventLuckMagicHigherRingData CreateEmpty()
{
var res = new EventLuckMagicHigherRingData();
res.SetEmpty();
return res;
}
public static EventLuckMagicHigherRingData Create(EventLuckMagicRing ring, System.DateTime? expireTime)
{
var res = new EventLuckMagicHigherRingData();
res.PointTo(ring);
if (expireTime != null)
res.ExpireTime = expireTime.Value;
else
res.ExpireTime = ZZTimeHelper.UtcNow().AddSeconds(-4);
return res;
}
}
public class EventLuckMagicPanelData
{
public EventLuckMagicTableContext TableContext;
public EventLuckMagicModel Model;
public EventLuckMagicSystem System;
public EventLuckMagicParamsCtrl ParamsCtrl;
public IEventAggregator EventAggregator;
public Vector2? SelectionPosition;
}
public class EventLuckMagicSpinParams
{
public float MaxInterval;
public float MinInterval;
public int ExtraLoopCount;
public AnimationCurve IntervalLerpCurve;
}
public class EventLuckMagicSpinCtx
{
public EventLuckMagicRing Ring;
public int Index;
public ItemData Reward;
public bool doesHideButton;
public int RoundCount;
}
public class EventRewardFlyStashRequest
{
public ItemData Reward;
public bool DoesPlayOpen;
// public Vector2 Position;
// public float SourceIconSize;
public RectTransform SourceIconRt;
public RectTransform SourceTextRt;
public EventRewardFlyStashRequest(ItemData reward, RectTransform sourceIconRt, bool doesPlayOpen = true, RectTransform sourceTextRt = null)
{
Reward = reward;
DoesPlayOpen = doesPlayOpen;
SourceIconRt = sourceIconRt;
SourceTextRt = sourceTextRt;
}
}
public class EventLuckMagicPlayfabData
{
public int EventId;
public int TicketCount;
public int ChainProgress;
public int InnerState, MiddleState, OuterState;
public int RoundCount;
public System.DateTime? HigherRingExpireTime;
public EEventLuckMagicRingType HigherRingType;
public Dictionary<int, int> DicTasks;
public const string Key = "EventLuckMagicPlayfabData";
private const string Splitter = "|", Comma = ",";
private const int Count = 11;
public string Serialize()
{
var sb = new StringBuilder();
sb.Append(EventId).Append(Splitter);
sb.Append(TicketCount).Append(Splitter);
sb.Append(ChainProgress).Append(Splitter);
sb.Append(InnerState).Append(Splitter);
sb.Append(MiddleState).Append(Splitter);
sb.Append(OuterState).Append(Splitter);
sb.Append(HigherRingExpireTime).Append(Splitter);
sb.Append((int)HigherRingType).Append(Splitter);
sb.Append(RoundCount).Append(Splitter);
if (DicTasks != null)
{
foreach (var kv in DicTasks)
sb.Append(kv.Key).Append(Comma);
sb.Append(Splitter);
foreach (var kv in DicTasks)
sb.Append(kv.Value).Append(Comma);
}
return sb.ToString();
}
public static EventLuckMagicPlayfabData Deserialize(string s)
{
try
{
if (s == null || s == "")
return null;
var tokens = s.Trim(Splitter.ToCharArray()).Split(Splitter);
if (tokens.Length != Count)
{
var e = new Exception($"[EventLuckMagic]Wrong amount of parameters. Expect {Count}, but got {tokens.Length} in \"{s}\".");
Debug.LogError(e);
return null;
}
// Debug.Log($"[EventLuckMagic] time string:{tokens[6]}");
var keyList = tokens[9].Trim(Comma[0]).Split(Comma).Select(int.Parse).ToList();
var valueList = tokens[10].Trim(Comma[0]).Split(Comma).Select(int.Parse).ToList();
if (keyList == null || valueList == null || keyList.Count != valueList.Count)
{
var e = new Exception($"[EventLuckMagic]Dictionary Error.");
Debug.LogError(e);
return null;
}
var dicTasks = new Dictionary<int, int>();
for (int i = 0; i < keyList.Count; i++)
dicTasks.Add(keyList[i], valueList[i]);
return new EventLuckMagicPlayfabData
{
EventId = int.Parse(tokens[0]),
TicketCount = int.Parse(tokens[1]),
ChainProgress = int.Parse(tokens[2]),
InnerState = int.Parse(tokens[3]),
MiddleState = int.Parse(tokens[4]),
OuterState = int.Parse(tokens[5]),
HigherRingExpireTime = ParseTime(tokens[6]),
HigherRingType = (EEventLuckMagicRingType)int.Parse(tokens[7]),
RoundCount = int.Parse(tokens[8]),
DicTasks = dicTasks
};
}
catch (Exception e)
{
Debug.Log($"[EventLuckMagic] Deserialize error: ");
Debug.LogError(e);
return null;
}
}
private static System.DateTime ParseTime(string timeString)
{
if (timeString == "")
return System.DateTime.MinValue;
else
try
{
return System.DateTime.Parse(timeString);
}
catch
{
Debug.LogError($"[EventLuckMagic] Failed to parse time string \"{timeString}\"");
return System.DateTime.MinValue;
}
}
public void Save()
{
var s = Serialize();
// Debug.Log($"[EventLuckMagic] Save playfab data : \n" + s);
PlayFabMgr.Instance.UpdateUserDataValue(Key, s);
}
}
public class EventLuckMagicPlayerPreferenceData
{
public Vector2? SelectionPosition;
public bool DoesSkipAnimation;
public static string Key => "EventLuckMagic" + GContext.container.Resolve<IUserService>().UserId;
private const char Splitter = '|', Comma = ',';
public static EventLuckMagicPlayerPreferenceData CreateEmpty()
{
var res = new EventLuckMagicPlayerPreferenceData();
res.SelectionPosition = null;
res.DoesSkipAnimation = false;
return res;
}
public string Serialize()
{
var sb = new StringBuilder();
sb.Append(DoesSkipAnimation).Append(Splitter);
if (SelectionPosition != null)
sb.Append(SelectionPosition.Value.x).Append(Comma).Append(SelectionPosition.Value.y).Append(Splitter);
return sb.ToString();
}
public static EventLuckMagicPlayerPreferenceData Deserialize(string s)
{
var res = new EventLuckMagicPlayerPreferenceData();
if (s == null || s == "")
return res;
try
{
var tokens = s.Trim(Splitter).Split(Splitter);
res.DoesSkipAnimation = bool.Parse(tokens[0]);
if (tokens.Length > 1)
{
var posTokens = tokens[1].Split(Comma);
res.SelectionPosition = new Vector2(float.Parse(posTokens[0]), float.Parse(posTokens[1]));
}
else
res.SelectionPosition = null;
}
catch (System.Exception e)
{
Debug.LogError($"[EventLuckMagic] Failed to deserialize:");
Debug.LogError(e);
}
return res;
}
public void Save()
{
var s = Serialize();
PlayerPrefs.SetString(Key, s);
}
}
public class EventLuckMagicEntranceData
{
public int TicketCount;
public DateTime ExpiryTime;
public DateTime StartTime;
public TimeSpan RemainingTime => ExpiryTime - ZZTimeHelper.UtcNow();
public bool IsActive => ZZTimeHelper.UtcNow() >= StartTime && ZZTimeHelper.UtcNow() < ExpiryTime;
public string Icon;
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 02825821ddd5d8f4abab51362df6d069
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,23 @@
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using GameCore;
public class EventLuckMagicDrawButtonView : MonoBehaviour
{
[SerializeField] private TMP_Text textCost, textBtn;
public Button ButtonDraw;
public void Init(int cost, EEventLuckMagicRingType ringType)
{
textCost.text = $"x{cost}";
var key = ringType switch
{
EEventLuckMagicRingType.OuterRing => EventLuckMagicAct.OuterRingBtnKey,
EEventLuckMagicRingType.MiddleRing => EventLuckMagicAct.MiddleRingBtnKey,
EEventLuckMagicRingType.InnerRing => EventLuckMagicAct.InnerRingBtnKey,
_ => throw new System.NotImplementedException(),
};
textBtn.text = LocalizationMgr.GetText(key);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 904ecd1c7d17aa94e966465e3f67db95
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,84 @@
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using System;
using UnityEngine.UI;
using UniRx;
using asap.core;
using game;
using GameCore;
public class EventLuckMagicEntranceButton : EventButtonResource
{
[SerializeField] private TMP_Text textTimer;
[SerializeField] private Button button;
[SerializeField] private Image icon;
private ILoadResourceService _loadResourceService;
private EventLuckMagicEntranceData _data;
private const string RedPointKey = "eventluckmagic.entrance";
private void Awake()
{
var model = GContext.container.Resolve<EventLuckMagicModel>();
if (model == null || model.RemainingTime.TotalSeconds <= 0)
{
gameObject.SetActive(false);
return;
}
_data = model.ToEntranceData();
UpdateTimer();
Observable.Interval(TimeSpan.FromSeconds(1f)).Subscribe(UpdateTimer).AddTo(this);
_loadResourceService = GContext.container.Resolve<ILoadResourceService>();
button.onClick.AddListener(EnterActAsync);
RedPointManager.Instance.SetRedPointState(RedPointKey,
model.TicketCount >= EventLuckMagicAct.TableContext.GetTicketRedPointThreshold()
|| model.ToChainPackData().DoNeedPackRedPoint);
CheckResource(new List<string>() { UITypes.EventLuckMagicPanel.Path, _data.Icon, EventLuckMagicAct.ActAddressable });
}
private void UpdateTimer(long _ = 0L)
{
textTimer.text = ConvertTools.ConvertTime2(_data.RemainingTime);
if (!_data.IsActive && gameObject.activeSelf)
{
// Debug.Log("[EventLuckMagic] Time's up in entrance!");
var _model = GContext.container.Resolve<EventLuckMagicModel>();
_model?.DisposeLuckyTaskSubscription();
GContext.container.Unregister<EventLuckMagicModel>();
gameObject.SetActive(false);
}
}
private async void EnterActAsync()
{
try
{
bool isReady = await _loadResourceService.Loads(
new List<string>() { UITypes.EventLuckMagicPanel.Path, EventLuckMagicAct.ActAddressable });
if (isReady)
{
GContext.Publish(new UnloadActToNextAct { actId = EventLuckMagicAct.ActAddressable, TransitionPanel = UITypes.CloudTransitionPanel });
}
else
{
var panel = await UIManager.Instance.ShowUI(UITypes.CloudTransitionPanel);
panel.GetComponent<CloudTransitionPanel>()
.SetBtn(true, () => GContext.Publish(new UnloadActToNextAct(EventLuckMagicAct.ActAddressable)));
}
}
catch (Exception e)
{
Debug.Log($"<color=#22a6f2>[EventLuckMagic] EnterActError: {e.Message}\n{e.StackTrace}</color>");
throw;
}
}
protected override void OnLoadEventResource()
{
if (_data.IsActive)
{
GContext.container.Resolve<IUIService>().SetImageSprite(icon, _data.Icon);
gameObject.SetActive(true);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a6ecf7cc3c46e7a499df007317299e87
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,14 @@
public enum EEventLuckMagicBlockType
{
Outer = 0,
Middle = 1,
Inner = 2,
RoadSign = 3
}
public enum EEventLuckMagicRingType
{
OuterRing = 1,
MiddleRing = 2,
InnerRing = 3
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0a2950f967efdb543ba81e5582bd2307
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,40 @@
using TMPro;
using UnityEngine;
using GameCore;
using UnityEngine.UI;
public class EventLuckMagicInfoPanel : MonoBehaviour
{
[SerializeField] private TMP_Text textExplore, textItemTransform;
[SerializeField] private RewardItemNew[] ring;
[SerializeField] private RewardItemNew TaskRewardUpper, TaskRewardLower;
[SerializeField] private Button btnClose;
private const string Key = "UI_EventSandDigPanel_7";
private void Awake()
{
btnClose.onClick.AddListener(OnClickClose);
}
public void Init(EventLuckMagicInfo info)
{
textExplore.text = LocalizationMgr.GetText(EventLuckMagicAct.OuterRingBtnKey);
textItemTransform.text = LocalizationMgr.GetFormatTextValue(Key, LocalizationMgr.GetText(info.TicketNameKey));
TaskRewardUpper.SetData(info.TaskRewardUpper);
TaskRewardLower.SetData(info.TaskRewardLower);
for (int i = 0; i < ring.Length; i++)
ring[i].SetData(info.Blocks[i]);
}
private void OnClickClose()
{
UIManager.Instance.DestroyUI(UITypes.EventLuckMagicInfoPanel);
}
}
public class EventLuckMagicInfo
{
public string TicketNameKey;
public ItemData[] Blocks;
public ItemData TaskRewardUpper, TaskRewardLower;
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ea8dd1e4b5716084492e0794606cb7be
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,41 @@
using UnityEngine;
using System.Threading.Tasks;
public class EventLuckMagicLightView : MonoBehaviour
{
[SerializeField] private Animation ani;
private const string StandBy = "light_loop", Grand = "light_reward_grand", Normal = "light_reward";
public void PlayStandBy()
{
ani.Play(StandBy);
}
public async void PlayGrand()
{
try
{
ani.Play(Grand);
await Task.Delay(System.TimeSpan.FromSeconds(ani.GetClip(Grand).length));
ani.Play(StandBy);
}
catch (System.Exception e)
{
Debug.LogError(e);
}
}
public async void PlayNormal()
{
try
{
ani.Play(Normal);
await Task.Delay(System.TimeSpan.FromSeconds(ani.GetClip(Normal).length));
ani.Play(StandBy);
}
catch (System.Exception e)
{
Debug.LogError(e);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 006414390db362942a7594e21ba79ee6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,511 @@
using UniRx;
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using System.Linq;
using UnityEngine.Assertions;
using System.Threading.Tasks;
using System;
using game;
using asap.core.common;
using GameCore;
using Game;
using asap.core;
public class EventLuckMagicMainPanel : MonoBehaviour
{
[SerializeField] private EventLuckMagicBlockView[] outerRing, middleRing, innerRing;
[SerializeField] private Button btnClose, btnTicket, btnInfo;
[SerializeField] private GameObject singleBtnGroup, doubleBtnGroup, goClickMask, fxReset;
[SerializeField] private TMP_Text textTicketCount, textHigherRingCountDown, textTimer;
[SerializeField] private EventLuckMagicTaskView[] taskViews;
[SerializeField] private RewardFly rewardFlyPrefab;
// [SerializeField] private RewardStashButton _rewardStashButton;
[SerializeField] private EventLuckMagicDrawButtonView btnDrawCurrentSingle, btnDrawCurrentDouble, btnDrawHigher;
[SerializeField] private EventLuckMagicSkipAnimationBtn skipSingle, skipDouble;
[SerializeField] private EventLuckMagicLightView lightView;
[SerializeField] private EventLuckMagicSelectionView selectionView;
[SerializeField] private LuckyTaskBtn luckyTaskBtn;
// private EventLuckMagicModel _model;
private EventLuckMagicSystem _system;
private EventLuckMagicTableContext _tableContext;
private EventLuckMagicParamsCtrl _paramsCtrl;
private IEventAggregator _eventAggregator;
private IObjectPoolService _objectPoolService;
private Dictionary<int, EventLuckMagicTaskView> _taskViewDict;
private EventLuckMagicSpinParams _outerSpinParams, _innerSpinParams, _middleSpinParams;
private const float RewardFlyDuration = 1.2f, resetFxDuration = 0.8f;
private int _evIsEnd, _evItemCost, _evRing, _evSquareId, _evRewardId, _evRewardCount,
_evAchieve_target_reward1, _evAchieve_target_reward2, _evTurnItem1, _evTurnItem2, _evRound;
private const string SfxSelectionStrong = "audio_ui_luckmagic_select_1", SfxSelectionWeak = "audio_ui_luckmagic_select_2";
private void Start()
{
btnClose.onClick.AddListener(OnClickClose);
var _model = GContext.container.Resolve<EventLuckMagicModel>();
btnDrawCurrentSingle.ButtonDraw.onClick.AddListener(() => DrawCurrentRing());
btnDrawCurrentDouble.ButtonDraw.onClick.AddListener(() => DrawCurrentRing());
btnDrawHigher.ButtonDraw.onClick.AddListener(() => DrawHigherRing());
btnTicket.onClick.AddListener(OnClickPack);
EventLuckMagicAct.EventAggregator.GetEvent<EventLuckMagicTicketChange>()
.Subscribe(_ => UpdateTicketCount()).AddTo(this);
btnInfo.onClick.AddListener(OnClickInfo);
lightView.PlayStandBy();
fxReset.SetActive(false);
luckyTaskBtn.Init(_model, _model.LuckyTaskRedPointKey);
}
public void Init(Vector2? selectionPosition = null)
{
_tableContext = EventLuckMagicAct.TableContext;
var _model = GContext.container.Resolve<EventLuckMagicModel>();
_system = EventLuckMagicAct.System;
GetParams(_model.ParamsCtrl);
for (int i = 0; i < outerRing.Length; i++)
outerRing[i].Init(_model.OuterRing.Blocks[i]);
for (int i = 0; i < middleRing.Length; i++)
middleRing[i].Init(_model.MiddleRing.Blocks[i]);
for (int i = 0; i < innerRing.Length; i++)
innerRing[i].Init(_model.InnerRing.Blocks[i]);
SetDrawButtons(!_model.HigherRingData.DoesExist);
_taskViewDict = new Dictionary<int, EventLuckMagicTaskView>();
var taskInfo = _tableContext.GetTaskInfo(_model.RoundCount);
for (int i = 0; i < taskInfo.Count; i++)
_taskViewDict.Add(taskInfo.Keys.ToList()[i], taskViews[i]);
UpdateTicketCount();
foreach (var kv in taskInfo)
_taskViewDict[kv.Key].Init(_model.TaskProgress[kv.Key], kv.Value, kv.Key);
_eventAggregator = EventLuckMagicAct.EventAggregator;
selectionView.ShowStandByOrHide(selectionPosition);
CreateRewardFlyObjectPool();
// _rewardStashButton.Init(_eventAggregator);
_eventAggregator.GetEvent<EventLuckMagicClickRoadSignNow>()
.Subscribe(_ => DrawHigherRing(true)).AddTo(this);
skipSingle.Init();
skipDouble.Init();
UpdateTimer();
Observable.Interval(TimeSpan.FromSeconds(1f)).Subscribe(UpdateTimer).AddTo(this);
var chainPackData = _model.ToChainPackData();
RedPointManager.Instance.SetRedPointState(chainPackData.RedPointKey, chainPackData.DoNeedPackRedPoint);
}
private async void ResetPanel()
{
var _model = GContext.container.Resolve<EventLuckMagicModel>();
try
{
// Debug.Log($"<color=red>[EventLuckMagic] ResetPanel.</color>");
SetDrawButtons(!_model.HigherRingData.DoesExist);
UpdateTicketCount();
selectionView.ShowStandByOrHide();
_taskViewDict.Values.Select((v, i) => (v, i)).ToList()
.ForEach(vi =>
{
vi.v.ResetTask(EventLuckMagicAct.TableContext.GetTaskReward(_model.RoundCount, vi.i == 0));
vi.v.PlayAnimation();
});
skipSingle.Init();
skipDouble.Init();
fxReset.SetActive(false);
fxReset.SetActive(true);
await Task.Delay(TimeSpan.FromSeconds(resetFxDuration));
for (int i = 0; i < outerRing.Length; i++)
outerRing[i].Init(_model.OuterRing.Blocks[i]);
for (int i = 0; i < middleRing.Length; i++)
middleRing[i].Init(_model.MiddleRing.Blocks[i]);
for (int i = 0; i < innerRing.Length; i++)
innerRing[i].Init(_model.InnerRing.Blocks[i]);
BlockInput(false);
}
catch (Exception e)
{
Debug.Log($"<color=red>[EventLuckMagic] ResetPanel error.</color>");
Debug.Log(e);
}
}
private void OnClickClose()
{
var _model = GContext.container.Resolve<EventLuckMagicModel>();
// Debug.Log($"<color=red>[EventLuckMagic] OnClickClose.</color>");
_model.ToPfData().Save();
_model.ToPpData().Save();
ReleaseRewardFlyObjectPool();
GContext.Publish(new UnloadActToNextAct());
}
private void SetDrawButtons(bool doesShowSingle)
{
var _model = GContext.container.Resolve<EventLuckMagicModel>();
singleBtnGroup.SetActive(doesShowSingle);
doubleBtnGroup.SetActive(!doesShowSingle);
skipSingle.Init();
skipDouble.Init();
if (!doesShowSingle)
{
StartCoroutine(ScrapRoadSignCountDown());
}
if (_model.CurrentRing == null)
return;
btnDrawCurrentSingle.Init(_model.CurrentRing.Cost, _model.CurrentRing.RingType);
btnDrawCurrentDouble.Init(_model.CurrentRing.Cost, _model.CurrentRing.RingType);
if (_model.HigherRingData.DoesExist)
btnDrawHigher.Init(_model.HigherRingData.Ring.Cost, _model.HigherRingData.Ring.RingType);
}
private IEnumerator ScrapRoadSignCountDown()
{
var _model = GContext.container.Resolve<EventLuckMagicModel>();
while (_model.HigherRingData.DoesExist)
{
textHigherRingCountDown.text = LocalizationMgr.GetFormatTextValue("UI_COMMON_end", ConvertTools.ConvertTime2(_model.HigherRingData.RemainingTime));
yield return new WaitForSeconds(1);
}
SetDrawButtons(true);
}
private void UpdateTicketCount()
{
var _model = GContext.container.Resolve<EventLuckMagicModel>();
textTicketCount.text = $"{_model.TicketCount}";
}
# if UNITY_EDITOR
private void Update()
{
if (Input.GetKeyDown(KeyCode.T))
{
_debugFlag = !_debugFlag;
}
}
private bool _debugFlag = false;
# endif
private void DrawCurrentRing(bool hideButton = false)
{
DrawInRing(GContext.container.Resolve<EventLuckMagicModel>().CurrentRing, hideButton);
}
private void DrawHigherRing(bool hideButton = true)
{
DrawInRing(GContext.container.Resolve<EventLuckMagicModel>().HigherRingData.Ring, hideButton);
}
private void DrawInRing(EventLuckMagicRing ring, bool doesHideButton = false)
{
var _model = GContext.container.Resolve<EventLuckMagicModel>();
if (ring == null)
{
Debug.LogError($"[EventLuckMagic] Ring is null.");
return;
}
if (_model.TicketCount < ring.Cost)
{
// Debug.Log($"[EventLuckMagic] Insufficient tickets.");
OnClickPack();
return;
}
if (!_system.Draw(ring, out var spinCtx, out _evSquareId))
{
ResetPanel();
return;
}
# if UNITY_EDITOR
if (_debugFlag)
{
if (ring.RingType == EEventLuckMagicRingType.OuterRing)
{
spinCtx.Index = 14;
spinCtx.Reward = new ItemData(8030102, 1);
}
else if (ring.RingType == EEventLuckMagicRingType.MiddleRing)
{
spinCtx.Index = 4;
spinCtx.Reward = new ItemData(8030103, 1);
}
}
# endif
BlockInput(true);
spinCtx.doesHideButton = doesHideButton;
if (doesHideButton)
{
_model.HigherRingData.SetEmpty();
}
_model.AddTicket(-ring.Cost);
_system.GrantReward(spinCtx);
_model.ToPfData().Save();
_evIsEnd = _model.IsGameDepleted ? 1 : 0;
_evItemCost = ring.Cost;
_evRing = ring.RingType switch
{
EEventLuckMagicRingType.OuterRing => 1,
EEventLuckMagicRingType.MiddleRing => 2,
EEventLuckMagicRingType.InnerRing => 3,
_ => 0
};
_evRewardId = spinCtx.Reward.id;
_evRewardCount = (int)spinCtx.Reward.count;
var keys = _model.TaskProgress.Keys.ToList();
_evAchieve_target_reward1 = spinCtx.Reward.id == keys[0] && _model.TaskProgress[keys[0]] >= 3 ? 1 : 0;
_evAchieve_target_reward2 = spinCtx.Reward.id == keys[1] && _model.TaskProgress[keys[1]] >= 3 ? 1 : 0;
_evTurnItem1 = _tableContext.IsRewardRoadSign(EEventLuckMagicRingType.OuterRing, spinCtx.Reward.id) ? 1 : 0;
_evTurnItem2 = _tableContext.IsRewardRoadSign(EEventLuckMagicRingType.MiddleRing, spinCtx.Reward.id) ? 1 : 0;
_evRound = _model.RoundCount;
// Debug.Log($"<color=red>[EventLuckMagic] -------------------Event Tracking---------------------</color>");
// Debug.Log($"[EventLuckMagic] is_end: {_evIsEnd}");
// Debug.Log($"[EventLuckMagic] item_cost: {_evItemCost}");
// Debug.Log($"[EventLuckMagic] ring: {_evRing}");
// Debug.Log($"[EventLuckMagic] square_id: {_evSquareId}");
// Debug.Log($"[EventLuckMagic] reward_id: {_evRewardId}");
// Debug.Log($"[EventLuckMagic] reward_count: {_evRewardCount}");
// Debug.Log($"[EventLuckMagic] achieve_target_reward1: {_evAchieve_target_reward1}");
// Debug.Log($"[EventLuckMagic] achieve_target_reward2: {_evAchieve_target_reward2}");
// Debug.Log($"[EventLuckMagic] turn_item1: {_evTurnItem1}");
// Debug.Log($"[EventLuckMagic] turn_item2: {_evTurnItem2}");
// Debug.Log($"[EventLuckMagic] -------------------End of Event Tracking---------------------");
# if AGG
using (var e = GEvent.GameEvent("event_luckmagic"))
{
e.AddContent("round", _evRound)
.AddContent("is_end", _evIsEnd)
.AddContent("item_cost", _evItemCost)
.AddContent("ring", _evRing)
.AddContent("square_id", _evSquareId)
.AddContent("reward_id", _evRewardId)
.AddContent("reward_count", _evRewardCount)
.AddContent("achieve_target_reward1", _evAchieve_target_reward1)
.AddContent("achieve_target_reward2", _evAchieve_target_reward2)
.AddContent("turn_item1", _evTurnItem1)
.AddContent("turn_item2", _evTurnItem2);
}
# endif
switch (ring.RingType)
{
case EEventLuckMagicRingType.OuterRing:
SpinWheel(spinCtx, outerRing, _outerSpinParams);
break;
case EEventLuckMagicRingType.MiddleRing:
SpinWheel(spinCtx, middleRing, _middleSpinParams);
break;
case EEventLuckMagicRingType.InnerRing:
SpinWheel(spinCtx, innerRing, _innerSpinParams);
break;
}
}
private async void SpinWheel(EventLuckMagicSpinCtx spinCtx, EventLuckMagicBlockView[] blockViews, EventLuckMagicSpinParams p)
{
var _model = GContext.container.Resolve<EventLuckMagicModel>();
try
{
var ringData = spinCtx.Ring;
var end = spinCtx.Index;
Assert.IsTrue(ringData.Blocks.Count == blockViews.Length,
$"RingData.Blocks.Count {ringData.Blocks.Count} != blockViews.Length {blockViews.Length}");
ringData.GetLoopAnimationInfo(end, p.ExtraLoopCount, out int startIdx, out int stepCount);
selectionView.ShowBlinkOrStandBy(blockViews[startIdx].transform.position);
int i = 0;
float interval = 0, ratio;
EventLuckMagicBlockView targetBlock = null;
if (!_model.DoesSkipAnimation)
{
while (i < stepCount)
{
ratio = p.IntervalLerpCurve.Evaluate((float)i / stepCount);
interval = Mathf.Lerp(p.MinInterval, p.MaxInterval, ratio);
await Task.Delay(TimeSpan.FromSeconds(interval));
i++;
targetBlock = blockViews[(startIdx + i) % blockViews.Length];
selectionView.ShowBlinkOrStandBy(targetBlock.transform.position);
GContext.Publish(new EventUISound(i % 2 == 0 ? SfxSelectionStrong : SfxSelectionWeak));
}
await Task.Delay(TimeSpan.FromSeconds(interval));
if (targetBlock == null)
{
BlockInput(false);
return;
}
}
else
{
targetBlock = blockViews[(startIdx + stepCount) % blockViews.Length];
selectionView.ShowBlinkOrStandBy(targetBlock.transform.position);
}
selectionView.ShowBlinkOrStandBy();
_model.ToPpData().Save();
if (_tableContext.IsRewardRoadSign(spinCtx.Reward.id, out _, out var dropId, out _))
{
// SetDrawButtons(false);
lightView.PlayNormal();
var alternativeReward = GContext.container.Resolve<PlayerItemData>().GetItemDataByDropId(dropId)[0];
GContext.Publish(new EventRewardFlyStashRequest(alternativeReward, targetBlock.GetComponent<RectTransform>()));
await Task.Delay(TimeSpan.FromSeconds(RewardFlyDuration));
var higherRingData = _model.HigherRingData;
var tcs = new TaskCompletionSource<bool>();
(await UIManager.Instance.ShowUINotLoading(UITypes.EventLuckMagicRoadSignPanel))
.GetComponent<EventLuckMagicRoadSignPanel>()
.Init(higherRingData.ExpireTime, ringData.RoadSignId,
higherRingData.Ring.RingType, higherRingData.Ring.Cost, tcs);
BlockInput(false);
await tcs.Task;
SetDrawButtons(!_model.HigherRingData.DoesExist);
}
else
{
lightView.PlayGrand();
if (_model.HigherRingData.DoesExist && _model.CurrentRing == _model.HigherRingData.Ring)
_model.HigherRingData.SetEmpty();
if (_tableContext.IsRewardProgressItem(spinCtx.Reward.id, 0, out _))
{
targetBlock.SetReceived(true);
SetDrawButtons(!_model.HigherRingData.DoesExist);
var e = new EventRewardFlyStashRequest(spinCtx.Reward, targetBlock.GetComponent<RectTransform>());
await taskViews[0].OnRewardFlyRequest(e);
await taskViews[1].OnRewardFlyRequest(e);
if (_model.TaskProgress[spinCtx.Reward.id] < EventLuckMagicModel.TaskProgressCount)
{
BlockInput(false);
return;
}
var rewardPanel = (await UIManager.Instance.ShowUINotLoading(UITypes.EventLuckMagicTaskRewardPopupPanel))
.GetComponent<EventLuckMagicTaskRewardPopupPanel>();
Debug.Log($"[EventLuckMagic] RoundCount: {_model.RoundCount}");
var taskInfo = _tableContext.GetTaskInfo(_model.RoundCount);
var tcs = new TaskCompletionSource<bool>();
rewardPanel.Init(new EventLuckMagicRewardPanelInfo
{
Reward = taskInfo[spinCtx.Reward.id],
TaskItemId = spinCtx.Reward.id,
TaskCompletionSource = tcs
});
BlockInput(false);
await tcs.Task;
}
else
{
lightView.PlayNormal();
targetBlock.SetReceived(true);
SetDrawButtons(!_model.HigherRingData.DoesExist);
// Broadcast to reward stash button
GContext.Publish(new EventRewardFlyStashRequest(spinCtx.Reward, targetBlock.GetComponent<RectTransform>()));
await Task.Delay(TimeSpan.FromSeconds(RewardFlyDuration));
BlockInput(false);
}
}
if (_model.IsGameDepleted)
{
Debug.Log($"[EventLuckMagic] Game Depleted @ Current Ring. Old RoundCOunt: {_model.RoundCount}");
//TODO: Reset performance
_model.AddRoundCount();
_model.Reset();
ResetPanel();
return;
}
}
catch (Exception ex)
{
Debug.LogError("[EventLuckMagic] SpinWheel error.");
Debug.LogError(ex);
BlockInput(false);
}
}
private void CreateRewardFlyObjectPool()
{
_objectPoolService = GContext.container.Resolve<IObjectPoolService>();
_objectPoolService.CreatePool(rewardFlyPrefab, 0, 10);
}
private void ReleaseRewardFlyObjectPool()
{
_objectPoolService?.DestroyPool(typeof(RewardFly));
}
private void GetParams(EventLuckMagicParamsCtrl p)
{
_paramsCtrl = p;
_outerSpinParams = new EventLuckMagicSpinParams()
{
MaxInterval = _paramsCtrl.OuterIntervalMax,
MinInterval = _paramsCtrl.OuterIntervalMin,
ExtraLoopCount = _paramsCtrl.OuterExtraLoopCount,
IntervalLerpCurve = _paramsCtrl.OuterIntervalLerpCurve,
};
_middleSpinParams = new EventLuckMagicSpinParams()
{
MaxInterval = _paramsCtrl.InnerIntervalMax,
MinInterval = _paramsCtrl.InnerIntervalMin,
ExtraLoopCount = _paramsCtrl.MiddleExtraLoopCount,
IntervalLerpCurve = _paramsCtrl.InnerIntervalLerpCurve,
};
_innerSpinParams = new EventLuckMagicSpinParams()
{
MaxInterval = _paramsCtrl.InnerIntervalMax,
MinInterval = _paramsCtrl.InnerIntervalMin,
ExtraLoopCount = _paramsCtrl.InnerExtraLoopCount,
IntervalLerpCurve = _paramsCtrl.InnerIntervalLerpCurve,
};
}
private async void OnClickPack()
{
// var chainData = GContext.container.Resolve<EventLuckMagicModel>().ToChainPackData();
// if (chainData.IsChainPackDepleted)
// {
// var normalPanel = (await UIManager.Instance.ShowUINotLoading(UITypes.LackOfCommonItemPopupPanel))
// .GetComponent<LackOfCommonItemPopupPanel>();
// normalPanel.Init(EventLuckMagicAct.TableContext.GetLackOfTicketPanelInfo());
// }
// else
// {
// var chainPanel = (await UIManager.Instance.ShowUINotLoading(UITypes.EventLuckMagicChainPackPanel))
// .GetComponent<ChainPackPanel>();
// chainPanel.Init(chainData);
// }
var triplePackPanel = (await UIManager.Instance.ShowUINotLoading(UITypes.EventLuckMagicTriplePackPanel))
.GetComponent<EventLuckyTriplePackPanel>();
triplePackPanel.Init(EventLuckyTriplePackData.Create(EventLuckMagicAct.TableContext.EventId, EventLuckMagicAct.TableContext.PackId));
}
private void UpdateTimer(long _ = 0L)
{
var _model = GContext.container.Resolve<EventLuckMagicModel>();
textTimer.text = LocalizationMgr.GetFormatTextValue("UI_COMMON_end", ConvertTools.ConvertTime2(_model.RemainingTime));
if (_model.RemainingTime.TotalSeconds <= 0)
OnTimeUp();
}
private void OnTimeUp()
{
// Debug.Log("[EventLuckMagic] Time's up in panel!");
OnClickClose();
var _model = GContext.container.Resolve<EventLuckMagicModel>();
_model?.DisposeLuckyTaskSubscription();
GContext.container.Unregister<EventLuckMagicModel>();
}
private async void OnClickInfo()
{
var panel = (await UIManager.Instance.ShowUINotLoading(UITypes.EventLuckMagicInfoPanel)).GetComponent<EventLuckMagicInfoPanel>();
panel.Init(EventLuckMagicAct.TableContext.GetInfoPanelInfo());
}
private void BlockInput(bool doesBlock)
{
goClickMask.SetActive(doesBlock);
}
}
public class EventLuckMagicTicketChange { }
/* public class EventLuckMagicBlockInput
{
public bool DoesBlock;
} */

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ab1bd0944c5dc2f4dba59594ec595923
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,19 @@
using UnityEngine;
[CreateAssetMenu(fileName = "EventLuckMagicParamsCtrl", menuName = "ScriptableObjects/EventParamsCtrl/LuckMagic")]
public class EventLuckMagicParamsCtrl : ScriptableObject
{
public float OuterIntervalMin = 0.1f;
public float OuterIntervalMax = 0.8f;
public int OuterExtraLoopCount = 1;
public AnimationCurve OuterIntervalLerpCurve;
public int MiddleExtraLoopCount = 2;
public float InnerIntervalMin = 0.2f;
public float InnerIntervalMax = 0.9f;
public int InnerExtraLoopCount = 2;
public AnimationCurve InnerIntervalLerpCurve;
public float RewardPopupPanelCloseDelay = 1f;
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6fb7a10ad1a21834980027d1b8c95ef6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,62 @@
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using GameCore;
using UniRx;
using asap.core;
using cfg;
using System.Threading.Tasks;
public class EventLuckMagicRoadSignPanel : MonoBehaviour
{
[SerializeField] private TMP_Text textTimer;
[SerializeField] private Image iconSign;
[SerializeField] private Button btnLater, btnClose;
[SerializeField] private EventLuckMagicDrawButtonView btnNow;
private System.DateTime _expireTime;
private System.TimeSpan RemainingTime => _expireTime - ZZTimeHelper.UtcNow();
private TaskCompletionSource<bool> _tcs;
public void Init(System.DateTime expireTime, int roadSignId, EEventLuckMagicRingType higherRingType,
int higherRingCost, TaskCompletionSource<bool> taskCompletionSource)
{
btnClose.onClick.AddListener(OnClickClose);
btnLater.onClick.AddListener(OnClickClose);
btnNow.ButtonDraw.onClick.AddListener(OnClickNow);
_expireTime = expireTime;
UpdateTimer();
Observable.Interval(System.TimeSpan.FromSeconds(1)).Subscribe(UpdateTimer).AddTo(this);
btnNow.Init(higherRingCost, higherRingType);
var roadSignIcon = GContext.container.Resolve<Tables>().TbItem[roadSignId].Icon;
GContext.container.Resolve<IUIService>().SetImageSprite(iconSign, roadSignIcon);
_tcs = taskCompletionSource;
}
private void OnClickClose()
{
_tcs.SetResult(false);
UIManager.Instance.DestroyUI(UITypes.EventLuckMagicRoadSignPanel);
}
private void UpdateTimer(long _ = 0L)
{
textTimer.text = LocalizationMgr.GetFormatTextValue("UI_COMMON_end", ConvertTools.ConvertTime2(RemainingTime));
if (RemainingTime.TotalSeconds <= 0)
OnClickClose();
}
private void OnClickNow()
{
UIManager.Instance.DestroyUI(UITypes.EventLuckMagicRoadSignPanel);
EventLuckMagicAct.EventAggregator.Publish(new EventLuckMagicClickRoadSignNow());
_tcs.SetResult(true);
}
}
public class EventLuckMagicClickRoadSignNow { }
/* public enum EEventLuckMagicRoadSignExitType
{
Now,
Later
} */

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 99f8e6e0da5b81d4fa4ae358e16c747b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,33 @@
using UnityEngine;
public class EventLuckMagicSelectionView : MonoBehaviour
{
[SerializeField] private GameObject fxLoop, fxNormal;
public void ShowStandByOrHide(Vector2? position = null)
{
if (!position.HasValue)
{
gameObject.SetActive(false);
return;
}
transform.position = position.Value;
gameObject.SetActive(true);
fxLoop.SetActive(true);
fxNormal.SetActive(false);
}
public void ShowBlinkOrStandBy(Vector2? position = null)
{
gameObject.SetActive(true);
if (!position.HasValue)
{
fxLoop.SetActive(true);
fxNormal.SetActive(false);
return;
}
transform.position = position.Value;
fxLoop.SetActive(false);
fxNormal.SetActive(true);//
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 822c8fcf2df9551448386dbe5884e1db
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,43 @@
using System.Collections;
using asap.core;
using UnityEngine;
using UnityEngine.UI;
public class EventLuckMagicSkipAnimationBtn : MonoBehaviour
{
private bool _doesSkip;
[SerializeField] private Button btn;
[SerializeField] private GameObject mark;
private float _clickInterval = 0.3f;
private void Start()
{
btn.onClick.AddListener(OnClick);
}
public void Init()
{
UpdateState();
}
private void UpdateState()
{
var model = GContext.container.Resolve<EventLuckMagicModel>();
_doesSkip = model.DoesSkipAnimation;
mark.SetActive(_doesSkip);
}
private void OnClick()
{
var model = GContext.container.Resolve<EventLuckMagicModel>();
model.DoesSkipAnimation = !model.DoesSkipAnimation;
UpdateState();
btn.interactable = false;
StopAllCoroutines();
StartCoroutine(ResetCountDown());
}
private IEnumerator ResetCountDown()
{
yield return new WaitForSeconds(_clickInterval);
btn.interactable = true;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5943c2c5e7b2afe419e87f6f9b655205
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,107 @@
using UnityEngine;
using GameCore;
using asap.core;
using System.Linq;
public class EventLuckMagicSystem
{
public const int BoardSize = 6;
private readonly PlayerItemData _playerItemData;
public EventLuckMagicSystem()
{
_playerItemData = GContext.container.Resolve<PlayerItemData>();
}
/// <summary>
/// Draw a random block from the ring.
/// </summary>
/// <param name="idx">The index of chosen block. Will be -1 if this draw fails.</param>
/// <param name="reward">The reward to be shown. Will be null if this draw fails.</param>
/// <returns>True if successfully get a index and reward.</returns>
public bool Draw(EventLuckMagicRing ring, out EventLuckMagicSpinCtx spinCtx, out int targetBlockTableId)
{
var _model = GContext.container.Resolve<EventLuckMagicModel>();
spinCtx = new EventLuckMagicSpinCtx();
spinCtx.Ring = ring;
spinCtx.Index = -1;
spinCtx.Reward = null;
targetBlockTableId = -1;
if (ring.IsDepleted)
{
Debug.Log($"[EventLuckMagic] This ring is Depleted.");
if (_model.IsGameDepleted)
{
_model.AddRoundCount();
_model.Reset();
}
return false;
}
var dic = ring.Blocks.Select((block, index) => (block, index))
.Where(x => x.block.IsTaken == false)
.ToDictionary(x => x.index, x => x.block.Weight);
var keys = dic.Keys.ToArray();
var weights = dic.Values.ToArray();
spinCtx.Index = keys[FtMathUtils.GetRandomIdxFromWeightList(weights)];
spinCtx.Reward = ring.Blocks[spinCtx.Index].Reward;
targetBlockTableId = ring.Blocks[spinCtx.Index].TableId;
spinCtx.RoundCount = _model.RoundCount;
return true;
}
public void GrantReward(EventLuckMagicSpinCtx spinCtx)
{
if (spinCtx == null || spinCtx.Reward == null)
return;
var _model = GContext.container.Resolve<EventLuckMagicModel>();
// Debug.Log($"[EventLuckMagic] Grant Reward {reward.id} * {reward.count}.");
var reward = spinCtx.Reward;
var sourceRing = spinCtx.Ring;
var idx = spinCtx.Index;
if (EventLuckMagicAct.TableContext.IsRewardRoadSign(reward.id, out var expireDuration, out int dropId, out _)
&& sourceRing.RingType != EEventLuckMagicRingType.InnerRing)
{
_model.LinkRings();
_model.HigherRingData.PointTo(sourceRing.HigherRing);
_model.HigherRingData.Activate(expireDuration);
// _playerItemData.AddItemByDrop(dropId);
GContext.Publish(new DeferredRewardStashService.EventStashDrop {DropId = dropId});
}
else if (EventLuckMagicAct.TableContext.IsRewardProgressItem(reward.id, spinCtx.RoundCount, out dropId))
{
sourceRing.Blocks[idx].Take();
_model.LinkRings();
_model.HigherRingData.PointTo(sourceRing.HigherRing);
// _playerItemData.AddItemByDrop(dropId, stash: true);
_model.UpdateTaskProgress(reward.id);
if (_model.IsTaskCompleted(reward.id))
{
// var progressReward = _playerItemData.AddItemByDrop(dropId)[0];
GContext.Publish(new DeferredRewardStashService.EventStashDrop {DropId = dropId});
}
}
else
{
sourceRing.Blocks[idx].Take();
_model.LinkRings();
_model.HigherRingData.PointTo(sourceRing.HigherRing);
// _playerItemData.AddItem(reward);
GContext.Publish(new DeferredRewardStashService.EventStashItem { Item = reward });
}
}
}
public class EventLuckMagicDrawEvent
{
public readonly EEventLuckMagicRingType Ring;
public readonly int Index;
public readonly ItemData Reward;
public bool DoesReset = false;
public EventLuckMagicDrawEvent(int index, ItemData reward, EEventLuckMagicRingType ring, bool reset = false)
{
Index = index;
Reward = reward;
Ring = ring;
DoesReset = reset;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8be8363aa80a11142872f29edf782b49
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,286 @@
using cfg;
using asap.core;
using System.Linq;
using GameCore;
using System.Collections.Generic;
using UnityEngine;
using System;
/// <summary>
/// Utility to get table data. Can only be used when event is active.
/// </summary>
public class EventLuckMagicTableContext
{
private FishingEvent _tableEvent;
private EventLuckMagic _tableMain;
private EventLuckMagicDrop[] _tableBlockDrops;
private TbEventLuckMagicLevel _tableRings;
private HashSet<int> _roadSignIds;
private PlayerItemData _playerItemData;
private FishingEventCycleItem3 _tableCycle;
private EventPackManager _packData;
private Tables _tables;
private EventLuckMagicTableContext() { }
public static EventLuckMagicTableContext ReadTables(int eventId)
{
var ctx = new EventLuckMagicTableContext();
ctx._tables = GContext.container.Resolve<Tables>();
var tables = ctx._tables;
var redirectId = tables.TbFishingEvent[eventId].RedirectID;
var cycleId = tables.TbFishingEventCycleItem3[redirectId].RedirectID;
ctx._tableEvent = tables.TbFishingEvent[eventId];
ctx._tableMain = tables.TbEventLuckMagic[cycleId];
ctx._tableCycle = tables.TbFishingEventCycleItem3[cycleId];
ctx._tableRings = tables.TbEventLuckMagicLevel;
ctx._roadSignIds = ctx._tableRings.DataList.Select(x => x.TurnItem).ToHashSet();
ctx._tableBlockDrops = tables.TbEventLuckMagicDrop.DataList.OrderBy(x => x.ID).ToArray();
ctx._playerItemData = GContext.container.Resolve<PlayerItemData>();
ctx._packData = tables.TbEventPackManager[ctx._tableMain.PackId];
return ctx;
}
public void GetBlocksInfo(out List<EventLuckMagicBlockInfo> infos)
{
infos = new List<EventLuckMagicBlockInfo>();
foreach (var bd in _tableBlockDrops)
{
var info = new EventLuckMagicBlockInfo();
info.RingType = (EEventLuckMagicRingType)(bd.ID / 100 % 10 /* - 1 */);
info.Reward = new ItemData(bd.Item, bd.Count);
_playerItemData.ItemTransition(info.Reward);
info.Weight = bd.Weight;
info.TableId = bd.ID;
infos.Add(info);
}
}
public void GetRingsInfo(out int[] costs, out int[] roadSignIds)
{
costs = _tableRings.DataList.Select(x => x.CostNumber).ToArray();
roadSignIds = _tableRings.DataList.Select(x => x.TurnItem).ToArray();
}
public bool IsRewardRoadSign(EEventLuckMagicRingType ringType, int rewardId)
{
if (!_tableRings.DataMap.TryGetValue((int)ringType, out var ring))
{
Debug.Log($"[EventLuckMagic] No table data found for ring type {ringType}");
return false;
}
return ring.TurnItem == rewardId;
}
public bool IsRewardRoadSign(int rewardId, out int expireDuration, out int drop, out int[] weightConfig)
{
var res = _roadSignIds.Contains(rewardId);
// Debug.Log($"[EventLuckMagic] {res}: {rewardId} is road sign?");
if (res)
{
var line = _tableRings.DataList.Where(x => x.TurnItem == rewardId).First();
expireDuration = line.TurnTime;
drop = line.TurnDrop;
weightConfig = line.TurnConfig.ToArray();
}
else
{
expireDuration = 0;
drop = 0;
weightConfig = null;
}
return res;
}
public bool IsRewardProgressItem(int rewardId, int roundCount, out int drop)
{
var idSeven = _tableMain.TargetRewardItem1;
var idHeart = _tableMain.TargetRewardItem2;
if (rewardId == idSeven)
{
drop = GetTaskRewardDropId(roundCount, true);
return true;
}
else if (rewardId == idHeart)
{
drop = GetTaskRewardDropId(roundCount, false);
return true;
}
drop = 0;
return false;
}
public EEventLuckMagicItemType JudgeItemId(int rewardId)
{
if (rewardId == _tableMain.TargetRewardItem1)
{
return EEventLuckMagicItemType.UpperTaskItem;
}
else if (rewardId == _tableMain.TargetRewardItem2)
{
return EEventLuckMagicItemType.LowerTaskItem;
}
return EEventLuckMagicItemType.None;
}
public bool IsRewardSpecial(int rewardId)
{
return IsRewardRoadSign(rewardId, out _, out _, out _) || IsRewardProgressItem(rewardId, 0, out _);
}
public Dictionary<int, ItemData> GetTaskInfo(int roundCount)
{
return new Dictionary<int, ItemData>()
{
{
_tableMain.TargetRewardItem1,
_playerItemData.GetItemDataByDropId(_tableMain.TargetRewardDrop1[roundCount < _tableMain.TargetRewardDrop1.Count ? roundCount : _tableMain.TargetRewardDrop1.Count - 1])[0]
},
{
_tableMain.TargetRewardItem2,
_playerItemData.GetItemDataByDropId(_tableMain.TargetRewardDrop2[roundCount < _tableMain.TargetRewardDrop2.Count ? roundCount : _tableMain.TargetRewardDrop2.Count - 1])[0]
},
};
}
public int GetTicketRedPointThreshold()
{
return _tableCycle.RedDot;
}
public Tuple<DateTime, DateTime> GetEventStartTimeAndEndTime()
{
try
{
var et = System.DateTime.Parse((_tableEvent.TimeDefinition as LimitedTime).EndTime);
var st = System.DateTime.Parse((_tableEvent.TimeDefinition as LimitedTime).StartTime);
return new Tuple<DateTime, DateTime>(st, et);
}
catch (System.Exception e)
{
Debug.LogError(e);
return new Tuple<DateTime, DateTime>(System.DateTime.MinValue, System.DateTime.MinValue);
}
}
public EventChainPackInfo GetChainPackInfo()
{
var chianList = GContext.container.Resolve<Tables>().TbEventPackManager[_tableMain.PackId].VIPPackList[0];
var expireTime = new System.DateTime();
try
{
expireTime = System.DateTime.Parse((_tableEvent.TimeDefinition as LimitedTime).EndTime);
}
catch (System.Exception e)
{
Debug.Log($"[EventLuckMagic] {e.Message}\n{e.StackTrace}");
return null;
}
var chainListIdSet = chianList.ToHashSet();
var packs = GContext.container.Resolve<Tables>().TbPack.DataList.Where(p => chainListIdSet.Contains(p.ID)).ToArray();//?
return new EventChainPackInfo()
{
ChainList = chianList,
ExpireTime = expireTime,
Packs = packs,
RedPointKey = "eventluckmagic.pack"
};
}
public int GetWelcomeGift()
{
return _tableCycle.WelcomeGift;
}
public LackOfCommonItemPopupPanelInfo GetLackOfTicketPanelInfo()
{
var res = new LackOfCommonItemPopupPanelInfo();
res.reward = new ItemData(_tableMain.Item, _tableMain.BuyCount);
res.Cost = _tableMain.Price;
res.CurrencyId = 1005;
return res;
}
public EventLuckMagicInfo GetInfoPanelInfo()
{
var res = new EventLuckMagicInfo();
GetBlocksInfo(out var list);
res.Blocks = list
.Where(b => b.RingType == EEventLuckMagicRingType.InnerRing)
.Select(b => b.Reward)
.ToArray();
res.TaskRewardUpper = _playerItemData.GetItemDataByDropId(GetTaskRewardDropId(0, true))[0];
res.TaskRewardLower = _playerItemData.GetItemDataByDropId(GetTaskRewardDropId(0, false))[0];
res.TicketNameKey = GContext.container.Resolve<Tables>().TbItem[_tableMain.Item].Name_l10n_key;
return res;
}
public string GetIcon()
{
return _tableMain.Icon;
}
/// <summary>
/// Get the right reward drop Id for the right task in the right round
/// </summary>
/// <param name="roundCount">Starts at 0</param>
/// <param name="isUpperTask">Upper or Lower task</param>
/// <returns> the drop id</returns>
public int GetTaskRewardDropId(int roundCount, bool isUpperTask)
{
List<int> rewardDropIdList;
rewardDropIdList = isUpperTask ? _tableMain.TargetRewardDrop1 : _tableMain.TargetRewardDrop2;
return rewardDropIdList[roundCount < rewardDropIdList.Count ? roundCount : rewardDropIdList.Count - 1];
}
public ItemData GetTaskReward(int roundCount, bool isUpperTask)
{
return _playerItemData.GetItemDataByDropId(GetTaskRewardDropId(roundCount, isUpperTask))[0];
}
public List<int> GetFirstLuckyTaskIdList()
{
return _tableMain.TaskRound1;
}
public List<int> GetLastLuckyTaskIdList()
{
return _tableMain.TaskRound2;
}
public int GetPackId()
{
return _tableMain.PackId;
}
public int EventId => _tableEvent.ID;
public int PackId => _tableMain.PackId;
public EventLuckMagicPanelUrlData GetUiPanelUrls()
{
var res = new EventLuckMagicPanelUrlData();
res.TriplePackPanelUrl = _packData.Panel;
return res;
}
}
public class EventLuckMagicBlockInfo
{
public EEventLuckMagicRingType RingType { get; set; }
public ItemData Reward { get; set; }
public int Weight { get; set; }
public int TableId { get; set; }
}
public enum EEventLuckMagicItemType
{
UpperTaskItem,
LowerTaskItem,
None
}
public class EventLuckMagicPanelUrlData
{
public string TriplePackPanelUrl{ get; set; }
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 02aaaaf3b981a4547be298f94e5fd5ce
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,49 @@
using System.Threading.Tasks;
using asap.core;
using GameCore;
using UnityEngine;
using UnityEngine.UI;
public class EventLuckMagicTaskRewardPopupPanel : MonoBehaviour
{
[SerializeField] private Button btnClaim;
[SerializeField] private RewardItemNew reward;
[SerializeField] private GameObject goUpperTask, goLowerTask;
private ItemData _rawRewardData;
private TaskCompletionSource<bool> _taskCompletionSource;
public void Init(EventLuckMagicRewardPanelInfo info)
{
btnClaim.onClick.AddListener(OnClickClaim);
bool isUpperTaskType = EventLuckMagicAct.TableContext.JudgeItemId(info.TaskItemId) == EEventLuckMagicItemType.UpperTaskItem;
goUpperTask.SetActive(isUpperTaskType);
goLowerTask.SetActive(!isUpperTaskType);
reward.SetData(info.Reward);
_rawRewardData = info.Reward;
_taskCompletionSource = info.TaskCompletionSource;
}
private async void OnClickClaim()
{
try
{
GContext.Publish(new EventRewardFlyStashRequest(_rawRewardData, reward.icon.GetComponent<RectTransform>()));
btnClaim.gameObject.SetActive(false);
await Task.Delay(System.TimeSpan.FromSeconds(
GContext.container.Resolve<EventLuckMagicModel>().ParamsCtrl.RewardPopupPanelCloseDelay));
_taskCompletionSource.SetResult(true);
UIManager.Instance.DestroyUI(UITypes.EventLuckMagicTaskRewardPopupPanel);
}
catch (System.Exception e)
{
Debug.Log(e);
}
}
}
public class EventLuckMagicRewardPanelInfo
{
public ItemData Reward;
public int TaskItemId;
public TaskCompletionSource<bool> TaskCompletionSource;
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7aa10f71496c76e4db468fa5f0a231b5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,110 @@
using UnityEngine;
using GameCore;
using asap.core;
using UniRx;
using asap.core.common;
using System.Threading.Tasks;
public class EventLuckMagicTaskView : MonoBehaviour
{
[SerializeField] private GameObject[] progressIcons, fxReceived;
[SerializeField] private RewardItemNew rewardDisplay;
[SerializeField] private Animation ani;
private int _progress = 0;
private IEventAggregator _eventAggregator;
private IObjectPoolService _objectPoolService;
private int _taskItemId;
private ItemData _reward;
private const string Normal = "target_nml", OnComplete = "target_full", Completed = "target_completed";
private RectTransform CurrentIcon
{
get
{
if (progressIcons.Length > _progress)
{
return progressIcons[_progress].GetComponent<RectTransform>();
}
Debug.LogError($"CurrentIcon is null, progress {_progress} not valid.");
return null;
}
}
public void Init(int progress, ItemData reward, int taskItemId)
{
rewardDisplay.SetData(reward);
UpdateProgress(progress);
PlayAnimation();
_eventAggregator = EventLuckMagicAct.EventAggregator;
// _eventAggregator?.GetEvent<EventRewardFlyRequest>().Subscribe(OnRewardFlyRequest).AddTo(this);
_objectPoolService = GContext.container.Resolve<IObjectPoolService>();
_progress = progress;
_taskItemId = taskItemId;
_reward = reward;
}
public void UpdateProgress(int progress, bool doesPlayFx = false)
{
for (int i = 0; i < progressIcons.Length; i++)
{
progressIcons[i].SetActive(i < progress);
fxReceived[i].SetActive(false);
}
_progress = progress;
if (doesPlayFx)
{
fxReceived[_progress - 1].SetActive(true);
}
}
public async Task OnRewardFlyRequest(EventRewardFlyStashRequest e)
{
if (e.Reward.id != _taskItemId)
return;
var pool = _objectPoolService.GetPool(typeof(RewardFly));
var rewardFly = pool.SpawnObject() as RewardFly;
var collectionItemFly = new CollectionItemFly
{
itemID = e.Reward.id,
numStr = "",
sourcePos = e.SourceIconRt.position,
destPos = CurrentIcon.position,
scale = transform.localScale,
isPlayOpen = true,
isPlayClose = true,
isDestinationRewardStash = true,
targetIconSize = CurrentIcon.rect.width
};
rewardFly.gameObject.SetActive(true);
await rewardFly.ShowAsync(collectionItemFly);
pool.DespawnObject(rewardFly);
UpdateProgress(GContext.container.Resolve<EventLuckMagicModel>().TaskProgress[e.Reward.id], true);
await PlayAnimationAsync();
}
public void PlayAnimation()
{
ani.Play(_progress >= 3 ? Completed : Normal);
}
private async Task PlayAnimationAsync()
{
if (_progress >= 3)
{
ani.Play(OnComplete);
await Task.Delay(System.TimeSpan.FromSeconds(ani.GetClip(OnComplete).length));
}
}
public void ResetTask(ItemData reward)
{
for (int i = 0; i < progressIcons.Length; i++)
{
progressIcons[i].SetActive(false);
fxReceived[i].SetActive(false);
}
_progress = 0;
rewardDisplay.SetData(reward);
_reward = reward;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7f2531147b86ccf4abb2b3e14a6645a5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,49 @@
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using GameCore;
using cfg;
public class EventLuckyTriplePackContentView : MonoBehaviour
{
[SerializeField] private RewardItemNew[] rewards;
[SerializeField] private Button btnBuy;
[SerializeField] private TMP_Text textPrice, textDiscount;
public void Init(EventLuckyTriplePackContentData data, System.Action onBuy)
{
btnBuy.onClick.AddListener(() => onBuy());
int idx = 0;
while (idx < data.Rewards.Length)
{
rewards[idx].SetData(data.Rewards[idx]);
idx++;
}
while (idx < rewards.Length)
{
rewards[idx].gameObject.SetActive(false);
idx++;
}
textPrice.text = data.TextPrice;
textDiscount.text = (data.Discount * 100).ToString("0.") + "%";
}
public void Reset()
{
rewards = new RewardItemNew[4];
for (int i = 1; i <= 4; i++)
rewards[i - 1] = transform.Find($"Item/reward/reward{i}").GetComponent<RewardItemNew>();
btnBuy = transform.Find("Item/btn_buy/btn_green").GetComponent<Button>();
textPrice = transform.Find("Item/btn_buy/btn_green/Ani_Container/p_text").GetComponent<TMP_Text>();
textDiscount = transform.Find("Item/tag_more/text_best").GetComponent<TMP_Text>();
}
}
public class EventLuckyTriplePackContentData
{
public string TextPrice;
public ItemData[] Rewards;
public float Discount;
public int DropId;
public IAPItemList IAPItemList;
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fddf69c1addfe7c498d3f5074468537e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,137 @@
using UnityEngine;
using UnityEngine.UI;
using GameCore;
using System;
using asap.core;
using cfg;
using System.Collections.Generic;
using System.Linq;
public class EventLuckyTriplePackPanel : MonoBehaviour
{
[SerializeField] private Button btnClose;
[SerializeField] private BingoTimer timer;
[SerializeField] private EventLuckyTriplePackContentView[] packViewList;
private int _eventId;
public void Start()
{
btnClose.onClick.AddListener(OnClickClose);
}
public void Init(EventLuckyTriplePackData data)
{
// var packData = EventLuckMagicAct.TableContext.GetTriplePackData();
timer.Init(data.ToTimerContext(OnClickClose));
for (int i = 0; i < packViewList.Length; i++)
{
var iap = data.PackDataList[i].IAPItemList;
var dropId = data.PackDataList[i].DropId;
packViewList[i].Init(data.PackDataList[i], () => OnClickBuy(dropId, iap));
}
_eventId = data.EventId;
}
private async void OnClickBuy(int dropId, IAPItemList iap)
{
try
{
var shopBuyTypeData = new ShopBuyTypeData
{
type = ShopBuyType.EventPack,
ID = _eventId
};
bool res = await GContext.container.Resolve<PlayerShopData>().OnBuy(dropId, shopBuyTypeData, iap,
GContext.container.Resolve<PlayerItemData>().GetItemDataByDropId(dropId));
if (res)
{
Debug.Log("[LuckTriplePack] Purchase Success.");
OnClickClose();
}
}
catch (Exception e)
{
Debug.Log($"[EventLuckyPack] Purchase Error.");
Debug.LogError(e);
}
}
private void OnClickClose()
{
UIManager.Instance.DestroyUI(gameObject.name);
}
}
public class EventLuckyTriplePackData
{
public DateTime ExpiryTime { get; set; }
public DateTime StartTime { get; set; }
public EventLuckyTriplePackContentData[] PackDataList { get; set; }
public int EventId { get; set; }
public ITimerContext ToTimerContext(Action onExpire)
{
return new TimerContext
{
ExpiryTime = ExpiryTime,
StartTime = StartTime,
OnExpire = onExpire
};
}
public static EventLuckyTriplePackData Create(int eventId, int packId)
{
var _tableEvent = GContext.container.Resolve<Tables>().TbFishingEvent[eventId];
var res = new EventLuckyTriplePackData();
var expireTime = new DateTime();
try
{
expireTime = DateTime.Parse((_tableEvent.TimeDefinition as LimitedTime).EndTime);
}
catch (Exception e)
{
Debug.Log($"[EventLuckMagic] {e.Message}\n{e.StackTrace}");
return null;
}
res.ExpiryTime = expireTime;
var startTime = new DateTime();
try
{
startTime = DateTime.Parse((_tableEvent.TimeDefinition as LimitedTime).StartTime);
}
catch (Exception e)
{
Debug.Log($"[EventLuckMagic] {e.Message}\n{e.StackTrace}");
return null;
}
res.ExpiryTime = expireTime;
var packDataList = new List<EventLuckyTriplePackContentData>();
var playerVipLevel = GContext.container.Resolve<PlayerData>().PriceLv;
var _packData = GContext.container.Resolve<Tables>().TbEventPackManager[packId];
var packIdList = playerVipLevel < _packData.VIPPackList.Count ? _packData.VIPPackList[playerVipLevel] : _packData.VIPPackList.Last();
for (int i = 0; i < packIdList.Count; i++)
{
var p = GContext.container.Resolve<Tables>().TbPack[packIdList[i]];
var d = new EventLuckyTriplePackContentData();
d.Rewards = GContext.container.Resolve<PlayerItemData>().GetItemDataByDropId(p.DropID).ToArray();
d.Discount = p.Rebate;
d.IAPItemList = GContext.container.Resolve<Tables>().TbIAPItemList.GetOrDefault(p.IAPID);
//Debug.Log($"_iap: {_iap}");
var sdde = new SKUDetailDataEvent(d.IAPItemList);
GContext.Publish(sdde);
d.TextPrice = sdde.price;
d.DropId = p.DropID;
packDataList.Add(d);
}
res.PackDataList = packDataList.ToArray();
res.EventId = _tableEvent.ID;
return res;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 26e045cf679b156479d43f501b6853a4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,67 @@
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using GameCore;
using asap.core;
using cfg;
using game;
public class LackOfCommonItemPopupPanel : MonoBehaviour
{
[SerializeField] private RewardItemNew reward;
[SerializeField] private Button btnBuy, btnMask;
[SerializeField] private Image iconCurrency;
[SerializeField] private TMP_Text textCurrencyCount, textTitle;
private PlayerItemData _playerItemData;
private LackOfCommonItemPopupPanelInfo _data;
private const string TitleDefaultKey = "UI_TurntableInfoPopupPanel_19";
private Item _reward;
public void Init(LackOfCommonItemPopupPanelInfo info)
{
reward.SetData(info.reward);
_reward = GContext.container.Resolve<Tables>().TbItem[info.reward.id];
var currencyIconUrl = GContext.container.Resolve<Tables>().TbItem[info.CurrencyId];
GContext.container.Resolve<IUIService>().SetImageSprite(iconCurrency, currencyIconUrl.Icon);
textCurrencyCount.text = info.Cost.ToString();
if (info.TitleKey != "")
textTitle.text = LocalizationMgr.GetText(info.TitleKey);
else
textTitle.text = LocalizationMgr.GetFormatTextValue(TitleDefaultKey, LocalizationMgr.GetFormatTextValue(_reward.Name_l10n_key));
btnBuy.onClick.AddListener(OnClickBuy);
btnMask.onClick.AddListener(OnClickContinue);
_playerItemData = GContext.container.Resolve<PlayerItemData>();
_data = info;
}
private void OnClickBuy()
{
var currencyCount = (int)_playerItemData.GetItemCount(_data.CurrencyId);
if (currencyCount < _data.Cost)
{
_ = UIManager.Instance.ShowUI(UITypes.LackOfResourceConfirmPopupPanel);
}
else
{
_playerItemData.AddItem(_data.reward);
_playerItemData.AddItemCount(_data.CurrencyId, -_data.Cost);
GContext.Publish(new ShowData(_data.reward));
GContext.Publish(new ShowData());
GContext.Publish(new ResAddEvent(1004));
UIManager.Instance.DestroyUI(UITypes.LackOfCommonItemPopupPanel);
}
}
private void OnClickContinue()
{
UIManager.Instance.DestroyUI(UITypes.LackOfCommonItemPopupPanel);
}
}
public class LackOfCommonItemPopupPanelInfo
{
public ItemData reward;
public int CurrencyId;
public int Cost;
public string TitleKey = "";
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f66cbaeff71107d408c5851a734d8639
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: