备份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,111 @@
using System;
using System.Collections;
using System.Collections.Generic;
using asap.core;
using GameCore;
using UnityEngine;
using TMPro;
using UniRx;
using UnityEngine.UI;
public class ChainPackPanel : MonoBehaviour
{
[SerializeField] private TMP_Text textTimer;
[SerializeField] private ShootingChainSlot[] slots;
[SerializeField] private ShootingChainSlot slot6;
[SerializeField] private Button btnClose;
[SerializeField] private Animation /*targetAnimation,*/ contentAnimation;
private readonly IEventAggregator _eventAggregator = new EventAggregator();
private static readonly int[] IndexFromToSlotIndex = { 0, 1, 3, 2, 4, 5 };
private IChainPackData _data;
private const string ContentAnimationShiftKey = "item_change", ContentAnimationIdleKey = "item_normal";
public void Init(IChainPackData data)
{
btnClose.onClick.AddListener(OnClickClose);
_data = data;
for (int i = 0; i < IndexFromToSlotIndex.Length; i++) // The idx here is a little confusing....
slots[i].Init(IndexFromToSlotIndex[i], _data, _eventAggregator);
_eventAggregator.GetEvent<EventChainPackClaimed>().Subscribe(OnClaim).AddTo(this);
textTimer.text = ConvertTools.ConvertTime2(_data.RemainingTime);
Observable.Interval(TimeSpan.FromSeconds(1.0f))
.Subscribe(_ =>
{
textTimer.text = ConvertTools.ConvertTime2(_data.RemainingTime);
if (_data.RemainingTime.TotalSeconds <= 0) OnClickClose();
})
.AddTo(this);
contentAnimation.Play(ContentAnimationIdleKey);
}
/// <summary>
/// Triggered when player click the claim button on the reward panel. Important.
/// </summary>
/// <param name="e">Contains the index of the slot that is being called.</param>
private void OnClaim(EventChainPackClaimed e)
{
StopAllCoroutines();
StartCoroutine(PlayParticle(e));
StartCoroutine(PlayButtonChange(e));
StartCoroutine(ShiftSlots());
RedPointManager.Instance.SetRedPointState(_data.RedPointKey, _data.DoNeedPackRedPoint);
}
[SerializeField] private float jiandaParticleDelay;
private IEnumerator PlayParticle(EventChainPackClaimed e)
{
yield return new WaitForSeconds(jiandaParticleDelay);
var slot = slots[IndexFromToSlotIndex[e.SlotIdx]];
slot.RewardPanelCallbackSubscription?.Dispose();
}
[SerializeField] private float jiandaButtonChangeDelay;
private IEnumerator PlayButtonChange(EventChainPackClaimed e)
{
yield return new WaitForSeconds(jiandaButtonChangeDelay);
var slot = slots[IndexFromToSlotIndex[e.SlotIdx]];
slot.RewardPanelCallbackSubscription?.Dispose();
slot.PlayButtonAnimation();
slot.PlayCanvasGroupEffect(false);
if (e.SlotIdx + 1 < IndexFromToSlotIndex.Length)
{
slots[IndexFromToSlotIndex[e.SlotIdx + 1]].SetLock(false);
slots[IndexFromToSlotIndex[e.SlotIdx + 1]].PlayCanvasGroupEffect(true);
}
}
[SerializeField] private float jiandaSlotShiftDelay;
private IEnumerator ShiftSlots()
{
yield return new WaitForSeconds(jiandaSlotShiftDelay);
if (!_data.IsEndGame)
{
slot6.Init(6, _data, _eventAggregator);
contentAnimation.Play(ContentAnimationShiftKey);
yield return new WaitForSeconds(35f / 60);
contentAnimation.Play(ContentAnimationIdleKey);
}
for (int i = 0; i < IndexFromToSlotIndex.Length; i++) // The idx here is a little confusing....
{
// Debug.Log($"[EventBreak]Index: {IndexFromToSlotIndex[i]}");
slots[i].Init(IndexFromToSlotIndex[i], _data, _eventAggregator);
}
}
private void OnClickClose()
{
// RedPointManager.Instance.SetRedPointState(EventShootingRangeData.PackRedPointId, _data.DoNeedPackRedPoint);
UIManager.Instance.DestroyUI(gameObject.name);
}
}
public class EventChainPackClaimed
{
public readonly int SlotIdx;
public List<int> ProgressRewardGot;
public EventChainPackClaimed(int slotIdx)
{
SlotIdx = slotIdx;
}
}

View File

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

View File

@@ -0,0 +1,24 @@
using UnityEngine;
using UnityEngine.UI;
using GameCore;
using System;
public class CloseSelfPanel : MonoBehaviour
{
[SerializeField] Button btnClose;
private void Start()
{
btnClose.onClick.AddListener(OnClickClose);
}
private void OnClickClose()
{
try
{
UIManager.Instance.DestroyUI(gameObject.name);
}
catch (Exception e)
{
Debug.Log($"<color=red>{e.Message}\n{e.StackTrace}</color>");
}
}
}

View File

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

View File

@@ -0,0 +1,46 @@
using System.Threading.Tasks;
using asap.core;
using GameCore;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;
public class EventBreakAct : AGameAct
{
public static EventBreakTableContext Ctx { get; set; }
public static DrillSystem DrillSystem { get; private set; }
public static string ActAddressable = "EventBreakAct";
public static IEventAggregator EventAggregator = new EventAggregator();
private IDeferredRewardStashService _rewardStashService;
private CanvasScaler _canvasScaler;
private readonly float normalScale = 0.75f, actScale = 1.0f, duration = 0.75f;
private readonly Vector2 targetResolution = new Vector2(1080, 2340);
private Vector2 originalResolution;
private void Awake()
{
_canvasScaler = UIManager.Instance.GetComponent<CanvasScaler>();
originalResolution = _canvasScaler.referenceResolution;
// DOTween.To(() => _canvasScaler.referenceResolution, v => _canvasScaler.referenceResolution = v, targetResolution, duration).SetEase(Ease.OutQuad);
_canvasScaler.referenceResolution = targetResolution;
}
public override async Task<bool> StartAsync()
{
_rewardStashService = GContext.container.Resolve<IDeferredRewardStashService>();
_rewardStashService.Reset();
DrillSystem = new DrillSystem(Ctx);
await UIManager.Instance.ShowUILoad(UITypes.EventBreakPanel);
return await base.StartAsync();
}
protected override void OnDestroy()
{
// DOTween.To(() => _canvasScaler.referenceResolution, v => _canvasScaler.referenceResolution = v, originalResolution, duration).SetEase(Ease.OutQuad);
_canvasScaler.referenceResolution = originalResolution;
UIManager.Instance.DestroyUI(UITypes.EventBreakPanel);
Debug.Log("[Break] EventBreakAct destroyed.");
}
}

View File

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

View File

@@ -0,0 +1,87 @@
using DG.Tweening;
using UnityEngine;
using GameCore;
using System;
public class EventBreakBlock : MonoBehaviour
{
[SerializeField] private RewardItemNew reward;
[SerializeField] private GameObject crack, mask, fxBreak;
[SerializeField] private RectTransform rectTransform;
public RectTransform RectTransform => rectTransform;
private DrillBlockData _blockData;
private float _fxLiftTime;
/// <summary>
/// Move Block from startPoint to endPoint within dropTime and set item to it
/// </summary>
/// <param name="blockData">Item inside. Could be empty.</param>
/// <param name="startPoint">Screen Position</param>
/// <param name="endPoint">Screen Position</param>
/// <param name="dropTime">In Seconds</param>
public void Appear(DrillBlockData blockData, float dropHeight, Vector2 endPoint, AnimationCurve easeCurve, float dropTime = 0.5f, float fxLifeTime = 1f)
{
var startPoint = endPoint + Vector2.up * dropHeight;
try
{
// Debug.Log($"[Break] Block Appear from {startPoint} to {endPoint}.", this);
transform.position = startPoint;
gameObject.SetActive(true);
if (blockData.IsEmpty)
SetEmpty();
else
SetReward(blockData.Item);
transform.DOMove(endPoint, dropTime).SetEase(easeCurve);
_blockData = blockData;
_fxLiftTime = fxLifeTime;
}
catch(Exception e)
{
Debug.Log($"Block Spawn Error: {e.Message}, {e.StackTrace}");
}
}
public void Break()
{
// Debug.Log($"[EventBreak] Block broken: {_blockData.IsEmpty}, {_blockData.ItemId}, {_blockData.ItemCount}.", this);
PlayBreakFx();
gameObject.SetActive(false);
if (_blockData == null || _blockData.IsEmpty)
return;
EventBreakAct.EventAggregator.Publish(new EventBreakBlockBreak{BreakPos = transform.position, Item = _blockData.Item});
}
private async void PlayBreakFx()
{
try
{
fxBreak.SetActive(false);
// await Awaiters.NextFrame;
fxBreak.SetActive(true);
// await Awaiters.NextFrame;
await System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(_fxLiftTime));
// await Awaiters.NextFrame;
fxBreak.SetActive(false);
}
catch (Exception e)
{
Debug.Log($"[EventBreak]Block Break Fx Error:{e.Message}\n{e.StackTrace}", this);
}
}
private void SetReward(ItemData item)
{
reward.SetData(item);
reward.gameObject.SetActive(true);
crack.SetActive(true);
mask.SetActive(true);
}
private void SetEmpty()
{
reward.gameObject.SetActive(false);
crack.SetActive(false);
mask.SetActive(false);
}
}

View File

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

View File

