备份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,36 @@
using System.Collections;
using System.Collections.Generic;
using cfg;
using UnityEngine;
public abstract class BaseEventData<T> where T: BaseEventRawData
{
private T _rawData;
public int EventId => _rawData.EventId;
public int RedirectId => _rawData.RedirectId;
private string _key;
public virtual void UploadData()
{
PlayFabMgr.Instance.UpdateUserDataValue(_key, Newtonsoft.Json.JsonConvert.SerializeObject(_rawData));
}
public virtual void LoadData(string s)
{
_rawData = Newtonsoft.Json.JsonConvert.DeserializeObject<T>(s);
}
public abstract void UpdateData(FishingEvent e);
}
public abstract class BaseEventRawData
{
public readonly int EventId;
public readonly int RedirectId;
protected BaseEventRawData(int eventId, int redirectId)
{
EventId = eventId;
RedirectId = redirectId;
}
}

View File

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

View File

@@ -0,0 +1,119 @@
using System;
using System.Collections;
using asap.core;
using GameCore;
using UnityEngine;
using TMPro;
using UniRx;
using UnityEngine.UI;
public class ShootingChainPackPanel : MonoBehaviour
{
[SerializeField] private TMP_Text textTimer /*,textProgress, textComplete*/;
[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 EventShootingRangeData _data;
private const string /*RedPointKey = "home.thanks_giving",*/
ContentAnimationShiftKey = "item_change",
ContentAnimationIdleKey = "item_normal";
private void Start()
{
btnClose.onClick.AddListener(OnClickClose);
_data = GContext.container.Resolve<EventShootingRangeData>();
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);
// _visualProgress = _data.TokenProgress;
// InitTargetProgress();
contentAnimation.Play(ContentAnimationIdleKey);
}
// private const string BubbleKey = "bubble_task";
/// <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());
}
[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....
{
slots[i].Init(IndexFromToSlotIndex[i], _data, _eventAggregator);
}
}
private void OnClickClose()
{
RedPointManager.Instance.SetRedPointState(EventShootingRangeData.PackRedPointId, _data.DoNeedPackRedPoint);
UIManager.Instance.DestroyUI(UITypes.ShootingChainPackPanel);
}
// public class EventShootingRangeChainPackClaimed
// {
// public readonly int SlotIdx;
// public List<int> ProgressRewardGot;
// public EventShootingRangeChainPackClaimed(int slotIdx)
// {
// SlotIdx = slotIdx;
// }
// }
}

View File

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

View File

@@ -0,0 +1,280 @@
using System;
using asap.core;
using GameCore;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using cfg;
using game;
using UniRx;
using System.Collections.Generic;
public class ShootingChainSlot : MonoBehaviour
{
private RewardItemNew[] _rewards;
private TMP_Text _textPrice;
private Button _btnBuy;
private GameObject _goLock, _goDone;
private Animation _animationPlayButton;
private IChainPackData _data;
private PlayerItemData _playerItemData;
private Pack _packData;
private List<ItemData> _rewardItemDataList;
/// <summary>
/// Position of the Slot, in zigzag snake style.
/// </summary>
private int _slotIndex;
private IAPItemList _iap;
private IEventAggregator _eventAggregator;
private GameObject[] _bgGos;
public IDisposable RewardPanelCallbackSubscription;
private CanvasGroup _canvasGroupSelected;
private const string ChangeKey = "buy_change2", IdleKey = "buy_normal2", DoneKey = "buy_done";
private bool IsThisSlotLocked
{
get
{
int finaleChainIdx = _data.ChainListCount - ThanksGivingPackData.SlotCount;
if (_data.ChainProgress >= finaleChainIdx) // Entering the ending stage
{
return _slotIndex > _data.ChainProgress - finaleChainIdx;
}
return _slotIndex == 0;
}
}
public void Init(int slotIdx, IChainPackData packData, IEventAggregator ea)
{
_btnBuy = transform.Find("Item/btn_buy/btn_green").GetComponent<Button>();
// _rewards = transform.Find("Item/reward").GetComponents<RewardItemNew>();
_rewards = new RewardItemNew[2];
_rewards[0] = transform.Find("Item/reward/reward1").GetComponent<RewardItemNew>();
_rewards[1] = transform.Find("Item/reward/reward2").GetComponent<RewardItemNew>();
_textPrice = transform.Find("Item/btn_buy/btn_green/Ani_Container/p_text").GetComponent<TMP_Text>();
_goLock = transform.Find("Item/btn_buy/btn_green/lock").gameObject;
_goDone = transform.Find("Item/done").gameObject;
_bgGos = new GameObject[2];
_bgGos[0] = transform.Find("Item/bg1").gameObject;
_bgGos[1] = transform.Find("Item/bg2").gameObject;
_animationPlayButton = transform.Find("Item").GetComponent<Animation>();
_animationPlayButton.Play(IdleKey);
_canvasGroupSelected = transform.Find("Item/current").GetComponent<CanvasGroup>();
_data = packData;
_slotIndex = slotIdx;
_playerItemData = GContext.container.Resolve<PlayerItemData>();
if (slotIdx == 6 && !_data.IsEndGame) // the extra one slot used in animation
_packData = _data.GetChainPackByChainProgress(_data.GetChainProgressBySlotIdx(slotIdx - 1));
else
_packData = _data.GetChainPackByChainProgress(_data.GetChainProgressBySlotIdx(slotIdx));
_rewardItemDataList = _playerItemData.GetItemDataByDropId(_packData.DropID);
_rewards[0].SetData(_rewardItemDataList[0]);
if (_rewardItemDataList.Count <= 1)
_rewards[1].gameObject.SetActive(false);
else
{
_rewards[1].gameObject.SetActive(true);
_rewards[1].SetData(_rewardItemDataList[1]);
}
SetupPrice(out var tmpText, out _iap);
_textPrice.text = tmpText;
SetSlotState();
_eventAggregator = ea;
_bgGos[0].SetActive(_packData.ID % 2 == 0);
_bgGos[1].SetActive(_packData.ID % 2 == 1);
}
private void SetSlotState()
{
int finaleChainIdx = _data.ChainListCount - ThanksGivingPackData.SlotCount;
int currentActiveSlotIndex = _data.ChainProgress >= finaleChainIdx ? _data.ChainProgress - finaleChainIdx : 0;
if (_slotIndex < currentActiveSlotIndex)//Done
{
_goLock.SetActive(false);
_animationPlayButton.Play(DoneKey);
_canvasGroupSelected.gameObject.SetActive(false);
_canvasGroupSelected.alpha = 0;
return;
}
if (_slotIndex == currentActiveSlotIndex)//Active
{
_goLock.SetActive(false);
_btnBuy.onClick.RemoveAllListeners();
_btnBuy.onClick.AddListener(OnClickBuy);
if (_animationPlayButton.GetClip(IdleKey) is not null)
_animationPlayButton.Play(IdleKey);
_canvasGroupSelected.gameObject.SetActive(true);
_canvasGroupSelected.alpha = 1;
return;
}
//Locked
_goLock.SetActive(true);
_canvasGroupSelected.gameObject.SetActive(false);
_canvasGroupSelected.alpha = 0;
_btnBuy.onClick.RemoveAllListeners();
_btnBuy.onClick.AddListener(() => ToastPanel.Show(LocalizationMgr.GetText("UI_ToastPanel_30")));
}
private void SetupPrice(out string price, out IAPItemList iap)
{
int IAPID = _packData.IAPID;
iap = GContext.container.Resolve<Tables>().TbIAPItemList.GetOrDefault(IAPID);
var sdde = new SKUDetailDataEvent(iap);
GContext.Publish(sdde);
price = sdde.price;
}
private async void OnClickBuy()
{
try
{
_btnBuy.onClick.RemoveAllListeners();
var shopBuyTypeData = new ShopBuyTypeData
{
type = ShopBuyType.EventPack,
ID = _data.EventId,
IsHide = true
};
RewardPanelCallbackSubscription?.Dispose();
RewardPanelCallbackSubscription = GContext.OnEvent<RewardPanelClose>().Subscribe(AlterEventData);
bool res = false;
if (_iap is null)
{
// GContext.Publish(new ShowData(_rewardItemDataList));
_playerItemData.AddItem(_rewardItemDataList);
_data.ChainProgress++;
// Debug.Log($"color=#f18c0aOn Click Buy</color>");
res = true;
TryPopRewards();
}
else
{
res = await GContext.container.Resolve<PlayerShopData>().OnBuy(
_packData.DropID, shopBuyTypeData, _iap, GContext.container.Resolve<PlayerItemData>().GetItemDataByDropId(_packData.DropID), RewardType.Normal);
if (res)
TryPopRewards();
}
//Will run ThanksGivingPackData.OnBuySuccess and show reward popup panel if res is true.
//I hate callback.
if (!res)
{
_btnBuy.onClick.AddListener(OnClickBuy);
RewardPanelCallbackSubscription?.Dispose();
}
else
{
ShootingRangeAct.EventAggregator.Publish(new ShootingRangeAct.EventAmmoBought());
}
// Debug.Log($"[EventLuckMagic] 3rd: {_data.GetHashCode()}");
_data.UploadData();
}
catch (Exception e)
{
Debug.LogError("[ChainSlot] Click Buy Error:", this);
Debug.LogError(e);
}
}
private void AlterEventData(RewardPanelClose _)
{
_eventAggregator.Publish(new EventChainPackClaimed(_slotIndex));
}
public void PlayButtonAnimation()
{
_animationPlayButton.Play(ChangeKey);
}
public void SetLock(bool state)
{
_goLock.SetActive(state);
}
[SerializeField] private float jiandaCanvasGroupFadeTime;
public void PlayCanvasGroupEffect(bool isFadeIn)
{
_canvasGroupSelected.gameObject.SetActive(true);
if (isFadeIn)
{
_canvasGroupSelected.alpha = 0;
_canvasGroupSelected.DOFadeAlpha(1, jiandaCanvasGroupFadeTime);
}
else
{
_canvasGroupSelected.alpha = 1;
_canvasGroupSelected.DOFadeAlpha(0, jiandaCanvasGroupFadeTime);
}
}
[SerializeField] private float jiandaButtonChangeDelay = 1.1f;
public static (int Type, int SubType) GetItemTypeInfo(int itemId)
{
var itemTable = GContext.container.Resolve<Tables>().TbItem;
var res = itemTable.DataMap.TryGetValue(itemId, out var itemData);
if (res)
return (itemData.Type, itemData.SubType);
else
{
Debug.LogWarning($"[ChainSlot] Item {itemId} is not included in item table");
return ErrorType;
}
}
private static (int Type, int SubType) ErrorType = (0, 0);
private void PopReward(int idx)
{
if (idx >= _rewardItemDataList.Count)
{
Debug.LogWarning($"[ChainSlot] idx{idx} out of range {_rewardItemDataList.Count}", this);
return;
}
var iconRt = _rewards[idx].transform.Find("icon") as RectTransform;
var typeInfo = GetItemTypeInfo(_rewardItemDataList[idx].id);
var particleAttractorData = new ParticleAttractorData
{
Type = typeInfo.Type,
SubType = typeInfo.SubType,
Priority = -1,
IgnorePack = true
};
GContext.Publish(particleAttractorData);
var targetPos = particleAttractorData.uIParticleAttractorCenter.transform.position;
var request = new BatchedRewardFlyRequest
{
itemID = _rewardItemDataList[idx].id,
Quantity = _rewardItemDataList[idx].count,
StartPoint = new BatchedRewardFlyPoint(iconRt),
EndPoint = new BatchedRewardFlyPoint(targetPos, 100, UIManager.Instance.transform.lossyScale.x),
isDestinationRewardStash = false,
AnimationParamIndex = 0,
sourceTextRt = iconRt.parent.Find("text_num") as RectTransform
};
GContext.Publish(request);
}
private async void TryPopRewards()
{
for (int i = 0; i < _rewardItemDataList.Count; i++)
{
var typeInfo = GetItemTypeInfo(_rewardItemDataList[i].id);
if (typeInfo.Type == 5 || typeInfo.Type == 9 && typeInfo.SubType == 2)
{
//fish card and fish box, do nothing
;
}
else if (typeInfo.Type == 11)
{
//fish buff, do nothing
;
}
else
{
PopReward(i);
}
}
await System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(0.5f));
GContext.Publish(new ShowData());
AlterEventData(new RewardPanelClose());
}
}

