feat(卡牌): 添加金币消耗机制
- 在 CardComp 中检查使用卡牌所需金币,不足时播放反弹动画并提示 - 在 MissionCardComp 中检查刷新卡牌所需金币,不足时提示 - 添加金币获取和设置方法,统一处理金币数值的取整和边界 - 更新 UI 显示逻辑,同时显示金币余额和刷新/升级消耗 - 使用卡牌或刷新时扣除相应金币并发送金币变更事件
This commit is contained in:
@@ -8,6 +8,7 @@ import { HeroInfo } from "../common/config/heroSet";
|
||||
import { SkillSet } from "../common/config/SkillSet";
|
||||
import { GameEvent } from "../common/config/GameEvent";
|
||||
import { oops } from "db://oops-framework/core/Oops";
|
||||
import { smc } from "../common/SingletonModuleComp";
|
||||
|
||||
|
||||
|
||||
@@ -161,6 +162,19 @@ export class CardComp extends CCComp {
|
||||
|
||||
useCard(): CardConfig | null {
|
||||
if (!this.cardData || this.isUsing) return null;
|
||||
const cardCost = Math.max(0, Math.floor(this.cardData.cost ?? 0));
|
||||
const currentCoin = this.getMissionCoin();
|
||||
if (currentCoin < cardCost) {
|
||||
oops.gui.toast(`金币不足,召唤需要${cardCost}`);
|
||||
this.playReboundAnim();
|
||||
mLogger.log(this.debugMode, "CardComp", "use card coin not enough", {
|
||||
uuid: this.cardData.uuid,
|
||||
type: this.cardData.type,
|
||||
cardCost,
|
||||
currentCoin
|
||||
});
|
||||
return null;
|
||||
}
|
||||
if (this.cardData.type === CardType.Hero) {
|
||||
const guard = {
|
||||
cancel: false,
|
||||
@@ -174,11 +188,18 @@ export class CardComp extends CCComp {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
this.setMissionCoin(currentCoin - cardCost);
|
||||
oops.message.dispatchEvent(GameEvent.CoinAdd, {
|
||||
syncOnly: true,
|
||||
delta: -cardCost
|
||||
});
|
||||
this.isUsing = true;
|
||||
const used = this.cardData;
|
||||
mLogger.log(this.debugMode, "CardComp", "use card", {
|
||||
uuid: used.uuid,
|
||||
type: used.type
|
||||
type: used.type,
|
||||
cost: cardCost,
|
||||
leftCoin: this.getMissionCoin()
|
||||
});
|
||||
this.playUseDisappearAnim(() => {
|
||||
this.cardUseComp?.onCardUsed(used);
|
||||
@@ -481,6 +502,17 @@ export class CardComp extends CCComp {
|
||||
[...clips].forEach(clip => anim.removeClip(clip, true));
|
||||
}
|
||||
|
||||
private getMissionCoin(): number {
|
||||
const missionData = smc?.vmdata?.mission_data;
|
||||
return Math.max(0, Math.floor(missionData?.coin ?? 0));
|
||||
}
|
||||
|
||||
private setMissionCoin(value: number) {
|
||||
const missionData = smc?.vmdata?.mission_data;
|
||||
if (!missionData) return;
|
||||
missionData.coin = Math.max(0, Math.floor(value));
|
||||
}
|
||||
|
||||
/** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件是触发组件处理自定义释放逻辑 */
|
||||
reset() {
|
||||
this.node.destroy();
|
||||
|
||||
@@ -22,6 +22,8 @@ export class MissionCardComp extends CCComp {
|
||||
private readonly buttonNormalScale: number = 1;
|
||||
private readonly buttonPressScale: number = 0.94;
|
||||
private readonly buttonClickScale: number = 1.06;
|
||||
@property({ tooltip: "每次刷新卡牌消耗金币" })
|
||||
refreshCost: number = 1;
|
||||
/** 四个插卡槽位(固定顺序分发:1~4) */
|
||||
@property(Node)
|
||||
cards_node:Node = null!
|
||||
@@ -106,7 +108,7 @@ export class MissionCardComp extends CCComp {
|
||||
}
|
||||
this.resetButtonScale(this.cards_chou);
|
||||
this.resetButtonScale(this.cards_up);
|
||||
this.updatePoolLvUI();
|
||||
this.updateCoinAndCostUI();
|
||||
this.updateHeroNumUI(false, false);
|
||||
this.node.active = true;
|
||||
const cards = this.buildDrawCards();
|
||||
@@ -161,14 +163,14 @@ export class MissionCardComp extends CCComp {
|
||||
}
|
||||
private onCoinAdd(args:any){
|
||||
if (args?.syncOnly) {
|
||||
this.updatePoolLvUI();
|
||||
this.updateCoinAndCostUI();
|
||||
this.playCoinChangeAnim((args?.delta ?? 0) > 0);
|
||||
return;
|
||||
}
|
||||
const v = typeof args === 'number' ? args : (args?.delta ?? args?.value ?? 0);
|
||||
if (v === 0) return;
|
||||
this.setMissionCoin(this.getMissionCoin() + v);
|
||||
this.updatePoolLvUI();
|
||||
this.updateCoinAndCostUI();
|
||||
this.playCoinChangeAnim(v > 0);
|
||||
}
|
||||
|
||||
@@ -260,8 +262,24 @@ export class MissionCardComp extends CCComp {
|
||||
|
||||
/** 抽卡按钮:每次固定抽4张,然后顺序分发给4个单卡脚本 */
|
||||
private onClickDraw() {
|
||||
const cost = this.getRefreshCost();
|
||||
const currentCoin = this.getMissionCoin();
|
||||
if (currentCoin < cost) {
|
||||
oops.gui.toast(`金币不足,刷新需要${cost}`);
|
||||
this.updateCoinAndCostUI();
|
||||
mLogger.log(this.debugMode, "MissionCardComp", "draw coin not enough", {
|
||||
currentCoin,
|
||||
cost
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.setMissionCoin(currentCoin - cost);
|
||||
this.playCoinChangeAnim(false);
|
||||
this.updateCoinAndCostUI();
|
||||
mLogger.log(this.debugMode, "MissionCardComp", "click draw", {
|
||||
poolLv: this.poolLv
|
||||
poolLv: this.poolLv,
|
||||
cost,
|
||||
leftCoin: this.getMissionCoin()
|
||||
});
|
||||
this.layoutCardSlots();
|
||||
const cards = this.buildDrawCards();
|
||||
@@ -278,7 +296,7 @@ export class MissionCardComp extends CCComp {
|
||||
const currentCoin = this.getMissionCoin();
|
||||
if (currentCoin < cost) {
|
||||
oops.gui.toast(`金币不足,升级需要${cost}`);
|
||||
this.updatePoolLvUI();
|
||||
this.updateCoinAndCostUI();
|
||||
mLogger.log(this.debugMode, "MissionCardComp", "pool upgrade coin not enough", {
|
||||
poolLv: this.poolLv,
|
||||
currentCoin,
|
||||
@@ -289,7 +307,7 @@ export class MissionCardComp extends CCComp {
|
||||
this.setMissionCoin(currentCoin - cost);
|
||||
this.poolLv += 1;
|
||||
this.playCoinChangeAnim(false);
|
||||
this.updatePoolLvUI();
|
||||
this.updateCoinAndCostUI();
|
||||
mLogger.log(this.debugMode, "MissionCardComp", "pool level up", {
|
||||
poolLv: this.poolLv,
|
||||
cost,
|
||||
@@ -423,6 +441,10 @@ export class MissionCardComp extends CCComp {
|
||||
const currentCoin = this.getMissionCoin();
|
||||
return currentCoin >= this.getUpgradeCost(this.poolLv);
|
||||
}
|
||||
|
||||
private canDrawCards() {
|
||||
return this.getMissionCoin() >= this.getRefreshCost();
|
||||
}
|
||||
/** 更新升级按钮上的等级文案,反馈当前卡池层级 */
|
||||
private updatePoolLvUI() {
|
||||
if (!this.cards_up) return;
|
||||
@@ -449,6 +471,24 @@ export class MissionCardComp extends CCComp {
|
||||
});
|
||||
}
|
||||
|
||||
private updateDrawCostUI() {
|
||||
if (!this.cards_chou) return;
|
||||
const nobg = this.cards_chou.getChildByName("nobg");
|
||||
if (nobg) {
|
||||
nobg.active = !this.canDrawCards();
|
||||
}
|
||||
const coinNode = this.cards_chou.getChildByName("coin");
|
||||
const numLabel = coinNode?.getChildByName("num")?.getComponent(Label);
|
||||
if (numLabel) {
|
||||
numLabel.string = `${this.getRefreshCost()}`;
|
||||
}
|
||||
}
|
||||
|
||||
private updateCoinAndCostUI() {
|
||||
this.updatePoolLvUI();
|
||||
this.updateDrawCostUI();
|
||||
}
|
||||
|
||||
private playCoinChangeAnim(isIncrease: boolean) {
|
||||
if (!this.coins_node || !this.coins_node.isValid) return;
|
||||
const target = this.coins_node.getChildByName("num") || this.coins_node;
|
||||
@@ -466,6 +506,10 @@ export class MissionCardComp extends CCComp {
|
||||
return CardsUpSet[lv] ?? 0;
|
||||
}
|
||||
|
||||
private getRefreshCost(): number {
|
||||
return Math.max(0, Math.floor(this.refreshCost));
|
||||
}
|
||||
|
||||
private ensureHeroInfoPanel(eid: number, model: HeroAttrsComp) {
|
||||
if (!this.hero_info_node || !this.hero_info_prefab) return;
|
||||
this.hero_info_node.active = true;
|
||||
|
||||
Reference in New Issue
Block a user