Files
ft/Client/Assets/Scripts/EventBossFight/Panel/EventBossFightMainPanel.cs
2026-06-29 21:18:33 +08:00

1309 lines
56 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using asap.core;
using cfg;
using DG.Tweening;
using game;
using GameCore;
using TMPro;
using UI.Wheel;
using UniRx;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.UI;
using UnityEngine.ResourceManagement.AsyncOperations;
using Random = UnityEngine.Random;
namespace EventBossFight
{
public partial class EventBossFightMainPanel : BasePanel
{
#region UI_ELEMENTS
private PlayableDirector _enterDirector;
//top
private RewardItemNew[] _bossReward;
private TMP_Text _textBossHp;
private Image _imgBossHpBar;
private GameObject _hpBossObj;
private RewardItemNew _bossRewardFinal;
private TMP_Text _textBossHpFinal;
private Image _imgBossHpBarFinal;
private GameObject _hpBossObjFinal;
private RewardItemNew _finalReward;
private TMP_Text _textTime;
private SandDigLevel[] _levels;
private Button _btnQuestionmark;
private GameObject _goBtnFightInfo;
private Button _btnFightInfo;
private TMP_Text _textBossAttackTime;
private TMP_Text _textBossAttackRange;
private GameObject _objTipsBoss;
//center
/// <summary>Boss 预制体父节点(仅挂载 Transform不要求根上 <see cref="PlayableDirector"/>)。</summary>
protected Transform _bossMount;
private PlayableDirector _playerDirector;
private EventBossFightTimelinePlayerCell _playerCell;
//bottom
private Button _btnAdd;
private Button _btnSpin;
private Button _btnClose;
private Button _btnMagnification;
private TMP_Text _textMagnification;
private GameObject _objMagnification;
private TMP_Text _textPlayerHp;
private TMP_Text _textPlayerChangeHp;
private RectTransform _iconHpTarget;
private Button _iconHpBtn;
private GameObject _tipsHp;
private Button _tipsHpBtnClose;
private Image _imgPlayerHpBar;
private Image[] _shields;
private Button[] _shieldBtns;
private GameObject _tipsShield;
private Button _tipsShieldBtnClose;
private TMP_Text _textSpin;
private TMP_Text _textTokenAmount;
private Image _imgTokenIcon;
private EventBossFightWheelRewardComponent _wheel;
private RewardFlyBatchController RewardFlyBatchCtrl;
/// <summary>付费复活:与转盘区域互斥,预制体上需有名为 btn_revive 的节点。</summary>
private GameObject _goPaidReviveRoot;
private GameObject _goSpinButtonRoot;
private GameObject _goMagnificationRoot;
private Button _btnPaidRevive;
private TMP_Text _textPaidRevivePrice;
//UI effect
private Animation _shieldAddAni;
private Animation _hpAddAni;
private GameObject _tokenShieldGameObject;
private GameObject _tokenHpGameObject;
//private Animation _tokenAddAni;
#endregion UI_ELEMENTS
#region FX
private GameObject fx_eventbossfight_warning;
private GameObject fx_eventbossfight_wheel_shieldswitch;
private GameObject fx_eventbossfight_wheel_healswitch;
private GameObject fx_eventbossfight_wheel_heal_01;
private GameObject fx_eventbossfight_wheel_heal_02;
#endregion
#region SerializeField
[Header("UI Effect")]
[SerializeField] [Min(0)]private float delayShowFailPanelTime=0.5f;
[SerializeField] [Min(0)] private float sliderChangeTime = 0.3f;
[SerializeField] [Min(0)] private float hpTextChangeTime = 1f;
[SerializeField] [Min(0)] private float panelOutAniTime = 0.3f;
[SerializeField] [Min(1)] private float infoOutTime = 2f;
[SerializeField] [Min(1)]
[Tooltip("boss攻击倒计时小于等于这个时间 就显示这个特效")]
private int bossAttackWarningSeconds = 30;
[Header("scene crack effect")]
[SerializeField]private Vector2 minPositonOffset = Vector2.zero;
[SerializeField]private Vector2 maxPositonOffset = Vector2.zero;
#region player
[Header("play attack")]
[SerializeField] [Tooltip("开始从转盘结束开始算时间结束开始播放boss受击动画")]
private float bossAttackedDelay1 = 0.5f;
[SerializeField][Tooltip("开始从转盘结束开始算时间结束开始播放boss受击动画")]
private float bossAttackedDelay2 = 0.5f;
[SerializeField] [Tooltip("开始从转盘结束开始算时间结束开始播放boss受击动画特效")]
private float bossAttackedFxDelay1 = 0.5f;
[SerializeField][Tooltip("开始从转盘结束开始算时间结束开始播放boss受击动画特效")]
private float bossAttackedFxDelay2 = 0.5f;
[SerializeField] [Tooltip("开始从转盘结束开始算时间结束开始播放boss血条动画")]
private float bossAttackedHpAniDelay1 = 0.5f;
[SerializeField][Tooltip("开始从转盘结束开始算时间结束开始播放boss血条动画")]
private float bossAttackedHpAniDelay2 = 0.5f;
[SerializeField] protected float playAttackTier2Interval=0.5f;
[SerializeField][Min(1)] protected int playAttackTier2Count =1;
[SerializeField] [Tooltip("血条清空之后延迟一个时间播boss死亡动画")]
private float bossDeathDelay = 0.5f;
[SerializeField][Tooltip("玩家攻击的震动数据必须有3个")]
List<EventBossFightShakeData> playerShakeData;
[Header("shield")]
[SerializeField] private float shieldAddTime = 0.5f;
[SerializeField] [Tooltip("连续播盾牌飞入动画的间隔时间")]
private float shieldAddIntervalTime = 0.5f;
[SerializeField] [Tooltip("盾牌飞入动画delay一段时间之后 刷新显示")]
private float shieldDelayTime1 = 0.5f;
[SerializeField] [Tooltip("盾牌飞入到破碎位置delay一段时间之后 播碎裂动画")]
private float shieldDelayTime2= 0.5f;
[SerializeField] private GameObject shieldGameObject;
[SerializeField] private float shieldReduceTime;
[Header("hp")]
[SerializeField] private float hpAddTime = 0.5f;
[Header("token")]
[SerializeField] private float tokenAddTime = 0.5f;
[SerializeField] private GameObject hurt_fx_position;
#endregion
#endregion
private bool _isRotating;
private bool _isOpening=true;
private bool _isBossDeath;
private bool _isPlayerDeath;
private readonly int _showRewardCount = 4;
private EventBossFightStage _stageConfigWithUI ;
private EventBossFightRectFollowerGraphic _eventRectFollowerGraphic;
protected IEventBossFightBossCell _bossCell;
private List<IWheelReward> _wheelRewards;
private EventBossFightManager _manager;
private EventBossFightManager Manager => _manager ??= GContext.container.Resolve<EventBossFightManager>();
protected EventBossFightData Data => Manager?.Data;
private GameObject[] _sceneCrackFxs=new GameObject[5];
private AsyncOperationHandle<GameObject> _bossInstantiateHandle;
protected virtual void Awake()
{
//fx
fx_eventbossfight_warning=gameObject.FindChildGameObject("fx_eventbossfight_warning");
fx_eventbossfight_wheel_shieldswitch=gameObject.FindChildGameObject("fx_eventbossfight_wheel_shieldswitch");
fx_eventbossfight_wheel_healswitch=gameObject.FindChildGameObject("fx_eventbossfight_wheel_healswitch");
fx_eventbossfight_wheel_heal_01=gameObject.FindChildGameObject("fx_eventbossfight_wheel_heal_01");
fx_eventbossfight_wheel_heal_02=gameObject.FindChildGameObject("fx_eventbossfight_wheel_heal_02");
for (int i = 0; i < 4; i++)
{
var obj = gameObject.FindChildGameObject($"fx_eventbossfight_submarine_attacked0{i+1}");
if (!obj) continue;
obj.SetActive(false);
_sceneCrackFxs[i]=obj;
}
_enterDirector=gameObject.FindChildGameObject("root").GetComponent<PlayableDirector>();
//top
_finalReward = gameObject.FindChildGameObject("p_final_reward").GetComponentInChildren<RewardItemNew>();
_textTime = gameObject.FindChildGameObject("p_text_event_time").GetComponent<TMP_Text>();
_bossReward = gameObject.FindChildGameObject("p_boss_reward").GetComponentsInChildren<RewardItemNew>();
_textBossHp = gameObject.FindChildGameObject("p_text_bossHp").GetComponent<TMP_Text>();
_imgBossHpBar=gameObject.FindChildGameObject("p_img_boss_hp_bar").GetComponent<Image>();
_bossRewardFinal=gameObject.FindChildGameObject("p_boss_reward_final").GetComponent<RewardItemNew>();
_textBossHpFinal = gameObject.FindChildGameObject("p_text_bossHp_final").GetComponent<TMP_Text>();
_imgBossHpBarFinal=gameObject.FindChildGameObject("p_img_boss_hp_bar_final").GetComponent<Image>();
_hpBossObj = gameObject.FindChildGameObject("hp_boss");
_hpBossObjFinal = gameObject.FindChildGameObject("hp_boss_final");
_levels = gameObject.FindChildGameObject("level").GetComponentsInChildren<SandDigLevel>();
_btnQuestionmark = gameObject.FindChildGameObject("p_btn_questionmark").GetComponentInChildren<Button>();
_btnQuestionmark.onClick.AddListener(OnClickBtnQuestionMark);
_goBtnFightInfo = gameObject.FindChildGameObject("p_btn_fight_info");
_btnFightInfo = _goBtnFightInfo.GetComponentInChildren<Button>();
_btnFightInfo.onClick.AddListener(OnClickBtnBossInfo);
_textBossAttackTime = gameObject.FindChildGameObject("p_text_boss_attack_time").GetComponent<TMP_Text>();
_textBossAttackRange = gameObject.FindChildGameObject("p_text_boss_attack_range").GetComponent<TMP_Text>();
_objTipsBoss = gameObject.FindChildGameObject("p_tips_boss");
//center
var bossGo = gameObject.FindChildGameObject("boss");
_bossMount = bossGo ? bossGo.transform : null;
hurt_fx_position = gameObject.FindChildGameObject("hurt_fx_position");
_playerCell = gameObject.FindChildGameObject("weapon").GetComponent<EventBossFightTimelinePlayerCell>();
_playerDirector = gameObject.FindChildGameObject("wheel").GetComponent<PlayableDirector>();
_eventRectFollowerGraphic =
gameObject.FindChildGameObject("fx_boss_bone_follower")?.GetComponent<EventBossFightRectFollowerGraphic>();
if (_eventRectFollowerGraphic)
_eventRectFollowerGraphic.enabled = false;
else
Debug.LogWarning(
"EventBossFightMainPanel请在 fx_boss_bone_follower 上添加 EventBossFightRectFollowerGraphic。",
this);
//bottom
_wheel = transform.GetComponentInChildren<EventBossFightWheelRewardComponent>(true);
_goSpinButtonRoot = gameObject.FindChildGameObject("btn_spin");
_goMagnificationRoot = gameObject.FindChildGameObject("btn_magnification");
_btnSpin = _goSpinButtonRoot.GetComponentInChildren<Button>();
_btnSpin.onClick.AddListener(OnClickBtnSpin);
_textSpin = _btnSpin.gameObject.FindChildGameObject("p_text_spin").GetComponentInChildren<TMP_Text>();
_btnMagnification = _goMagnificationRoot.GetComponentInChildren<Button>();
_btnMagnification.onClick.AddListener(OnClickBtnMagnification);
_textMagnification = _btnMagnification.gameObject.FindChildGameObject("text_magnification")
.GetComponent<TMP_Text>();
_objMagnification = _btnMagnification.gameObject.FindChildGameObject("magnification_max");
_btnAdd = gameObject.FindChildGameObject("btn_add").GetComponentInChildren<Button>();
_btnAdd.onClick.AddListener(OnClickBtnAdd);
_btnClose = gameObject.FindChildGameObject("p_btn_close").GetComponent<Button>();
_btnClose.onClick.AddListener(OnClickBtnClose);
_textPlayerHp = gameObject.FindChildGameObject("p_text_player_hp").GetComponent<TMP_Text>();
_textPlayerChangeHp=gameObject.FindChildGameObject("p_text_player_hp_deduct").GetComponent<TMP_Text>();
_imgPlayerHpBar=gameObject.FindChildGameObject("p_img_player_hp_bar").GetComponent<Image>();
_shields = gameObject.FindChildGameObject("p_shields").GetComponentsInChildren<Image>();
_shieldBtns=gameObject.FindChildGameObject("p_shields").GetComponentsInChildren<Button>();
foreach (var shieldBtn in _shieldBtns)
{
shieldBtn.onClick.AddListener(OnClickBtnShield);
}
_textTokenAmount = gameObject.FindChildGameObject("p_text_token_amount").GetComponent<TMP_Text>();
_imgTokenIcon = gameObject.FindChildGameObject("p_img_token_icon").GetComponent<Image>();
_iconHpTarget=gameObject.FindChildGameObject("p_icon_hp_target").GetComponent<RectTransform>();
_iconHpBtn = _iconHpTarget.GetComponent<Button>();
_iconHpBtn.onClick.AddListener(OnClickBtnHpIcon);
_tipsHp=gameObject.FindChildGameObject("p_tips_hp");
_tipsHpBtnClose=gameObject.FindChildGameObject("p_tips_hp_btn_close").GetComponent<Button>();
_tipsHpBtnClose.onClick.AddListener(OnClickBtnHpIconClose);
_tipsShield=gameObject.FindChildGameObject("p_tips_sheild");
_tipsShieldBtnClose=gameObject.FindChildGameObject("p_tips_sheild_btn_close").GetComponent<Button>();
_tipsShieldBtnClose.onClick.AddListener(OnClickBtnShieldIconClose);
_shieldAddAni=gameObject.FindChildGameObject("shield_add").GetComponent<Animation>();
_hpAddAni=gameObject.FindChildGameObject("hp_add").GetComponent<Animation>();
_tokenShieldGameObject=gameObject.FindChildGameObject("token_add_shield");
_tokenHpGameObject=gameObject.FindChildGameObject("token_add_hp");
RewardFlyBatchCtrl = gameObject.FindChildGameObject(nameof(RewardFlyBatchCtrl))
.GetComponent<RewardFlyBatchController>();
_goPaidReviveRoot = gameObject.FindChildGameObject("btn_revive");
if (_goPaidReviveRoot)
{
_btnPaidRevive = _goPaidReviveRoot.GetComponentInChildren<Button>(true);
_textPaidRevivePrice = _goPaidReviveRoot.GetComponentInChildren<TMP_Text>(true);
if (_btnPaidRevive)
_btnPaidRevive.onClick.AddListener(OnClickBtnPaidRevive);
_goPaidReviveRoot.SetActive(false);
}
GContext.OnEvent<RewardPanelClose>().Subscribe(OnRewardPanelClose).AddTo(disposables);
}
protected override void Start()
{
base.Start();
OnStart();
GContext.container.Resolve<GuideDataCenter>().InspectTriggerGuide("EventBossFightUnderseaPanel",curPanelName:gameObject.name);
Observable.Interval(TimeSpan.FromSeconds(1f)).Subscribe(UpdateTimer).AddTo(disposables);
}
public void OnStart()
{
_ = OnStartAsync();
}
private async Task OnStartAsync()
{
try
{
if (!ValidateBossStageForStart())
return;
_bossInstantiateHandle = await EventBossFightPerStageVideoBossLoader.LoadAddressableBossIfNeededAsync(
_bossMount, Data.InitConfig, Data.StageCountFrom1, _bossInstantiateHandle);
InitData();
_ = UpdateBossAttackTime(false, true);
InitUI();
ShowUI();
ShowBossSpine();
if (Data.IsShowTips)
{
OnClickBtnBossInfo();
Manager.SetShowTipsState(false);
}
ShowProgressReward();
UpdateTimer(0);
PlayEnterDirectorAndHandoffToBossIdle();
PrefetchNextBossBundleIfNeeded();
}
catch (Exception e)
{
Debug.LogError(e);
}
}
private bool ValidateBossStageForStart()
{
if (Data == null || Data.InitConfig == null)
return false;
if (string.IsNullOrEmpty(Data.InitConfig.AssetBundle))
{
Debug.LogError("EventBossFightInitConfig.AssetBundle 未配置Boss 视频分包必填。");
return false;
}
var resolvedCount = Manager.GetResolvedStageIds().Count;
if (Data.StageCountFrom1 < 1 || Data.StageCountFrom1 > resolvedCount)
{
Debug.LogError($"Boss 关卡索引非法 StageCountFrom1={Data.StageCountFrom1}");
return false;
}
if (!_bossMount)
{
Debug.LogError("EventBossFight未找到 boss 挂载节点。");
return false;
}
if (!EventBossFightPerStageVideoBossLoader.IsBundledBossReadyForStage(Data.InitConfig,
Data.StageCountFrom1))
{
Debug.LogError("EventBossFight无法解析本关 Boss Addressables 键。");
return false;
}
return true;
}
private void PrefetchNextBossBundleIfNeeded()
{
if (Data?.InitConfig == null)
return;
if (Data.IsLastStage)
return;
var nextKey = EventBossFightBossBundleKeys.GetAddressableKey(Data.InitConfig, Data.StageCountFrom1 + 1);
if (string.IsNullOrEmpty(nextKey))
return;
var loadResourceService = GContext.container.Resolve<ILoadResourceService>();
// 与 InstantiateAsync / CheckResourceLoadQueue 传入的字符串必须一致Addressables 按「地址或 Label」解析
// 由组配置决定该 key 是资产 Address、是 Label 还是与 prefab 名相同;只要与可寻址条目一致即可下载依赖 Bundle。
loadResourceService.EnqueueBundleSilently(new List<string> { nextKey });
}
/// <summary>
/// 面板 enter Timeline 与当前关 Boss Cell 的 show→idle 并行Boss show 结束与切 idle 由 Cell 自行驱动。
/// </summary>
private void PlayEnterDirectorAndHandoffToBossIdle()
{
_isOpening = true;
if (_enterDirector)
{
_enterDirector.stopped -= OnEnterDirectorRootStopped;
_enterDirector.stopped += OnEnterDirectorRootStopped;
_enterDirector.Play();
}
RunBossShowThenIdleAsync();
}
private void OnEnterDirectorRootStopped(PlayableDirector d)
{
if (d)
d.stopped -= OnEnterDirectorRootStopped;
}
private async void RunBossShowThenIdleAsync()
{
try
{
if (_bossCell is EventBossFightTimelineBossCellVideo vb)
await vb.PlayShowThenIdleAsync();
else if (_bossCell != null)
{
_bossCell.ShowGameObject();
_bossCell.PlayIdle(_bossCell.BossTimelineDirector);
}
}
catch (Exception e)
{
Debug.LogException(e);
}
finally
{
_isOpening = false;
}
}
private void InitData()
{
//ui 显示数据
CheckStageState();
_isOpening = true;
_isBossDeath = false;
_isPlayerDeath = false;
_stageConfigWithUI = Data.StageConfig;
}
private void InitBossSpine()
{
if (!_bossMount)
return;
for (var i = 0; i < _bossMount.childCount; i++)
_bossMount.GetChild(i).gameObject.SetActive(false);
var canvasGroup = _bossMount.GetComponent<CanvasGroup>();
if (!canvasGroup)
return;
canvasGroup.alpha = 1;
}
private void ShowBossSpine()
{
Transform stageChild = null;
if (EventBossFightPerStageVideoBossLoader.TryGetBossRootFromHandle(_bossInstantiateHandle, out var fromHandle))
stageChild = fromHandle;
else if (EventBossFightPerStageVideoBossLoader.TryFindEmbeddedBossSlotRoot(_bossMount, Data.InitConfig,
Data.StageCountFrom1, out var embedded))
stageChild = embedded;
if (stageChild == null)
{
Debug.LogError(
$"[EventBossFightMainPanel] 当前关 Boss 未就绪(无 Addressables 实例且 boss 下无嵌入式槽位StageCountFrom1={Data.StageCountFrom1},期望子物体名:{EventBossFightBossBundleKeys.GetAddressableKey(Data.InitConfig, Data.StageCountFrom1)}",
_bossMount);
return;
}
// InitBossSpine 会关掉 boss 下所有子物体;须先激活本关槽位根,否则 Cell.SetActive 无法显示
stageChild.gameObject.SetActive(true);
_bossCell = EventBossFightPerStageVideoBossLoader.ResolveVideoBossCell(stageChild);
if (_bossCell == null)
{
Debug.LogError(
$"Boss 上未找到 EventBossFightTimelineBossCellVideoStageCountFrom1={Data.StageCountFrom1}",
stageChild);
return;
}
_bossCell.ShowGameObject();
OnBossCellBound(_bossCell);
ResetVideoBossCellDirectorState();
}
private void ResetVideoBossCellDirectorState()
{
if (_bossCell is not EventBossFightTimelineBossCellVideo vb)
return;
var cd = vb.CellPlayableDirector;
if (!cd)
return;
// 勿在 playableAsset==null 时 Play():图可能未建立,后续 WaitDirectorSegmentFinished 会误判已结束,入场 show 被跳过。
cd.Stop();
cd.time = 0;
cd.extrapolationMode = DirectorWrapMode.None;
cd.playableAsset = null;
}
private void OnBossCellBound(IEventBossFightBossCell cell)
{
if (cell is not EventBossFightTimelineBossCellVideo videoBoss)
return;
videoBoss.InitFlash();
BindBossHurtAnchorsFromHurtFxPosition(videoBoss);
if (!_eventRectFollowerGraphic)
return;
if (videoBoss.bossFollowAnchor)
_eventRectFollowerGraphic.SetTarget(videoBoss.bossFollowAnchor);
_eventRectFollowerGraphic.enabled = true;
}
/// <summary>
/// 受击飘字/特效挂点:收集 <see cref="hurt_fx_position"/> 下<strong>全部</strong>带 RectTransform 的直接子节点(顺序同 Hierarchy写入分包 Cell。
/// </summary>
private void BindBossHurtAnchorsFromHurtFxPosition(EventBossFightTimelineBossCellVideo videoBoss)
{
if (!hurt_fx_position || !videoBoss)
return;
var parent = hurt_fx_position.transform;
var ordered = new List<RectTransform>();
for (var c = 0; c < parent.childCount; c++)
{
var ch = parent.GetChild(c);
if (ch.TryGetComponent<RectTransform>(out var rt))
ordered.Add(rt);
}
if (ordered.Count == 0)
{
Debug.LogWarning(
"EventBossFightMainPanelhurt_fx_position 下没有带 RectTransform 的直接子节点,受击挂点将回退 bossFollowAnchor。",
hurt_fx_position);
return;
}
videoBoss.bossHurtAnchors = ordered.ToArray();
}
/// <summary>受击随机挂点下标:与 <see cref="EventBossFightTimelineBossCellVideo.bossHurtAnchors"/> 数量一致;无挂点则返回 0由 GetHurtAnchor 回退跟随点)。</summary>
private static int PickRandomBossHurtAnchorIndex(EventBossFightTimelineBossCellVideo vb)
{
var n = vb != null && vb.bossHurtAnchors != null ? vb.bossHurtAnchors.Length : 0;
return n > 0 ? Random.Range(0, n) : 0;
}
private void CheckStageState()
{
Manager.CheckStageBossStateNoRewardPanel();
Manager.CheckStageIsMax();
Manager.CheckPlayIsDead();
if (Data.IsShowGuide)
{
Manager.SetGuideState(false);
return;
}
if (Data.IsRest)
Manager.ShowReviewPanel();
Manager.ApplyPendingFightBootstrapIfNeeded();
}
protected override void OnDestroy()
{
EventBossFightPerStageVideoBossLoader.ReleaseAddressableBoss(ref _bossInstantiateHandle);
if (_enterDirector)
_enterDirector.stopped -= OnEnterDirectorRootStopped;
_sceneCrackFxs = null;
_wheelRewards?.Clear();
_wheelRewards = null;
_btnAdd.onClick.RemoveAllListeners();
if (_btnPaidRevive)
_btnPaidRevive.onClick.RemoveListener(OnClickBtnPaidRevive);
_btnSpin.onClick.RemoveAllListeners();
_btnFightInfo.onClick.RemoveAllListeners();
_btnQuestionmark.onClick.RemoveAllListeners();
_btnMagnification.onClick.RemoveAllListeners();
_btnClose.onClick.RemoveAllListeners();
_iconHpBtn.onClick.RemoveAllListeners();
_tipsHpBtnClose.onClick.RemoveAllListeners();
_tipsShieldBtnClose.onClick.RemoveAllListeners();
foreach (var shieldBtn in _shieldBtns)
{
shieldBtn.onClick.RemoveAllListeners();
}
UIManager.Instance?.UI3DCamera?.gameObject?.SetActive(false);
base.OnDestroy();
}
private void InitUI()
{
_textTime.text = string.Empty;
_textSpin.text = string.Empty;
_textBossAttackRange.text = string.Empty;
_textBossAttackTime.text = string.Empty;
_textBossHp.text = string.Empty;
_textBossHpFinal.text = string.Empty;
_textMagnification.text = string.Empty;
_textPlayerHp.text = string.Empty;
_objMagnification.SetActive(false);
_objTipsBoss.SetActive(false);
_imgBossHpBar.fillAmount = 1;
_imgBossHpBarFinal.fillAmount = 1;
_imgPlayerHpBar.fillAmount = 1;
for (int i = 0; i < _shields.Length; i++)
{
_shields[i].gameObject.SetActive(false);
}
InitBossSpine();
}
private TimeSpan _nextAttackTime;
private void UpdateTimer(long obj)
{
if (Data == null)
return;
_textTime.text = ConvertTools.ConvertTime2(Data.RemainingTime);
_= UpdateBossAttackTime();
}
private async Task UpdateBossAttackTime(bool isShowAttackEffect=true,bool isRemainOnce=false)
{
if (Manager.IsAwaitingPaidRevive())
return;
if (Data.HasPendingLastAttack&&isShowAttackEffect)
{
if(_isOpening) return;
if (Manager.ExecutePendingLastAttack(out var isReduceShield, out var isReducePlayerHp, out int damage))
{
_textPlayerChangeHp.text = $"-{damage}";
await PlayBossAttackEffect(isReduceShield, isReducePlayerHp);
} //todo 表现和数据没分开 ,表现影响了数据的处理
return;
}
if(_isBossDeath||_isPlayerDeath)
return;
if (Data.IsRest&&!_isBossDeath)
_nextAttackTime = TimeSpan.FromSeconds(_stageConfigWithUI.AttackInterval) ;
else
_nextAttackTime=DateTimeOffset.FromUnixTimeSeconds(Data.BossAttackTime).DateTime-ZZTimeHelper.UtcNow();
fx_eventbossfight_warning.gameObject.SetActive(_nextAttackTime.TotalSeconds <= bossAttackWarningSeconds);
if (_nextAttackTime.TotalSeconds <= 0&&!_isRotating)
{
if (isShowAttackEffect&&_isOpening)return;
if (Manager.TryBossAttack(out var isReduceShield,out var isReducePlayerHp,isRemainOnce,out int damage))
{
if (isShowAttackEffect)
{
_textPlayerChangeHp.text = $"-{damage}";
await PlayBossAttackEffect(isReduceShield,isReducePlayerHp);
//Manager.TryTriggerGuidance();
}
}
}
var time = _nextAttackTime > TimeSpan.Zero ? _nextAttackTime : TimeSpan.Zero;
_textBossAttackTime.text = ConvertTools.ConvertTime2(time);
}
private void ShowUI()
{
if (Data == null) return;
ShowMagnificationInfo();
ShowLevelInfo();
ShowWheelReward();
ShowTokenAmount();
ShowPlayerHp();
ShowPlayerShield();
ShowBossHp();
ShowTokenImage();
var attackRange = Manager.GetBossAttackRange(_stageConfigWithUI);
_textBossAttackRange.text=$"{attackRange.minDamage}~{attackRange.maxDamage} ";
SetButtonState(true);
_finalReward.InflationRate = Data.InflationRate;
_finalReward.SetDropIcon("", Manager.GetFinalBossRewardsDropID());
_bossRewardFinal.InflationRate = Data.InflationRate;
_bossRewardFinal.SetDropIcon("", Manager.GetFinalBossRewardsDropID());
_hpBossObj.SetActive(!Data.IsLastStage);
_hpBossObjFinal.SetActive(Data.IsLastStage);
ApplyPaidReviveAndSpinLayout();
}
private void ShowProgressReward()
{
var progressRewards = Manager.GetBossRewards();
if (progressRewards is not { Count: > 0 }) return;
for (var i = 0; i < progressRewards.Count; i++)
{
if(i>=_bossReward.Length) break;
_bossReward[i].SetData(progressRewards[i]);
_bossReward[i].gameObject.SetActive(true);
}
}
private void ShowTokenImage()
{
var itemImgName = Manager.GetTokenName();
if(!string.IsNullOrEmpty(itemImgName))
_ = GContext.container.Resolve<IUIService>().SetImageSprite(_imgTokenIcon, itemImgName);
}
private void ShowPlayerShield(bool isShowAddEffect=false)
{
for (int i = 0; i < _shields.Length; i++)
{
var shield = _shields[i];
var isActive=shield.isActiveAndEnabled;
shield.gameObject.SetActive(i < Data.PlayerShowShield);
var fx=shield.gameObject.FindChildGameObject("fx_eventbossfight_wheel_shield");
if(!fx.activeInHierarchy)
fx.SetActive(!isActive && shield.isActiveAndEnabled && isShowAddEffect);
}
}
private int currentPlayerShowHp=0;
private void ShowPlayerHp()
{
currentPlayerShowHp=Data.PlayerShowHp;
_textPlayerHp.text=$"{Data.PlayerShowHp}";
_imgPlayerHpBar.fillAmount = (float)Data.PlayerShowHp / _stageConfigWithUI.PlayerHP;
UpdateFightInfoVisibility();
}
/// <summary>玩家阵亡时隐藏 Boss 出手说明与倒计时;存活或治疗后恢复。</summary>
private void UpdateFightInfoVisibility()
{
var alive = Data != null && Data.PlayerRemainHp > 0;
if (_goBtnFightInfo)
_goBtnFightInfo.SetActive(alive);
if (!alive && _objTipsBoss)
_objTipsBoss.SetActive(false);
}
private void PlayPlayerHpTextAni()
{
DOTween.To(() => currentPlayerShowHp, x => currentPlayerShowHp = x, Data.PlayerShowHp, hpTextChangeTime).OnUpdate(() =>
{
_textPlayerHp.text =$"{currentPlayerShowHp}";
}).SetId(nameof(_textPlayerHp));
}
private void ShowBossHp()
{
_textBossHp.text=$"{Data.BossRemainHp}";
_textBossHpFinal.text=$"{Data.BossRemainHp}";
_imgBossHpBar.fillAmount=(float)Data.BossRemainHp/_stageConfigWithUI.BossHP;
_imgBossHpBarFinal.fillAmount=(float)Data.BossRemainHp/_stageConfigWithUI.BossHP;
}
private void ShowTokenAmount()
{
_textTokenAmount.text=$"{Manager.GetTokenCount()}";
}
private void ShowWheelReward()
{
_wheelRewards = Manager.GetWheelRewards();
if (_wheelRewards == null || _wheelRewards.Count == 0) return ;
_wheel.SetData(_wheelRewards);
_wheel.ShowUI();
}
private void ShowMagnificationInfo()
{
_textMagnification.text = $"X{Data.Magnification}";
_textSpin.text=$"X{Data.Magnification*Data.InitConfig.SpinRequire}";
var spinMag = Data.InitConfig.SpinMag;
_objMagnification.SetActive(spinMag != null && spinMag.Count > 0 &&
spinMag[spinMag.Count - 1] == Data.Magnification);
}
private void ShowLevelInfo()
{
if (Data == null) return;
var stageCount = Manager.GetResolvedStageIds().Count;
if (stageCount <= 0) return;
var curIndex = (Data.StageCountFrom1-1) % stageCount;
int startIndex= curIndex - 1;
var offsetIndex = stageCount - _showRewardCount;
if (curIndex <= 1)
startIndex = 0;
else if (curIndex > offsetIndex)
startIndex = offsetIndex;
for (int i = 0; i < _showRewardCount; i++)
{
int index = startIndex + i;
if (index >= stageCount)
break;
int state = 0;
if (index < curIndex)
state = 2;
else if (index == curIndex)
state = 1;
_levels[i].SetState(state);
_levels[i].SetTextNum($"{index + 1}");
}
_levels[_showRewardCount - 1].SetTextNum($"{stageCount}");
}
#region Button
private void OnClickBtnQuestionMark()
{
if (Data?.InitConfig == null) return;
UITypes.EventBossFightInfoPanel.SetType(Data.InitConfig.InfoPanel);
_ = UIManager.Instance.ShowUILoad(UITypes.EventBossFightInfoPanel);
}
private void OnClickBtnMagnification()
{
if (Manager.IsAwaitingPaidRevive())
return;
var index = Data.InitConfig.SpinMag.FindIndex(x => x == Data.Magnification);
var targetIndex=index+1;
if(targetIndex>=Data.InitConfig.SpinMag.Count)
targetIndex=0;
Data.Magnification = Data.InitConfig.SpinMag[targetIndex];
ShowMagnificationInfo();
ShowWheelReward();
}
private void OnClickBtnClose()
{
try
{
EventBossFightActTransition.PublishSwitchToFishing(Data?.InitConfig);
}
catch (Exception e)
{
Debug.LogError(e);
}
}
/// <summary>阵亡弹窗点确认关闭后回到主界面时刷新:显示复活入口、隐藏转盘与倍率。</summary>
public void OnReturnFromEndingPopupToMain()
{
ApplyPaidReviveAndSpinLayout();
ShowPlayerHp();
}
void ApplyPaidReviveAndSpinLayout()
{
if (Manager == null || Data == null)
return;
var awaiting = Manager.IsAwaitingPaidRevive();
if (_goSpinButtonRoot)
_goSpinButtonRoot.SetActive(!awaiting);
if (_goMagnificationRoot)
_goMagnificationRoot.SetActive(!awaiting);
if (_goPaidReviveRoot)
{
_goPaidReviveRoot.SetActive(awaiting);
if (awaiting && _textPaidRevivePrice)
{
var iapId = Manager.GetPaidReviveIapTableId();
GContext.container.Resolve<PlayerItemData>().ResolveIapId(iapId, out _, out var price);
_textPaidRevivePrice.text =
LocalizationMgr.GetFormatTextValue("UI_Event1v1BattleSlapPanel_15", price);
}
}
}
private async void OnClickBtnPaidRevive()
{
try
{
if (!Manager.IsAwaitingPaidRevive())
return;
if (!await Manager.TryPurchasePaidReviveAsync())
return;
OnPaidReviveSuccess();
}
catch (Exception e)
{
Debug.LogError(e);
}
}
/// <summary>付费复活成功后清除死亡表现并恢复转盘区域显示。</summary>
public void OnPaidReviveSuccess()
{
_isPlayerDeath = false;
ShowUI();
}
private void OnClickBtnAdd()
{
Manager.ShowFestPack();
}
private void OnClickBtnHpIcon()
{
_tipsHp.SetActive(true);
}
private void OnClickBtnHpIconClose()
{
_tipsHp.SetActive(false);
}
private void OnClickBtnShield()
{
_tipsShield.SetActive(true);
}
private void OnClickBtnShieldIconClose()
{
_tipsShield.SetActive(false);
}
private void OnClickBtnBossInfo()
{
_objTipsBoss.SetActive(!_objTipsBoss.activeInHierarchy);
Task.Run(async () =>
{
await Awaiters.Seconds(infoOutTime);
_objTipsBoss?.SetActive(false);
});
}
private void OnClickBtnSpin()
{
if (_isRotating) return;
if (Manager.IsAwaitingPaidRevive())
return;
if(!Manager.TryUseToken()) return;
ShowTokenAmount();
_isRotating = true;
SetButtonState(false);
var index =Manager.GetRandomRewardIndex();
var reward=_wheelRewards[index];
Manager.UseDropItem(reward.Index,Data.Magnification,out var convertTokenCount,out var amount);
var spinType = Manager.GetSpinType(reward.Index);
Manager.Agg_event_bossfight(Data.StageCountFrom1,
Data.RoundCountFrom1,Data.Magnification, spinType, Data.PlayerShieldCount,
Data.PlayerRemainHp, convertTokenCount,Data.BossRemainHp, Data.BossFightStageGroupIndex + 1);
_ = _wheel.PlayEffect(index, reward, ()=>WheelEffectCallBack(reward.Index,amount,convertTokenCount));
}
private async void WheelEffectCallBack(int spinPointID,int addAmount,int convertTokenCount)
{
try
{
await ShowDropItemEffect(spinPointID, addAmount, convertTokenCount);
_isRotating = false;
Manager.CheckStageBossState();
UpdateFightInfoVisibility();
await UpdateBossAttackTime();
SetButtonState(true);
}
catch (Exception e)
{
Debug.LogError(e);
}
}
private void SetButtonState(bool isEnable)
{
if(_btnAdd)
_btnAdd.enabled = isEnable;
if(_btnQuestionmark)
_btnQuestionmark.enabled = isEnable;
if (_btnPaidRevive && Manager.IsAwaitingPaidRevive())
_btnPaidRevive.enabled = isEnable;
if(_btnSpin && _goSpinButtonRoot && _goSpinButtonRoot.activeInHierarchy)
_btnSpin.enabled=isEnable;
if(_btnClose)
_btnClose.enabled = isEnable;
if (_btnMagnification && _goMagnificationRoot && _goMagnificationRoot.activeInHierarchy)
_btnMagnification.enabled = isEnable;
}
#endregion
#region playerEffect
private async Task ShowDropItemEffect(int spinPointID,int addAmount,int convertTokenCount)
{
var spinPointConfig =Manager.Tables.TbEventBossFightSpinPoints.GetOrDefault(spinPointID);
switch (spinPointConfig.SpinType)
{
case nameof(EEventBossFightSpinType.Cure):
await PlayRevertHp(convertTokenCount,addAmount);
break;
case nameof(EEventBossFightSpinType.Shield):
await PlayerAddShield(convertTokenCount,addAmount);
break;
case nameof(EEventBossFightSpinType.AttackTier1):
await PlayAttackTier1();
break;
case nameof(EEventBossFightSpinType.AttackTier2):
await PlayAttackTier2();
break;
}
}
private async Task PlayRevertHp(int convertTokenCount,int addAmount)
{
fx_eventbossfight_wheel_heal_01.SetActive(false);
fx_eventbossfight_wheel_heal_02.SetActive(false);
fx_eventbossfight_wheel_healswitch.SetActive(false);
_hpAddAni.gameObject.SetActive(true);
_hpAddAni.GetComponentInChildren<TMP_Text>().text = $"x{addAmount}";
_hpAddAni.Play();
var currentFillAmount = _imgPlayerHpBar.fillAmount;
await Awaiters.Seconds(hpAddTime);
await PlayHpAddFly(addAmount);
fx_eventbossfight_wheel_heal_01.SetActive(true);
fx_eventbossfight_wheel_heal_02.SetActive(!Mathf.Approximately(currentFillAmount, 1));
await PlayPlayerHpChangeAni();
if (convertTokenCount > 0)
{
var source = (RectTransform)_tokenHpGameObject.FindChildGameObject("icon").transform;
var sourceText = (RectTransform)_tokenHpGameObject.FindChildGameObject("text").transform;
fx_eventbossfight_wheel_healswitch.SetActive(true);
await PlayTokenAddFly(convertTokenCount,source,sourceText);
}
}
private async Task PlayReduceHp()
{
await PlayPlayerHpChangeAni();
}
private async Task PlayPlayerHpChangeAni()
{
PlayPlayerHpTextAni();
var fillAmount = (float)Data.PlayerShowHp / _stageConfigWithUI.PlayerHP;
await _imgPlayerHpBar.DOFillAmount(fillAmount, sliderChangeTime).AsyncWaitForCompletion();
}
private async Task PlayHpAddFly(int addAmount)
{
var targetRect = GetHpRewardFlyTarget();
var request = new BatchedRewardFlyRequest
{
Icon = new BatchedRewardFlyRequestIcon{icon=_hpAddAni.GetComponentInChildren<Image>().sprite},
//Quantity = addAmount,
StartPoint = new BatchedRewardFlyStartPoint(GetHpRewardFlySource()),
EndPoint = new BatchedRewardFlyEndPoint(targetRect),
IsDestinationRewardStash = true,
AnimationParamIndex = 0
};
await RewardFlyBatchCtrl.OnRewardFlyRequestAsync(request);
}
private RectTransform GetHpRewardFlySource()
{
return _hpAddAni.GetComponentInChildren<Image>().rectTransform;
}
private RectTransform GetHpRewardFlyTarget()
{
return _iconHpTarget;
}
private async Task PlayerAddShield(int convertTokenCount,int addAmount)
{
fx_eventbossfight_wheel_shieldswitch.gameObject.SetActive(false);
_shieldAddAni.gameObject.SetActive(true);
_shieldAddAni.GetComponentInChildren<TMP_Text>().text = $"x{addAmount}";
_shieldAddAni.Play();
await Awaiters.Seconds(shieldAddTime);
var targets= GetShieldRewardFlyTarget(addAmount);
var remain = addAmount - targets.Count;
int animationParamIndex = 0;
foreach (var target in targets)
{
await Awaiters.Seconds(shieldAddIntervalTime);
_= PlayShieldAddFly(1,target,()=>target?.gameObject.SetActive(true),shieldDelayTime1,animationParamIndex);
animationParamIndex = 1;
}
if (convertTokenCount <= 0)
return;
// PlayShieldAddSwitchFly(addAmount);
await Awaiters.Seconds(shieldAddIntervalTime);
var fxRect=(RectTransform)fx_eventbossfight_wheel_shieldswitch.transform;
await PlayShieldAddFly(remain,fxRect,()=>
fx_eventbossfight_wheel_shieldswitch.gameObject.SetActive(true),shieldDelayTime2,animationParamIndex);
var source = (RectTransform)_tokenShieldGameObject.FindChildGameObject("icon").transform;
var sourceText = (RectTransform)_tokenShieldGameObject.FindChildGameObject("text").transform;
await PlayTokenAddFly(remain,source,sourceText);
}
private async Task PlayShieldAddFly(int addAmount,RectTransform target,Action callback,float delayTime,int animationParamIndex)
{
var request = new BatchedRewardFlyRequest
{
Icon = new BatchedRewardFlyRequestIcon{icon=_shieldAddAni.GetComponentInChildren<Image>().sprite},
//Quantity = addAmount,
StartPoint = new BatchedRewardFlyStartPoint(GetShieldRewardFlySource()),
EndPoint = new BatchedRewardFlyEndPoint(target),
IsDestinationRewardStash = true,
AnimationParamIndex = animationParamIndex
};
var task= RewardFlyBatchCtrl.OnRewardFlyRequestAsync(request);
await Awaiters.Seconds(delayTime);
callback?.Invoke();
await task;
}
private async Task PlayReduceShield()
{
UIManager.Instance.UI3DCamera.gameObject.SetActive(true);
shieldGameObject.SetActive(true);
shieldGameObject.GetComponentInChildren<Animation>()?.Play();
await Awaiters.Seconds(shieldReduceTime);
ShowPlayerShield();
UIManager.Instance.UI3DCamera.gameObject.SetActive(false);
shieldGameObject.SetActive(false);
}
private async Task PlayAttackTier1()
{
_=_playerCell.PlayTimelineAttack1(_playerDirector);
PlayBossAttackedFx(bossAttackedFxDelay1,1);
PlayPlayerAttackShake(0);
PlayBossHpSliderEffect(bossAttackedHpAniDelay1);
await PlayBossAttacked(bossAttackedDelay1,1);
}
private async Task PlayAttackTier2()
{
_=_playerCell.PlayTimelineAttack2(_playerDirector);
PlayBossAttackedFxMultiplier(bossAttackedFxDelay2,2);
PlayPlayerAttackShake(1);
PlayPlayerAttackShake(2);
PlayBossHpSliderEffect(bossAttackedHpAniDelay2);
await PlayBossAttacked(bossAttackedDelay2, 2);
}
private async void PlayBossAttackedFx(float delayTime, int index)
{
try
{
if (!_eventRectFollowerGraphic)
return;
var rf = _eventRectFollowerGraphic;
rf.enabled = true;
rf.gameObject.SetActive(false);
for (var i = 0; i < rf.transform.childCount; i++)
rf.transform.GetChild(i).gameObject.SetActive(false);
await Awaiters.Seconds(delayTime);
if (_bossCell is EventBossFightTimelineBossCellVideo vb)
rf.SetTarget(vb.GetHurtAnchor(PickRandomBossHurtAnchorIndex(vb)));
rf.gameObject.SetActive(true);
if (index >= 1 && index - 1 < rf.transform.childCount)
rf.transform.GetChild(index - 1).gameObject.SetActive(true);
}
catch (Exception e)
{
Debug.LogError(e);
}
}
private async void PlayBossAttackedFxMultiplier(float delayTime, int index)
{
try
{
if (!_eventRectFollowerGraphic)
return;
var rf = _eventRectFollowerGraphic;
rf.enabled = true;
rf.gameObject.SetActive(false);
await Awaiters.Seconds(delayTime);
var lastIndex = 0;
for (var i = 0; i < playAttackTier2Count; i++)
{
for (var j = 0; j < rf.transform.childCount; j++)
rf.transform.GetChild(j).gameObject.SetActive(false);
var targetIndex = 0;
if (_bossCell is EventBossFightTimelineBossCellVideo vbMul)
{
var n = vbMul.bossHurtAnchors != null ? vbMul.bossHurtAnchors.Length : 0;
targetIndex = PickRandomBossHurtAnchorIndex(vbMul);
if (n > 1 && targetIndex == lastIndex)
targetIndex = targetIndex - 1 < 0 ? targetIndex + 1 : targetIndex - 1;
rf.SetTarget(vbMul.GetHurtAnchor(targetIndex));
}
lastIndex = targetIndex;
rf.enabled = true;
rf.gameObject.SetActive(true);
if (index >= 1 && index - 1 < rf.transform.childCount)
rf.transform.GetChild(index - 1).gameObject.SetActive(true);
await Awaiters.Seconds(playAttackTier2Interval);
}
}
catch (Exception e)
{
Debug.LogError(e);
}
}
private async Task PlayBossAttacked(float delayTime,int index)
{
await Awaiters.Seconds(delayTime);
await _bossCell.PlayTimelineAttacked(_bossCell.BossTimelineDirector, index);
await Awaiters.Seconds(bossDeathDelay);
if (Data.BossRemainHp == 0)
{
_isBossDeath = true;
await _bossCell.PlayTimelineDeath(_bossCell.BossTimelineDirector);
}
}
private async void PlayBossHpSliderEffect(float delayTime)
{
try
{
await Awaiters.Seconds(delayTime);
var fillAmount = (float)Data.BossRemainHp / _stageConfigWithUI.BossHP;
if (Data.IsLastStage)
await _imgBossHpBarFinal.DOFillAmount(fillAmount, sliderChangeTime)
.OnComplete(ShowBossHp).AsyncWaitForCompletion();
else
await _imgBossHpBar.DOFillAmount(fillAmount, sliderChangeTime)
.OnComplete(ShowBossHp).AsyncWaitForCompletion();
}
catch (Exception e)
{
Debug.LogError(e);
}
}
private RectTransform GetShieldRewardFlySource()
{
return _shieldAddAni.GetComponentInChildren<Image>().rectTransform;
}
private List<RectTransform> GetShieldRewardFlyTarget(int addAmount)
{
var targets = new List<RectTransform>();
for (int i = 0; i < _shields.Length; i++)
{
if(!_shields[i].isActiveAndEnabled)
targets.Add((RectTransform)_shields[i].transform);
if(targets.Count>=addAmount)
break;
}
return targets;
}
private async Task PlayTokenAddFly(int convertTokenCount,RectTransform source,RectTransform sourceText)
{
if(convertTokenCount<=0) return;
await Awaiters.Seconds(tokenAddTime);
var targetRect = GetTokenRewardFlyTarget();
var request = new BatchedRewardFlyRequest
{
Icon = new BatchedRewardFlyRequestIcon{icon=_imgTokenIcon.sprite},
Quantity = convertTokenCount,
StartPoint = new BatchedRewardFlyStartPoint(source,sourceText),
EndPoint = new BatchedRewardFlyEndPoint(targetRect),
IsDestinationRewardStash = true,
AnimationParamIndex = 0
};
await RewardFlyBatchCtrl.OnRewardFlyRequestAsync(request);
ShowTokenAmount();
}
private RectTransform GetTokenRewardFlyTarget()
{
return _imgTokenIcon.rectTransform;
}
#endregion
#region bossEffect
private async Task PlayBossAttackEffect(bool isReduceShield, bool isReducePlayerHp)
{
SetButtonState(false);
_ = _bossCell.PlayTimelineAttack(_bossCell.BossTimelineDirector);
var data = _bossCell.BossAttackShakeData;
if (isReduceShield)
{
await Awaiters.Seconds(data.delayShieldTime);
await PlayReduceShield();
}
if(isReducePlayerHp)
{
await Awaiters.Seconds(data.delayTime);
PlayShake(data);
PlaySceneCrackEffect();
if (_bossCell.PlayerAttackedFx)
_bossCell.PlayerAttackedFx.SetActive(true);
_= _playerCell.PlayTimelineAttacked(_playerDirector);
await PlayReduceHp();
if (_bossCell.PlayerAttackedFx)
_bossCell.PlayerAttackedFx.SetActive(false);
}
_isPlayerDeath=Data.PlayerShowHp == 0;
UpdateFightInfoVisibility();
await Awaiters.Seconds(delayShowFailPanelTime);
Manager.CheckStagePlayerState();
SetButtonState(true);
}
#endregion
private void OnRewardPanelClose(RewardPanelClose data)
{
ShowTokenAmount();
}
private async void PlayPlayerAttackShake(int index)
{
try
{
if (index >= playerShakeData.Count)
{
Debug.LogError("playerShakeData index out of range");
return;
}
var data = playerShakeData[index];
await Awaiters.Seconds(data.delayTime);
PlayShake(data);
}
catch (Exception e)
{
Debug.LogError(e);
}
}
private void PlayShake(EventBossFightShakeData data)
{
((RectTransform)transform).DOShakeAnchorPos( data.shakeDuration,data.to, data.shakeVibrato, data.shakeRandomness, data.snapping, data.fadeOut, data.randomnessMode)
.SetEase(data.shakeEase);
}
private void PlaySceneCrackEffect()
{
foreach (var obj in _sceneCrackFxs)
{
if(obj)
obj.SetActive(false);
}
var index = Random.Range(0, 4);
var effectObj =_sceneCrackFxs[index];
if (!effectObj) return;
var x= Random.Range(minPositonOffset.x, maxPositonOffset.x);
var y= Random.Range(minPositonOffset.y, maxPositonOffset.y);
((RectTransform)effectObj.transform).anchoredPosition = new Vector2(x, y);
effectObj.gameObject.SetActive(true);
}
}
}