View File

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

View File

@@ -0,0 +1,67 @@
using System;
using asap.core;
using cfg;
using GameCore;
using UnityEngine;
using TMPro;
using UnityEngine.UI;
using UniRx;
public class ShootingNormalPackPanel : MonoBehaviour
{
[SerializeField]
private TMP_Text textTimer, textPriceLeft, textPriceRight, textCountLeft, textCountRight, textDiscount;
[SerializeField] private Button btnClose, btnBuyLeft, btnBuyRight;
private EventShootingRangeData _data;
private IAPItemList _iapLeft, _iapRight;
private PlayerItemData _playerItemData;
private void Awake()
{
btnClose.onClick.AddListener(OnClickClose);
// _tables = GContext.container.Resolve<Tables>();
_data = GContext.container.Resolve<EventShootingRangeData>();
_playerItemData = GContext.container.Resolve<PlayerItemData>();
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);
_playerItemData.ResolveIapId(_data.NormalPacks[0].IAPID, out _iapLeft, textPriceLeft);
_playerItemData.ResolveIapId(_data.NormalPacks[1].IAPID, out _iapRight, textPriceRight);
btnBuyLeft.onClick.AddListener(() => _ = OnClickBuy(_data.NormalPacks[0], _iapLeft));
btnBuyRight.onClick.AddListener(() => _ = OnClickBuy(_data.NormalPacks[1], _iapRight));
textCountLeft.text =
((int)_playerItemData.GetItemDataByDropId(_data.NormalPacks[0].DropID)[0].count).ToString();
textCountRight.text =
((int)_playerItemData.GetItemDataByDropId(_data.NormalPacks[1].DropID)[0].count).ToString();
textDiscount.text = LocalizationMgr.GetFormatTextValue("UI_FishingShopPanel_2", GetDiscountNumber());
}
private int GetDiscountNumber()
{
float discount = _data.NormalPacks[1].Rebate * 100;
return (int)discount;
}
private async System.Threading.Tasks.Task OnClickBuy(Pack pack, IAPItemList iapItemList)
{
if (_data.RemainingTime.TotalSeconds <= 0)
return;
bool res = await GContext.container.Resolve<PlayerShopData>().OnBuy(pack.DropID,
new ShopBuyTypeData { type = ShopBuyType.EventPack, ID = _data.EventId }, iapItemList,
_playerItemData.GetItemDataByDropId(pack.DropID));
if (res)
{
ShootingRangeAct.EventAggregator.Publish(new ShootingRangeAct.EventAmmoBought());
OnClickClose();
}
}
private void OnClickClose()
{
RedPointManager.Instance.SetRedPointState(EventShootingRangeData.PackRedPointId, false);
UIManager.Instance.DestroyUI(UITypes.ShootingNormalPackPanel);
}
}

View File

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

View File

