You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
AdLike2048/assets/script/ui/BattleGame/BattleFirstGuidePresenter.ts

145 lines
5.0 KiB

3 weeks ago
import { Node, sp } from 'cc';
import { MergeEventType, type MergeEvent } from 'db://assets/mx/module/merge';
import type { BattleBagSession } from '../../battle/bag/BattleBagSession';
import { BattleSpinePlayback } from '../../battle/presentation/BattleSpinePlayback';
import { RankDataManager } from '../../manager/RankDataManager';
/** 引导手指 Spine 动画 */
const FINGER_ANIM = '点击';
/** 步骤节点父名 */
const STEPS_NODE = 'steps';
/** 第一步:点召唤 */
const STEP_SUMMON = '2';
/** 第二步:拖字上阵 */
const STEP_DRAG = '3';
/** 手指节点名 */
const FINGER_NODE = '引导手指';
/**
* 新玩家首次进战弱引导:点召唤 → 拖字上阵。
*/
export class BattleFirstGuidePresenter {
/** 引导根 */
private _root: Node | null = null;
/** 点召唤文案 */
private _stepSummon: Node | null = null;
/** 拖字文案 */
private _stepDrag: Node | null = null;
/** 手指 */
private _finger: Node | null = null;
/** 手指 Spine */
private _fingerSk: sp.Skeleton | null = null;
/** 本机背包 */
private _bag: BattleBagSession | null = null;
/** 当前步:0 未开 / 2 点召唤 / 3 拖字 */
private _step = 0;
/**
* 绑定并按存档决定是否展示第一步。
* @param root ui_guide
* @param bag 本机背包会话
*/
bind(root: Node | null, bag: BattleBagSession | null): void {
this.unbind();
if (!root?.isValid) {
console.error('[BattleFirstGuide] ui_guide 缺失');
return;
}
root.active = false;
if (!RankDataManager.shouldShowFirstBattleGuide()) return;
const steps = root.getChildByName(STEPS_NODE);
this._stepSummon = steps?.getChildByName(STEP_SUMMON) ?? null;
this._stepDrag = steps?.getChildByName(STEP_DRAG) ?? null;
this._finger = root.getChildByName(FINGER_NODE) ?? null;
this._fingerSk = this._finger?.getComponent(sp.Skeleton) ?? null;
if (!this._stepSummon?.isValid || !this._stepDrag?.isValid || !this._finger?.isValid) {
console.error('[BattleFirstGuide] ui_guide 子节点缺失');
return;
}
if (!bag) {
console.error('[BattleFirstGuide] bagSession 未就绪');
return;
}
this._root = root;
this._bag = bag;
this._bag.on(MergeEventType.TilePlaced, this._onPlayerDrag);
this._bag.on(MergeEventType.TileMoved, this._onPlayerDrag);
this._showSummon();
}
/** 召唤刷新成功:藏手指,切到拖字提示 */
onSummonOk(): void {
if (this._step !== 2) return;
this._showDrag();
const curWaveNum = gg.game.CurentBattle.CurentWaveNum;
gg.sdk.reportDY('inLevel', `${gg.game.getReportDYBattleCountLabel(curWaveNum)}-新手引导1点召唤`);
}
/** 停动画、解监听、藏根 */
unbind(): void {
if (this._bag) {
this._bag.off(MergeEventType.TilePlaced, this._onPlayerDrag);
this._bag.off(MergeEventType.TileMoved, this._onPlayerDrag);
}
this._stopFinger();
if (this._root?.isValid) this._root.active = false;
this._root = null;
this._stepSummon = null;
this._stepDrag = null;
this._finger = null;
this._fingerSk = null;
this._bag = null;
this._step = 0;
}
/** 第一步:手指点召唤 + 文案 2 */
private _showSummon(): void {
const root = this._root;
if (!root?.isValid) return;
this._step = 2;
root.active = true;
if (this._stepSummon) this._stepSummon.active = true;
if (this._stepDrag) this._stepDrag.active = false;
if (this._finger) this._finger.active = true;
this._playFinger();
}
/** 第二步:只留拖字文案 */
private _showDrag(): void {
this._step = 3;
if (this._stepSummon) this._stepSummon.active = false;
if (this._stepDrag) this._stepDrag.active = true;
this._stopFinger();
if (this._finger) this._finger.active = false;
}
/** 玩家拖到地图:结束引导 */
private readonly _onPlayerDrag = (_event: MergeEvent): void => {
if (this._step !== 3) return;
RankDataManager.markFirstBattleGuideDone();
this.unbind();
const curWaveNum = gg.game.CurentBattle.CurentWaveNum;
gg.sdk.reportDY('inLevel', `${gg.game.getReportDYBattleCountLabel(curWaveNum)}-新手引导2拖字上阵`);
};
/** 循环播手指点击 */
private _playFinger(): void {
const sk = this._fingerSk;
if (!sk?.isValid) {
console.error('[BattleFirstGuide] 引导手指缺少 Spine');
return;
}
BattleSpinePlayback.play(sk, FINGER_ANIM, { loop: true });
}
/** 停手指 Spine */
private _stopFinger(): void {
const sk = this._fingerSk;
if (!sk?.isValid) return;
BattleSpinePlayback.clearPendingComplete(sk);
BattleSpinePlayback.resetTracks(sk);
}
}