@@ -0,0 +1,95 @@
using DG.Tweening;
using Spine.Unity;
using UnityEngine;
using System.Threading.Tasks;
using System;
using GameCore;
using asap.core;
using Game;
public class EventBreakBoxingGlove : EventBreakDrillDisplay
{
public override float Y
{
get
{
aniSpring.Skeleton.UpdateWorldTransform();
var bones = aniSpring.Skeleton.Bones;
var bone = bones.Items[59];
// var worldPos = bone.GetWorldPosition(aniSpring.transform, 100);
var worldPos = bone.GetWorldPosition(aniSpring.transform, UIManager.Instance.CanvasScaler.referencePixelsPerUnit);
return worldPos.y;
}
}
private Vector3 _originalPos;
[SerializeField] private SkeletonGraphic aniSpring;
private const string Idle = "boxing_idle", Push = "boxing_start", Pull = "boxing_return";
private readonly string[] _launchAudios =
new string[] { "audio_ui_eventbreak_boxing_start_01",
"audio_ui_eventbreak_boxing_start_02",
"audio_ui_eventbreak_boxing_start_03" };
private int _tunnelIdx;
public override Tween GetDrillTween(Vector3 endPos, float duration = 0.5f)
{
// transform.position = _originalPos;
// var push = transform.DOMove(endPos, duration).SetEase(Ease.InSine);
// var pull = transform.DOMove(_originalPos, duration).SetEase(Ease.InSine);
// return DOTween.Sequence().Append(push).Append(pull);
float t = 0;
return DOTween.To(() => t, x => t = x, 1f, duration);
}
public override void Init(int tunnelIndex)
{
_originalPos = transform.position;
PlayAnimation(Idle);
_tunnelIdx = tunnelIndex;
}
public override async void PlayDrill(float readyDuration = 0)
{
try
{
Debug.Log("[EventBreak] Play Drill.");
GContext.Publish(new EventUISound(_launchAudios[_tunnelIdx]));
await PlayAnimationAsync(Push);
await PlayAnimationAsync(Pull);
}
catch (Exception e)
{
Debug.Log($"[EventBreak] Play Drill Error");
Debug.LogError(e);
}
}
public override void PlayEnter(Vector3 startPos)
{
// Debug.Log("[EventBreak] Play Enter in boxing.");
}
private async Task PlayAnimationAsync(string animationName, double duration = 0)
{
if (aniSpring == null)
return;
var animationEntry = aniSpring.AnimationState.SetAnimation(0, animationName, false);
if (duration == 0)
duration = animationEntry.Animation.Duration;
await Task.Delay(TimeSpan.FromSeconds(duration));
// var bl = aniSpring.Skeleton.Bones.ToList();
// for (int i = 0; i < bl.Count; i++)
// {
// Debug.Log($"[EventBreak] {i}: {bl[i].Data.Name} at height {bl[i].WorldY}");
// }
}
private void PlayAnimation(string animationName)
{
aniSpring.AnimationState.SetAnimation(0, animationName, false);
}
private void Reset()
{
aniSpring = transform.Find("spine").GetComponent<SkeletonGraphic>();
}
}

View File

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

View File

@@ -0,0 +1,379 @@
using System.Linq;
using UnityEngine;
using SystemRandom = System.Random;
using System.Text;
using System;
using UnityEngine.Assertions;
using GameCore;
using cfg;
using System.Collections.Generic;
using asap.core;
public class DrillBlockData
{
public ItemData Item { get; set; }
public bool IsEmpty => Item == null || Item.id == -1 || (int)Item.count == 0;
public static DrillBlockData CreateEmpty()
{
return new DrillBlockData();
}
}
public class DrillJobModel
{
public int Cost { get; set; }
public DrillBlockData[] Blocks { get; set; }
}
public class EventBreakTaskGenerationInfo
{
public int TableId { get; set; }
public int CurrentGemProgress { get; set; }
public int TargetItemId { get; set; }
}
public class EventBreakTaskInfo
{
public int TaskId { get; set; }
public int TargetItemId { get; set; }
public ItemData Reward { get; set; }
public int TotalGemRequired { get; set; }
public int CurrentGemProgress { get; set; }
}
public class DrillModel : IHasChainPack
{
public int EventId { get; set; }
public int TicketCount { get; private set; }
public DrillJobModel[] DrillJobList { get; set; }
public EventBreakTaskInfo[] TaskInfoList { get; set; }
public int[] DrillJobSeeds { get; set; }
public int ChainPackProgress;
public void Update(int eventId, EventBreakPfData pfData = null) // new event
{
if (pfData == null || pfData.EventId != eventId)
{
GenSeeds();
EventBreakAct.Ctx.GetFreshNewModelData(DrillJobSeeds, out var welcomeGift, out var drillJobs, out var taskInfoList);
EventId = eventId;
TicketCount = welcomeGift;
TaskInfoList = taskInfoList;
DrillJobList = drillJobs;
ChainPackProgress = 0;
ToPlayfabData().Save();
return;
}
// var playerPreferenceData = EventBreakPlayerPreferenceData.Get(EventBreakAct.Ctx.TunnelCount);
EventId = eventId;
TicketCount = pfData.TicketCount;
DrillJobSeeds = pfData.DrillJobSeeds;
TaskInfoList = EventBreakAct.Ctx.GetTaskInfoArray(pfData.TaskData);
DrillJobList = EventBreakAct.Ctx.GetDrillJobModels(pfData.DrillJobSeeds);
ChainPackProgress = pfData.ChainPackProgress;
return;
}
private void GenSeeds()
{
DrillJobSeeds ??= new int[EventBreakAct.Ctx.TunnelCount];
for (int i = 0; i < DrillJobSeeds.Length; i++)
DrillJobSeeds[i] = 0;
// ToPlayfabData().Save();
}
public void UpdateSeed(int idx)
{
// DrillJobSeeds ??= new int[EventBreakAct.Ctx.TunnelCount];
if (EventBreakAct.Ctx.DoesSeedNeedInc(idx, DrillJobSeeds[idx]))
{
DrillJobSeeds[idx]++;
ToPlayfabData().Save();
return;
}
Assert.IsTrue(idx >= 0 && idx < DrillJobSeeds.Length,
$"[EventBreak] Cannot genenrate seed, idx {idx} is out of range [0, {DrillJobSeeds.Length}]");
var seed = DateTime.Now.Millisecond;
DrillJobSeeds[idx] = new SystemRandom(seed).Next();
ToPlayfabData().Save();
}
public bool AddTicket(int add)
{
if (TicketCount + add < 0)
return false;
TicketCount += add;
ToPlayfabData().Save();
GContext.container.Resolve<FishingEventData>().SaveTransitionData(EventId, TicketCount);
EventBreakAct.EventAggregator.Publish(new EventTicketUpdate());
return true;
}
public EventBreakPfData ToPlayfabData()
{
return new EventBreakPfData
{
EventId = EventId,
TicketCount = TicketCount,
TaskData = TaskInfoList.Select(i => (i.TaskId, i.CurrentGemProgress)).ToArray(),
ChainPackProgress = ChainPackProgress,
DrillJobSeeds = DrillJobSeeds
};
}
public void SetChainProgress(int p)
{
ChainPackProgress = p;
}
public int GetChainProgress()
{
return ChainPackProgress;
}
public void Save()
{
ToPlayfabData().Save();
}
public GenericChainPackData<DrillModel> ToChainPackData()
{
return GenericChainPackData<DrillModel>.Create(this, EventBreakAct.Ctx.GetPackData());
}
}
public class EventBreakPfData
{
public int EventId { get; set; }
public int TicketCount { get; set; }
public int ChainPackProgress { get; set; }
public (int id, int progress)[] TaskData { get; set; }
public int[] DrillJobSeeds { get; set; }
private const string Splitter = ",";
public const string PfKey = "EventBreak";
/// <summary>
/// Temporary stash.
/// </summary>
// public static EventBreakPfData Stash = null;
private const int TokenCount = 12;
public string Serialize()
{
var s = new StringBuilder();
s.Append(EventId + Splitter);
s.Append(TicketCount + Splitter);
s.Append(ChainPackProgress + Splitter);
foreach (var (id, progress) in TaskData)
s.Append(id + Splitter + progress + Splitter);
foreach (var seed in DrillJobSeeds)
s.Append(seed + Splitter);
return s.ToString();
}
public static EventBreakPfData Deserialize(string s)
{
if (s == null)
{
Debug.Log($"[EventBreak]Null string.");
return null;
}
var res = new EventBreakPfData();
var tokens = s.Trim(Splitter[0]).Split(Splitter);
if (tokens.Length != TokenCount)
{
Debug.Log($"[EventBreak]Wrong string format: string \"{s}\" has {tokens.Length} tokens, and the expected number is {TokenCount}");
return null;
}
try
{
res.EventId = int.Parse(tokens[0]);
res.TicketCount = int.Parse(tokens[1]);
res.ChainPackProgress = int.Parse(tokens[2]);
res.TaskData = new (int id, int progress)[3];
int i = 3;
while (i < 9)
{
res.TaskData[i / 2 - 1] = (int.Parse(tokens[i]), int.Parse(tokens[i + 1]));
i += 2;
}
res.DrillJobSeeds = new int[3];
while (i < TokenCount)
{
res.DrillJobSeeds[i - 9] = int.Parse(tokens[i]);
i++;
}
}
catch (Exception e)
{
Debug.Log($"[EventBreak]Possible parse error: {e.Message}\n{e.StackTrace}");
return null;
}
return res;
}
public void Save()
{
var s = Serialize();
PlayFabMgr.Instance.UpdateUserDataValue(PfKey, s);
}
}
[Obsolete]
public class EventBreakPlayerPreferenceDataLegacy
{
public int[] Seeds { get; set; }
private const string Splitter = ",", PpKey = "EventBreakCache";
public static EventBreakPlayerPreferenceDataLegacy Get(int seedCount = 3)
{
var s = PlayerPrefs.GetString(PpKey);
if (s == "")
return GenSeeds(seedCount);
var res = Deserialize(s);
if (res == null)
return GenSeeds(seedCount);
return res;
}
private static EventBreakPlayerPreferenceDataLegacy GenSeeds(int count)
{
var seeds = new int[count];
var rng = new SystemRandom(DateTime.Now.Millisecond);
for (int i = 0; i < count; i++)
seeds[i] = rng.Next();
return new EventBreakPlayerPreferenceDataLegacy
{
Seeds = seeds
};
}
private static EventBreakPlayerPreferenceDataLegacy Deserialize(string s)
{
var tokens = s.Trim(Splitter[0]).Split(Splitter);
var seeds = new int[tokens.Length];
try
{
for (int i = 0; i < tokens.Length; i++)
seeds[i] = int.Parse(tokens[i]);
return new EventBreakPlayerPreferenceDataLegacy
{
Seeds = seeds
};
}
catch (Exception e)
{
Debug.Log($"[EventBreak]Possible parse error: {e.Message}\n{e.StackTrace}");
return null;
}
}
private string Serialize()
{
var sb = new StringBuilder();
foreach (var seed in Seeds)
{
sb.Append(seed + Splitter);
}
return sb.ToString();
}
public void Save()
{
var s = Serialize();
PlayerPrefs.SetString(PpKey, s);
}
}
public class EventBreakUIData
{
public string MainPanelUrl { get; set; }
public string InfoPanelUrl { get; set; }
public string ChainPackPanelUrl { get; set; }
public string NormalPackPanelUrl { get; set; }
public string RewardPanelUrl { get; set; }
}
public class EventBreakChainPackGenerationInfo
{
public List<int> ChainList { get; set; }
public DateTime ExpireTime { get; set; }
public Pack[] Packs { get; set; }
}
// public class EventBreakChainPackData : IChainPackData
// {
// private const int SlotCount = 6;
// private List<int> ChainList { get; set; }
// private Pack[] Packs { get; set; }
// public bool IsEndGame => ChainProgress > ChainList.Count - SlotCount;
// public int ChainListCount => ChainList.Count;
// public int ChainProgress { get; set; }
// public int EventId { get; set; }
// private DateTime ExpireTime { 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 => "eventbreak.pack";
// public EventBreakChainPackData(EventBreakChainPackGenerationInfo info, int eventId, ref int chainProgress)
// {
// ChainList = info.ChainList;
// ChainProgress = chainProgress;
// EventId = eventId;
// ExpireTime = info.ExpireTime;
// Packs = info.Packs;
// }
// public Pack GetChainPackByChainProgress(int chainProgress)
// {
// // Debug.Log($"[EventBreak] chainProgress: {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}");
// // Debug.Log($"[EventBreak] slotIdx: {slotIdx}, chainProgress: {res}");
// return res;
// }
// // Is this needed or what?
// public List<int> GetTokenProgressRewardAfterAddingToken(int tokenAdded)
// {
// throw new NotImplementedException();
// }
// public void UploadData()
// {
// EventBreakAct.DrillModel.ChainPackProgress = ChainProgress;
// EventBreakAct.DrillModel.ToPlayfabData().Save();
// }
// public void OnBuySuccess()
// {
// ChainProgress++;
// UploadData();
// }
// public List<ItemData> GetItemsByPackDropId(int dropId)
// {
// throw new NotImplementedException();
// }
// }