@@ -0,0 +1,329 @@
using System;
using System.Collections.Generic;
using System.Linq;
using asap.core;
using GameCore;
using UniRx;
using UnityEngine;
using UnityEngine.Assertions;
public class ShootingRangeAct : AGameAct
{
private EventShootingRangeData _data;
public const int AmmoCost = 1;
private WinterShootingRangePanel _mainPanel;
private int _clickableCounter;
[SerializeField] private List<ShootingRound> stageList;
public static IEventAggregator EventAggregator = new EventAggregator();
private readonly CompositeDisposable _disposables = new CompositeDisposable();
/// <summary>
/// This method is used in a weird way that Assertion Error can not be caught.
/// </summary>
/// <returns></returns>
public override async System.Threading.Tasks.Task<bool> StartAsync()
{
// await Awaiters.NextFrame;
_clickableCounter = 0;
BlockClick();
_data = GContext.container.Resolve<EventShootingRangeData>();
_data.HasBeenOpened = true;
_mainPanel = (await UIManager.Instance.ShowUILoad(UITypes.EventWinterShootingPanel)).GetComponent<WinterShootingRangePanel>();
// _mainPanel.Init();
GContext.container.Resolve<IDeferredRewardStashService>().Reset();
EventAggregator.GetEvent<EventPanelClose>().Subscribe(_ => UnblockClick()).AddTo(_disposables);
EventAggregator.GetEvent<EventPanelOpen>().Subscribe(_ => BlockClick()).AddTo(_disposables);
EventAggregator.GetEvent<EventRewardPanelClose>().Subscribe(OnRewardPanelClose).AddTo(_disposables);
GContext.OnEvent<DeferredRewardStashPanel.EventStashPanelClose>().Subscribe(_ => UnblockClick()).AddTo(_disposables);
GContext.OnEvent<DeferredRewardStashPanel.EventStashPanelOpen>().Subscribe(_ => BlockClick()).AddTo(_disposables);
ClearStages();
GContext.Publish(new EndTransition());
// await LoadStageAsync();
LoadStage();
UnblockClick();
GContext.OnEvent<EventShootingRangeDebug>().Subscribe(DebugShootingRange).AddTo(this);
return await base.StartAsync();
}
private void Update()
{
if (_clickableCounter == 0 && Input.GetMouseButtonDown(0))
{
if (_data.RemainingTime.TotalSeconds <= -5)
_mainPanel.OnClickClose();
BlockClick();
var target = SelectTarget()?.GetComponent<ShootingTarget>();
if (!target || _data.IsTargetHit(target.targetIdx))
{
UnblockClick();
return;
}
ShootWithoutDisplay(target.targetIdx, out var rewardIndex, out var rewards);
if (rewardIndex == -1)
{
UnblockClick();
return;
}
int eventTrackingHook = rewards.Where(reward => reward.id == 1001).Sum(reward => (int)reward.count);
/*
Debug.Log($"<color=#fe231b>Event tracking:</color>");
Debug.Log($"<color=#fe231b> round: {_data.RoundCount + 1}</color>");
Debug.Log($"<color=#fe231b> stage: {_data.CurrentStageIdx + 1}</color>");
Debug.Log($"<color=#fe231b> target: {_data.GetHitTargetCount()}</color>");
Debug.Log($"<color=#fe231b> is_over: {(rewardIndex == 0 ? 1 : 0)}</color>");
Debug.Log($"<color=#fe231b> drop_list: {_data.CurrentStage.DropId[rewardIndex]}</color>");
Debug.Log($"<color=#fe231b> reward_hook: {eventTrackingHook}</color>");
Debug.Log($"<color=#fe231b> combine_id: {(_data.RoundCount + 1) * 10000 + (_data.CurrentStageIdx + 1) * 100 + _data.GetHitTargetCount()}</color>");
*/
#if AGG
using (var e = GEvent.GameEvent("event_shooting"))
{
e.AddContent("round", _data.RoundCount + 1)
.AddContent("stage", _data.CurrentStageIdx + 1)
.AddContent("target", _data.GetHitTargetCount())
.AddContent("is_over", rewardIndex == 0 ? 1 : 0)
.AddContent("drop_list", _data.CurrentStage.DropId[rewardIndex])
.AddContent("reward_hook", eventTrackingHook)
.AddContent("combine_id",
(_data.RoundCount + 1) * 10000 + (_data.CurrentStageIdx + 1) * 100 + _data.GetHitTargetCount());
}
#endif
#if UNITY_EDITOR
if (Input.GetKeyDown(KeyCode.R))
{
_data.ResetData();
}
#endif
bool isFinal = _data.IsFinalStage;
if (rewardIndex == 0)
_data.SwitchToNextStage();
_data.UploadData();
Display(target, rewardIndex == 0, isFinal, rewards);
}
}
/*public static void SubscribeEvent<T>(T e, Action<T> a)
{
EventAggregator.GetEvent<T>().Subscribe(a).AddTo(Disposables);
}*/
private void ClearStages()
{
Assert.IsTrue(_data.CurrentStageIdx >= 0 && _data.CurrentStageIdx < stageList.Count,
$"Stage index {_data.CurrentStageIdx} is out of range {stageList.Count}");
Debug.Log("Load Stage start.");
foreach (var stage in stageList)
{
stage.Hide();
}
}
private async System.Threading.Tasks.Task LoadStageAsync()
{
await stageList[_data.CurrentStageIdx].ShowAsync();
}
private void LoadStage()
{
stageList[_data.CurrentStageIdx].Show();
}
private GameObject SelectTarget()
{
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out var hit) && hit.collider.CompareTag("ShootingTarget"))
return hit.collider.gameObject;
return null;
}
private void ShootWithoutDisplay(int targetIdx, out int rewardIdx, out List<ItemData> rewards)
{
rewardIdx = -1;
rewards = null;
/*if (_data.IsGameDepleted)
{
Debug.Log("Game depleted.");
return;
}*/
if (_data.AmmoCount < AmmoCost)
{
Debug.Log("Not enough ammo.");
// _mainPanel.ShowAmmoTip();
_mainPanel.OnClickSupply();
return;
}
_data.AddAmmo(-AmmoCost);
var processedWeightList = _data.CurrentStage.Weight.Select((w, i) => _data.IsRewardCollected(i) ? 0 : w).ToList();
processedWeightList[0] = _data.IsGrandPrizeAllowed ? processedWeightList[0] : 0;
rewardIdx = _data.PickRandomIndex(processedWeightList);
// Debug.Log($"Got reward No.{rewardIdx}, dropId {_data.CurrentStage.DropId[rewardIdx]}.");
rewards = GContext.container.Resolve<PlayerItemData>()
.GetItemDataByDropId(_data.CurrentStage.DropId[rewardIdx]);
foreach (var reward in rewards)
{
if (reward.id != _data.CycleItem.ItemId)
GContext.Publish(new DeferredRewardStashService.EventStashItem { Item = reward });
else
GContext.container.Resolve<PlayerItemData>().AddItem(reward);
}
_data.SetRewardCollected(rewardIdx);
_data.SetTargetHit(targetIdx);
}
[Tooltip("开镜动画出现延迟")][SerializeField] private float jiandaAimDelay;
[Tooltip("靶子碎裂延迟")][SerializeField] private float jiandaTargetBreakDelay;
[Tooltip("过关面板出现延迟")][SerializeField] private float jiandaRewardPanelPopupDelay;
[Tooltip("切换关卡延迟")][SerializeField] private float jiandaSwitchStageDelay;
[Tooltip("奖励出现并飞入延迟")]
[SerializeField]
private float jiandaRewardFlyDelay;
[Tooltip("雪人出现延迟")][SerializeField] private float jiandaSnowManPopupDelay;
[Tooltip("允许面板操作的延迟,从点击开始")]
[SerializeField]
private float jiandaUnblockDelay = 2.1f;
[Tooltip("奖励出现时,相对于靶子的,奖励位置偏移")]
[SerializeField]
private Vector2 jiandaRewardPositionOffset = new Vector2(0, 0);
private void Display(ShootingTarget target, bool needSwitchStage, bool isFinalStage,
List<ItemData> rewards)
{
if (needSwitchStage && rewards is null)
{
Debug.LogWarning($"Empty grand prize.");
return;
}
_mainPanel.UpdateAmmoCount(AmmoCost);
// var localHitPosition = _mainPanel.GetUiHitPosition(target.gameObject);
var localHitPosition = UIManager.Instance.WorldToScreen(target.transform.position);
_ = _mainPanel.ShowCrosshairAfterDelay(localHitPosition, jiandaAimDelay);
_ = target.PlayBreakAnimationWithDelay(jiandaTargetBreakDelay);
if (needSwitchStage)
{
_ = _mainPanel.ShowSnowmanAfterDelay(localHitPosition + jiandaRewardPositionOffset, jiandaSnowManPopupDelay);
_ = ShowRewardPopupWithDelay(rewards, isFinalStage, jiandaRewardPanelPopupDelay);
// Will unblock when panel is closed!
// Will receive event when panel is closed.
}
else
{
_ = System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(jiandaUnblockDelay))
.ContinueWith(_ => UnblockClick());
_ = _mainPanel.PlayRewardFlyWithDelay(rewards[0], localHitPosition + jiandaRewardPositionOffset, jiandaRewardFlyDelay);
// UnblockClick();
}
}
private async System.Threading.Tasks.Task ShowRewardPopupWithDelay(List<ItemData> rewards, bool doesShowFinal,
float delay)
{
await System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(delay));
var finalRewardPopup = (await UIManager.Instance.ShowUI(UITypes.ShootingRangeFinalRewardPopup))
.GetComponent<ShootingRangeFinalRewardPopupPanel>();
finalRewardPopup.Init(rewards, doesShowFinal);
}
private void OnRewardPanelClose(EventRewardPanelClose e)
{
BlockClick();
if (e.IsFinalStage)
{
_mainPanel.OnClickClose();
}
else
{
_ = _mainPanel.MoveSnowmanAfterDelayAndUpdateTarget(0f);
for (int i = 0; i < e.Rewards.Length; i++)
{
_ = _mainPanel.PlayRewardFlyWithDelay(e.Rewards[i], e.RewardPositionList[i], 0f);
}
_ = SwitchStageWithDelay(jiandaSwitchStageDelay);
}
}
private async System.Threading.Tasks.Task SwitchStageWithDelay(float delay)
{
await System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(delay));
ClearStages();
var panel = await UIManager.Instance.ShowUI(UITypes.ShootingRangeTransitionPanel);
await System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(0.8f));
_mainPanel.UpdateAmmoCount();
_mainPanel.SetRewards();
panel.GetComponent<CloudTransitionPanel>().EndTransition(new EndTransition());
// await LoadStageAsync();
LoadStage();
UnblockClick();
}
private void LogRewardState()
{
Debug.Log("Checking reward status.");
for (int i = 0; i < _data.CurrentStage.DropId.Count; i++)
{
Debug.Log($" Reward {i}: {_data.IsRewardCollected(i)}");
}
// Debug.Log();
}
private void BlockClick()
{
_clickableCounter++;
// Debug.Log($"<color=#a6a6a6>Block to: {_clickableCounter}.</color>");
}
private void UnblockClick()
{
_clickableCounter--;
// Debug.Log($"<color=#a6a6a6>Unblock to: {_clickableCounter}.</color>");
}
protected override void OnDestroy()
{
RedPointManager.Instance.SetRedPointState(EventShootingRangeData.EntranceRedPointId,
_data.DoNeedEntranceRedPoint);
_disposables?.Dispose();
Debug.Log("Exit ShootingRangeAct.");
// GContext.container.Resolve<IDeferredRewardStashService>().Flush();
}
public class EventPanelClose
{
}
public class EventPanelOpen
{
}
public class EventRewardPanelClose
{
public bool IsFinalStage;
public ItemData[] Rewards;
public Vector2[] RewardPositionList;
}
public class EventAmmoBought
{
}
private void DebugShootingRange(EventShootingRangeDebug e)
{
_data.SwitchToStage(e.StageIdx);
ClearStages();
_ = LoadStageAsync();
}
}
public class EventShootingRangeDebug
{
public int StageIdx;
}

