330 lines
12 KiB
C#
330 lines
12 KiB
C#
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;
|
|
}
|