View File

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

View File

@@ -0,0 +1,96 @@
using UnityEngine;
using Spine.Unity;
using System.Threading.Tasks;
using System;
using DG.Tweening;
using asap.core;
using Game;
public class EventBreakDrill : EventBreakDrillDisplay
{
[SerializeField] private SkeletonGraphic aniDrill;
private const string _drillAnimationStart = "drill_start", _drillAnimationSpin = "drill_spin", _drillAnimationIdle = "drill_idle";
[SerializeField] private float _jiandaDrillResetDuration = 0.3f;
[SerializeField] private GameObject fxDrill;
private Vector3 _originalPos;
public override void Init(int tunnelIndex)
{
_originalPos = transform.position;
gameObject.SetActive(false);
// Debug.Log($"[EventBreak] Wakeup! Drill {tunnelIndex} init!", this);
}
public override async void PlayDrill(float readyDuration = 0)
{
// Debug.Log($"[EventBreak] Wakeup! Drill played!", this);
fxDrill.SetActive(true);
GContext.Publish(new EventUISound("audio_ui_drill_drill_launch", 0));
await PlayDrillAnimationReady(_drillAnimationStart, readyDuration);
PlayDrillAnimationLoop(_drillAnimationSpin);
}
private void PlayIdle()
{
fxDrill.SetActive(false);
PlayDrillAnimationLoop(_drillAnimationIdle);
}
private async Task PlayDrillAnimationReady(string animationName, double duration = 0)
{
if (aniDrill == null)
return;
var animationEntry = aniDrill.AnimationState.SetAnimation(0, animationName, false);
if (duration == 0)
duration = animationEntry.Animation.Duration;
await Task.Delay(TimeSpan.FromSeconds(duration));
}
private void PlayDrillAnimationLoop(string animationName)
{
try
{
var animationEntry = aniDrill.AnimationState.SetAnimation(0,animationName, true);
}
catch(Exception e)
{
Debug.Log($"[EventBreak] Play Spine Animation Error: {e.Message}\n{e.StackTrace}");
}
}
override public async void PlayEnter(Vector3 startPos)
{
try
{
var endPos = _originalPos;
PlayIdle();
transform.position = startPos;
await Awaiters.NextFrame;
gameObject.SetActive(true);
transform.DOMove(endPos, _jiandaDrillResetDuration);
}
catch(Exception e)
{
Debug.Log($"[EventBreak]{e.Message}\n{e.StackTrace}");
}
}
override public Tween GetDrillTween(Vector3 endPos, float duration = 0.5f)
{
transform.position = _originalPos;
return transform.DOMove(endPos, duration).SetEase(Ease.InSine);
}
override public float Y => transform.position.y;
}
public abstract class EventBreakDrillDisplay : MonoBehaviour
{
abstract public void PlayEnter(Vector3 startPos);
abstract public void PlayDrill(float readyDuration = 0);
abstract public Tween GetDrillTween(Vector3 endPos, float duration);
abstract public float Y {get;}
abstract public void Init(int tunnelIndex);
}

View File

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

View File

@@ -0,0 +1,98 @@
using asap.core;
using game;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using System;
using GameCore;
using UniRx;
using System.Collections.Generic;
public class EventBreakEntranceButton : EventButtonResource
{
[SerializeField] private Image icon;
[SerializeField] private TMP_Text textTimer;
[SerializeField] private Button button;
private ILoadResourceService _loadResourceService;
private EventBreakEntranceData _btnData;
private const string EntranceRedPointKey = "eventbreak.enter";
private void Awake()
{
if (EventBreakAct.Ctx == null)
{
gameObject.SetActive(false);
return;
}
_btnData = EventBreakAct.Ctx.GetEntranceButtonData();
var _drillModel = GContext.container.Resolve<DrillModel>();
if (_btnData == null || !_btnData.IsActive)
{
gameObject.SetActive(false);
return;
}
UpdateTimer();
Observable.Interval(TimeSpan.FromSeconds(1f)).Subscribe(UpdateTimer).AddTo(this);
var chainPackData = GContext.container.Resolve<DrillModel>().ToChainPackData();
RedPointManager.Instance.SetRedPointState(EntranceRedPointKey,
_drillModel.TicketCount >= _btnData.RedPointTicketThreshold
|| chainPackData.DoNeedPackRedPoint);
CheckResource(new List<string>() { UITypes.EventBreakPanel.Path, EventBreakAct.ActAddressable, _btnData.BtnIconUrl });
}
private void Start()
{
button.onClick.AddListener(EnterDrillActAsync);
_loadResourceService = GContext.container.Resolve<ILoadResourceService>();
}
private async void EnterDrillActAsync()
{
try
{
bool isReady = await _loadResourceService.Loads(
new List<string>() { UITypes.EventBreakPanel.Path, EventBreakAct.ActAddressable });
if (isReady)
{
// Debug.Log($"<color=#22a6f2>[EventBreak] Download Ready!</color>");
GContext.Publish(new UnloadActToNextAct { actId = EventBreakAct.ActAddressable, TransitionPanel = UITypes.CloudTransitionPanel });
}
else
{
// Debug.Log($"<color=#22a6f2>[EventBreak] Download Not Ready!</color>");
var panel = await UIManager.Instance.ShowUI(UITypes.CloudTransitionPanel);
panel.GetComponent<CloudTransitionPanel>().SetBtn(true, () => GContext.Publish(new UnloadActToNextAct(EventBreakAct.ActAddressable)));
}
}
catch (Exception e)
{
Debug.Log($"<color=#22a6f2>[EventBreak] EnterActError: {e.Message}\n{e.StackTrace}</color>");
throw;
}
}
private void UpdateTimer(long _ = 0L)
{
textTimer.text = ConvertTools.ConvertTime2(_btnData.RemainingTime);
if (!_btnData.IsActive)
Destroy(gameObject);
}
protected override void OnLoadEventResource()
{
if (_btnData.IsActive)
{
GContext.container.Resolve<IUIService>().SetImageSprite(icon, _btnData.BtnIconUrl);
gameObject.SetActive(true);
}
}
}
public class EventBreakEntranceData
{
public string BtnIconUrl { get; set; }
public DateTime ExpiryTime { get; set; }
public DateTime StartTime { get; set; }
public TimeSpan RemainingTime => ExpiryTime - ZZTimeHelper.UtcNow();
public bool IsActive => ZZTimeHelper.UtcNow() >= StartTime && ZZTimeHelper.UtcNow() < ExpiryTime;
public int RedPointTicketThreshold { get; set; }
}

View File

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

View File