View File

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

View File

@@ -0,0 +1,12 @@
using UnityEngine;
public class ShootingRangeBlocker : MonoBehaviour
{
protected virtual void Awake()
{
ShootingRangeAct.EventAggregator.Publish(new ShootingRangeAct.EventPanelOpen());
}
protected virtual void OnDestroy()
{
ShootingRangeAct.EventAggregator.Publish(new ShootingRangeAct.EventPanelClose());
}
}

View File

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

View File

@@ -0,0 +1,30 @@
using Cinemachine;
using Unity.Mathematics;
using UnityEngine;
public class ShootingRangeCameraAspectAdjustment : MonoBehaviour
{
[SerializeField] private CinemachineVirtualCamera virtualCamera;
[SerializeField] private float aspectUpperLimit = 2.2f;
private void Start()
{
if (virtualCamera == null)
{
Debug.LogError("No Virtual Camera found.", this);
return;
}
float aspect = (float)Screen.height / Screen.width;
// Debug.Log($"[FOV]height: {Screen.height}, width: {Screen.width}, aspect: {aspect}]");
var oldFov = virtualCamera.m_Lens.FieldOfView;
// Debug.Log($"[FOV]old fov: {oldFov}");
if (aspect >= 16.0 / 9)
{
var newFov = 2 * math.atan(math.tan(oldFov * 0.5f / 180 * math.PI) * 9 / 16 * (aspect < aspectUpperLimit ? aspect : aspectUpperLimit)) / math.PI * 180;
// Debug.Log($"[FOV]new fov raw{newFov}");
// while (newFov < 0)
// newFov += 180;
// Debug.Log($"[FOV]new fov{newFov}");
virtualCamera.m_Lens.FieldOfView = newFov;
}
}
}

View File

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

View File

