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/BattleRevive/UIBattleRevive.ts

192 lines
7.2 KiB

3 weeks ago
//*********************
// create by 流云
// time: Thu Sep 25 2025
// desc:
//*********************
import { _decorator, Label, Node, sp, Sprite } from 'cc';
import { Auto_BattleRevive } from './Auto_BattleRevive';
import {
BattleReviveNodes,
playBattleReviveOpen,
prepareBattleReviveOpen,
stopBattleReviveOpen,
syncBtnLayout,
} from './BattleReviveOpenAnim';
import { UIID } from '../../game/ConfigRes';
import { GEvent } from 'db://assets/mx/module/event/GEvent';
import { readRevivePeachRewardAmount } from '../../battle/runtime/BattleRuntime';
import { IPopAnimConfig } from 'db://assets/mx/module/ui/popAnim';
const { ccclass } = _decorator;
@ccclass('UIBattleRevive')
export class UIBattleRevive extends Auto_BattleRevive {
private _reviveNodes: BattleReviveNodes = null;
onLoad(): void {
super.onLoad();
this._bindReviveNodes();
}
/** preparePopOpenPose 可能在 onLoad 之前调用,需惰性绑定节点 */
private _bindReviveNodes(): void {
if (this._reviveNodes || !this.ui_center) return;
const progressNode = this.lb_progress?.node ?? this.ui_center.getChildByName('lb_progress');
this._reviveNodes = {
bg: this.ui_center.getChildByName('复活背景'),
title: this._resolveReviveTitle(),
spine: this._resolveReviveSpine(),
progressBg: this.ui_center.getChildByName('圆角矩形 1160'),
progressPrefix: this.ui_center.getChildByName('Label'),
progressLabel: progressNode,
progressSuffix: this.ui_center.getChildByName('Label-001'),
rewardLabel: this.ui_center.getChildByName('复活奖励'),
rewardPanel: this.ui_center.getChildByName('组 2562'),
tipText: this.ui_center.getChildByName('Label2'),
btnLayout: this.ui_center.getChildByName('btnLayout'),
};
}
/** 预制体里有两个「复活继续」:取带 Spine 的角色动画,跳过标题 Sprite */
private _resolveReviveSpine(): Node {
for (const c of this.ui_center.children) {
if (c.name === '复活继续' && c.getComponent(sp.Skeleton)) return c;
}
console.log('[UIBattleRevive] revive spine node not found');
return null;
}
/** 预制体里有两个「复活继续」:取带 Sprite 的标题图,跳过废弃 Spine */
private _resolveReviveTitle(): Node {
for (const c of this.ui_center.children) {
if (c.name === '复活继续' && c.getComponent(Sprite)) return c;
}
return this.ui_center.getChildByName('复活继续');
}
onDisable(): void {
if (this._reviveNodes) {
stopBattleReviveOpen(this._reviveNodes);
}
super.onDisable();
}
preparePopOpenPose(): void {
const cfg = this.uiInfo?.uiconf?.popAnim as IPopAnimConfig | undefined;
if (!cfg) return;
// UIManager 会在 onLoad 前调用;此处仅遮罩,节点隐藏与序列在 onInit 执行
gg.ui.popAnim.prepareOpen(this.node, cfg.mask ?? 'dim', 'none');
}
playPopFromConfig(): void {
const cfg = this.uiInfo?.uiconf?.popAnim as IPopAnimConfig | undefined;
if (!cfg) return;
if (cfg.mask !== 'none') {
this.popMask(cfg.mask ?? 'dim');
}
}
onInit(): void {
this.refreshFailReviveLeftNum();
syncBtnLayout(this._reviveNodes?.btnLayout);
this.refreshGameProgress();
if (this._reviveNodes) {
prepareBattleReviveOpen(this._reviveNodes);
}
this._playReviveMotivation();
}
private _playReviveMotivation(): void {
if (!this._reviveNodes) return;
const progressPercent = this._readProgressPercent();
const reviveBtn = this.btnFreeRevive.active ? this.btnFreeRevive : this.btnAdRevive;
playBattleReviveOpen({
nodes: this._reviveNodes,
progressPercent,
reviveBtn,
onComplete: () => {
this.notifyOpenAnimEnd();
},
});
}
private _readProgressPercent(): number {
const raw = parseInt(this.lb_progress.string, 10);
return Number.isFinite(raw) ? raw : 0;
}
refreshGameProgress() {
let curDeadMonsterNum = gg.game.CurentBattle.MonsterDeadNum;
let totalMonsterNum = gg.game.CurentBattle.TotalMonsterNum;
this.lb_progress.string = `${Math.floor((totalMonsterNum - curDeadMonsterNum) / totalMonsterNum * 100)}%`
}
refreshFailReviveLeftNum() {
if (!this.btnAdRevive?.isValid || !this.btnFreeRevive?.isValid) return;
let curFailReviveLeftNum = gg.game.CurentBattle.curFailReviveLeftNum;
this.btnAdRevive.getChildByName('leftTimes').getComponent(Label).string = gg.lang.get('剩余次数x{1}', [curFailReviveLeftNum])
this.btnFreeRevive.getChildByName('leftTimes').getComponent(Label).string = gg.lang.get('剩余次数x{1}', [curFailReviveLeftNum])
this.btnFreeRevive.active = gg.game.CurentSelectChapterId == 1 && curFailReviveLeftNum >= 2
this.btnAdRevive.active = !this.btnFreeRevive.active
}
click_btnBack(): void {
let curWaveNum = gg.game.CurentBattle.CurentWaveNum;
gg.sdk.reportDY("inLevel", `${gg.game.getReportDYBattleLabel(curWaveNum)}-放弃复活`)
this.close(2).then(() => {
gg.game.CurentBattle.gameOver(false);
gg.ui.openPanel(UIID.BattleFail);
});
}
click_btnAdRevive() {
gg.sdk.showVideoAd((res) => {
if (res) {
let curWaveNum = gg.game.CurentBattle.CurentWaveNum;
gg.sdk.reportDY("inLevel", `${gg.game.getReportDYBattleLabel(curWaveNum)}-AD-广告复活`)
gg.game.CurentBattle.curFailReviveLeftNum--;
this.refreshFailReviveLeftNum()
this.close(2).then(() => {
this.gameReborn();
GEvent.Ins.emit(GEvent.GameReborn)
});
} else {
gg.ui.showToast('观看视频失败');
}
})
}
click_btnFreeRevive(): void {
let curWaveNum = gg.game.CurentBattle.CurentWaveNum;
gg.sdk.reportDY("inLevel", `${gg.game.getReportDYBattleLabel(curWaveNum)}-复活`)
gg.game.CurentBattle.curFailReviveLeftNum--;
this.refreshFailReviveLeftNum()
this.close(2).then(() => {
this.gameReborn();
GEvent.Ins.emit(GEvent.GameReborn)
});
}
gameReborn(): void {
const battle = gg.game.CurentBattle;
gg.ui.removeQueuedPopPanels(UIID.BattleRevive);
battle.setCurentWallHp(battle.WallMaxHp);
battle.resetAliveMonstersToBornPosAfterRevive();
const peach = readRevivePeachRewardAmount();
if (peach > 0) {
battle.addCoinNum(peach);
battle.lastRevivePeachGrant = peach;
GEvent.Ins.emit(GEvent.UpdateGameCoinNum);
GEvent.Ins.emit(GEvent.RevivePeachGrant, peach);
} else {
console.error(
'[UIBattleRevive] revive peach amount is 0, reward=',
peach,
);
}
GEvent.Ins.emit(GEvent.playerHit);
battle.session.leaveWaitReviveToCombat();
}
}