@@ -0,0 +1,78 @@
using System;
using asap.core;
using cfg;
using GameCore;
using UnityEngine;
using TMPro;
using UnityEngine.UI;
using UniRx;
public class EventBreakNormalPackPanel : MonoBehaviour
{
[SerializeField]
private TMP_Text textTimer, textPriceLeft, textPriceRight, textCountLeft, textCountRight, textDiscount;
[SerializeField] private Button btnClose, btnBuyLeft, btnBuyRight;
private IAPItemList _iapLeft, _iapRight;
private PlayerItemData _playerItemData;
private DateTime _expireTime;
private TimeSpan RemainingTime => _expireTime - ZZTimeHelper.UtcNow();
private int _eventId;
private Pack _packLeft, _packRight;
public void Init(EventBreakNormalPackInfo info)
{
btnClose.onClick.AddListener(OnClickClose);
_eventId = info.EventId;
_packLeft = info.PackLeft;
_packRight = info.PackRight;
_expireTime = info.ExpireTime;
_playerItemData = GContext.container.Resolve<PlayerItemData>();
textTimer.text = ConvertTools.ConvertTime2(RemainingTime);
Observable.Interval(TimeSpan.FromSeconds(1.0f)).Subscribe(_ =>
{
textTimer.text = ConvertTools.ConvertTime2(RemainingTime);
if (RemainingTime.TotalSeconds <= 0) OnClickClose();
}).AddTo(this);
_playerItemData.ResolveIapId(_packLeft.IAPID, out _iapLeft, textPriceLeft);
_playerItemData.ResolveIapId(_packRight.IAPID, out _iapRight, textPriceRight);
btnBuyLeft.onClick.AddListener(() => _ = OnClickBuy(_packLeft.DropID, _iapLeft));
btnBuyRight.onClick.AddListener(() => _ = OnClickBuy(_packRight.DropID, _iapRight));
textCountLeft.text =
((int)_playerItemData.GetItemDataByDropId(_packLeft.DropID)[0].count).ToString();
textCountRight.text =
((int)_playerItemData.GetItemDataByDropId(_packRight.DropID)[0].count).ToString();
textDiscount.text = LocalizationMgr.GetFormatTextValue("UI_FishingShopPanel_2", GetDiscountNumber());
}
private int GetDiscountNumber()
{
float discount = _packRight.Rebate * 100;
return (int)discount;
}
private async System.Threading.Tasks.Task OnClickBuy(int dropId, IAPItemList iapItemList)
{
if (RemainingTime.TotalSeconds <= 0)
return;
bool res = await GContext.container.Resolve<PlayerShopData>().OnBuy(dropId,
new ShopBuyTypeData { type = ShopBuyType.EventPack, ID = _eventId }, iapItemList,
_playerItemData.GetItemDataByDropId(dropId));
if (res)
{
EventBreakAct.EventAggregator.Publish(new EventTicketUpdate());
OnClickClose();
}
}
private void OnClickClose()
{
// RedPointManager.Instance.SetRedPointState(EventShootingRangeData.PackRedPointId, false);
UIManager.Instance.DestroyUI(gameObject.name);
}
}
public class EventBreakNormalPackInfo
{
public int EventId;
public Pack PackLeft, PackRight;
public DateTime ExpireTime;
}

View File

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

View File

@@ -0,0 +1,225 @@
using asap.core;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using game;
using UniRx;
using System;
using GameCore;
using System.Linq;
using System.Threading.Tasks;
using System.Collections;
public class EventDrillPanel : MonoBehaviour
{
[SerializeField] private TMP_Text textTimer, textTicketCount;
[SerializeField] private Button btnClose, btnPack, btnInfo;
[SerializeField] private EventBreakTunnelView[] tunnels;
[SerializeField] private EventBreakTaskView[] tasks;
[SerializeField] private float _jiandaBlockSpawnInterval = 0.1f, _jiandaBlockDropTime = 0.5f,_jiandaDrillReadyDuration = 0.5f,
_jiandaDrillDuration = 0.8f, _jiandaTaskChangeDuration = 0.5f, _jiandaBarFlashDuration = 1f, _jiandaBlockDropHeight = 1680f,
_jiandaRewardFlyDuration = 2f, _jiandaResetTunnelDelay = 3f, _jiandaButtonPressedDuration = 0.3f, _jiandaDrillDetectionRange = 50f,
_jiandaBlockDropSfxDelay = 0.3f, _jiandaRewardShowDuration = 2.0f;
[SerializeField] private GameObject rewardFly, clickMask;
[SerializeField] private AnimationCurve _jiandaBlockEaseCurve;
private Coroutine _unblockCoroutine = null;
private int _blockCounter;
private EventBreakEntranceData _btnData;
private void Awake()
{
btnClose.onClick.AddListener(OnClose);
_btnData = EventBreakAct.Ctx.GetEntranceButtonData();
UpdateTimer();
Observable.Interval(TimeSpan.FromSeconds(1f)).Subscribe(UpdateTimer).AddTo(this);
OnTicketCountChange();
btnPack.onClick.AddListener(OnClickPack);
btnInfo.onClick.AddListener(OnClickInfo);
_blockCounter = 0;
}
private void Start()
{
var drillModel = GContext.container.Resolve<DrillModel>();
GContext.container.Resolve<GuideDataCenter>().InspectTriggerGuide(gameObject.name);
if (tunnels.Length != drillModel.DrillJobList.Length || tunnels.Length != tasks.Length)
{
Debug.LogError("[EventBreak]Tunnel count not match!");
return;
}
for (int i = 0; i < tunnels.Length; i++)
{
var tunnelInfo = new EventBreakTunnelViewInitInfo{
Job = drillModel.DrillJobList[i],
SpawnInterval = _jiandaBlockSpawnInterval,
DropDuration = _jiandaBlockDropTime,
DrillDuration = _jiandaDrillDuration,
DropHeight = _jiandaBlockDropHeight,
Idx = i,
EaseCurve = _jiandaBlockEaseCurve,
DrillReadyDuration = _jiandaDrillReadyDuration,
ResetTunnelDelay = _jiandaResetTunnelDelay,
ButtonPressedDuration = _jiandaButtonPressedDuration,
DrillDetectionRange = _jiandaDrillDetectionRange,
BlockDropSfxDelay = _jiandaBlockDropSfxDelay
};
tunnels[i].Init(tunnelInfo);
var taskInfo = drillModel.TaskInfoList[i];
tasks[i].Init(taskInfo, _jiandaTaskChangeDuration, _jiandaBarFlashDuration, _jiandaRewardFlyDuration, rewardFly, _jiandaRewardShowDuration);
}
EventBreakAct.EventAggregator.GetEvent<EventTicketUpdate>()
.Subscribe(OnTicketCountChange).AddTo(this);
EventBreakAct.EventAggregator.GetEvent<EventBreakInsufficientTicket>()
.Subscribe(_ => OnClickPack()).AddTo(this);
EventBreakAct.EventAggregator.GetEvent<EventBreakBlockInput>()
.Subscribe(HandleBlockEvent).AddTo(this);
EventBreakAct.EventAggregator.GetEvent<EventBreakBlockBreak>()
.Subscribe(_ => HandleBlockEvent(new EventBreakBlockInput(EEventBreakBlockInputOperation.Block))).AddTo(this);
var chainPackData = drillModel.ToChainPackData();
RedPointManager.Instance.SetRedPointState(chainPackData.RedPointKey, chainPackData.DoNeedPackRedPoint);
}
private void OnClose()
{
GContext.Publish(new UnloadActToNextAct());
}
private void OnTicketCountChange(EventTicketUpdate _ = null)
{
var n = GContext.container.Resolve<DrillModel>().TicketCount;
textTicketCount.text = n.ToString();
var res = EventBreakAct.Ctx.IsTicketEnough(n);
for (int i = 0; i < tunnels.Length; i++)
tunnels[i].SetAvailabilityDisplay(res[i]);
textTicketCount.color = res.All(r => !r)? Color.red : Color.white;
}
private void UpdateTimer(long _ = 0L)
{
textTimer.text = ConvertTools.ConvertTime2(_btnData.RemainingTime);
}
private async void OnClickPack()
{
try
{
PlayBtnPressedAnimation();
GameObject go;
var chainPackData = GContext.container.Resolve<DrillModel>().ToChainPackData();
if (chainPackData.ChainProgress >= chainPackData.ChainListCount)
{
go = await UIManager.Instance.ShowUINotLoading(UITypes.EventBreakNormalPackPanel);
var normalPanel = go.GetComponent<EventBreakNormalPackPanel>();
normalPanel.Init(EventBreakAct.Ctx.GetNormalPackInfo());
return;
}
go = await UIManager.Instance.ShowUINotLoading(UITypes.EventBreakChainPackPanel);
var panel = go.GetComponent<ChainPackPanel>();
panel.Init(chainPackData);
}
catch (Exception e)
{
Debug.Log($"[EventBreak]Pack Error: {e.Message}\n{e.StackTrace}");
}
}
private async void PlayBtnPressedAnimation()
{
btnPack.GetComponent<Animator>().Play("Pressed");
await Task.Delay(TimeSpan.FromSeconds(_jiandaButtonPressedDuration));
btnPack.GetComponent<Animator>().Play("Normal");
}
private async void OnClickInfo()
{
try
{
await UIManager.Instance.ShowUINotLoading(UITypes.EventBreakInfoPanel);
}
catch (Exception e)
{
Debug.Log($"[EventBreak]{e.Message}\n{e.StackTrace}");
}
}
private void HandleBlockEvent(EventBreakBlockInput e)
{
switch (e.BlockOperation)
{
case EEventBreakBlockInputOperation.Block:
BlockInput();
break;
case EEventBreakBlockInputOperation.Unblock:
UnblockInput();
break;
case EEventBreakBlockInputOperation.StrongUnblock:
UnblockInputStrong();
break;
default:
break;
}
}
private void BlockInput()
{
_blockCounter++;
clickMask.SetActive(true);
StartUnblockCountDown();
// Debug.Log($"[EventBreak]Block: {_blockCounter}");
}
private void UnblockInput()
{
_blockCounter--;
// Debug.Log($"[EventBreak]Unblock: {_blockCounter}");
if (_blockCounter <= 0)
{
clickMask.SetActive(false);
_blockCounter = 0;
}
}
private void UnblockInputStrong()
{
_blockCounter = 0;
clickMask.SetActive(false);
// Debug.Log($"[EventBreak]Strong Unblock: {_blockCounter}");
}
private void StartUnblockCountDown()
{
if (_unblockCoroutine != null)
StopAllCoroutines();
_unblockCoroutine = StartCoroutine(UnBlockCoroutine());
}
private IEnumerator UnBlockCoroutine()
{
yield return new WaitForSeconds(5);
clickMask.SetActive(false);
}
}
public class EventTicketUpdate
{
}
public class EventBreakInsufficientTicket
{
}
public class EventBreakBlockInput
{
public EEventBreakBlockInputOperation BlockOperation = EEventBreakBlockInputOperation.Block;
public EventBreakBlockInput(EEventBreakBlockInputOperation bo)
{
BlockOperation = bo;
}
}
public enum EEventBreakBlockInputOperation
{
Block,
Unblock,
StrongUnblock
}