@@ -0,0 +1,356 @@
using System;
using System.Collections.Generic;
using asap.core;
using cfg;
using UnityEngine;
using UnityEngine.Assertions;
using GameCore;
public class EventShootingRangeData : IChainPackData
{
private RawData _data = new RawData();
private readonly Tables _tables = GContext.container.Resolve<Tables>();
private readonly TbPack _pack = GContext.container.Resolve<Tables>().TbPack;
private readonly TbEventPackManager _eventPackManager = GContext.container.Resolve<Tables>().TbEventPackManager;
private readonly TbEventShootingRangeMain _shootingRangeMainTable =
GContext.container.Resolve<Tables>().TbEventShootingRangeMain;
public const string Key = "EventShootingRangeData",
PackRedPointId = "EventShooting.Pack",
EntranceRedPointId = "EventShooting.Enter";
private const int SlotCount = 6;
public int EventId => _data.EventId;
public int RedirectId => _data.RedirectId;
public int AmmoCount => _data.AmmoCount;
public bool HasBeenOpened
{
get => _data.HasBeenOpened;
set => _data.HasBeenOpened = value;
}
public TimeSpan RemainingTime =>
DateTime.Parse((_tables.TbFishingEvent[_data.EventId].TimeDefinition as LimitedTime)?.EndTime) -
ZZTimeHelper.UtcNow();
public bool IsActive => _tables.TbFishingEvent.DataMap.ContainsKey(_data.EventId) &&
_tables.TbFishingEventCycleItem2.DataMap.ContainsKey(_data.CycleId) &&
_tables.TbEventShootingRangeMain.DataMap.ContainsKey(_data.RedirectId) &&
_tables.TbEventPackManager.DataMap.ContainsKey(_tables
.TbEventShootingRangeMain[_data.RedirectId].PackId) &&
RemainingTime.TotalSeconds > 0 &&
ZZTimeHelper.UtcNow() >=
DateTime.Parse((_tables.TbFishingEvent[_data.EventId].TimeDefinition as LimitedTime)
?.StartTime);
public EventShootingRangeMain EventShootingRange =>
GContext.container.Resolve<Tables>().TbEventShootingRangeMain[RedirectId];
public EventShootingRangeStage CurrentStage =>
_tables.TbEventShootingRangeStage[EventShootingRange.StageList[CurrentStageIdx]];
public int CurrentStageIdx => _data.CurrentStageIdx % EventShootingRange.StageList.Count;
public int RoundCount => _data.CurrentStageIdx / EventShootingRange.StageList.Count;
// public bool IsGameDepleted =>
// _data.CurrentStageIdx < 0 || _data.CurrentStageIdx >= EventShootingRange.StageList.Count;
public bool IsGrandPrizeAllowed => CurrentStageShootCount >= CurrentStage.MinAttempts - 1;
public bool IsFinalStage => CurrentStageIdx == EventShootingRange.StageList.Count - 1;
public int CurrentStageShootCount
{
get
{
int count = 0;
var flag = _data.RewardFlag;
while (flag > 0)
{
count += (int)(flag & 1);
flag >>= 1;
}
return count;
}
}
private List<int> ChainList => _tables.TbEventPackManager[_tables.TbEventShootingRangeMain[_data.RedirectId].PackId]
.VIPPackList[0];
public int ChainListCount => ChainList.Count;
public bool IsChainPackDepleted => _data.ChainProgress >= ChainListCount;
public bool IsEndGame => _data.ChainProgress > ChainList.Count - SlotCount;
public bool DoNeedPackRedPoint
{
get
{
if (!IsChainPackDepleted && ChainProgress < ChainListCount)
return _pack[_eventPackManager[EventShootingRange.PackId].VIPPackList[0][ChainProgress]].IAPID == 0;
return false;
}
}
public bool DoNeedEntranceRedPoint => !HasBeenOpened || _data.AmmoCount >= CycleItem.RedDot;
public int ChainProgress
{
get => _data.ChainProgress;
set => _data.ChainProgress = value;
}
public Pack[] NormalPacks
{
get
{
// return [_tables.TbPack[EventShootingRange.PackId2], _tables.TbPack[EventShootingRange.PackId2 + 1]
var normalPackIds = _tables.TbEventPackManager[EventShootingRange.PackId2].VIPPackList[0];
var packs = new Pack[normalPackIds.Count];
for (int i = 0; i < normalPackIds.Count; i++)
{
packs[i] = _tables.TbPack[normalPackIds[i]];
}
return packs;
}
}
public string AmmoIconUrl => GContext.container.Resolve<Tables>().TbItem[CycleItem.ID].Icon;
public string AmmoNameUrl => GContext.container.Resolve<Tables>().TbItem[CycleItem.ID].Name_l10n_key;
public List<int> GetTokenProgressRewardAfterAddingToken(int tokenAdded)
{
throw new NotImplementedException();
}
public FishingEventCycleItem2 CycleItem => _tables.TbFishingEventCycleItem2[_data.CycleId];
#region UI Resources
public string ChainPackPanelUrl => _shootingRangeMainTable[RedirectId].ChainPackPanel;
public string PackPanelUrl => _shootingRangeMainTable[RedirectId].PackPanel;
public string InfoPanelUrl => _shootingRangeMainTable[RedirectId].InfoPanel;
public string MainPanelUrl => _shootingRangeMainTable[RedirectId].EventPanel;
public string RewardPanelUrl => _shootingRangeMainTable[RedirectId].EventRewardPanel;
public string ShootingRangeAct => _shootingRangeMainTable[RedirectId].Scene;
public string EntranceIcon => _shootingRangeMainTable[RedirectId].IconEvent;
public string PackIcon => _shootingRangeMainTable[RedirectId].IconPackage;
public string TransitionPanelUrl => _shootingRangeMainTable[RedirectId].TransPanel;
#endregion
public int AmmoId => CycleItem.ItemId;
public string RedPointKey => throw new NotImplementedException();
public int GetChainProgressBySlotIdx(int slotIdx)
{
// Debug.Log($"<color=#f18c0a>Progress: {ChainProgress}</color>");
int res;
if (_data.ChainProgress > ChainList.Count - SlotCount)
res = ChainList.Count - SlotCount + slotIdx;
else
res = _data.ChainProgress + slotIdx;
Assert.IsTrue(res < ChainList.Count, $"Progress {res} out of range: {ChainListCount}");
return res;
}
public void UpdateData(FishingEvent e)
{
if (EventId == e.ID)
return;
_data = new RawData
{
EventId = e.ID,
CycleId = e.RedirectID,
RedirectId = _tables.TbFishingEventCycleItem2[e.RedirectID].RedirectID,
AmmoCount = _tables.TbFishingEventCycleItem2[e.RedirectID].WelcomeGift,
HasBeenOpened = false
};
UploadData();
}
public void LoadData(string s)
{
_data = Newtonsoft.Json.JsonConvert.DeserializeObject<RawData>(s);
// _data.EventId = 0;
// Debug.Log($"<color=#4d90fe>ShootingRangeDataLoaded: {s}</color>");
}
public void UploadData()
{
var message = Newtonsoft.Json.JsonConvert.SerializeObject(_data);
// Debug.Log($"<color=#4d90fe>ShootingRangeDataUploaded: {message}</color>");
PlayFabMgr.Instance.UpdateUserDataValue(Key, message);
}
public void AddAmmo(int count)
{
_data.AmmoCount += count;
GContext.container.Resolve<FishingEventData>().SaveTransitionData(_data.EventId, _data.AmmoCount);
UploadData();
}
public int PickRandomIndex(IList<int> weightList)
{
Assert.IsTrue(weightList is { Count: >= 1 }, "WeightList contains no weight.");
var acc = new List<int> { weightList[0] };
for (int i = 1; i < weightList.Count; i++)
acc.Add(weightList[i] + acc[i - 1]);
int random = UnityEngine.Random.Range(0, acc[^1]);
for (int i = 0; i < acc.Count; i++)
{
if (random < acc[i])
{
return i;
}
}
return -1;
}
/// <summary>
/// Checkout to next stage.
/// </summary>
/// <returns>False if next stage is out of range.</returns>
public void SwitchToNextStage()
{
_data.CurrentStageIdx++;
// _data.CurrentStageIdx %= EventShootingRange.StageList.Count;
ResetRewardFlag();
ResetTargetFlag();
// return _data.CurrentStageIdx < EventShootingRange.StageList.Count;
}
public void SwitchToStage(int n)
{
_data.CurrentStageIdx = n;
ResetRewardFlag();
ResetTargetFlag();
}
public Pack GetChainPackByChainProgress(int chainProgress)
{
return _tables.TbPack[ChainList[chainProgress]];
}
public void OnBuySuccess()
{
if (ChainProgress >= ChainListCount)
{
Debug.LogError($"Trying to buy pack no.{ChainProgress} while there are/is only {ChainListCount} packs.");
return;
}
_data.ChainProgress++;
}
#if UNITY_EDITOR
public void ResetData()
{
_data.AmmoCount = 200;
ResetRewardFlag();
ResetTargetFlag();
_data.CurrentStageIdx = 11;
UploadData();
Debug.Log("<color=#4d90fe>Data reset.</color>");
}
#endif
#region Flags
public void ResetRewardFlag()
{
_data.RewardFlag = 0;
}
/// <summary>
/// Check if reward No.idx in current stage is claimed.
/// </summary>
/// <param name="idx">Index of current reward. Starts with 0.</param>
/// <returns>True if this reward is collected.</returns>
public bool IsRewardCollected(int idx)
{
Assert.IsTrue(idx < CurrentStage.DropId.Count,
$"Attempting to get reward{idx} status, while we have only {CurrentStage.DropId.Count} rewards.");
long idxFlag = (long)1 << idx;
return (_data.RewardFlag & idxFlag) == idxFlag;
}
public void SetRewardCollected(int idx)
{
Assert.IsTrue(idx < CurrentStage.DropId.Count,
$"Attempting to set reward{idx} as got, while we have only {CurrentStage.DropId.Count} rewards.");
_data.RewardFlag |= (long)1 << idx;
}
public void ResetTargetFlag()
{
_data.TargetFlag = 0;
}
public bool IsTargetHit(int idx)
{
/*Assert.IsTrue(idx < CurrentStage.DropId.Count,
$"Attempting to get target{idx} status, while we have only {CurrentStage.DropId.Count} targets.");
Assert.IsTrue(false, "JP wins!");
Assert.IsTrue(false,
$"Attempting to get target{idx} status, while we have only {CurrentStage.DropId.Count} targets.");*/
if (idx >= CurrentStage.DropId.Count)
Debug.LogWarning($"尝试获取{idx}号靶子的状态,但是咱只有{CurrentStage.DropId.Count}个Drop。这很奇怪。");
long idxFlag = (long)1 << idx;
return (_data.TargetFlag & idxFlag) == idxFlag;
}
public void SetTargetHit(int idx)
{
// Assert.IsTrue(idx < CurrentStage.DropId.Count,
// $"Attempting to get target{idx} status, while we have only {CurrentStage.DropId.Count} targets.");
if (idx >= CurrentStage.DropId.Count)
Debug.LogWarning($"尝试打击{idx}号靶子,但是咱只有{CurrentStage.DropId.Count}个Drop。这很奇怪。");
_data.TargetFlag |= ((long)1 << idx);
}
public int GetHitTargetCount()
{
int count = 0;
long num = _data.TargetFlag;
while (num != 0)
{
num &= num - 1;
count++;
}
return count;
}
public List<ItemData> GetItemsByPackDropId(int dropId)
{
throw new NotImplementedException();
}
#endregion
private struct RawData
{
public int EventId;
public int CycleId;
public int RedirectId;
public int AmmoCount;
/// <summary>
/// Used in flag fashion.
/// </summary>
public long RewardFlag;
/// <summary>
/// Used in flag fashion.
/// </summary>
public long TargetFlag;
/// <summary>
/// Stage index that starts from 0. May exceed total stage count, indicating how many rounds player has counted.
/// </summary>
public int CurrentStageIdx;
public int ChainProgress;
public bool HasBeenOpened;
}
}

