Files
back_cantanBuilding/Assets/Scripts/EventStrikeLucky/EventLuckMagicMainPanel.cs
2026-05-26 16:15:54 +08:00

512 lines
22 KiB
C#

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;
} */