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

1262 lines
47 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using asap.core;
using Assets.Scripts.UI.AnimationSimulator;
using GameCore;
using cfg;
using DataCenter;
using DG.Tweening;
using EnhancedUI.EnhancedScroller;
using EventPartnerGather;
using game;
using Game;
using TMPro;
using UniRx;
using UnityEngine;
using UnityEngine.Serialization;
using UnityEngine.UI;
using EEventBuildState = EventPartnerGatherRequests.EEventBuildState;
using Tween = DG.Tweening.Tween;
namespace UI.PartnerGather.Mining
{
/// <summary>
/// 事件合作伙伴抽奖挖矿面板控制器
/// 负责管理抽奖转盘UI、挖矿进度显示、场景控制器绑定等核心功能
///
/// 建议挂载在EventPartnerDrawMiningPanel UI预制体的根对象上
///
/// UI结构建议
/// EventPartnerDrawMiningPanel (挂载此脚本)
/// ├── root/
/// │ ├── turntable/Scroll_item (转盘滚动区域)
/// │ ├── btn_common_green/btn_green (抽奖按钮)
/// │ └── turnable/select (选中效果)
/// ├── btn_close (关闭按钮)
/// └── SettlementPanel/ (结算面板,可选)
/// ├── Rewards/ (奖励显示区域)
/// └── Trophy/ (奖杯显示区域)
///
/// 重要说明:
/// - 此脚本会自动查找和绑定采集场景控制器
/// - 需要正确设置转盘相关的UI引用
/// - 支持节点结算过场动画和奖杯显示系统
/// </summary>
///
// public class SpinItemData
// {
// public EventPartnerMineSpinPoint spinPoint;
// public int _dataId;
// public float _moreValue = 0F;
// public int _multiple = 1;
// public bool isSelected = false;
// }
public class EventPartnerDrawMiningPanel : BasePanel, IEnhancedScrollerDelegate
{
private const bool EnableTraceLogs = false;
// 管理器
private EventPartnerGatherManager _manager;
[Header("倍数选择")]
[SerializeField]
private EventPartnerMiningMultiplierController multiplierController;
//
[Header("采集场景配置(运行时自动设置)")]
[SerializeField]
private EventPartnerMiningSceneController miningScene;
private bool _isProcessingResult = false;
[Header("Complete Spin Curve")]
[SerializeField] private AnimationCurve completeMoveProfile;
[FormerlySerializedAs("AnimationSimulator")]
[Header("转盘移动参数")]
public AnimationSimulatorComponent animationSimulator;
#region LEVEL_BAR
// 更新点数即等级
[Header("=== 等级进度显示 ===")]
[Tooltip("等级节点控制器数组 - 每个节点对应一个挖矿阶段")]
public EventPartnerMiningLevelController[] levels;
private readonly List<Image> _levelBars = new();
//
private readonly List<Transform> _levelTransform = new();
private const float FillTime = 0.4f;
#endregion
private Transform _turntable; // 转盘
// private PanelScroll _scrollList; // 滚动列表
// 滚动列表
private EnhancedScroller _enhancedScroller;
// Cell
private EventPartnerSpinItemView _cellView;
private Transform _select; // 选中效果
private Transform _priceItem; // 列表滚动中的数据
private Button _clickMask;
private Button _btnDebug;
// 按钮
private Button _btnClose;
private Button _btnSpin;
private Button _btnMoreSpin;
private Button _btnFreeSpin; // FreeSpin按钮
private Button _btnAdd;
private Transform _transBtnSpin;
private Transform _transMoreSpin;
private Transform _transFreeSpin;
private TMP_Text _txtMoreSpinTime;
private Transform _iconTicket;
private TMP_Text _ticketTextNum;
// 切换倍率按钮
private Button _btnBeilv;
private ScrollRect _scrollRect;
private RectTransform _viewport;
private RectTransform _content;
private RectTransform _itemTemplate;
// 记录当前的Item
private readonly List<EventPartnerSpinItemView> _spinItemViews = new();
// private readonly List<int> _dataIndexMap = new();
//
private Transform tag_more;
private Transform tag_super;
private Transform tag_free;
private Transform _fxUIFinished;
// [Header("结算过场配置")]
// public Transform settlementPanel; // 结算面板
// public Transform trophyDisplay; // 奖杯显示区域
// public Transform nodeCompletionEffect; // 节点完成特效
// public AudioClip settlementSound; // 结算音效
// public AudioClip trophySound; // 奖杯音效
private bool _isShowingSettlement = false;
// 当前点数列表
//
private List<EventPartnerMineSpinPoint> _spinPointDatas;
// private readonly List<SpinItemData> _spinItemDatas = new ();
// 0,1,2 停靠在第二个格子
private int _starGrid = 2;
private float offsetX = 0;
private int _dataCount;
private int _poolSize;
private float _itemWidth;
private float _startX = 0f;
private bool _animating;
private float _autoScrollSpeed = 60f;
private bool _autoScroll = false;
// 自动滚动累积位移(用于与步进动画叠加)
private float _autoScrollAccumulation = 0f;
// 移动几个格子
private int _moveGridNum = 0;
// 移动位移
private float _moveAccumulation = 0f;
private float _autoMoveScrollAccumulation = 0f;
//
private Tween _spinSequence;
// private float _totalDuration = 2.5f;
[SerializeField]
private float gridDuration = 0.1f; // 每个格子的速度
// 收集的点数
private int _currentPoints;
// 当前的倍数
private int _multipleValue = 1;
//
// private float cellViewSize = 235.02f;
// 当前的Spin 状态
public ESpinState CurrentSpinState { get; set; }
private Timer _moreSpinTimer; // 定时器
private CompositeDisposable _disposables = new();
private void Awake()
{
// animationSimulator=this.GetComponent<AnimationSimulatorComponent>();
_manager = GContext.container.Resolve<EventPartnerGatherManager>();
//
_btnDebug = transform.Find("btn_debug").GetComponent<Button>();
_btnDebug.gameObject.SetActive(false);
_btnSpin = transform.Find("root/btn_spin/btn_green").GetComponent<Button>();
_btnFreeSpin = transform.Find("root/btn_spin_free/btn_green").GetComponent<Button>();
_btnMoreSpin = transform.Find("root/btn_spin_more/btn_green").GetComponent<Button>();
_btnAdd = transform.Find("root/icon_ticket/btn_add").GetComponent<Button>();
_txtMoreSpinTime = transform.Find("root/btn_spin_more/btn_green/Ani_Container/text_time").GetComponent<TMP_Text>();
// _txtMoreSpinTime.gameObject.SetActive(false);
_fxUIFinished = transform.Find("fx_ui_finished");
_transBtnSpin = transform.Find("root/btn_spin");
_transFreeSpin = transform.Find("root/btn_spin_free");
_transMoreSpin = transform.Find("root/btn_spin_more");
_btnClose = transform.Find("btn_close").GetComponent<Button>();
_clickMask = transform.Find("root/click_mask").GetComponent<Button>();
// _scrollList = transform.Find("root/turntable/Scroll_item").GetComponent<PanelScroll>();
_enhancedScroller = transform.Find("root/turntable/Scroll_View").GetComponent<EnhancedScroller>();
_priceItem = transform.Find("root/turntable/item");
_cellView = _priceItem.GetComponent<EventPartnerSpinItemView>();
_select = transform.Find("root/turntable/select");
_iconTicket = transform.Find("root/icon_ticket");
_ticketTextNum = transform.Find("root/icon_ticket/text_num").GetComponent<TMP_Text>();
_btnBeilv = transform.Find("root/btn_beilv").GetComponent<Button>();
tag_more = transform.Find("root/tag_more");
tag_super = transform.Find("root/tag_super");
tag_free = transform.Find("root/tag_free");
for (var i = 0; i < 4; ++i)
{
_levelBars.Add(transform.Find($"root/level/bg_bar/bar_{i}").GetComponent<Image>());
_levelBars[i].fillAmount = 0f;
}
for (var i = 1; i <= 5; ++i)
{
_levelTransform.Add(transform.Find($"root/level/level{i}"));
}
multiplierController.Init(_manager.GetSpinMag());
//
GContext.OnEvent<EventPartnerMiningMultiplierChange>().Subscribe(OnMultiplierChange).AddTo(_disposables);;
GContext.OnEvent<EventPartnerGatherBonusEndEvent>().Subscribe(OnRefreshBonus).AddTo(_disposables);
GContext.OnEvent<EventPartnerGatherUpdateTicketCount>().Subscribe(OnUpdateTicketCount).AddTo(_disposables);
GContext.OnEvent<EventPartnerGatherPlayTrophy>().Subscribe(OnPlayTrophy).AddTo(_disposables);
GContext.OnEvent<EventPartnerGatherShowPack>().Subscribe(_ => ShowPackPanel()).AddTo(disposables);
}
protected override void Start()
{
base.Start();
// _btnDebug.gameObject.SetActive(GContext.container.Resolve<IConfig>().Get("GM", "0") == "1");
_btnSpin.onClick.AddListener(OnSpin);
_btnFreeSpin.onClick.AddListener(OnSpin);
_btnMoreSpin.onClick.AddListener(OnSpin);
_btnClose.onClick.AddListener(OnClickCloseBtn);
_btnDebug.onClick.AddListener(OnDebug);
_btnAdd.onClick.AddListener(OnBtnAdd);
_clickMask.onClick.AddListener(OnClickMaster);
var playerItemData = GContext.container.Resolve<PlayerItemData>();
for (int i = 0; i < _levelTransform.Count; ++i)
{
var idx = i;
_levelTransform[i].GetComponent<Button>().onClick.AddListener(()=> OnLevelBtn(idx));
var itemNew = _levelTransform[i].Find("bubble_reward/reward").GetComponent<RewardItemNew>();
var dropId = _manager.EventPartnerMineMainData.StageReward[i];
var listItems = playerItemData.GetItemDataByDropIdLureInflation(_manager.GatherData.InflationRate, dropId);
itemNew.SetData(listItems.FirstOrDefault());
}
CreateCompleteMoveProfile();
InitScroll();
// 设置当前的代币值
_ticketTextNum.text = _manager.GatherData.TicketCount.ToString();
}
public void Reset()
{
for (var i = 0; i < 4; ++i)
{
if (_levelBars[i])
{
_levelBars[i].fillAmount = 0f;
}
}
_fxUIFinished.gameObject.SetActive(false);
transform.Find("root").gameObject.SetActive(true);
transform.Find("btn_close").gameObject.SetActive(true);
// transform.Find("btn_debug").gameObject.SetActive(true);
// _btnDebug.gameObject.SetActive(GContext.container.Resolve<IConfig>().Get("GM", "0") == "1");
}
private async Task PlayEffect(int index)
{
ELog($"PlayEffect index={index}");
// index = 0;
var rect = animationSimulator.GetComponent<RectTransform>();
var random = index;
var nomalizeScale = _enhancedScroller.Container.sizeDelta.x / 3;
var param = new AnimationSimulatorComponent.Parameter();
param.scale = nomalizeScale;
param.startValue = _enhancedScroller.ScrollPosition;
// param.offsetDirection = RandomOffsetDirection(puzzleRewards[random]);
param.offsetDirection = true;
param.updateCallback = (currentVelocity, currentValue)
=>
{
// Log($" currentValue {currentValue} c {(currentValue % nomalizeScale) + nomalizeScale} currentVelocity {currentVelocity}");
if (currentValue < 0) currentValue = (currentValue % nomalizeScale) + nomalizeScale;
_enhancedScroller.ScrollPosition = currentValue;
};
param.uniformCompletionStartCallBack = (currentValue)
=>
{
var postion = _enhancedScroller.GetScrollPositionForDataIndex(random, EnhancedScroller.CellViewPositionEnum.Before);
var baseValue = Mathf.Abs(( postion- rect.sizeDelta.x / 2 + _itemWidth /2 ) % nomalizeScale);
var direction= currentValue>0?1:-1;
var targetValue = currentValue + direction*(nomalizeScale - Mathf.Abs(currentValue % nomalizeScale));
var resValue = Mathf.Abs(targetValue + baseValue) > Mathf.Abs(currentValue) ? targetValue + baseValue : targetValue + baseValue - nomalizeScale;
// Debug.Log($"jsd {this.GetType().Name} random {random} postion {postion} baseValue{baseValue} currentValue{currentValue} targetValue {targetValue} {targetValue + baseValue} res {resValue}");
return resValue % nomalizeScale;
};
await animationSimulator.PlayEffect(param);
// Debug.Log($"jsd {this.GetType().Name} PlayEffect END");
}
private void OnClickMaster()
{
ELog("ClickMaster");
// throw new NotImplementedException();
foreach (var t in _levelTransform)
{
var bubble = t.Find("bubble_reward");
bubble.gameObject.SetActive(false);
}
}
private async void ShowFinalReward()
{
// await Awaiters.Seconds();
var bubble = _levelTransform[^1].Find("bubble_reward");
bubble.gameObject.SetActive(true);
await Awaiters.Seconds(3);
bubble.GetComponent<Animation>().Play("bubble_out");
await Awaiters.Seconds(0.2f);
bubble.gameObject.SetActive(false);
}
private async void OnLevelBtn(int idx)
{
ELog($"OnLevelButton index={idx}");
for (var i = 0; i < _levelTransform.Count; ++i)
{
var bubble = _levelTransform[i].Find("bubble_reward");
if (i != idx && bubble)
{
bubble.gameObject.SetActive(false);
}
}
// for (var i = 0; i < _levelTransform.Count; ++i)
{
var bubble = _levelTransform[idx].Find("bubble_reward");
if (bubble)
{
bubble.gameObject.SetActive(true);
await Awaiters.Seconds(3);
bubble.GetComponent<Animation>().Play("bubble_out");
await Awaiters.Seconds(0.2f);
bubble.gameObject.SetActive(false);
}
}
}
private void OnDebug()
{
ELog("DebugClick");
miningScene.ShowDebugView();
}
private void OnEnable()
{
Trace("OnEnable");
_fxUIFinished.gameObject.SetActive(false);
SetInteractable(false);
}
private void OnDisable()
{
Trace("OnDisable");
_fxUIFinished.gameObject.SetActive(false);
}
private void InitSpinStateDisplay()
{
var buildPartner = _manager.CurrentBuildPartner;
if (buildPartner == null)
{
return;
}
var timeSpan = _manager.GetMoreTimeSpan(buildPartner.SlotId);
var seconds = timeSpan.TotalSeconds;
var freeSpinNum = _manager.GetFreeSpin(buildPartner.SlotId);
if (seconds < 1)
{
if (freeSpinNum > 0)
{
CurrentSpinState = ESpinState.Freespin;
_ = UpdateSpinState(ESpinState.Freespin);
}
else
{
CurrentSpinState = ESpinState.Normal;
_ = UpdateSpinState(ESpinState.Normal);
}
return;
}
if (freeSpinNum > 0)
{
CurrentSpinState = ESpinState.Freespin;
_ = UpdateSpinState(ESpinState.Freespin);
}
else
{
CurrentSpinState = ESpinState.Morespin;
_ = UpdateSpinState(ESpinState.Morespin);
}
UpdateCurrentSpinItems();
UpdateMoreTimeCountDown();
EnableAutoScroll(true);
}
private void StartCountDownMoreTime(float seconds)
{
_moreSpinTimer?.Cancel();
_moreSpinTimer = null;
var buildPartner = _manager.CurrentBuildPartner;
var timeCount = _manager.GetMoreTimeSpan(buildPartner.SlotId);
_txtMoreSpinTime.text = ConvertTools.ConvertTime4(timeCount);
_moreSpinTimer = this.AttachTimer(seconds, null,
elapsed =>
{
var now = _manager.GetMoreTimeSpan(buildPartner.SlotId);
if (now.TotalMilliseconds <= 0)
{
_moreSpinTimer?.Cancel();
_moreSpinTimer = null;
_manager.EnsureBonusValid();
}
// _txtMoreSpinTime.text = ConvertTools.ConvertTime2(now.Days, now.Hours, now.Minutes, now.Seconds);
_txtMoreSpinTime.text = ConvertTools.ConvertTime4(now);
}, useRealTime: true);
}
private void CreateCompleteMoveProfile()
{
// completeMoveProfile = new AnimationCurve();
// // 加速阶段 (0-0.2) - 从0快速上升
// completeMoveProfile.AddKey(new Keyframe(0f, 0f, 0f, 2f)); // 起始点斜率为2
// completeMoveProfile.AddKey(new Keyframe(0.2f, 0.3f, 3f, 3f)); // 加速结束
// // 匀速阶段 (0.2-0.7) - 线性增长
// completeMoveProfile.AddKey(new Keyframe(0.7f, 0.85f, 1f, 1f)); // 匀速阶段
// // 减速阶段 (0.7-0.9) - 逐渐减速
// completeMoveProfile.AddKey(new Keyframe(0.9f, 1.05f, 0.5f, -2f)); // 开始减速
// // 中止阶段 (0.9-0.95) - 到达目标稍微超调
// completeMoveProfile.AddKey(new Keyframe(0.95f, 1.08f, 0f, -5f)); // 超调峰值
// // 回弹阶段 (0.95-1.0) - 回弹到最终位置
// completeMoveProfile.AddKey(new Keyframe(1f, 1f, 0f, 0f)); // 最终位置
// // 设置切线模式使曲线更平滑
// for (int i = 0; i < completeMoveProfile.keys.Length; i++)
// {
// completeMoveProfile.SmoothTangents(i, 0.3f);
// }
}
/// <summary>
/// 供外部代码设置采集场景控制器
/// </summary>
public void SetMiningScene(EventPartnerMiningSceneController sceneController)
{
miningScene = sceneController;
ELog($"SetMiningScene controller={sceneController?.name ?? "null"}");
}
private void Update()
{
if (_autoScroll && _dataCount > 0)
{
AutoScroll(Time.deltaTime);
}
}
public void OnEnter()
{
InitSpinStateDisplay();
ShowFinalReward();
_noCheating = false;
}
public async void InitScroll()
{
await UpdateScrollList();
EnableAutoScroll(true);
}
private async Task UpdateScrollList()
{
_scrollRect = _enhancedScroller.GetComponent<ScrollRect>();
_viewport = _scrollRect.viewport;
_content = _scrollRect.content;
// .parent as RectTransform;
_itemTemplate = (RectTransform)_priceItem;
_spinPointDatas = _manager.EventPartnerMineSpinPointList;
_dataCount = _spinPointDatas?.Count ?? 0;
if (_dataCount == 0)
{
if (_btnSpin) _btnSpin.interactable = false;
return;
}
// foreach (var spinPointData in _spinPointDatas)
// {
// var itemData = new SpinItemData()
// {
// spinPoint = spinPointData,
// // _dataId =
// _moreValue = 0F,
// _multiple = 1,
// };
// _spinItemDatas.Add(itemData);
// }
_itemWidth = _itemTemplate.rect.width;
var visibleItemNum = Mathf.RoundToInt(_viewport.rect.width / _itemWidth);
_starGrid = visibleItemNum / 2;
var offsetW = visibleItemNum * _itemWidth - _viewport.rect.width;
_startX = _content.rect.width / 2 + (_starGrid ) * _itemWidth ;
_poolSize = Mathf.CeilToInt(_viewport.rect.width / _itemWidth) + 4; // 前后各两个
offsetX = -offsetW * 0.5f;
BuildItemPool();
_priceItem.gameObject.SetActive(false);
_enhancedScroller.Delegate = this;
_enhancedScroller.ReloadData();
var nomalizeScale = _enhancedScroller.Container.sizeDelta.x / 3;
if (offsetX < 0)
offsetX = (Mathf.Abs(offsetX) % nomalizeScale) + nomalizeScale;
_enhancedScroller.ScrollPosition = offsetX;
// var iCount = _spinItemViews.Count;
// Log($"iCount = {iCount}");
await Task.CompletedTask;
}
private void BuildItemPool()
{
_spinItemViews.Clear();
// _dataIndexMap.Clear();
// for (int i = 0; i < _poolSize; i++)
// {
// var r = Instantiate(_itemTemplate, _content);
// r.gameObject.SetActive(true);
// r.anchoredPosition = new Vector2(_startX - i * _itemWidth,r.anchoredPosition.y);
// var spinItemView = r.GetComponent<EventPartnerSpinItemView>();
// _spinItemViews.Add(spinItemView);
// var di = i % _dataCount;
// _dataIndexMap.Add(di);
// BindItem(spinItemView, di);
// }
// _content.anchoredPosition = Vector2.zero;
// _scrollRect.enabled = false;
}
// private async void UpdateSelectionVisual(int targetIdxId)
// {
// // for (int i = 0; i < _spinItemViews.Count; i++)
// // {
// // _spinItemViews[i].UpdateSelected(targetIdxId);
// // }
// }
//Event
private void OnMultiplierChange(EventPartnerMiningMultiplierChange evt)
{
Trace("MultiplierChange");
_multipleValue = multiplierController.Multiplier;
foreach (var itemView in _spinItemViews)
{
itemView?.UpdateMultiple(_multipleValue);
}
// foreach (var spinItemData in _spinItemDatas)
// {
// spinItemData._multiple = _multipleValue;
// }
// _enhancedScroller.RefreshActiveCellViews();
}
// 触发一下事件
private void OnRefreshBonus(EventPartnerGatherBonusEndEvent evt)
{
Trace("RefreshBonus");
_ = UpdateSpinState(ESpinState.Normal);
}
public async void OnPlayTrophy(EventPartnerGatherPlayTrophy evt)
{
Trace("PlayTrophy");
_fxUIFinished.gameObject.SetActive(false);
await Awaiters.NextFrame;
_fxUIFinished.gameObject.SetActive(true);
}
// 事件,更新当前代币
private void OnUpdateTicketCount(EventPartnerGatherUpdateTicketCount evt)
{
_ticketTextNum.text = _manager.GatherData.TicketCount.ToString();
}
private void UpdateContentPosition(float additionalOffset = 0f,bool isPositive = true)
{
// 统一位置计算:基准位置 + 自动滚动累积 + 额外偏移
// Log($"UpdateContentPosition -> {additionalOffset}");
var finalX = _autoMoveScrollAccumulation + additionalOffset;
// _content.anchoredPosition = new Vector2(finalX, _content.anchoredPosition.y);
var di = isPositive ? -1 : 1;
_enhancedScroller.ScrollPosition += finalX * di;
}
private void AutoScroll(float dt)
{
_autoMoveScrollAccumulation = _autoScrollSpeed * dt;
// 应用累积的自动滚动位移
// while (_autoMoveScrollAccumulation >= _itemWidth)
// {
// _autoMoveScrollAccumulation -= _itemWidth;
// //NormalizeAfterStepRight();
// // NormalizeAfterStepLeft();
// // UpdateAllGrids();
// }
// 使用统一位置更新方法
UpdateContentPosition();
}
private void ClearSelection()
{
foreach (var elem in _spinItemViews)
{
elem.SetSelected(false);
}
// foreach (var itemData in _spinItemDatas)
// {
// itemData.isSelected = false;
// }
// _enhancedScroller.RefreshActiveCellViews();
}
private async Task SpinToAsync(EventPartnerMineSpinPoint target,ESpinState buffer, int loops)
{
ELog($"SpinToAsync targetSpinId={target?.ID}");
// if (_animating || target == null || _dataCount == 0)
// return;
// return;
var dataTargetIndex = _spinPointDatas.IndexOf(target);
if (dataTargetIndex < 0)
dataTargetIndex = 0;
_animating = true;
EnableAutoScroll(false);
ClearSelection();
// 好像存在问题
var index = dataTargetIndex;
// transform.Find("root/turntable/fx_ui_partnermining_wheel_spin").gameObject.SetActive(false);
var effectObj = transform.Find("root/turntable/fx_ui_partnermining_wheel_spin");
effectObj.gameObject.SetActive(true);
await PlayEffect(index);
effectObj.gameObject.SetActive(false);
transform.Find("root/turntable/select/fx_ui_partnermining_wheel_select").gameObject.SetActive(true);
// UpdateSelectionVisual(target.ID);
await Awaiters.Seconds(0.5f);
transform.Find("root/turntable/select/fx_ui_partnermining_wheel_select").gameObject.SetActive(false);
_animating = false;
}
public void SetInteractable(bool v)
{
_btnSpin.interactable = v;
_btnMoreSpin.interactable = v;
_btnFreeSpin.interactable = v;
_btnClose.interactable = v && !_animating;
_btnBeilv.interactable = v && (CurrentSpinState != ESpinState.Freespin);
}
public void EnableAutoScroll(bool on)
{
// return;
_autoScroll = on;
}
public void SetAutoScrollSpeed(float s)
{
_autoScrollSpeed = Mathf.Max(0f, s);
}
public void ResumeAutoScroll()
{
// 供后续逻辑调用,恢复自动滚动
EnableAutoScroll(true);
}
protected override void OnDestroy()
{
_disposables.Dispose();
_disposables = null;
//
_btnFreeSpin.onClick.RemoveAllListeners();
_btnMoreSpin.onClick.RemoveAllListeners();
_btnClose.onClick.RemoveAllListeners();
_btnSpin.onClick.RemoveAllListeners();
}
private void UpdateLevel(int level)
{
Trace($"UpdateLevel level={level}");
if (levels == null || levels.Length == 0) return;
level = Mathf.Clamp(level, 0, levels.Length);
for (var i = 0; i < levels.Length; ++i)
{
if (i < level)
levels[i].UpdateStatus(LevelStatus.Done);
else if (i == level)
levels[i].UpdateStatus(LevelStatus.Current);
else
levels[i].UpdateStatus(LevelStatus.Normal);
}
}
public void SetMiningProgress(int progress)
{
Trace($"SetMiningProgress progress={progress}");
UpdateLevel(Mathf.Min(progress, levels?.Length ?? 0));
}
public void FinishStep(int step)
{
Trace($"FinishStep step={step}");
UpdateLevel(step);
if (step < levels.Length)
{
var level = levels[step - 1];
var bgDone = level.bg_done;
bgDone.GetComponent<Animation>() .Play("level_done");
}
}
public void SetMiningPoints(int points)
{
Trace($"SetMiningPoints points={points}");
_currentPoints = points;
var step = _manager.CalcMiningProgressNew(points);
if (step < 1)
return;
for (var i = 0; i < step; ++i)
{
_levelBars[i].fillAmount = 1;
}
var pt = points - _manager.GetCumulativeStepPoint(step -1);
var percent = (float)pt / _manager.NodeSteps[step];
Trace($"SetMiningPointsProgress points={points} stagePoints={pt} percent={percent}");
// if (step > 0)
{
_levelBars[step - 1].fillAmount = percent;
}
}
public void UpdateBarProgress(int step, float percent)
{
Trace($"UpdateBarProgress step={step} percent={percent}");
if (step > 0)
{
_levelBars[step - 1].fillAmount = percent;
}
}
private async Task UpdateSpinState(ESpinState spinState)
{
Trace($"UpdateSpinState state={spinState}");
// CurrentSpinState = spinState;
if (spinState == ESpinState.Freespin)
{
_transFreeSpin.gameObject.SetActive(true);
_transBtnSpin.gameObject.SetActive(false) ;
_transMoreSpin.gameObject.SetActive(false);
_btnBeilv.interactable = false;
}
else if (spinState == ESpinState.Morespin)
{
_transMoreSpin.gameObject.SetActive(true) ;
_transFreeSpin.gameObject.SetActive(false);
_transBtnSpin.gameObject.SetActive(false);
_btnBeilv.interactable = true;
}
else // Normal
{
_transBtnSpin.gameObject.SetActive(true) ;
_transFreeSpin.gameObject.SetActive(false);
_transMoreSpin.gameObject.SetActive(false);
_btnBeilv.interactable = true;
}
// UpdateSpinItemsMore();
}
private float GetBonusPercent()
{
var buildPartner = _manager.CurrentBuildPartner;
if (buildPartner == null)
{
return 0F;
}
var slotId = buildPartner.SlotId;
// var (bonusPercent,bonusExpireUtc) = _manager.GatherData.BuilderPartnerBonus[slotId];
var (bonusPercent, bonusExpireUtc) = _manager.GatherData.PartnerBonus;
if (_manager.IsBonusActive(slotId))
{
return bonusPercent;
}
return 0F;
}
public void UpdateCurrentSpinItems()
{
var buildPartner = _manager.CurrentBuildPartner;
var slotId = buildPartner.SlotId;
// var (bonusPercent,bonusExpireUtc) = _manager.GatherData.BuilderPartnerBonus[slotId];
var (bonusPercent,bonusExpireUtc) = _manager.GatherData.PartnerBonus;
if (_manager.IsBonusActive(slotId))
{
foreach (var itemView in _spinItemViews)
{
itemView?.UpdateMore(bonusPercent);
}
}
else
{
foreach (var itemView in _spinItemViews)
{
itemView?.UpdateMore(0);
}
}
}
public void UpdateSpinItemsMore()
{
var slotId = _manager.CurrentBuildPartner.SlotId;
// var (bonusPercent,bonusExpireUtc) = _manager.GatherData.BuilderPartnerBonus[slotId];
var (bonusPercent,bonusExpireUtc) = _manager.GatherData.PartnerBonus;
if (_manager.IsBonusActive(slotId))
{
foreach (var itemView in _spinItemViews)
{
itemView?.UpdateMore(bonusPercent);
}
}
}
public void UpdateSpinItemsNormal()
{
foreach (var itemView in _spinItemViews)
{
itemView?.UpdateMore(0);
}
}
private void UpdateMoreTimeCountDown()
{
// BuildPartner buildPartner;
Trace("UpdateMoreTimeCountDown");
var slotId = _manager.CurrentBuildPartner.SlotId;
var timeSpan = _manager.GetMoreTimeSpan(slotId);
var seconds = timeSpan.TotalSeconds;
if (seconds < 1)
return;
StartCountDownMoreTime((float)seconds);
}
public void RunCollectOreAnimation(int step, int oreCount)
{
Trace($"RunCollectOreAnimation step={step} oreCount={oreCount} currentPoints={_currentPoints}");
_currentPoints += oreCount;
if (step > 0) // 刨除第一组的点数
{
var pt = _currentPoints - _manager.NodeCumulativeSteps[step -1];
var percent = (float)pt / _manager.NodeSteps[step];
Trace($"RunCollectOreAnimationProgress currentPoints={_currentPoints} stagePoints={pt} percent={percent}");
_levelBars[step - 1].DOFillAmount(percent, FillTime);
}
else
{
_levelBars[step].fillAmount = 0f;
}
Trace($"RunCollectOreAnimationDone step={step} oreCount={oreCount} currentPoints={_currentPoints}");
}
private bool _noCheating = false;
public async void OnSpin()
{
if (_isProcessingResult) return;
var spinPoint = _manager.GetSpinPointElem(_noCheating);
if (spinPoint == null) return;
ELog($"SpinStart eventId={_manager?.EventId} slotId={_manager?.CurrentBuildPartner?.SlotId} spinId={spinPoint.ID} cheating={_noCheating}");
_noCheating = true;
if (true)
{
// miningScene.Test();
// return;
}
_isProcessingResult = true;
SetInteractable(false);
var cost = _manager.CalcSpinCost(_multipleValue);
if (CurrentSpinState == ESpinState.Freespin)
{
cost = 0;
}
var points = _manager.ResolveSpinAndGetPoints(spinPoint,out var buffer);
var ret = await _manager.BuildWorks(points * _multipleValue,cost);
if (!ret)
{
// DO SMthing
_isProcessingResult = false;
SetInteractable(true);
return;
}
_manager.DoEventWithSpinState(spinPoint);
OnSpinStart();
await OnSpinLogic(spinPoint,points,buffer,_multipleValue);
OnSpinFinished(buffer);
}
private void OnSpinStart()
{
GContext.Publish(new EventUISound("audio_ui_partnermining_wheel_spin"));
}
private async void OnSpinFinished(ESpinState status)
{
ELog($"SpinFinished eventId={_manager?.EventId} state={status}");
_manager.UpdateSpinData();
UpdateCurrentSpinState(status);
ClearSelection();
await miningScene.CheckForStepCompletion();
_isProcessingResult = false;
EnableAutoScroll(true);
SetInteractable(true);
}
private void UpdateCurrentSpinState(ESpinState status)
{
if (status == ESpinState.Normal)
{
var timeSpan = _manager.GetMoreTimeSpan(_manager.CurrentBuildPartner.SlotId);
var seconds = timeSpan.TotalSeconds;
Trace($"UpdateCurrentSpinState slotId={_manager.CurrentBuildPartner.SlotId} moreSpan={timeSpan} seconds={seconds}");
if (seconds < 1 ) // 时间到
{
_ = UpdateSpinState(status);
UpdateSpinItemsNormal();
CurrentSpinState = ESpinState.Normal;
}
else
{
// 继续保持MoreSpin
CurrentSpinState = ESpinState.Morespin;
_ = UpdateSpinState(ESpinState.Morespin);
}
}
else if (status == ESpinState.Freespin)
{
var timeSpan = _manager.GetMoreTimeSpan(_manager.CurrentBuildPartner.SlotId);
var seconds = timeSpan.TotalSeconds;
if (seconds < 1) // 时间到
{
UpdateSpinItemsNormal();
}
CurrentSpinState = ESpinState.Freespin;
_ = UpdateSpinState(status);
}
else if (status == ESpinState.Morespin)
{
_ = UpdateSpinState(status);
UpdateMoreTimeCountDown();
UpdateSpinItemsMore();
CurrentSpinState = status;
}
}
private async Task OnSpinLogic(EventPartnerMineSpinPoint spinResult,int points, ESpinState buffer ,int multipleValue)
{
// var points = _manager.ResolveSpinAndGetPoints(spinResult, out var buffer);
// if (buffer == ESpinState.Morespin)
// {
// _moreSpinTimer?.Cancel();
// _moreSpinTimer = null;
// }
await SpinToAsync(spinResult,buffer,1);
var showType = spinResult.ShowType;
var pointType = GetBufferTypeString(buffer);
Trace($"OnSpinLogicInner points={points} multiple={multipleValue} pointType={pointType}");
var partnerId = _manager.CurrentBuildPartner?.PartnerId ?? "";
if (_manager.CurrentBuildPartner is { IsPartnerRobot: true })
{
partnerId = "robot";
}
// Log($"PlayGetFinalReward->{partnerId}");
#if AGG
using (var e = GEvent.GameEvent("event_partners_gather"))
{
e.AddContent("teammate_id", partnerId)
.AddContent("multiple", _multipleValue)
.AddContent("point_type", pointType)
.AddContent("points", points)
.AddContent("position_id", _manager.CurrentBuildPartner.SlotId)
.AddContent("is_free", buffer.Equals(ESpinState.Freespin) ? 1 : 0)
.AddContent("is_more", buffer.Equals(ESpinState.Morespin) ? 1 : 0);
}
#endif
switch (buffer)
{
case ESpinState.Freespin:
await OnFreeSpin(points, multipleValue,showType);
break;
case ESpinState.Morespin:
await OnMoreSpin(points,multipleValue,showType);
break;
case ESpinState.Normal:
default:
await OnSpinNormal(points, multipleValue,showType);
break;
}
}
private string GetBufferTypeString(ESpinState buffer)
{
return buffer switch
{
ESpinState.Normal => "normal",
ESpinState.Freespin => "free",
ESpinState.Morespin => "more",
_ => "normal"
};
}
// private async Task OnSpinLogic(EventPartnerMineSpinPoint spinResult,int points, ESpinState buffer, int multipleValue)
// {
// Log($"OnSpinLogic -> {spinResult} {multipleValue}");
// if (_isProcessingResult || spinResult == null)
// return;
// _isProcessingResult = true;
// try
// {
// // 解析抽奖结果
// await OnSpinLogicInner(spinResult,points,buffer,multipleValue);
// }
// finally
// {
// _isProcessingResult = false;
// }
// }
private async Task OnMoreSpin(int points,int multipleValue,string showType)
{
if (_manager?.GatherData == null) return;
// var slotId = _manager.CurrentBuildPartner.SlotId;
// var (bonusPercent, bonusExpireUtc) = _manager.GatherData.BuilderPartnerBonus[slotId];
await OnSpinNormal(points,multipleValue,showType);
var bonusPercent = _manager.BonusPercent;
var bonusExpireDuration = _manager.BonusExpireDuration;
Trace($"OnMoreSpin bonusPercent={bonusPercent} bonusExpireSec={bonusExpireDuration}");
tag_more.gameObject.SetActive(true);
await Awaiters.Seconds(1.15f);
tag_more.gameObject.SetActive(false);
var effectObj = transform.Find("root/turntable/fx_ui_partnermining_wheel_specialmore");
effectObj.gameObject.SetActive(true);
await Awaiters.Seconds(1f);
effectObj.gameObject.SetActive(false);
}
private async Task OnFreeSpin(int points,int multipleValue,string showType = "Basic")
{
ELog($"OnFreeSpinStart points={points} multiple={multipleValue}");
await OnSpinNormal(points,multipleValue,showType,useCost:false);
// var spinPoint = _manager.GetSpinPointElem(true);
// Log($"OnSpin -> {spinPoint.ID} {spinPoint.SpinPointParam.json}");
tag_free.gameObject.SetActive(true);
Trace("FreeSpinAnimationDisplay");
await Awaiters.Seconds(1.2f);
tag_free.gameObject.SetActive(false);
// await UpdateSpinState(ESpinState.Freespin);
ELog("FreeSpinFinished");
}
private async Task OnSpinNormal(int points,int multipleValue,string showType = "Basic", bool useCost = true)
{
ELog($"OnSpinNormal points={points} multiple={multipleValue}");
if (points > 0)
{
var normalPoints = multipleValue * points;
_manager.AddPoints(normalPoints); // 更新底层数据,放在最上面是不是更好
if (string.Equals(showType, "Master"))
{
tag_super.gameObject.SetActive(true);
Trace("SpinNormalChangeAnimationState");
await Awaiters.Seconds(1.2f);
tag_super.gameObject.SetActive(false);
}
// 开始采集流程
if (miningScene)
{
await miningScene.MainPlayerMining(normalPoints,showType);
}
}
}
private void OnBtnAdd()
{
ShowPackPanel();
}
private async void ShowPackPanel()
{
var packData = new EventNeoNormalPackData
{
EventId = _manager.EventId,
PackId = _manager.EventPartnerMineMainData.PackId,
Panel = _manager.EventPartnerMineMainData.PackPanel
};
await EventNeoNormalPackPanel.TryShowAsync(packData);
}
public async void OnClickCloseBtn()
{
var service = GContext.container.Resolve<EventPartnerService>();
var resp = await service.GetEventDetail(_manager.EventId);
if (resp != null)
{
switch (resp.State)
{
case EEventBuildState.Success:
_manager.LoadBuilderData(resp);
break;
// _gatherManager.SubscribeEvent();
// return true;
}
_manager.FinishMining();
}
// GContext.Publish(new UnloadActToNextAct());
}
private static void ELog(object t)
{
#if UNITY_EDITOR
Debug.Log($"<color=cyan>EventPartnerDrawMiningPanel -> {t} </color>");
#endif
}
[System.Diagnostics.Conditional("UNITY_EDITOR")]
private static void Trace(object t)
{
if (!EnableTraceLogs) return;
ELog(t);
}
public int GetNumberOfCells(EnhancedScroller scroller)
{
return _spinPointDatas.Count;
}
public float GetCellViewSize(EnhancedScroller scroller, int dataIndex)
{
//throw new NotImplementedException();
// return cellViewSize;
return _itemWidth;
}
public EnhancedScrollerCellView GetCellView(EnhancedScroller scroller, int dataIndex, int cellIndex)
{
// throw new NotImplementedException();
var cell = scroller.GetCellView(_cellView);
if (cell is not EventPartnerSpinItemView puzzleCell) return null;
cell.gameObject.SetActive(true);
puzzleCell.Bind(_spinPointDatas[dataIndex],dataIndex);
// puzzleCell.SetData(_spinItemDatas[dataIndex],dataIndex);
// puzzleCell.UpdateMore();
// _spinItemViews.RemoveAt(0);
puzzleCell.UpdateMore(GetBonusPercent());
puzzleCell.UpdateMultiple(_multipleValue);
_spinItemViews.Add(puzzleCell);
if (_spinItemViews.Count > _spinPointDatas.Count)
{
_spinItemViews.RemoveAt(0);
}
return cell;
}
public void HideUI()
{
transform.Find("root").gameObject.SetActive(false);
transform.Find("btn_close").gameObject.SetActive(false);
transform.Find("btn_debug").gameObject.SetActive(false);
_fxUIFinished.gameObject.SetActive(false);
}
}
}