View File

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

View File

@@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
using asap.core;
using game;
using GameCore;
using TMPro;
using UniRx;
using UnityEngine;
using UnityEngine.UI;
public class ShootingRangeEntranceButton : EventButtonResource
{
[SerializeField] private TMP_Text textTimer;
[SerializeField] private Button btn;
[SerializeField] private Image icon;
private EventShootingRangeData _data;
private ILoadResourceService _loadResourceService;
private const string ShootingRangeResourceLabel = "EventShooting";
private void Awake()
{
_data = GContext.container.Resolve<EventShootingRangeData>();
_loadResourceService = GContext.container.Resolve<ILoadResourceService>();
if (_data is not { IsActive: true })
{
gameObject.SetActive(false);
return;
}
textTimer.text = ConvertTools.ConvertTime2(_data.RemainingTime);
Observable.Interval(TimeSpan.FromSeconds(1.0f)).Subscribe(_ =>
{
textTimer.text = ConvertTools.ConvertTime2(_data.RemainingTime);
if (_data.RemainingTime.TotalSeconds <= 0)
gameObject.SetActive(false);
}).AddTo(this);
btn.onClick.AddListener(OnEnterShootingRangeAct);
RedPointManager.Instance.SetRedPointState(EventShootingRangeData.EntranceRedPointId, _data.DoNeedEntranceRedPoint || _data.DoNeedPackRedPoint);
CheckResource(new List<string>() { _data.ShootingRangeAct, _data.EntranceIcon });
}
private void OnEnterShootingRangeAct()
{
try
{
OnEnterShootingRangeActAsync();
}
catch (Exception e)
{
Debug.Log(e.Message);
throw;
}
}
private async void OnEnterShootingRangeActAsync()
{
//TODO: Will have different bundles in the future.
bool isReady = await _loadResourceService.Load(_data.ShootingRangeAct);
if (isReady)
{
Debug.Log($"<color=#22a6f2>[Shooting Range] Download Ready!</color>");
GContext.Publish(new UnloadActToNextAct
{ actId = _data.ShootingRangeAct, TransitionPanel = UITypes.ShootingRangeTransitionPanel });
}
else
{
Debug.Log($"<color=#22a6f2>[Shooting Range] Download Not Ready!</color>");
var panel = await UIManager.Instance.ShowUI(UITypes.CloudTransitionPanel);
panel.GetComponent<CloudTransitionPanel>().SetBtn(true,
() => GContext.Publish(new UnloadActToNextAct(_data.ShootingRangeAct)));
}
}
protected override void OnLoadEventResource()
{
if (_data != null && _data.RemainingTime.TotalSeconds > 0)
{
_ = GContext.container.Resolve<IUIService>().SetImageSprite(icon, _data.EntranceIcon);
gameObject.SetActive(true);
}
}
}

View File

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

View File

@@ -0,0 +1,36 @@
using System.Collections.Generic;
using GameCore;
using UnityEngine;
using UnityEngine.UI;
public class ShootingRangeFinalRewardPopupPanel : MonoBehaviour
{
[SerializeField] private Button btnNormal, btnFinal;
[SerializeField] private GameObject rewardRoot, finalRewardRoot;
[SerializeField] private ShootingRewardLayout normalRewardLayout, finalRewardLayout;
private ShootingRangeAct.EventRewardPanelClose _panelCloseEvent;
public void Init(List<ItemData> rewardItems, bool isFinalStage = false)
{
btnNormal.onClick.AddListener(OnClickClaim);
btnFinal.onClick.AddListener(OnClickClaim);
rewardRoot.SetActive(!isFinalStage);
finalRewardRoot.SetActive(isFinalStage);
normalRewardLayout.SetRewards(rewardItems);
finalRewardLayout.SetRewards(rewardItems);
_panelCloseEvent = new ShootingRangeAct.EventRewardPanelClose
{
IsFinalStage = isFinalStage,
Rewards = rewardItems.ToArray(),
};
}
private void OnClickClaim()
{
// This panel does not use extra ShootingRangeBlocker.cs script.
ShootingRangeAct.EventAggregator.Publish(new ShootingRangeAct.EventPanelClose());
_panelCloseEvent.RewardPositionList = finalRewardLayout.isActiveAndEnabled ? finalRewardLayout.PositionList : normalRewardLayout.PositionList;
ShootingRangeAct.EventAggregator.Publish(_panelCloseEvent);
UIManager.Instance.DestroyUI(UITypes.ShootingRangeFinalRewardPopup);
}
}

View File

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

View File

@@ -0,0 +1,21 @@
using asap.core;
using GameCore;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public class ShootingRangeInfoPanel : MonoBehaviour
{
[SerializeField] private Button btnClose;
[SerializeField] private Image ammoIcon;
[SerializeField] private TMP_Text textExplain;
private EventShootingRangeData _data;
private void Awake()
{
btnClose.onClick.AddListener(() => UIManager.Instance.DestroyUI(UITypes.ShootingRangeInfoPanel));
_data = GContext.container.Resolve<EventShootingRangeData>();
GContext.container.Resolve<IUIService>().SetImageSprite(ammoIcon, _data.AmmoIconUrl);
textExplain.text =
LocalizationMgr.GetFormatTextValue("UI_EventSandDigPanel_7", LocalizationMgr.GetText(_data.AmmoNameUrl));
}
}

View File

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

View File

@@ -0,0 +1,77 @@
using asap.core;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using UniRx;
using System;
using GameCore;
public class ShootingRangePackButton : MonoBehaviour
{
[SerializeField] private TMP_Text textTimer;
[SerializeField] private Button btn;
[SerializeField] private Image icon;
private EventShootingRangeData _data;
private UIType PackPanelUi => _data.IsChainPackDepleted ? UITypes.ShootingNormalPackPanel : UITypes.ShootingChainPackPanel;
private void Start()
{
// Shutdown shooting range pack button.
gameObject.SetActive(false);
return;
/*
_data = GContext.container.Resolve<EventShootingRangeData>();
if (_data is not { IsActive: true })
{
gameObject.SetActive(false);
return;
}
textTimer.text = ConvertTools.ConvertTime2(_data.RemainingTime);
if (_data.RemainingTime.TotalSeconds <= 0)
gameObject.SetActive(false);
Observable.Interval(TimeSpan.FromSeconds(1.0f)).Subscribe(_ =>
{
textTimer.text = ConvertTools.ConvertTime2(_data.RemainingTime);
if (_data.RemainingTime.TotalSeconds <= 0)
gameObject.SetActive(false);
}).AddTo(this);
RedPointManager.Instance.SetRedPointState(EventShootingRangeData.PackRedPointId, _data.DoNeedPackRedPoint);
GContext.container.Resolve<IUIService>().SetImageSprite(icon, _data.PackIcon);
btn.onClick.AddListener(OnClickOpen);
*/
}
private async void OnClickOpen()
{
var res = await UIManager.Instance.ShowUILoad(PackPanelUi);
if (res == null)
{
Debug.LogWarning($"[ShootingRange] ShootingRange Pack panel not loaded correctly.");
}
}
// private async System.Threading.Tasks.Task<bool> LoadAssetBundle()
// {
// var loadResourceService = GContext.container.Resolve<ILoadResourceService>();
// return await loadResourceService.Load(PackPanelUi.Path);
// }
/*
private async System.Threading.Tasks.Task EnterEventPartnerAct()
{
_homeCanvasGroup.blocksRaycasts = false;
if (await LoadAssetBundle())
{
GContext.Publish(new UnloadActToNextAct("EventPartnerAct"));
}
else
{
var panel = await UIManager.Instance.ShowUI(UITypes.CloudTransitionPanel);
panel.GetComponent<CloudTransitionPanel>().SetBtn(true, () => GContext.Publish(new UnloadActToNextAct("EventPartnerAct")));
//var panel = await UIManager.Instance.ShowUI(UITypes.FishingDownLoadPopupPanel);
//panel.GetComponent<FishingDownLoadPopupPanel>().SetBtn(null, () => GContext.Publish(new UnloadActToNextAct("EventPartnerAct")));
}
_homeCanvasGroup.blocksRaycasts = true;
}
*/
}

