feat(mission): 添加抽卡面板付费开启与按钮高亮逻辑

1. 重构任务面板抽卡相关逻辑,为四个抽卡/商店面板添加开启费用机制,每次使用后费用递增
2. 新增面板重复开启校验,避免重复扣费
3. 优化英雄抽卡按钮的高亮状态,与面板展开状态绑定
4. 调整预设文件中任务面板UI元素的位置与尺寸适配新逻辑
5. 新增费用显示UI更新,在按钮上展示当前开启成本
This commit is contained in:
panFD
2026-08-06 08:08:36 +08:00
parent 4d6f1493b2
commit 6542da6a61
2 changed files with 112 additions and 13 deletions

View File

@@ -99,7 +99,7 @@ export class MissionCardComp extends CCComp {
nock_node: Node = null!
/** 英雄面板显示按钮 */
/** 英雄抽卡面板显示按钮 */
@property(Node)
showHeros: Node = null!
@property(Node)
@@ -191,6 +191,14 @@ export class MissionCardComp extends CCComp {
private readonly panelHideScale: Vec3 = new Vec3(0, 0, 1);
/** 是否已初始化面板布局 */
private hasInitPanelLayout: boolean = false;
/** 英雄抽卡面板是否处于展开状态(驱动 showHeros 按钮 active 高亮) */
private isCardPanelShown: boolean = false;
/** 抽卡面板开启初始金币费用 */
private static readonly PANEL_OPEN_BASE_COST = 5;
/** 抽卡面板每抽 1 次的费用递增 */
private static readonly PANEL_OPEN_COST_STEP = 5;
/** 各抽卡面板当前开启费用 [英雄抽卡, 装备, 技能, 药品] */
private panelOpenCosts: number[] = [];
/** 是否已缓存卡牌面板基准缩放 */
private hasCachedCardsBaseScale: boolean = false;
/** 卡牌面板基准缩放(从场景读取) */
@@ -280,6 +288,7 @@ export class MissionCardComp extends CCComp {
this.layoutCardSlots();
this.clearAllCards();
this.resetButtonScale(this.cards_chou);
this.resetPanelOpenCosts();
this.updateCoinAndCostUI();
this.updateHeroNumUI(false, false);
if (this.node && this.node.isValid) {
@@ -507,6 +516,9 @@ export class MissionCardComp extends CCComp {
*/
private onShowSkillsClick() {
oops.audio.playEffect("music/button");
if (this.isOverlayPanelShown(2)) return;
// 开启技能面板需支付金币,金币不足则提示并中止
if (!this.tryPayPanelOpenCost(2)) return;
this.slideToPanel(2);
}
@@ -517,6 +529,9 @@ export class MissionCardComp extends CCComp {
*/
private onShowShopClick() {
oops.audio.playEffect("music/button");
if (this.isOverlayPanelShown(3)) return;
// 开启药品面板需支付金币,金币不足则提示并中止
if (!this.tryPayPanelOpenCost(3)) return;
this.slideToPanel(3);
}
@@ -866,6 +881,16 @@ export class MissionCardComp extends CCComp {
return [this.showHeros, this.showEquips, this.showSkills, this.showShop];
}
/**
* 判断覆盖面板index≥1当前是否处于展开状态避免重复开启导致重复扣费。
* @param index 面板下标1=装备 2=技能 3=药品)
*/
private isOverlayPanelShown(index: number): boolean {
if (this.currentPanelIndex !== index) return false;
const node = this.getPanelNodes()[index];
return !!node && node.isValid && node.active;
}
/**
* 初始化面板布局:
* 1. 英雄面板index=0为常驻基准面板始终显示。
@@ -961,7 +986,9 @@ export class MissionCardComp extends CCComp {
/**
* 更新面板 tab 按钮的 active 子节点状态。
* 当前激活面板对应的按钮 active 高亮,其余关闭。
* 装备/技能/药品按钮按 currentPanelIndex 高亮;
* 英雄抽卡面板cardPanNode不在覆盖面板数组内
* showHeros 按钮按 isCardPanelShown 高亮:面板展开时显示 active关闭时隐藏。
*/
private updatePanelButtonStates() {
const buttons = this.getPanelShowButtons();
@@ -970,7 +997,8 @@ export class MissionCardComp extends CCComp {
if (!btn || !btn.isValid) continue;
const activeChild = btn.getChildByName("active");
if (activeChild) {
activeChild.active = (i === this.currentPanelIndex);
const shouldActive = i === 0 ? this.isCardPanelShown : (i === this.currentPanelIndex);
activeChild.active = shouldActive;
}
}
}
@@ -989,11 +1017,20 @@ export class MissionCardComp extends CCComp {
}
/**
* 英雄面板按钮回调:收起覆盖面板,回到英雄面板(index=0)。
* 英雄面板按钮回调:
* 英雄面板herosPanNode为常驻基准面板固定不动
* 点击按钮收起装备/技能/药品覆盖面板并显示英雄抽卡面板cardPanNode
*/
private onShowHerosClick() {
oops.audio.playEffect("music/button");
// 已展开则不重复开启(不重复扣费)
if (this.isCardPanelShown) return;
// 开启英雄抽卡面板需支付金币,金币不足则提示并中止
if (!this.tryPayPanelOpenCost(0)) return;
// 收起装备/技能/药品覆盖面板
this.slideToPanel(0);
// 显示英雄抽卡面板(缩放 0→1并点亮按钮 active 高亮)
this.showCardsPanel();
}
// ======================== 英雄信息盒herosBoxNode ========================
@@ -1061,12 +1098,59 @@ export class MissionCardComp extends CCComp {
}
}
/**
* 支付抽卡面板开启费用:
* 金币足够则扣除当前费用,并将该面板费用递增 PANEL_OPEN_COST_STEP
* 不足则弹出"金币不足"小提示并返回 false。
* @param panelIndex 面板下标0=英雄抽卡 1=装备 2=技能 3=药品)
* @returns 是否支付成功
*/
private tryPayPanelOpenCost(panelIndex: number): boolean {
const cost = this.panelOpenCosts[panelIndex] ?? MissionCardComp.PANEL_OPEN_BASE_COST;
if (!MissionEconomy.spendCoin(cost)) {
oops.message.dispatchEvent(GameEvent.ShowSmallTip, "buy_coin");
return false;
}
this.panelOpenCosts[panelIndex] = cost + MissionCardComp.PANEL_OPEN_COST_STEP;
this.updatePanelOpenCostUI();
return true;
}
/** 重置 4 个抽卡面板开启费用为初始值(任务开始时调用) */
private resetPanelOpenCosts() {
this.panelOpenCosts = [
MissionCardComp.PANEL_OPEN_BASE_COST,
MissionCardComp.PANEL_OPEN_BASE_COST,
MissionCardComp.PANEL_OPEN_BASE_COST,
MissionCardComp.PANEL_OPEN_BASE_COST
];
this.updatePanelOpenCostUI();
}
/** 刷新 4 个显示按钮上的开启费用显示(按钮下无 cost/num 标签子节点时自动跳过) */
private updatePanelOpenCostUI() {
const buttons = this.getPanelShowButtons();
for (let i = 0; i < buttons.length; i++) {
const btn = buttons[i];
if (!btn || !btn.isValid) continue;
const costNode = btn.getChildByName("cost") ?? btn.getChildByName("num");
const label = costNode ? costNode.getComponent(Label) : null;
if (label) {
label.string = `${this.panelOpenCosts[i] ?? MissionCardComp.PANEL_OPEN_BASE_COST}`;
}
}
}
/**
* 显示卡牌面板:缩放从 0 动画放大到 1
*/
private onShowCardsClick() {
oops.audio.playEffect("music/button");
this.showOverlayPanel(this.cardPanNode);
// 已展开则不重复开启(不重复扣费)
if (this.isCardPanelShown) return;
// 空槽位点开英雄抽卡面板同样需支付金币
if (!this.tryPayPanelOpenCost(0)) return;
this.showCardsPanel();
}
/**
@@ -1077,9 +1161,21 @@ export class MissionCardComp extends CCComp {
this.hideCardsPanel();
}
/** 隐藏卡牌面板:缩放缩小到 0不含按钮音效供系统逻辑复用 */
/**
* 显示卡牌面板:缩放 0→1并点亮 showHeros 按钮的 active 高亮。
* 统一开合入口,供按钮点击与系统逻辑复用。
*/
private showCardsPanel() {
this.isCardPanelShown = true;
this.showOverlayPanel(this.cardPanNode);
this.updatePanelButtonStates();
}
/** 隐藏卡牌面板:缩放缩小到 0同时隐藏 showHeros 按钮的 active 高亮 */
private hideCardsPanel() {
this.isCardPanelShown = false;
this.hideOverlayPanelNode(this.cardPanNode);
this.updatePanelButtonStates();
}
/**
@@ -1105,6 +1201,9 @@ export class MissionCardComp extends CCComp {
*/
private onShowEquipsClick() {
oops.audio.playEffect("music/button");
if (this.isOverlayPanelShown(1)) return;
// 开启装备面板需支付金币,金币不足则提示并中止
if (!this.tryPayPanelOpenCost(1)) return;
this.slideToPanel(1);
}
@@ -1503,9 +1602,9 @@ export class MissionCardComp extends CCComp {
}
// 刷新所有刷新按钮的费用显示(含刷新石/金币切换与置灰状态)
this.updateDrawCostUI();
// 显示卡牌面板(默认进入准备阶段时展开,缩放放大到 1
// 显示卡牌面板(默认进入准备阶段时展开,缩放放大到 1,点亮按钮 active 高亮
if (this.cardPanNode && this.cardPanNode.isValid) {
this.showOverlayPanel(this.cardPanNode);
this.showCardsPanel();
mLogger.log(this.debugMode, "MissionCardComp", "enterPreparePhase cardPanNode", {
active: this.cardPanNode.active,
position: this.cardPanNode.position,