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 { SkillSet } from "../common/config/SkillSet";
|
||||||
import { GameEvent } from "../common/config/GameEvent";
|
import { GameEvent } from "../common/config/GameEvent";
|
||||||
import { oops } from "db://oops-framework/core/Oops";
|
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 {
|
useCard(): CardConfig | null {
|
||||||
if (!this.cardData || this.isUsing) return 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) {
|
if (this.cardData.type === CardType.Hero) {
|
||||||
const guard = {
|
const guard = {
|
||||||
cancel: false,
|
cancel: false,
|
||||||
@@ -174,11 +188,18 @@ export class CardComp extends CCComp {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.setMissionCoin(currentCoin - cardCost);
|
||||||
|
oops.message.dispatchEvent(GameEvent.CoinAdd, {
|
||||||
|
syncOnly: true,
|
||||||
|
delta: -cardCost
|
||||||
|
});
|
||||||
this.isUsing = true;
|
this.isUsing = true;
|
||||||
const used = this.cardData;
|
const used = this.cardData;
|
||||||
mLogger.log(this.debugMode, "CardComp", "use card", {
|
mLogger.log(this.debugMode, "CardComp", "use card", {
|
||||||
uuid: used.uuid,
|
uuid: used.uuid,
|
||||||
type: used.type
|
type: used.type,
|
||||||
|
cost: cardCost,
|
||||||
|
leftCoin: this.getMissionCoin()
|
||||||
});
|
});
|
||||||
this.playUseDisappearAnim(() => {
|
this.playUseDisappearAnim(() => {
|
||||||
this.cardUseComp?.onCardUsed(used);
|
this.cardUseComp?.onCardUsed(used);
|
||||||
@@ -481,6 +502,17 @@ export class CardComp extends CCComp {
|
|||||||
[...clips].forEach(clip => anim.removeClip(clip, true));
|
[...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) 删除组件是触发组件处理自定义释放逻辑 */
|
/** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件是触发组件处理自定义释放逻辑 */
|
||||||
reset() {
|
reset() {
|
||||||
this.node.destroy();
|
this.node.destroy();
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ export class MissionCardComp extends CCComp {
|
|||||||
private readonly buttonNormalScale: number = 1;
|
private readonly buttonNormalScale: number = 1;
|
||||||
private readonly buttonPressScale: number = 0.94;
|
private readonly buttonPressScale: number = 0.94;
|
||||||
private readonly buttonClickScale: number = 1.06;
|
private readonly buttonClickScale: number = 1.06;
|
||||||
|
@property({ tooltip: "每次刷新卡牌消耗金币" })
|
||||||
|
refreshCost: number = 1;
|
||||||
/** 四个插卡槽位(固定顺序分发:1~4) */
|
/** 四个插卡槽位(固定顺序分发:1~4) */
|
||||||
@property(Node)
|
@property(Node)
|
||||||
cards_node:Node = null!
|
cards_node:Node = null!
|
||||||
@@ -106,7 +108,7 @@ export class MissionCardComp extends CCComp {
|
|||||||
}
|
}
|
||||||
this.resetButtonScale(this.cards_chou);
|
this.resetButtonScale(this.cards_chou);
|
||||||
this.resetButtonScale(this.cards_up);
|
this.resetButtonScale(this.cards_up);
|
||||||
this.updatePoolLvUI();
|
this.updateCoinAndCostUI();
|
||||||
this.updateHeroNumUI(false, false);
|
this.updateHeroNumUI(false, false);
|
||||||
this.node.active = true;
|
this.node.active = true;
|
||||||
const cards = this.buildDrawCards();
|
const cards = this.buildDrawCards();
|
||||||
@@ -161,14 +163,14 @@ export class MissionCardComp extends CCComp {
|
|||||||
}
|
}
|
||||||
private onCoinAdd(args:any){
|
private onCoinAdd(args:any){
|
||||||
if (args?.syncOnly) {
|
if (args?.syncOnly) {
|
||||||
this.updatePoolLvUI();
|
this.updateCoinAndCostUI();
|
||||||
this.playCoinChangeAnim((args?.delta ?? 0) > 0);
|
this.playCoinChangeAnim((args?.delta ?? 0) > 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const v = typeof args === 'number' ? args : (args?.delta ?? args?.value ?? 0);
|
const v = typeof args === 'number' ? args : (args?.delta ?? args?.value ?? 0);
|
||||||
if (v === 0) return;
|
if (v === 0) return;
|
||||||
this.setMissionCoin(this.getMissionCoin() + v);
|
this.setMissionCoin(this.getMissionCoin() + v);
|
||||||
this.updatePoolLvUI();
|
this.updateCoinAndCostUI();
|
||||||
this.playCoinChangeAnim(v > 0);
|
this.playCoinChangeAnim(v > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,8 +262,24 @@ export class MissionCardComp extends CCComp {
|
|||||||
|
|
||||||
/** 抽卡按钮:每次固定抽4张,然后顺序分发给4个单卡脚本 */
|
/** 抽卡按钮:每次固定抽4张,然后顺序分发给4个单卡脚本 */
|
||||||
private onClickDraw() {
|
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", {
|
mLogger.log(this.debugMode, "MissionCardComp", "click draw", {
|
||||||
poolLv: this.poolLv
|
poolLv: this.poolLv,
|
||||||
|
cost,
|
||||||
|
leftCoin: this.getMissionCoin()
|
||||||
});
|
});
|
||||||
this.layoutCardSlots();
|
this.layoutCardSlots();
|
||||||
const cards = this.buildDrawCards();
|
const cards = this.buildDrawCards();
|
||||||
@@ -278,7 +296,7 @@ export class MissionCardComp extends CCComp {
|
|||||||
const currentCoin = this.getMissionCoin();
|
const currentCoin = this.getMissionCoin();
|
||||||
if (currentCoin < cost) {
|
if (currentCoin < cost) {
|
||||||
oops.gui.toast(`金币不足,升级需要${cost}`);
|
oops.gui.toast(`金币不足,升级需要${cost}`);
|
||||||
this.updatePoolLvUI();
|
this.updateCoinAndCostUI();
|
||||||
mLogger.log(this.debugMode, "MissionCardComp", "pool upgrade coin not enough", {
|
mLogger.log(this.debugMode, "MissionCardComp", "pool upgrade coin not enough", {
|
||||||
poolLv: this.poolLv,
|
poolLv: this.poolLv,
|
||||||
currentCoin,
|
currentCoin,
|
||||||
@@ -289,7 +307,7 @@ export class MissionCardComp extends CCComp {
|
|||||||
this.setMissionCoin(currentCoin - cost);
|
this.setMissionCoin(currentCoin - cost);
|
||||||
this.poolLv += 1;
|
this.poolLv += 1;
|
||||||
this.playCoinChangeAnim(false);
|
this.playCoinChangeAnim(false);
|
||||||
this.updatePoolLvUI();
|
this.updateCoinAndCostUI();
|
||||||
mLogger.log(this.debugMode, "MissionCardComp", "pool level up", {
|
mLogger.log(this.debugMode, "MissionCardComp", "pool level up", {
|
||||||
poolLv: this.poolLv,
|
poolLv: this.poolLv,
|
||||||
cost,
|
cost,
|
||||||
@@ -423,6 +441,10 @@ export class MissionCardComp extends CCComp {
|
|||||||
const currentCoin = this.getMissionCoin();
|
const currentCoin = this.getMissionCoin();
|
||||||
return currentCoin >= this.getUpgradeCost(this.poolLv);
|
return currentCoin >= this.getUpgradeCost(this.poolLv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private canDrawCards() {
|
||||||
|
return this.getMissionCoin() >= this.getRefreshCost();
|
||||||
|
}
|
||||||
/** 更新升级按钮上的等级文案,反馈当前卡池层级 */
|
/** 更新升级按钮上的等级文案,反馈当前卡池层级 */
|
||||||
private updatePoolLvUI() {
|
private updatePoolLvUI() {
|
||||||
if (!this.cards_up) return;
|
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) {
|
private playCoinChangeAnim(isIncrease: boolean) {
|
||||||
if (!this.coins_node || !this.coins_node.isValid) return;
|
if (!this.coins_node || !this.coins_node.isValid) return;
|
||||||
const target = this.coins_node.getChildByName("num") || this.coins_node;
|
const target = this.coins_node.getChildByName("num") || this.coins_node;
|
||||||
@@ -466,6 +506,10 @@ export class MissionCardComp extends CCComp {
|
|||||||
return CardsUpSet[lv] ?? 0;
|
return CardsUpSet[lv] ?? 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getRefreshCost(): number {
|
||||||
|
return Math.max(0, Math.floor(this.refreshCost));
|
||||||
|
}
|
||||||
|
|
||||||
private ensureHeroInfoPanel(eid: number, model: HeroAttrsComp) {
|
private ensureHeroInfoPanel(eid: number, model: HeroAttrsComp) {
|
||||||
if (!this.hero_info_node || !this.hero_info_prefab) return;
|
if (!this.hero_info_node || !this.hero_info_prefab) return;
|
||||||
this.hero_info_node.active = true;
|
this.hero_info_node.active = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user