View File

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

View File

@@ -0,0 +1,52 @@
using System.Collections.Generic;
using GameCore;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public class ShootingRangeRewardTip : MonoBehaviour
{
[SerializeField] private GameObject rewardEmptyGo1, rewardEmptyGo2;
[SerializeField] private GameObject[] rewardGos;
[SerializeField] private RewardItemNew[] rewards;
[SerializeField] private TMP_Text textTarget, textOwned;
[SerializeField] private Button btnClose;
[SerializeField] private GameObject tipGo;
public void Awake()
{
btnClose.onClick.AddListener(() => gameObject.SetActive(false));
gameObject.SetActive(false);
}
/// <summary>
/// Init this tip.
/// </summary>
/// <param name="items">Items to be shown in this tip.</param>
public void Init(List<ItemData> items)
{
if (items.Count == 1)
{
rewardEmptyGo1.SetActive(true);
rewardEmptyGo2.SetActive(true);
rewardGos[0].SetActive(true) ;
for (int i = 1; i < rewardGos.Length; i++)
{
rewardGos[i].SetActive(false);
}
rewards[0].SetData(items[0]);
}
else if (items.Count > 1)
{
rewardEmptyGo1.SetActive(false);
rewardEmptyGo2.SetActive(false);
for (int i = 0; i < rewardGos.Length; i++)
{
rewardGos[i].SetActive(i < items.Count);
if (i >= items.Count) continue;
rewards[i].SetData(items[i], abbr: true);
// rewards[i].text_num.gameObject.SetActive(false);
}
}
// textPoint.text = LocalizationMgr.GetFormatTextValue("UI_EventPartnerFishbowlPanel_7", score, targetScore);
}
}

View File

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

View File

@@ -0,0 +1,27 @@
using System.Collections.Generic;
using GameCore;
using UnityEngine;
using System.Linq;
public class ShootingRewardLayout : MonoBehaviour
{
[SerializeField] private GameObject[] itemsGoList;
[SerializeField] private RewardItemNew[] rewardList;
public Vector2[] PositionList => rewardList.Select(x => (Vector2)x.transform.position).ToArray();
public void SetRewards(List<ItemData> rewardItems, bool forceLight = false)
{
for (int i = 0; i < rewardList.Length; i++)
{
if (i >= rewardItems.Count)
{
itemsGoList[i].SetActive(false);
continue;
}
itemsGoList[i].SetActive(true);
rewardList[i].SetData(rewardItems[i], true, false, forceLight);
}
}
}

View File

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

View File

@@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using asap.core;
using UnityEngine;
using UnityEngine.Assertions;
public class ShootingRound : MonoBehaviour
{
private List<ShootingTarget> _targetList;
private EventShootingRangeData _data;
private void Awake()
{
_targetList = new List<ShootingTarget>();
foreach (Transform child in transform)
{
var target = child.GetComponent<ShootingTarget>();
if (!target) continue;
_targetList.Add(target);
}
_data = GContext.container.Resolve<EventShootingRangeData>();
}
private const float TargetPopupDuration = 0.5f;
public async System.Threading.Tasks.Task ShowAsync()
{
gameObject.SetActive(true);
foreach (var target in _targetList)
{
target.gameObject.SetActive(false);
}
if (_targetList.Count <= 0)
return;
var delay = TargetPopupDuration / _targetList.Count;
for (int i = 0; i < _targetList.Count; i++)
{
bool isHit = _data.IsTargetHit(i);
_targetList[i].InitAndPlayAppearAnimation(isHit, _data.CurrentStageIdx, i);
if (!isHit)
await System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(delay));
}
}
public void Show()
{
gameObject.SetActive(true);
foreach (var target in _targetList)
{
target.gameObject.SetActive(false);
}
if (_targetList.Count <= 0)
return;
var delay = TargetPopupDuration / _targetList.Count;
for (int i = 0; i < _targetList.Count; i++)
{
bool isHit = _data.IsTargetHit(i);
_targetList[i].InitAndPlayAppearAnimation(isHit, _data.CurrentStageIdx, i);
// if (!isHit)
// await System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(delay));
}
}
public void Hide()
{
gameObject.SetActive(false);
}
private static int ParseTargetIndex(string goName)
{
var tokens = goName.Split('(', ')');
Assert.IsTrue(tokens.Length >= 3, $"Name {goName} is supposed to contain brackets.");
return int.Parse(tokens[1]);
}
}

View File

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

View File

@@ -0,0 +1,49 @@
using System;
using UnityEngine;
public class ShootingTarget : MonoBehaviour
{
public int stageIdx, targetIdx;
public Animation ani;
private const string Break = "breaking", Broken = "broken", Normal = "normal", Appear = "into";
public void InitAndPlayAppearAnimation(bool isHit, int stageIdx, int targetIdx)
{
this.stageIdx = stageIdx;
this.targetIdx = targetIdx;
gameObject.SetActive(!isHit);
if (!isHit)
PlayAppear();
}
public async System.Threading.Tasks.Task PlayBreakAnimationWithDelay(float delay = 0f)
{
await System.Threading.Tasks.Task.Delay(System.TimeSpan.FromSeconds(delay));
ani.Play(Break);
await System.Threading.Tasks.Task.Delay(System.TimeSpan.FromSeconds(14f / 60));
gameObject.SetActive(false);
}
public void PlayAppear()
{
try{
ani.Play(Appear);
}
catch(Exception e)
{
Debug.LogError(e.Message);
Debug.LogError(e.StackTrace);
}
}
// private void Start()
// {
// var enumerator = ani.GetEnumerator();
// using var d = enumerator as IDisposable;
// while (enumerator.MoveNext())
// {
// Debug.Log(enumerator.Current);
// }
// }
}

View File

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

View File