View File

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

View File

@@ -0,0 +1,75 @@
using UnityEngine;
using UniRx;
using System;
using asap.core;
using Game;
using DG.Tweening;
public class EventBreakStashButtonFxCtrl : MonoBehaviour
{
[SerializeField] private DeferredRewardStashButton rewardStashButton;
[SerializeField] private GameObject rewardFly;
[SerializeField] private float jiandaRewardShowDuration = 2.0f;
private void Start()
{
EventBreakAct.EventAggregator.GetEvent<EventBreakBlockBreak>().Subscribe(OnBlockBreak).AddTo(this);
}
private void OnBlockBreak(EventBreakBlockBreak e)
{
if (EventBreakAct.Ctx.IsItemGem(e.Item))
return;
MakeRewardFly(e);
}
private async void MakeRewardFly(EventBreakBlockBreak e)
{
try
{
var fly = Instantiate(rewardFly, transform).GetComponent<RewardItemNew>();
fly.SetRewardPopupData(e.Item);
fly.transform.position = e.BreakPos;
fly.gameObject.SetActive(true);
if (EventBreakAct.Ctx.IsItemFishCard(e.Item))
{
// Debug.Log($"[EventBreak] FishCard: From {rewardFly.transform.position} to {transform.position}");
_ = PlayFishCardBundleAudio();
fly.GetComponent<Animation>().Play("reward_common_open");
await System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(jiandaRewardShowDuration));
fly.GetComponent<Animation>().Play("reward_common_close");
await System.Threading.Tasks.Task.Delay(24 * 1000 / 60);
fly.GetComponent<CanvasGroup>().alpha = 1;
await Awaiters.NextFrame;
await DOTween.To(() => fly.transform.position,
value => fly.transform.position = value, transform.position, 1.1f)
.AsyncWaitForCompletion();
rewardStashButton.PlayReceiveAnimationWithDelay(0f);
EventBreakAct.EventAggregator.Publish(new EventBreakBlockInput(EEventBreakBlockInputOperation.Unblock));
Destroy(fly.gameObject);
}
else
{
fly.GetComponent<Animation>().Play("reward_common_open");
await System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(jiandaRewardShowDuration));
fly.GetComponent<Animation>().Play("reward_common_close");
await System.Threading.Tasks.Task.Delay(16 * 1000 / 60);
rewardStashButton.PlayReceiveAnimationWithDelay(1f);
await Awaiters.NextFrame;
await fly.ParticleAttractor();
// await System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(1.1f));
EventBreakAct.EventAggregator.Publish(new EventBreakBlockInput(EEventBreakBlockInputOperation.Unblock));
Destroy(fly.gameObject);
}
}
catch (Exception ex)
{
Debug.Log($"[EventBreak] BreakBlockError: {ex.Message}\n{ex.StackTrace}");
}
}
private async System.Threading.Tasks.Task PlayFishCardBundleAudio()
{
GContext.Publish(new EventUISound("audio_ui_break_rewardfly"));
await System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(0.25f));
GContext.Publish(new EventUISound("audio_ui_break_rewardget"));
}
}

View File

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

View File

@@ -0,0 +1,110 @@
using System.Collections.Generic;
using System.Text;
using asap.core;
using GameCore;
using UnityEngine;
public class DrillSystem
{
private readonly EventBreakTableContext _drillDataHub;
private readonly PlayerItemData _playerItemData = GContext.container.Resolve<PlayerItemData>();
private int _evTunnel, _evTicketConsume, _evGemGet, _evTaskId;
private string _evReward;
private Dictionary<int, int> _evNormalRewardDic;
public DrillSystem(EventBreakTableContext drillDataHub)
{
_drillDataHub = drillDataHub;
}
public bool DoDrillJob(int jobIdx)
{
var _drillModel = GContext.container.Resolve<DrillModel>();
var jobData = _drillModel.DrillJobList[jobIdx];
if (!_drillModel.AddTicket(-jobData.Cost))
{
Debug.Log("[EventBreak] Insufficient ticket.");
return false;
}
_evTunnel = jobIdx + 1;
_evTicketConsume = jobData.Cost;
_evGemGet = 0;
_evNormalRewardDic = new Dictionary<int, int>();
_evReward = "";
_evTaskId = 0;
ProcessBlocks(ref _drillModel.TaskInfoList[jobIdx], jobData.Blocks);
/*
Debug.Log($"[EventBreak]<color=#fe231b>Event tracking:</color>");
Debug.Log($"[EventBreak]<color=#fe231b> tunnel: {_evTunnel}</color>");
Debug.Log($"[EventBreak]<color=#fe231b> item_consume: {_evTicketConsume}</color>");
Debug.Log($"[EventBreak]<color=#fe231b> gem_count: {_evGemGet}</color>");
Debug.Log($"[EventBreak]<color=#fe231b> reward_normal: {_evReward}</color>");
Debug.Log($"[EventBreak]<color=#fe231b> milestone_task: {_evTaskId}</color>");
*/
#if AGG
using (var e = GEvent.GameEvent("event_drill"))
{
e.AddContent("tunnel", _evTunnel)
.AddContent("item_consume", _evTicketConsume)
.AddContent("gem_count", _evGemGet)
.AddContent("reward_normal", _evReward)
.AddContent("milestone_task", _evTaskId);
}
#endif
_drillModel.UpdateSeed(jobIdx);
_drillModel.DrillJobList[jobIdx] = _drillDataHub.GetDrillJob(jobIdx, _drillModel.DrillJobSeeds[jobIdx]);
return true;
}
private void ProcessBlocks(ref EventBreakTaskInfo taskInfo, IEnumerable<DrillBlockData> blocks)
{
var _drillModel = GContext.container.Resolve<DrillModel>();
foreach (var block in blocks)
{
if (block.IsEmpty)
continue;
if (block.Item.id != taskInfo.TargetItemId)
{
GrantPlayerReward(block.Item);
if (!_evNormalRewardDic.TryAdd(block.Item.id, (int) block.Item.count))
_evNormalRewardDic[block.Item.id] += (int) block.Item.count;
continue;
}
taskInfo.CurrentGemProgress += (int)block.Item.count;
_evGemGet++;
if (taskInfo.CurrentGemProgress < taskInfo.TotalGemRequired)
continue;
GrantPlayerReward(taskInfo.Reward);
_evTaskId = taskInfo.TaskId;
taskInfo = _drillDataHub.GetNextTaskInfo(taskInfo);
}
_evReward = SerializeRewardDic(_evNormalRewardDic);
_drillModel.ToPlayfabData().Save();
}
private string SerializeRewardDic(Dictionary<int, int> d)
{
var res = new StringBuilder();
if (d == null || d.Count <= 0)
return "";
foreach (var kv in d)
{
res.Append("(");
res.Append(kv.Key);
res.Append(",");
res.Append(kv.Value);
res.Append("),");
}
return res.ToString();
}
public void GrantPlayerReward(ItemData item)
{
// Debug.Log($"[Drill] Add rewards: id {item.id} count {item.count}");
// _playerItemData.AddItem(item);
GContext.Publish(new DeferredRewardStashService.EventStashItem {Item = item});
}
}

View File

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

View File

