From bbd3e01ae527c6a36ff9aea26dd76f073404621a Mon Sep 17 00:00:00 2001 From: panw Date: Thu, 21 May 2026 09:51:32 +0800 Subject: [PATCH] =?UTF-8?q?refactor(map):=20=E9=87=8D=E6=9E=84=E5=B1=80?= =?UTF-8?q?=E5=86=85=E7=BB=8F=E6=B5=8E=E7=B3=BB=E7=BB=9F=EF=BC=8C=E7=BB=9F?= =?UTF-8?q?=E4=B8=80=E5=B0=81=E8=A3=85=E9=87=91=E5=B8=81=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新建MissionEconomy类作为局内经济统一管理入口,整合原分散在HInfoComp、MissionComp、CardComp、MissionCardComp中的金币计算、消费、收益统计逻辑,移除各组件中重复的getMissionCoin、setMissionCoin、getRefreshCost等工具方法,统一维护评分系统的金币统计,提升代码可维护性。 --- assets/script/game/map/CardComp.ts | 52 +++----- assets/script/game/map/HInfoComp.ts | 16 +-- assets/script/game/map/MissionCardComp.ts | 59 +++------ assets/script/game/map/MissionComp.ts | 19 +-- assets/script/game/map/MissionEconomy.ts | 112 ++++++++++++++++++ assets/script/game/map/MissionEconomy.ts.meta | 9 ++ 6 files changed, 164 insertions(+), 103 deletions(-) create mode 100644 assets/script/game/map/MissionEconomy.ts create mode 100644 assets/script/game/map/MissionEconomy.ts.meta diff --git a/assets/script/game/map/CardComp.ts b/assets/script/game/map/CardComp.ts index 03a24e9b..5e657b07 100644 --- a/assets/script/game/map/CardComp.ts +++ b/assets/script/game/map/CardComp.ts @@ -33,6 +33,7 @@ import { smc } from "../common/SingletonModuleComp"; import { UIID } from "../common/config/GameUIConfig"; import { HeroAttrsComp } from "../hero/HeroAttrsComp"; import { TalentType } from "../common/config/TalentSet"; +import { MissionEconomy } from "./MissionEconomy"; @@ -291,19 +292,7 @@ export class CardComp extends CCComp { useCard(): CardConfig | null { if (!this.cardData || this.isUsing) return null; const cardCost = this.card_cost; - 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; - } + // 英雄卡特殊校验:通过 guard 对象实现"可取消"模式 if (this.cardData.type === CardType.Hero) { const guard = { @@ -319,16 +308,24 @@ export class CardComp extends CCComp { return null; } } - // 扣除金币 - this.setMissionCoin(currentCoin - cardCost); - // 【评分系统 - 效率分】记录购卡消耗的金币,以及刷新后的选中卡次数(命中率分子) - smc.vmdata.scores.gold_spent += cardCost; + + // 使用统一经济管理入口消费金币 + const success = MissionEconomy.spendCoin(cardCost); + if (!success) { + 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: MissionEconomy.getCoin() + }); + return null; + } + + // 【评分系统 - 效率分】记录刷新后的选中卡次数(命中率分子) smc.vmdata.scores.refresh_hit_count++; - oops.message.dispatchEvent(GameEvent.CoinAdd, { - syncOnly: true, - delta: -cardCost - }); // 标记使用中,阻止并发操作 this.isUsing = true; const used = this.cardData; @@ -336,7 +333,7 @@ export class CardComp extends CCComp { uuid: used.uuid, type: used.type, cost: cardCost, - leftCoin: this.getMissionCoin() + leftCoin: MissionEconomy.getCoin() }); // 播放消失动画 → 动画结束后清槽并分发效果 this.playUseDisappearAnim(() => { @@ -1194,18 +1191,7 @@ export class CardComp extends CCComp { // ======================== 数据访问 ======================== - /** 从全局单例获取当前局内金币数量 */ - private getMissionCoin(): number { - const missionData = smc?.vmdata?.mission_data; - return Math.max(0, Math.floor(missionData?.coin ?? 0)); - } - /** 设置当前局内金币数量(自动向下取整并 clamp 至 >= 0) */ - private setMissionCoin(value: number) { - const missionData = smc?.vmdata?.mission_data; - if (!missionData) return; - missionData.coin = Math.max(0, Math.floor(value)); - } /** ECS 组件移除时的释放钩子:销毁节点 */ reset() { diff --git a/assets/script/game/map/HInfoComp.ts b/assets/script/game/map/HInfoComp.ts index cb1ecea9..42529c52 100644 --- a/assets/script/game/map/HInfoComp.ts +++ b/assets/script/game/map/HInfoComp.ts @@ -35,6 +35,7 @@ import { mLogger } from "../common/Logger"; import { MissionHeroCompComp } from "./MissionHeroComp"; import { MoveComp } from "../hero/MoveComp"; import { FacSet } from "../common/config/GameSet"; +import { MissionEconomy } from "./MissionEconomy"; const {property, ccclass } = _decorator; @@ -311,19 +312,8 @@ export class HInfoComp extends CCComp { }); if (!removed) return; - // 卖出英雄金币收益 - const baseSellGold = 1; // 基础卖出金币 - const goldBoost = HeroAttrsComp.getFieldSkillTotalValue(FieldSkillType.SellGold); - let totalSellGold = baseSellGold + goldBoost; - - // 应用天赋 SellBonus (增加数值) - const bonusGold = HeroAttrsComp.getTalentValue(TalentType.SellBonus); - if (bonusGold > 0) { - totalSellGold += bonusGold; - } - totalSellGold = Math.floor(totalSellGold); - - oops.message.dispatchEvent(GameEvent.CoinAdd, { delta: totalSellGold }); + // 使用统一经济管理入口出售英雄 + MissionEconomy.executeSellHero(); oops.gui.remove(UIID.IBox); } diff --git a/assets/script/game/map/MissionCardComp.ts b/assets/script/game/map/MissionCardComp.ts index a6f380cf..fc404603 100644 --- a/assets/script/game/map/MissionCardComp.ts +++ b/assets/script/game/map/MissionCardComp.ts @@ -49,6 +49,7 @@ import { FacSet, FightSet } from "../common/config/GameSet"; import { MoveComp } from "../hero/MoveComp"; import { MissionHeroCompComp } from "./MissionHeroComp"; import { TalentType } from "../common/config/TalentSet"; +import { MissionEconomy } from "./MissionEconomy"; const { ccclass, property } = _decorator; @@ -315,24 +316,15 @@ export class MissionCardComp extends CCComp { /** * 金币变化事件回调: - * - syncOnly=true:仅同步 UI 显示(金币已被外部修改过)。 - * - 否则:累加 delta 到 mission_data.coin 后刷新 UI。 + * 仅负责 UI 更新和动画表现。数据更新已由 MissionEconomy 统一处理。 */ private onCoinAdd(event: string, args: any){ const payload = args ?? event; - if (payload?.syncOnly) { - this.updateCoinAndCostUI(); - this.playCoinChangeAnim((payload?.delta ?? 0) > 0); - return; - } const v = typeof payload === 'number' ? payload : (payload?.delta ?? payload?.value ?? 0); - if (v === 0) return; - this.setMissionCoin(this.getMissionCoin() + v); - // 【评分系统 - 效率分】精确统计整局游戏的总收入与额外支出(如卖卡、技能扣费等) - if (v > 0) smc.vmdata.scores.gold_earned += v; - else smc.vmdata.scores.gold_spent -= v; this.updateCoinAndCostUI(); - this.playCoinChangeAnim(v > 0); + if (v !== 0) { + this.playCoinChangeAnim(v > 0); + } } /** 战斗开始:不收起面板,不再强制清空卡牌 */ @@ -583,27 +575,22 @@ export class MissionCardComp extends CCComp { // oops.gui.toast("战斗阶段无法抽卡"); // return; // } - const cost = this.getRefreshCost(); - const currentCoin = this.getMissionCoin(); - if (currentCoin < cost) { + const cost = MissionEconomy.getRefreshCost(this.refreshCost); + const success = MissionEconomy.executeRefresh(this.refreshCost); + if (!success) { oops.gui.toast(`金币不足,刷新需要${cost}`); this.updateCoinAndCostUI(); mLogger.log(this.debugMode, "MissionCardComp", "draw coin not enough", { - currentCoin, + currentCoin: MissionEconomy.getCoin(), cost }); return; } - this.setMissionCoin(currentCoin - cost); - // 【评分系统 - 效率分】记录因刷新卡池消耗的金币,以及刷新次数 - smc.vmdata.scores.gold_spent += cost; - smc.vmdata.scores.refresh_count++; - this.playCoinChangeAnim(false); - this.updateCoinAndCostUI(); + mLogger.log(this.debugMode, "MissionCardComp", "click draw", { poolLv: this.poolLv, cost, - leftCoin: this.getMissionCoin() + leftCoin: MissionEconomy.getCoin() }); this.layoutCardSlots(); const cards = this.buildDrawCards(); @@ -797,12 +784,12 @@ export class MissionCardComp extends CCComp { } private canUpPool() { if (this.poolLv >= CARD_POOL_MAX_LEVEL) return false; - const currentCoin = this.getMissionCoin(); + const currentCoin = MissionEconomy.getCoin(); return currentCoin >= this.getUpgradeCost(this.poolLv); } private canDrawCards() { - return this.getMissionCoin() >= this.getRefreshCost(); + return MissionEconomy.getCoin() >= MissionEconomy.getRefreshCost(this.refreshCost); } /** 更新升级按钮上的等级文案,反馈当前卡池层级 */ private updatePoolLvUI() { @@ -860,7 +847,7 @@ export class MissionCardComp extends CCComp { const coinNode = this.cards_chou.getChildByName("coin"); const numLabel = coinNode?.getChildByName("num")?.getComponent(Label); if (numLabel) { - numLabel.string = `${this.getRefreshCost()}`; + numLabel.string = `${MissionEconomy.getRefreshCost(this.refreshCost)}`; } } @@ -887,12 +874,7 @@ export class MissionCardComp extends CCComp { return Math.max(0, baseCost - discount); } - private getRefreshCost(): number { - let cost = this.refreshCost; - const discount = HeroAttrsComp.getTalentValue(TalentType.RefreshDiscount); - cost = Math.max(0, cost - discount); - return Math.floor(cost); - } + private clearHeroInfoPanels() { if (this.cachedHInfoComps) { @@ -1050,21 +1032,14 @@ export class MissionCardComp extends CCComp { return Math.max(0, Math.floor(missionData?.hero_num ?? 0)); } - private getMissionCoin(): number { - const missionData = this.getMissionData(); - return Math.max(0, Math.floor(missionData?.coin ?? 0)); - } + private getCurrentWave(): number { const missionData = this.getMissionData(); return Math.max(1, Math.floor(missionData?.level ?? 1)); } - private setMissionCoin(value: number) { - const missionData = this.getMissionData(); - if (!missionData) return; - missionData.coin = Math.max(0, Math.floor(value)); - } + private getMissionHeroMaxNum(): number { const missionData = this.getMissionData(); diff --git a/assets/script/game/map/MissionComp.ts b/assets/script/game/map/MissionComp.ts index b64edbe1..db480de7 100644 --- a/assets/script/game/map/MissionComp.ts +++ b/assets/script/game/map/MissionComp.ts @@ -47,6 +47,7 @@ import { CardInitCoins } from "../common/config/CardSet"; import { Timer } from "db://oops-framework/core/common/timer/Timer"; import { FieldSkillType } from "../common/config/SkillSet"; import { spawningEngine } from "./RogueConfig"; +import { MissionEconomy } from "./MissionEconomy"; const { ccclass, property } = _decorator; /** 任务(关卡)生命周期阶段 */ @@ -795,23 +796,11 @@ export class MissionComp extends CCComp { if (wave <= 1) return; if (wave <= this.lastPrepareCoinWave) return; - let reward = Math.max(0, Math.floor(this.prepareBaseCoinReward)); + // 使用统一经济管理入口发放每波金币 + const reward = MissionEconomy.executeWaveGold(this.prepareBaseCoinReward); - // 增加驻场技能金币收益 - const goldBoost = HeroAttrsComp.getFieldSkillTotalValue(FieldSkillType.WaveGold); - reward += goldBoost; - - if (reward <= 0) { - this.lastPrepareCoinWave = wave; - return; - } - smc.vmdata.mission_data.coin = Math.max(0, Math.floor((smc.vmdata.mission_data.coin ?? 0) + reward)); - // 【评分系统 - 效率分】记录每波次发放的金币奖励收入 - smc.vmdata.scores.gold_earned += reward; this.lastPrepareCoinWave = wave; - oops.message.dispatchEvent(GameEvent.CoinAdd, { delta: reward, syncOnly: true }); - - mLogger.log(this.debugMode, "MissionComp", "grantPrepareCoinByWave", { wave, reward, boost: goldBoost, coin: smc.vmdata.mission_data.coin }); + mLogger.log(this.debugMode, "MissionComp", "grantPrepareCoinByWave", { wave, reward, coin: smc.vmdata.mission_data.coin }); } // ======================== 怪物数量管理 ======================== diff --git a/assets/script/game/map/MissionEconomy.ts b/assets/script/game/map/MissionEconomy.ts new file mode 100644 index 00000000..bcb7b1d0 --- /dev/null +++ b/assets/script/game/map/MissionEconomy.ts @@ -0,0 +1,112 @@ +import { smc } from "../common/SingletonModuleComp"; +import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops"; +import { GameEvent } from "../common/config/GameEvent"; +import { HeroAttrsComp } from "../hero/HeroAttrsComp"; +import { FieldSkillType } from "../common/config/SkillSet"; +import { TalentType } from "../common/config/TalentSet"; +import { FightSet } from "../common/config/GameSet"; + +/** + * 局内经济统一管理类 + * 负责统一处理金币的增减、各种费用的计算以及战绩评分中的金币统计。 + */ +export class MissionEconomy { + /** 获取当前金币 */ + static getCoin(): number { + return Math.max(0, Math.floor(smc.vmdata.mission_data.coin ?? 0)); + } + + /** 增加金币并更新统计 */ + static addCoin(amount: number) { + if (amount <= 0) return; + amount = Math.floor(amount); + smc.vmdata.mission_data.coin = this.getCoin() + amount; + smc.vmdata.scores.gold_earned += amount; + + // 发送 UI 更新事件,这里我们统一使用 syncOnly 通知 UI 刷新即可 + oops.message.dispatchEvent(GameEvent.CoinAdd, { delta: amount, syncOnly: true }); + } + + /** 消费金币并更新统计 */ + static spendCoin(amount: number): boolean { + if (amount <= 0) return true; + amount = Math.floor(amount); + const current = this.getCoin(); + if (current < amount) return false; + + smc.vmdata.mission_data.coin = current - amount; + smc.vmdata.scores.gold_spent += amount; + + // 发送 UI 更新事件 + oops.message.dispatchEvent(GameEvent.CoinAdd, { delta: -amount, syncOnly: true }); + return true; + } + + /** + * 计算卡牌刷新费用 + * @param baseCost 基础费用,默认为1 + */ + static getRefreshCost(baseCost: number = 1): number { + let cost = baseCost; + const discount = HeroAttrsComp.getTalentValue(TalentType.RefreshDiscount); + cost = Math.max(0, cost - discount); + return Math.floor(cost); + } + + /** + * 执行刷新卡牌并扣除金币 + */ + static executeRefresh(baseCost: number = 1): boolean { + const cost = this.getRefreshCost(baseCost); + const success = this.spendCoin(cost); + if (success) { + smc.vmdata.scores.refresh_count++; + } + return success; + } + + /** + * 计算英雄出售金币 + */ + static getSellGold(): number { + const baseSellGold = 1; // 基础卖出金币 + const goldBoost = HeroAttrsComp.getFieldSkillTotalValue(FieldSkillType.SellGold); + let totalSellGold = baseSellGold + goldBoost; + // 应用天赋 SellBonus (增加数值) + const bonusGold = HeroAttrsComp.getTalentValue(TalentType.SellBonus); + if (bonusGold > 0) { + totalSellGold += bonusGold; + } + return Math.floor(totalSellGold); + } + + /** + * 执行出售英雄并增加金币 + */ + static executeSellHero(): number { + const gold = this.getSellGold(); + this.addCoin(gold); + return gold; + } + + /** + * 计算每波基础金币收益 + */ + static getWaveGold(baseReward: number): number { + let reward = Math.max(0, Math.floor(baseReward)); + const goldBoost = HeroAttrsComp.getFieldSkillTotalValue(FieldSkillType.WaveGold); + reward += goldBoost; + return reward; + } + + /** + * 执行发放每波金币 + */ + static executeWaveGold(baseReward: number): number { + const reward = this.getWaveGold(baseReward); + if (reward > 0) { + this.addCoin(reward); + } + return reward; + } +} diff --git a/assets/script/game/map/MissionEconomy.ts.meta b/assets/script/game/map/MissionEconomy.ts.meta new file mode 100644 index 00000000..cfd650d8 --- /dev/null +++ b/assets/script/game/map/MissionEconomy.ts.meta @@ -0,0 +1,9 @@ +{ + "ver": "4.0.24", + "importer": "typescript", + "imported": true, + "uuid": "49695a42-7cc6-457d-8370-0aaa398fb0f4", + "files": [], + "subMetas": {}, + "userData": {} +}