@@ -0,0 +1,242 @@
using asap.core;
using game;
using GameCore;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using UniRx;
using System;
using System.Collections.Generic;
using cfg;
using DG.Tweening;
using Game;
using RectTransform = UnityEngine.RectTransform;
public class WinterShootingRangePanel : MonoBehaviour
{
#region UI_ELEMENTS
[SerializeField] private Image barStageProgress, iconAmmo, iconPack;
[SerializeField] private TMP_Text textStageProgress, textTimer, textAmmoCount;
[SerializeField] private Button btnClose, btnSupply, btnInfo, btnTopPrize, btnAmmoTip;
[SerializeField] private List<RewardItemNew> rewards;
[SerializeField] private RectTransform scopeRect, stashRect, snowManRect, snowManTargetIcon;
[SerializeField] private RewardItemNew rewardFlyInstance;
[SerializeField] private ShootingRangeRewardTip rewardTip;
[SerializeField] private GameObject ticketTip;
[SerializeField] private DeferredRewardStashButton rewardStashButton;
#endregion
private EventShootingRangeData _data;
private const float ProgressIncGap = 0.8f;
[Tooltip("奖励飞入背包后背包响应延迟,从奖励粒子特效出现开始计算,不是从奖励出现、消失动画开始计算")] [SerializeField]
private float jiandaBagPackResponseDelay = 1.0f;
[Tooltip("从奖励出现动画开始播放到奖励消失动画开始播放的时间差")] [SerializeField]
private float jiandaRewardCloseAnimationDelay = 0.8f;
private int _ammoCountDisplay;
// private int _stageIdx;
private Tables _tables;
private void Awake()
{
btnClose.onClick.AddListener(OnClickClose);
btnInfo.onClick.AddListener(OnClickInfo);
btnSupply.onClick.AddListener(OnClickSupply);
btnTopPrize.onClick.AddListener(() => rewardTip.gameObject.SetActive(true));
btnAmmoTip.onClick.AddListener(ShowAmmoTip);
_tables = GContext.container.Resolve<Tables>();
ShootingRangeAct.EventAggregator.GetEvent<ShootingRangeAct.EventAmmoBought>().Subscribe(_ => UpdateAmmoCount())
.AddTo(this);
_data = GContext.container.Resolve<EventShootingRangeData>();
rewardTip.Init(GContext.container.Resolve<PlayerItemData>()
.GetItemDataByDropId(_tables.TbEventShootingRangeStage[_data.EventShootingRange.StageList[^1]].DropId[0]));
_ammoCountDisplay = _data.AmmoCount;
GContext.container.Resolve<GuideDataCenter>().InspectTriggerGuide(gameObject.name);
InitTaskBubble();
SetRewards();
GContext.container.Resolve<IUIService>().SetImageSprite(iconAmmo,
GContext.container.Resolve<Tables>().GetItemIconName(_data.CycleItem.ItemId));
UpdateAmmoCount();
textTimer.text = ConvertTools.ConvertTime2(_data.RemainingTime);
Observable.Interval(TimeSpan.FromSeconds(1.0f)).Subscribe(_ =>
{
textTimer.text =
ConvertTools.ConvertTime2(_data.RemainingTime.TotalSeconds <= 0
? TimeSpan.Zero
: _data.RemainingTime);
}).AddTo(this);
rewardFlyInstance.gameObject.SetActive(false);
snowManRect.gameObject.SetActive(false);
GContext.container.Resolve<IUIService>().SetImageSprite(iconPack, _data.PackIcon);
RedPointManager.Instance.SetRedPointState(EventShootingRangeData.PackRedPointId, _data.DoNeedPackRedPoint);
}
public void OnClickSupply()
{
_ = UIManager.Instance.ShowUI(_data.IsChainPackDepleted
? UITypes.ShootingNormalPackPanel
: UITypes.ShootingChainPackPanel);
}
private void OnClickInfo()
{
_ = UIManager.Instance.ShowUILoad(UITypes.ShootingRangeInfoPanel);
}
public void OnClickClose()
{
UIManager.Instance.DestroyUI(UITypes.EventWinterShootingPanel);
GContext.Publish(new UnloadActToNextAct { TransitionPanel = UITypes.ShootingRangeTransitionPanel });
}
private void InitTaskBubble()
{
// _stageIdx = _data.CurrentStageIdx;
barStageProgress.fillAmount = (float)_data.CurrentStageIdx / _data.EventShootingRange.StageList.Count;
textStageProgress.text = $"{_data.CurrentStageIdx}/{_data.EventShootingRange.StageList.Count}";
}
public void UpdateTaskBubble()
{
// _stageIdx = _data.CurrentStageIdx;
barStageProgress.DOFillAmount((float)_data.CurrentStageIdx / _data.EventShootingRange.StageList.Count,
ProgressIncGap);
textStageProgress.text = $"{_data.CurrentStageIdx}/{_data.EventShootingRange.StageList.Count}";
}
public void SetRewards()
{
var items = GContext.container.Resolve<PlayerItemData>().GetItemDataByDropId(_data.CurrentStage.DropId[0]);
for (int i = 0; i < rewards.Count; i++)
{
if (i >= items.Count)
rewards[i].gameObject.SetActive(false);
else
rewards[i].SetData(items[i]);
}
}
/// <summary>
/// Will decrease ammo display by consumedAmmo if consumedAmmo is not 0, regardless of actual ammo count. Otherwise, will update actual ammo count.
/// </summary>
/// <param name="consumedAmmo">Set to 0 if needing to update actual ammo number, or else.</param>
public void UpdateAmmoCount(int consumedAmmo = 0)
{
if (consumedAmmo == 0)
_ammoCountDisplay = _data.AmmoCount;
else
_ammoCountDisplay -= consumedAmmo;
textAmmoCount.text = _ammoCountDisplay.ToString();
textAmmoCount.color = _data.AmmoCount < ShootingRangeAct.AmmoCost ? Color.red : Color.white;
}
// private Vector2 _localHitPosition;
public Vector2 GetUiHitPosition(GameObject target)
{
// Vector2 localHitPosition = ConvertTools.WorldToScreenPoint(target.transform.position);
// Debug.Log($"localHitPosition leyuan: {localHitPosition}");
var screenPoint = RectTransformUtility.WorldToScreenPoint(Camera.main, target.transform.position);
// Debug.Log($"ScreenPoint: {screenPoint}");
RectTransformUtility.ScreenPointToLocalPointInRectangle(GetComponent<RectTransform>(), screenPoint,
Camera.main, out var localHitPosition);
// Debug.Log($"localHitPosition: {localHitPosition}");
return localHitPosition;
}
public async System.Threading.Tasks.Task ShowCrosshairAfterDelay(Vector3 pos, float delay)
{
scopeRect.gameObject.SetActive(false);
scopeRect.position = pos;
await System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(delay));
scopeRect.gameObject.SetActive(true);
await System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(1f));
scopeRect.gameObject.SetActive(false);
}
[SerializeField] private float jiandaRewardFlyDuration = 0.5f;
public async System.Threading.Tasks.Task PlayRewardFlyWithDelay(ItemData item, Vector2 pos, float delay)
{
// var rewardRect = rewardFly.gameObject.GetComponent<RectTransform>();
var rewardRect = Instantiate(rewardFlyInstance.gameObject, transform).GetComponent<RectTransform>();
var rewardFly = rewardRect.gameObject.GetComponent<RewardItemNew>();
await System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(delay));
rewardFly.SetRewardPopupData(item);
rewardRect.position = pos;
rewardFly.gameObject.SetActive(true);
if (_tables.TbItem[item.id].Type == 5)
{
rewardFly.GetComponent<Animation>().Play("reward_common_open");
await System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(jiandaRewardCloseAnimationDelay));
rewardFly.GetComponent<Animation>().Play("reward_common_close");
await System.Threading.Tasks.Task.Delay(24 * 1000 / 60);
rewardFly.GetComponent<CanvasGroup>().alpha = 1;
await Awaiters.NextFrame;
_ = PlayFishCardBundleAudio();
await DOTween
.To(() => rewardRect.localPosition, value => rewardRect.localPosition = value, stashRect.localPosition,
jiandaRewardFlyDuration).AsyncWaitForCompletion();
rewardStashButton.PlayReceiveAnimationWithDelay(0f);
}
else
{
rewardFly.GetComponent<Animation>().Play("reward_common_open");
await System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(jiandaRewardCloseAnimationDelay));
rewardFly.GetComponent<Animation>().Play("reward_common_close");
await System.Threading.Tasks.Task.Delay(5 * 1000 / 60);
Debug.Log($"<color=#f18c0a>reward id: {item.id}</color>");
if (item.id != _data.AmmoId)
rewardStashButton.PlayReceiveAnimationWithDelay(jiandaBagPackResponseDelay);
if (item.id == _data.AmmoId)
{
_ = UpdateAmmoCountAfterDelay(1.0f);
}
await rewardFly.ParticleAttractor();
}
Destroy(rewardFly.gameObject);
}
private async System.Threading.Tasks.Task PlayFishCardBundleAudio()
{
GContext.Publish(new EventUISound("audio_ui_shooting_winter_rewardfly"));
await System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(0.25f));
GContext.Publish(new EventUISound("audio_ui_shooting_winter_rewardget"));
}
private async System.Threading.Tasks.Task UpdateAmmoCountAfterDelay(float delay)
{
await System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(delay));
UpdateAmmoCount();
}
public async System.Threading.Tasks.Task ShowSnowmanAfterDelay(Vector3 pos, float delay)
{
snowManRect.position = pos;
snowManRect.localScale = Vector3.one;
await System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(delay));
snowManRect.gameObject.SetActive(true);
// GContext.Publish(new EventUISound("audio_ui_reward_icon_1"));
}
public async System.Threading.Tasks.Task MoveSnowmanAfterDelayAndUpdateTarget(float delay)
{
await System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(delay));
snowManRect.DOScale(0.5f, jiandaRewardFlyDuration);
await DOTween
.To(() => snowManRect.position, value => snowManRect.position = value,
snowManTargetIcon.position, jiandaRewardFlyDuration).AsyncWaitForCompletion();
snowManRect.gameObject.SetActive(false);
UpdateTaskBubble();
}
public void ShowAmmoTip()
{
ticketTip.SetActive(true);
}
}

View File

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