@@ -0,0 +1,420 @@
using cfg;
using asap.core;
using GameCore;
using SystemRandom = System.Random;
using UnityEngine;
using System.Linq;
using System.Collections.Generic;
using UnityEngine.Assertions;
using System;
using Castle.Core.Internal;
public class EventBreakTableContext
{
#region Private Table References
private readonly EventDrillMain _tableMain;
private readonly EventDrillTunnel[] _tableTunnels;
private readonly TbEventDrillReward _tableTask;
private readonly FishingEvent _tableEvent;
private readonly FishingEventCycleItem2 _tableCycle;
private readonly Tables _tables = GContext.container.Resolve<Tables>();
#endregion
public int TunnelCount => _tableTunnels.Length;
private readonly PlayerItemData _playerItemData = GContext.container.Resolve<PlayerItemData>();
public SystemRandom Random;
public readonly int BlockCountPerTunnel = 8;
private EventBreakTableContext(EventDrillMain tableMain, EventDrillTunnel[] tableTunnels, TbEventDrillReward tableTask, FishingEvent tableEvent, FishingEventCycleItem2 tableCycle, Tables tables)
{
_tableMain = tableMain;
_tableTunnels = tableTunnels;
_tableTask = tableTask;
_tableEvent = tableEvent;
_tableCycle = tableCycle;
_tables = tables;
}
public static EventBreakTableContext ReadTables(int eventId, Tables tables)
{
int redirectId, cycleId;
cycleId = tables.TbFishingEvent[eventId].RedirectID;
redirectId = tables.TbFishingEventCycleItem2[cycleId].RedirectID;
var tableEvent = tables.TbFishingEvent[eventId];
var tableCycle = tables.TbFishingEventCycleItem2[cycleId];
var tableMain = tables.TbEventDrillMain[redirectId];
var tableTunnels = tables.TbEventDrillTunnel.DataList.Where(t => tableMain.TunnelList.Contains(t.Tunnel)).ToArray();
var tableTask = tables.TbEventDrillReward;
return new EventBreakTableContext(tableMain, tableTunnels, tableTask, tableEvent, tableCycle, tables);
}
#region TaskInfoProcess
public EventBreakTaskInfo GetTaskInfo(int taskId, int tunnelIdx, int gemProgress = 0)
{
if (!_tableTask.DataMap.TryGetValue(taskId, out var taskTableData))
{
Debug.Log($"[EventBreak]Task id {taskId} not found in table.");
return null;
}
int targetItemId = GetItemIdFromDrop(_tableTunnels[tunnelIdx].DropGem);
if (targetItemId == -1)
{
return null;
}
// var taskReward = GetBlockDataFromDropId(_tableTask[taskId].DropGem);
var taskReward = _playerItemData.GetItemDataByDropId(_tableTask[taskId].DropGem)[0];
return new EventBreakTaskInfo
{
TaskId = taskTableData.TaskID,
TargetItemId = targetItemId,
Reward = taskReward,
TotalGemRequired = _tableTask[taskId].TokenRequired,
CurrentGemProgress = gemProgress
};
}
public EventBreakTaskInfo GetNextTaskInfo(EventBreakTaskInfo taskInfo)
{
Assert.IsTrue(taskInfo.CurrentGemProgress >= taskInfo.TotalGemRequired, "[EventBreak]Current gem progress is less than total gem required.");
var dataFlag = _tables.TbEventDrillReward.DataMap.TryGetValue(taskInfo.TaskId, out var taskTableData);
if (!dataFlag)
{
Debug.Log($"[Drill]Task id {taskInfo.TaskId} not found in reward table.");
return null;
}
var nextTaskId = taskTableData.NextTarget;
dataFlag = _tables.TbEventDrillReward.DataMap.TryGetValue(nextTaskId, out var nextTaskTableData);
if (!dataFlag)
{
Debug.Log($"[Drill]Next task id {nextTaskId} not found in reward table, end of mission chain.");
return null;
}
// var taskReward = GetBlockDataFromDropId(nextTaskTableData.DropGem);
var taskReward = _playerItemData.GetItemDataByDropId(nextTaskTableData.DropGem)[0];
return new EventBreakTaskInfo
{
TaskId = nextTaskId,
TargetItemId = taskInfo.TargetItemId,
Reward = taskReward,
TotalGemRequired = nextTaskTableData.TokenRequired,
CurrentGemProgress = taskInfo.CurrentGemProgress - taskInfo.TotalGemRequired
};
}
#endregion
public void GetFreshNewModelData(int[] jobSeeds, out int welcomeGift, out DrillJobModel[] drillJobs, out EventBreakTaskInfo[] taskInfoList)
{
welcomeGift = _tableCycle.WelcomeGift;
drillJobs = new DrillJobModel[TunnelCount];
taskInfoList = new EventBreakTaskInfo[TunnelCount];
var defaultTaskIds = _tableTunnels.Select(t => t.TaskList).ToArray();
for (int i = 0; i < TunnelCount; i++)
{
drillJobs[i] = GetDrillJob(i, jobSeeds[i]);
taskInfoList[i] = GetTaskInfo(_tableTunnels[i].TaskList, i);
}
}
public int GetEntranceRedDotTicketThreshold()
{
return _tableCycle.RedDot;
}
public DrillJobModel[] GetDrillJobModels(int[] seeds)
{
var res = new DrillJobModel[seeds.Length];
for (int i = 0; i < seeds.Length; i++)
res[i] = GetDrillJob(i, seeds[i]);
return res;
}
public EventBreakTaskInfo[] GetTaskInfoArray((int id, int progress)[] taskData)
{
var res = new EventBreakTaskInfo[taskData.Length];
for (int i = 0; i < taskData.Length; i++)
{
// Debug.Log($"[EventBreak]Task init: id {taskData[i].id}, progress {taskData[i].progress}");
res[i] = GetTaskInfo(taskData[i].id, i, taskData[i].progress);
}
return res;
}
/// <summary>
/// Get DrillJob. Before calling this, do save the seed if necessarry.
/// </summary>
/// <param name="idx">In which tunnel</param>
/// <param name="seed">By what rng seed. If seed is less than table threshold, fallback into initial fixed drops.</param>
/// <returns>The drill job</returns>
public DrillJobModel GetDrillJob(int idx, int seed)
{
var tunnelData = _tableTunnels[idx];
var res = new DrillJobModel
{
Cost = tunnelData.ItemRequired,
};
var rewardBlockDatas = new List<DrillBlockData>();
var blockDatas = new List<DrillBlockData>();
for (int i = 0; i < BlockCountPerTunnel; i++)
blockDatas.Add(DrillBlockData.CreateEmpty());
SystemRandom rng;
var gemId = GetItemIdFromDrop(tunnelData.DropGem);
if (IsSeedFixed(idx, seed))
{
rng = new SystemRandom(seed + idx);
var dropId = tunnelData.FixDropId[seed];
var items = _playerItemData.GetItemDataByDropId(dropId);
foreach (var item in items)
{
if (item.id == gemId)
{
int n = (int)item.count;
while (n > 0)
{
rewardBlockDatas.Add(new DrillBlockData { Item = new ItemData(item.id, 1) });
n--;
}
}
else
rewardBlockDatas.Add(new DrillBlockData { Item = item });
}
}
else
{
rng = new SystemRandom(seed);
Assert.IsTrue(idx >= 0 && idx < _tableTunnels.Length, $"Tunnel Index {idx} not within range [0, {_tableTunnels.Length - 1}].");
var dropIds = GetTunnelDropIds(_tableTunnels[idx], rng);
Assert.IsTrue(dropIds.Count <= BlockCountPerTunnel, "[EventBreak]Reward count is greater than block count");
foreach (var dropId in dropIds)
rewardBlockDatas.AddRange(GetBlockDataFromDropId(dropId, rng, gemId));
}
var itemCount = rewardBlockDatas.Count;
// int i = itemCount;
// while (i < BlockCountPerTunnel)
// {
// blockDatas.Add(DrillBlockData.CreateEmpty());
// i++;
// }
rewardBlockDatas = rewardBlockDatas.OrderBy(x => rng.Next()).ToList();
if (rewardBlockDatas.IsNullOrEmpty())
{
Debug.LogError($"[EventBreak] No reward found in tunnel {idx}");
res.Blocks = blockDatas.ToArray();
return res;
}
var indicesToPick = Enumerable.Range(0, BlockCountPerTunnel).ToList();
int idxPicked = rng.Next(0, BlockCountPerTunnel);
blockDatas[idxPicked] = rewardBlockDatas[0];
indicesToPick.Remove(idxPicked);
indicesToPick.Remove(idxPicked + 1);
indicesToPick.Remove(idxPicked - 1);
for (int i = 1; i < rewardBlockDatas.Count; i++)
{
idxPicked = indicesToPick[rng.Next(0, indicesToPick.Count)];
blockDatas[idxPicked] = rewardBlockDatas[i];
indicesToPick.Remove(idxPicked);
}
res.Blocks = blockDatas.ToArray();
return res;
}
public bool IsSeedFixed(int idx, int seed)
{
return seed >= 0 && seed < _tableTunnels[idx].FixDropId.Count;
}
public bool DoesSeedNeedInc(int idx, int seed)
{
return seed >= 0 && seed < _tableTunnels[idx].FixDropId.Count - 1;
}
private List<ItemData> GetInitTunnelDropIds(EventDrillTunnel tunnel, int fixedDropIdx)
{
if (fixedDropIdx < 0 || fixedDropIdx >= tunnel.FixDropId.Count)
{
return null;
}
return _playerItemData.GetItemDataByDropId(tunnel.FixDropId[fixedDropIdx]);
}
/// <summary>
/// Get the drop ids for the tunnel. First drop is the the gem of the tunnel.
/// </summary>
/// <param name="tunnel">tunnel data from table</param>
/// <returns>The dropIds for the tunnel.</returns>
private List<int> GetTunnelDropIds(EventDrillTunnel tunnel, SystemRandom rng)
{
var dropIds = new List<int>();
dropIds.Add(tunnel.DropGem);
var count = tunnel.DropCountList[FtMathUtils.GetRandomIdxFromWeightList(tunnel.DropWeightList, rng)];
while (count > 0)
{
dropIds.Add(tunnel.DropItemId);
count--;
}
return dropIds;
}
/// <summary>
/// Assuming that Random state is set before calling. Will seperate gem.
/// </summary>
/// <param name="dropId">The drop id that represents a weighted random item.</param>
/// <returns>The actual item id and count.</returns>
private DrillBlockData[] GetBlockDataFromDropId(int dropId, SystemRandom rng, int gemId)
{
ItemData item;
var res = new List<DrillBlockData>();
if (!_tables.TbDrop.DataMap.TryGetValue(dropId, out var drop))
{
Debug.Log($"[EventBreak]Drop id {dropId} not found.");
return res.ToArray();
}
if (drop.Type != DropType.Weight)
{
Debug.Log($"[EventBreak]Unsupported drop type {drop.Type} from drop Id {dropId}.");
return res.ToArray();
}
if (rng == null)
{
Debug.Log($"[EventBreak]Need random number generator for this drop type.");
return res.ToArray();
}
try
{
var idx = FtMathUtils.GetRandomIdxFromWeightList(drop.DropList.DropProbList, rng);
item = new ItemData(drop.DropList.DropIDList[idx], drop.DropList.DropCountList[idx]);
}
catch (Exception e)
{
Debug.LogError($"[EventBreak]Invalid drop id {drop}: {e.Message}\n{e.StackTrace}");
return res.ToArray();
}
_playerItemData.ItemTransition(item);
if (item.id == gemId)
for (int i = 0; i < (int)item.count; i++)
res.Add(new DrillBlockData { Item = new ItemData(id: gemId, count: 1) });
else
res.Add(new DrillBlockData { Item = item });
return res.ToArray();
}
private int GetItemIdFromDrop(int dropId)
{
if (!_tables.TbDrop.DataMap.TryGetValue(dropId, out var drop))
{
Debug.Log($"[EventBreak]Drop id {dropId} not found.");
return -1;
}
return drop.DropList.DropIDList[0];
}
public EventBreakEntranceData GetEntranceButtonData()
{
var res = new EventBreakEntranceData();
res.BtnIconUrl = _tableMain.Icon;
res.RedPointTicketThreshold = _tableCycle.RedDot;
var et = new DateTime();
var st = new DateTime();
try
{
et = DateTime.Parse((_tableEvent.TimeDefinition as LimitedTime).EndTime);
st = DateTime.Parse((_tableEvent.TimeDefinition as LimitedTime).StartTime);
}
catch (Exception e)
{
Debug.Log($"[EventBreak] {e.Message}\n{e.StackTrace}");
return null;
}
finally
{
res.ExpiryTime = et;
res.StartTime = st;
}
return res;
}
public EventBreakUIData GetUIData()
{
return new EventBreakUIData
{
MainPanelUrl = _tableMain.UIPanel,
InfoPanelUrl = _tableMain.InfoPanel,
ChainPackPanelUrl = _tableMain.ChainPackPanel,
NormalPackPanelUrl = _tableMain.PackPanel,
RewardPanelUrl = _tableMain.RewardPanel
};
}
public EventChainPackInfo GetPackData()
{
var chianList = _tables.TbEventPackManager[_tableMain.PackId].VIPPackList[0];
var expireTime = new DateTime();
try
{
expireTime = DateTime.Parse((_tableEvent.TimeDefinition as LimitedTime).EndTime);
}
catch (Exception e)
{
Debug.Log($"[EventBreak] {e.Message}\n{e.StackTrace}");
return null;
}
var chainListIdSet = chianList.ToHashSet();
var packs = _tables.TbPack.DataList.Where(p => chainListIdSet.Contains(p.ID)).ToArray();//?
return new EventChainPackInfo()
{
ChainList = chianList,
ExpireTime = expireTime,
Packs = packs,
RedPointKey = "eventbreak.pack"
};
}
public bool[] IsTicketEnough(int ticketCount)
{
return _tableTunnels.Select(t => ticketCount >= t.ItemRequired).ToArray();
}
public bool IsItemGem(ItemData item)
{
return _tableTunnels.Any(t => GetItemIdFromDrop(t.DropGem) == item.id);
}
public int GetGemIdx(int gemId)
{
int idx = 0;
while (idx < _tableTunnels.Length)
{
if (GetItemIdFromDrop(_tableTunnels[idx].DropGem) == gemId)
return idx;
idx++;
}
return idx;
}
public EventBreakNormalPackInfo GetNormalPackInfo()
{
var expireTime = new DateTime();
try
{
expireTime = DateTime.Parse((_tableEvent.TimeDefinition as LimitedTime).EndTime);
}
catch (Exception e)
{
Debug.Log($"[EventBreak] {e.Message}\n{e.StackTrace}");
return null;
}
var packList = _tables.TbEventPackManager[_tableMain.PackId2].VIPPackList[0];
return new EventBreakNormalPackInfo
{
EventId = _tableEvent.ID,
PackLeft = _tables.TbPack[packList[0]],
PackRight = _tables.TbPack[packList[1]],
ExpireTime = expireTime,
};
}
public bool IsItemFishCard(ItemData item)
{
return _tables.TbItem[item.id].Type == 5;
}
}

View File

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

View File

@@ -0,0 +1,40 @@
using System;
using GameCore;
using UnityEngine;
using UnityEngine.UI;
public class EventBreakTaskRewardPopupPanel : MonoBehaviour
{
[SerializeField] private RewardItemNew reward;
[SerializeField] private GameObject[] gemBanners;
[SerializeField] private Button btnClaim;
private Action _action;
public void Init(ItemData rewardItem, int tunnelIdx, Action claimMark = null)
{
// Debug.Log($"[EventBreak] Init!!!!!!!!!!", this);
reward.SetData(rewardItem, abbr: true);
for (int i = 0; i < gemBanners.Length; i++)
gemBanners[i].SetActive(i == tunnelIdx);
btnClaim.onClick.AddListener(OnClaim);
_action = claimMark;
}
private async void OnClaim()
{
try
{
// Debug.Log($"[EventBreak] Claim!!!!!!!!!!", this);
btnClaim.onClick.RemoveAllListeners();
_ = reward.ParticleAttractor();
await System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(1.2f));
UIManager.Instance.DestroyUI(UITypes.EventBreakRewardPopupPanel);
_action?.Invoke();
}
catch (Exception e)
{
Debug.LogError(e);
btnClaim.onClick.AddListener(OnClaim);
}
}
}

View File

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

View File

@@ -0,0 +1,178 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using asap.core;
using DG.Tweening;
using GameCore;
using TMPro;
using UniRx;
using UnityEngine;
using UnityEngine.UI;
public class EventBreakTaskView : MonoBehaviour
{
[SerializeField] private RewardItemNew reward;
[SerializeField] private Image barProgress;
[SerializeField] private TMP_Text textProgress;
[SerializeField] private Transform rewardFlyTarget;
[SerializeField] private GameObject fxGem, fxBar;
[SerializeField] private Animation aniTask;
private int _targetItemId, _taskId;
private float _taskChangeDuration, _barFlashDuration, _rewardFlyDuration, _rewardShowDuration;
private GameObject _rewardFly;
private ItemData _rewardItemData;
private bool _isUpdatingTaskDisplay = false;
private void Start()
{
EventBreakAct.EventAggregator.GetEvent<EventBreakBlockBreak>().Subscribe(OnBlockBreak).AddTo(this);
}
public void Init(EventBreakTaskInfo info, float taskChangeDuration, float barFlashDuration, float rewardFlyDuration, GameObject rewardFly, float rewardShowDuration)
{
reward.SetData(info.Reward, abbr: true);
barProgress.fillAmount = (float)info.CurrentGemProgress / info.TotalGemRequired;
textProgress.text = $"{info.CurrentGemProgress}/{info.TotalGemRequired}";
_targetItemId = info.TargetItemId;
// Debug.Log($"[EventBreak] target item id:{_targetItemId}", this);
_taskId = info.TaskId;
_taskChangeDuration = taskChangeDuration;
_barFlashDuration = barFlashDuration;
_rewardFly = rewardFly;
_rewardItemData = info.Reward;
_rewardFlyDuration = rewardFlyDuration;
_rewardShowDuration = rewardShowDuration;
}
private async void OnBlockBreak(EventBreakBlockBreak e)
{
try
{
var drillModel = GContext.container.Resolve<DrillModel>();
if (e.Item.id != _targetItemId)
return;
await MakeRewardFly(e);
var info = drillModel.TaskInfoList.First(i => i.TargetItemId == _targetItemId);
UpdateDisplay(info);
}
catch (Exception ex)
{
Debug.Log($"[EventBreak] BreakBlockError: {ex.Message}\n{ex.StackTrace}");
}
}
private async Task MakeRewardFly(EventBreakBlockBreak e)
{
try
{
var rewardFly = Instantiate(_rewardFly, transform.parent).GetComponent<RewardItemNew>();
rewardFly.SetRewardPopupData(e.Item);
rewardFly.transform.position = e.BreakPos;
rewardFly.gameObject.SetActive(true);
var t = rewardFly.transform.Find("fx_eventbreakdrill_reward_show");
if (t != null)
t.gameObject.SetActive(true);
t = rewardFly.transform.Find("fx_eventbreakdrill_reward_fly");
if (t != null)
t.gameObject.SetActive(true);
rewardFly.GetComponent<Animation>().Play("reward_common_open");
await Task.Delay(TimeSpan.FromSeconds(_rewardShowDuration));
rewardFly.GetComponent<Animation>().Play("reward_common_close");
await Task.Delay(24 * 1000 / 60);
rewardFly.GetComponent<CanvasGroup>().alpha = 1;
rewardFly.text_num.gameObject.SetActive(false);
rewardFly.transform.localScale = Vector3.one * 0.64f;
await Awaiters.NextFrame;
// _ = rewardFly.ParticleAttractor();
await Task.Delay(TimeSpan.FromSeconds(_rewardFlyDuration));
await rewardFly.transform.DOMove(rewardFlyTarget.position, _rewardFlyDuration).AsyncWaitForCompletion();
Destroy(rewardFly.gameObject);
// UIManager.BlockInput(5f);
}
catch (Exception ex)
{
Debug.Log($"[EventBreak] BreakBlockError: {ex.Message}\n{ex.StackTrace}");
}
}
/// <summary>
/// will never be running twice at the same time.
/// </summary>
/// <param name="info">current task info, the actual one</param>
public async void UpdateDisplay(EventBreakTaskInfo info)
{
if (_isUpdatingTaskDisplay)
return;
try
{
// UIManager.BlockInput(5f);
_isUpdatingTaskDisplay = true;
PlayGemFx();
var s = textProgress.text.Split("/");
var currentCount = int.Parse(s[0]);
var totalCount = int.Parse(s[1]);
if (_taskId != info.TaskId)
{
await DOTween.To(() => currentCount, v => currentCount = v, totalCount, _taskChangeDuration)
.OnUpdate(() =>
{
barProgress.fillAmount = (float)currentCount / totalCount;
textProgress.text = $"{currentCount}/{totalCount}";
})
.AsyncWaitForCompletion();
await PlayProgressBarFx();
var panel = await UIManager.Instance.ShowUINotLoading(UITypes.EventBreakRewardPopupPanel);
var t = new TaskCompletionSource<int>();
panel.GetComponent<EventBreakTaskRewardPopupPanel>().Init(_rewardItemData, EventBreakAct.Ctx.GetGemIdx(gemId: _targetItemId), () => t.SetResult(1));
await t.Task;
EventBreakAct.EventAggregator.Publish(new EventBreakBlockInput(EEventBreakBlockInputOperation.StrongUnblock));
await Awaiters.NextFrame;
currentCount = 0;
totalCount = info.TotalGemRequired;
aniTask.Play("reward_refresh");
await Awaiters.NextFrame;
reward.SetData(info.Reward, abbr: true);
barProgress.fillAmount = 0f;
textProgress.text = $"0/{info.TotalGemRequired}";
_taskId = info.TaskId;
_rewardItemData = info.Reward;
await Awaiters.NextFrame;
}
await DOTween.To(() => currentCount, v => currentCount = v, info.CurrentGemProgress, _taskChangeDuration)
.OnUpdate(() =>
{
barProgress.fillAmount = (float)currentCount / totalCount;
textProgress.text = $"{currentCount}/{totalCount}";
})
.AsyncWaitForCompletion();
_isUpdatingTaskDisplay = false;
EventBreakAct.EventAggregator.Publish(new EventBreakBlockInput(EEventBreakBlockInputOperation.Unblock));
}
catch (Exception ex)
{
Debug.Log($"[EventBreak] TaskView: {ex.Message}\n{ex.StackTrace}", this);
_isUpdatingTaskDisplay = false;
}
}
private void PlayGemFx()
{
fxGem.SetActive(false);
fxGem.SetActive(true);
}
private async Task PlayProgressBarFx()
{
fxBar.SetActive(false);
fxBar.SetActive(true);
await Task.Delay(TimeSpan.FromSeconds(_taskChangeDuration));
fxBar.SetActive(false);
}
}
public class EventBreakBlockBreak
{
public Vector2 BreakPos { get; set; }
public ItemData Item {get; set;}
}

View File

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

View File

@@ -0,0 +1,185 @@
using System;
using System.Threading.Tasks;
using DG.Tweening;
using UnityEngine;
using UnityEngine.Assertions;
using UnityEngine.UI;
using TMPro;
using System.Collections.Generic;
using asap.core;
using Game;
public class EventBreakTunnelView : MonoBehaviour
{
[SerializeField] private EventBreakBlock[] blocks;
[SerializeField] private Button btnDrill;
[SerializeField] private Transform endPivot, drillStartPivot;
[SerializeField] private EventBreakDrillDisplay drillDisplay;
[SerializeField] private GameObject fxButtonGlitter;
[SerializeField] private TMP_Text textCost;
[SerializeField] private Animator aniBtnDrill;
private float _spawnInterval = 0.1f, _dropDuration = 0.5f, _drillDuration = 0.8f, _dropHeight = 1680,
_drillReadyDuration = 0.5f, _resetTunnelDelay = 10f, _btnPressedDuration = 0.3f, _drillDetectionRange = 50f,
_blockDropSfxDelay = 0.1f;
private AnimationCurve _easeCurve;
private int _tunnelIdx;
private List<Vector3> _blockEndPoints;
private void Start()
{
btnDrill.onClick.AddListener(async () => await StartDrilling());
// foreach (var block in blocks)
// Debug.Log($"[EventBreak] block height: {block.name} at {block.transform.position.y}");
}
public void Init(EventBreakTunnelViewInitInfo info)
{
_blockEndPoints = new List<Vector3>();
foreach (var block in blocks)
{
block.gameObject.SetActive(false);
_blockEndPoints.Add(block.transform.position);
}
drillDisplay.Init(info.Idx);
_spawnInterval = info.SpawnInterval;
_dropDuration = info.DropDuration;
_drillDuration = info.DrillDuration;
_tunnelIdx = info.Idx;
_dropHeight = info.DropHeight;
textCost.text = info.Job.Cost.ToString();
_easeCurve = info.EaseCurve;
_drillReadyDuration = info.DrillReadyDuration;
_resetTunnelDelay = info.ResetTunnelDelay;
_btnPressedDuration = info.ButtonPressedDuration;
_drillDetectionRange = info.DrillDetectionRange;
_blockDropSfxDelay = info.BlockDropSfxDelay;
SetTunnel(info.Job);
}
public async void SetTunnel(DrillJobModel job)
{
try
{
EventBreakAct.EventAggregator.Publish(new EventBreakBlockInput(EEventBreakBlockInputOperation.Block));
aniBtnDrill.Play("Normal");
int jobCount = job.Blocks.Length, blockCount = blocks.Length;
Assert.IsTrue(jobCount == blockCount, $"[EventBreak]Block count mismatch. Got {jobCount} jobs and {blockCount} blocks");
drillDisplay.PlayEnter(drillStartPivot.position);
PlayBlockFallSfx(_blockDropSfxDelay);
for (int i = blocks.Length - 1; i >= 0; i--)
{
blocks[i].Appear(job.Blocks[i], dropHeight: _dropHeight, endPoint: _blockEndPoints[i], dropTime: _dropDuration, easeCurve: _easeCurve);
await Task.Delay(TimeSpan.FromSeconds(_spawnInterval));
}
await Task.Delay(TimeSpan.FromSeconds(_dropDuration + 0.1f));
EventBreakAct.EventAggregator.Publish(new EventBreakBlockInput(EEventBreakBlockInputOperation.Unblock));
}
catch (Exception e)
{
Debug.Log($"[EventBreak] TunnelInitiationError: {e.Message}\n{e.StackTrace}");
}
}
private async void PlayBlockFallSfx(float delay = 0)
{
try
{
await Task.Delay(TimeSpan.FromSeconds(delay));
GContext.Publish(new EventUISound("audio_ui_drill_brick_falling", 0));
}
catch (Exception e)
{
Debug.Log($"[EventBreak] SFX error: {e.Message}\n{e.StackTrace}");
}
}
public async Task StartDrilling()
{
// Debug.Log($"[EventBreak] Click No.{_tunnelIdx}!", this);
if (EventBreakAct.DrillSystem.DoDrillJob(_tunnelIdx))
{
EventBreakAct.EventAggregator.Publish(new EventBreakBlockInput(EEventBreakBlockInputOperation.Block));
PlayBtnPressed();
drillDisplay.PlayDrill();
await Task.Delay(TimeSpan.FromSeconds(_drillReadyDuration));
drillDisplay.GetDrillTween(endPivot.transform.position, _drillDuration)
.OnUpdate(DrillBlocks)
.OnComplete(OnDrillComplete);
}
else
{
EventBreakAct.EventAggregator.Publish(new EventBreakInsufficientTicket());
}
}
public void StartDrillingTest()
{
// Debug.Log($"[EventBreak] Click No.{_tunnelIdx}!", this);
drillDisplay.PlayDrill();
drillDisplay.GetDrillTween(endPivot.transform.position, _drillDuration)
.OnUpdate(DrillBlocks);
// .OnComplete(OnDrillComplete);
}
private async void OnDrillComplete()
{
try
{
await Task.Delay(TimeSpan.FromSeconds(_resetTunnelDelay));
var dm = GContext.container.Resolve<DrillModel>();
SetTunnel(dm.DrillJobList[_tunnelIdx]);
EventBreakAct.EventAggregator.Publish(new EventBreakBlockInput(EEventBreakBlockInputOperation.Unblock));
}
catch (Exception e)
{
Debug.Log($"[EventBreak] ResetTunnelError: {e.Message}\n{e.StackTrace}");
}
}
private void DrillBlocks()
{
foreach (var b in blocks)
{
if (b.gameObject.activeSelf == false)
continue;
var delta = b.transform.position.y - drillDisplay.Y;
if (delta > _drillDetectionRange)
continue;
b.Break();
}
}
public void SetAvailabilityDisplay(bool doesShow)
{
fxButtonGlitter.SetActive(doesShow);
textCost.color = doesShow ? Color.white : Color.red;
}
private async void PlayBtnPressed()
{
var isFxOn = fxButtonGlitter.activeInHierarchy;
try
{
aniBtnDrill.Play("Pressed");
fxButtonGlitter.SetActive(false);
await Task.Delay(TimeSpan.FromSeconds(_btnPressedDuration));
aniBtnDrill.Play("Normal");
fxButtonGlitter.SetActive(isFxOn);
}
catch (Exception e)
{
Debug.Log($"[EventBreak] Button Error: {e.Message}\n{e.StackTrace}");
}
}
}
public class EventBreakTunnelViewInitInfo
{
public DrillJobModel Job { get; set; }
public float SpawnInterval { get; set; }
public float DropDuration { get; set; }
public float DrillDuration { get; set; }
public float DropHeight { get; set; }
public float DrillReadyDuration { get; set; }
public float ResetTunnelDelay { get; set; }
public float ButtonPressedDuration { get; set; }
public float DrillDetectionRange { get; set; }
public float BlockDropSfxDelay { get; set; }
public int Idx { get; set; }
public AnimationCurve EaseCurve { get; set; }
}

View File

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