refactor: 将刷新石替换为银币作为卡牌刷新消耗
1. 重构全局配置,移除刷新石相关定义,新增银币刷新消耗常量 2. 新增局外持久货币银币的数据结构与管理逻辑 3. 重构卡牌刷新经济系统,统一使用银币进行刷新消耗 4. 更新UI显示与事件通知,适配银币系统变更 5. 调整清屏奖励逻辑,将刷新石奖励改为金币奖励
This commit is contained in:
@@ -21,6 +21,8 @@ export interface GameDate {
|
||||
mission?: number,
|
||||
diamond?: number,
|
||||
gold?: number,
|
||||
/** 银币:局外持久货币,用于局内刷新英雄卡牌,仅通过日常任务等途径积攒 */
|
||||
silver?: number,
|
||||
task?: number,
|
||||
noStop?: boolean,
|
||||
showInfo?: boolean,
|
||||
@@ -110,6 +112,8 @@ export class SingletonModuleComp extends ecs.Comp {
|
||||
mission: 1,
|
||||
diamond: 100, //商店购买 及 双倍奖励资源
|
||||
gold: 1000,
|
||||
/** 银币:刷新英雄卡牌专用,每局不重置,仅日常积攒 */
|
||||
silver: 0,
|
||||
task: 0,
|
||||
noStop: false,
|
||||
showInfo: true,
|
||||
@@ -157,7 +161,6 @@ export class SingletonModuleComp extends ecs.Comp {
|
||||
level: 1,//关卡等级
|
||||
max_mission: 4,//最大关卡
|
||||
coin: 0,
|
||||
refresh_stone: 0,//刷新石(刷新卡池时优先消耗,不足时消耗金币)
|
||||
time: 15 * 60,//游戏时间
|
||||
},
|
||||
scores: {
|
||||
@@ -216,6 +219,7 @@ export class SingletonModuleComp extends ecs.Comp {
|
||||
|
||||
gold: 0, // 金币数据(MVVM绑定字段,镜像 data.gold)
|
||||
diamond: 0, // 钻石数据(MVVM绑定字段,镜像 data.diamond)
|
||||
silver: 0, // 银币数据(MVVM绑定字段,镜像 data.silver,刷新卡牌消耗)
|
||||
switch_effect: true, // 音效开关(MVVM绑定字段)
|
||||
switch_music: true, // 音乐开关(MVVM绑定字段)
|
||||
};
|
||||
@@ -324,6 +328,7 @@ export class SingletonModuleComp extends ecs.Comp {
|
||||
public syncCurrencyToView(): void {
|
||||
this.vmdata.gold = this.data.gold ?? 0;
|
||||
this.vmdata.diamond = this.data.diamond ?? 0;
|
||||
this.vmdata.silver = this.data.silver ?? 0;
|
||||
}
|
||||
getGameDate() {
|
||||
let data: GameDate = {
|
||||
@@ -363,6 +368,22 @@ export class SingletonModuleComp extends ecs.Comp {
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* 变更银币(正数获得 / 负数消耗),以 data 为权威源并镜像到 vmdata。
|
||||
* Why: 银币为局外持久货币,仅用于刷新英雄卡牌,日常任务等途径积攒。
|
||||
* @param silver 变动量
|
||||
* @param is_sync 是否标记脏并触发云端/本地同步
|
||||
*/
|
||||
updateSilver(silver: number, is_sync: boolean = true) {
|
||||
this.data.silver = Math.max(0, (this.data.silver ?? 0) + silver);
|
||||
this.vmdata.silver = this.data.silver;
|
||||
if (is_sync) {
|
||||
gameDataSync.markDataDirty();
|
||||
}
|
||||
oops.message.dispatchEvent(GameEvent.SILVER_UPDATE)
|
||||
return true
|
||||
}
|
||||
|
||||
updateSwitchEffect(isOpen: boolean, is_sync: boolean = true) {
|
||||
this.vmdata.switch_effect = isOpen;
|
||||
if (oops.audio) oops.audio.switchEffect = isOpen;
|
||||
|
||||
@@ -79,7 +79,7 @@ export enum GameEvent {
|
||||
UpdateMissionGet = "UpdateMissionGet",
|
||||
GlobalAttrChange = "GlobalAttrChange",
|
||||
CoinAdd = "CoinAdd",
|
||||
RefreshStone = "RefreshStone", // 刷新石数量变更事件
|
||||
SILVER_UPDATE = "SILVER_UPDATE", // 银币数量变更事件(刷新卡牌消耗)
|
||||
ShowSmallTip = "ShowSmallTip",
|
||||
CardPoolUpgrade = "CardPoolUpgrade",
|
||||
TriggerSkill = "TriggerSkill", // 瞬间触发施法事件
|
||||
|
||||
@@ -73,9 +73,8 @@ export enum FightSet {
|
||||
REFRESH_COST = 2,
|
||||
BASE_COST = 5,
|
||||
INIT_COIN = 7, // 初始金币数
|
||||
INIT_REFRESH_STONE = 3, // 初始刷新石数量
|
||||
/** 单次刷新消耗的刷新石数量 */
|
||||
REFRESH_STONE_COST = 1,
|
||||
/** 单次刷新卡牌消耗的银币数量 */
|
||||
SILVER_REFRESH_COST = 1,
|
||||
/** 全局默认闪避率(百分点),heroSet 未配置时生效 */
|
||||
DEFAULT_DODGE = 15,
|
||||
/** 全局默认命中率(百分点),heroSet 未配置时生效 */
|
||||
|
||||
@@ -25,6 +25,8 @@ const { ccclass, property } = _decorator;
|
||||
const FAST_CLEAR_COIN = 2;
|
||||
/** 清屏奖励:极速清场(< 50% 时长) */
|
||||
const ULTRA_CLEAR_COIN = 5;
|
||||
/** 清屏奖励:全员存活(allAlive)额外金币 */
|
||||
const ALL_ALIVE_COIN = 3;
|
||||
/** 连杀分级金币爆发(tier 0/1/2 对应 5/10/20 连杀) */
|
||||
const COMBO_COIN = [2, 5, 10];
|
||||
|
||||
@@ -58,7 +60,7 @@ export class BattleBannerComp extends CCComp {
|
||||
private onWaveClear(event: string, data: { wave: number; clearTime: number; allAlive: boolean; fastClear: number }) {
|
||||
if (data.allAlive) {
|
||||
this.playBanner("Perfect!", new Color(255, 80, 80), 1.2);
|
||||
MissionEconomy.addRefreshStone(1);
|
||||
MissionEconomy.addCoin(ALL_ALIVE_COIN);
|
||||
oops.audio.playEffect("music/flash");
|
||||
} else if (data.fastClear === 2) {
|
||||
this.playBanner("极速清场!", new Color(255, 170, 0), 1.15);
|
||||
|
||||
@@ -81,8 +81,6 @@ export class MissionCardComp extends CCComp {
|
||||
private readonly buttonPressScale: number = 0.94;
|
||||
/** 按钮弹起缩放(峰值) */
|
||||
private readonly buttonClickScale: number = 1.06;
|
||||
/** 抽卡(刷新)费用 */
|
||||
refreshCost: number = FightSet.REFRESH_COST;
|
||||
/** 卡牌面板展开/收起动画时长(秒) */
|
||||
cardsPanelMoveDuration: number = 0.2;
|
||||
|
||||
@@ -170,7 +168,7 @@ export class MissionCardComp extends CCComp {
|
||||
/** 英雄数量显示节点(含 icon + num 子节点) */
|
||||
@property(Node)
|
||||
hero_num_node: Node = null!
|
||||
/** 刷新石数量显示节点(含 icon + num 子节点) */
|
||||
/** 银币数量显示节点(含 icon + num 子节点) */
|
||||
@property(Node)
|
||||
refresh_stone_num_node: Node = null!
|
||||
|
||||
@@ -330,6 +328,7 @@ export class MissionCardComp extends CCComp {
|
||||
this.resetButtonScale(this.cards_refresh);
|
||||
this.resetPanelOpenCosts();
|
||||
this.updateCoinAndCostUI();
|
||||
this.updateSilverNumUI();
|
||||
this.updateHeroNumUI(false, false);
|
||||
if (this.node && this.node.isValid) {
|
||||
this.node.active = true;
|
||||
@@ -416,7 +415,7 @@ export class MissionCardComp extends CCComp {
|
||||
this.on("PhasePrepareStart", this.onPhasePrepareStart, this);
|
||||
|
||||
oops.message.on(GameEvent.CoinAdd, this.onCoinAdd, this);
|
||||
oops.message.on(GameEvent.RefreshStone, this.onRefreshStone, this);
|
||||
oops.message.on(GameEvent.SILVER_UPDATE, this.onSilverUpdate, this);
|
||||
oops.message.on(GameEvent.MasterCalled, this.onMasterCalled, this);
|
||||
oops.message.on(GameEvent.HeroDead, this.onHeroDead, this);
|
||||
oops.message.on(GameEvent.HeroSell, this.onHeroSell, this);
|
||||
@@ -477,13 +476,14 @@ export class MissionCardComp extends CCComp {
|
||||
}
|
||||
}
|
||||
|
||||
/** 刷新石数量变更:刷新刷新按钮状态/费用显示,并播放数量变化动画 */
|
||||
private onRefreshStone(event: string, args: any) {
|
||||
/** 银币数量变更:刷新银币数值显示 + 刷新按钮状态/费用显示,并播放数量变化动画 */
|
||||
private onSilverUpdate(event: string, args: any) {
|
||||
const payload = args ?? event;
|
||||
const v = typeof payload === 'number' ? payload : (payload?.delta ?? payload?.value ?? 0);
|
||||
this.updateSilverNumUI();
|
||||
this.updateDrawCostUI();
|
||||
if (v !== 0) {
|
||||
this.playRefreshStoneChangeAnim(v > 0);
|
||||
this.playSilverChangeAnim(v > 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -506,9 +506,10 @@ export class MissionCardComp extends CCComp {
|
||||
* 挂在 showHeros / showEquips / showSkills / showShop 按钮节点(按钮下需预置 smalltip 子节点)
|
||||
* @param text 可选:覆盖气泡文字(默认读 prefab 中配置的文本)
|
||||
*/
|
||||
public showSmallTip(type: "refresh_coin" | "buy_coin" | "hero_full" | "panel_hero_full" | "panel_equip_full" | "panel_skill_full" | "panel_shop_full", text?: string) {
|
||||
public showSmallTip(type: "refresh_silver" | "refresh_coin" | "buy_coin" | "hero_full" | "panel_hero_full" | "panel_equip_full" | "panel_skill_full" | "panel_shop_full", text?: string) {
|
||||
let targetNode: Node | null = null;
|
||||
switch (type) {
|
||||
case "refresh_silver":
|
||||
case "refresh_coin":
|
||||
targetNode = this.cards_refresh;
|
||||
break;
|
||||
@@ -673,7 +674,7 @@ export class MissionCardComp extends CCComp {
|
||||
/** 解除按钮监听,避免节点销毁后回调泄漏 */
|
||||
private unbindEvents() {
|
||||
oops.message.off(GameEvent.CoinAdd, this.onCoinAdd, this);
|
||||
oops.message.off(GameEvent.RefreshStone, this.onRefreshStone, this);
|
||||
oops.message.off(GameEvent.SILVER_UPDATE, this.onSilverUpdate, this);
|
||||
oops.message.off(GameEvent.MasterCalled, this.onMasterCalled, this);
|
||||
oops.message.off(GameEvent.HeroDead, this.onHeroDead, this);
|
||||
oops.message.off(GameEvent.HeroSell, this.onHeroSell, this);
|
||||
@@ -1447,10 +1448,9 @@ export class MissionCardComp extends CCComp {
|
||||
this.playButtonResetAnim(this.skill_refresh);
|
||||
}
|
||||
|
||||
/** 装备刷新:扣费后重新抽取 3 张装备展示 */
|
||||
/** 装备刷新:扣银币后重新抽取 3 张装备展示 */
|
||||
private onClickEquipRefresh() {
|
||||
const cost = MissionEconomy.getRefreshCost(this.refreshCost);
|
||||
const success = MissionEconomy.executeRefresh(this.refreshCost);
|
||||
const success = MissionEconomy.executeRefresh();
|
||||
if (!success) {
|
||||
this.showSmallTip("refresh_coin");
|
||||
return;
|
||||
@@ -1458,10 +1458,9 @@ export class MissionCardComp extends CCComp {
|
||||
this.populateEquipments();
|
||||
}
|
||||
|
||||
/** 药品刷新:扣费后重新抽取 3 张商品展示 */
|
||||
/** 药品刷新:扣银币后重新抽取 3 张商品展示 */
|
||||
private onClickShopRefresh() {
|
||||
const cost = MissionEconomy.getRefreshCost(this.refreshCost);
|
||||
const success = MissionEconomy.executeRefresh(this.refreshCost);
|
||||
const success = MissionEconomy.executeRefresh();
|
||||
if (!success) {
|
||||
this.showSmallTip("refresh_coin");
|
||||
return;
|
||||
@@ -1469,9 +1468,9 @@ export class MissionCardComp extends CCComp {
|
||||
this.populateShopItems();
|
||||
}
|
||||
|
||||
/** 技能刷新:扣费后重新抽取 3 张技能卡展示 */
|
||||
/** 技能刷新:扣银币后重新抽取 3 张技能卡展示 */
|
||||
private onClickSkillRefresh() {
|
||||
const success = MissionEconomy.executeRefresh(this.refreshCost);
|
||||
const success = MissionEconomy.executeRefresh();
|
||||
if (!success) {
|
||||
this.showSmallTip("refresh_coin");
|
||||
return;
|
||||
@@ -1568,18 +1567,18 @@ export class MissionCardComp extends CCComp {
|
||||
|
||||
/**
|
||||
* 刷新卡池按钮核心逻辑:
|
||||
* 1. 检查金币/刷新石是否足够 → 不够则 toast 提示。
|
||||
* 2. 扣除费用、播放金币动画。
|
||||
* 1. 检查银币是否足够 → 不够则 toast 提示。
|
||||
* 2. 扣除银币费用。
|
||||
* 3. 重新布局槽位 → 从卡池构建 3 张卡 → 分发到槽位(三选一展示)。
|
||||
*/
|
||||
private onClickDraw() {
|
||||
const cost = MissionEconomy.getRefreshCost(this.refreshCost);
|
||||
const success = MissionEconomy.executeRefresh(this.refreshCost);
|
||||
const cost = MissionEconomy.getSilverRefreshCost();
|
||||
const success = MissionEconomy.executeRefresh();
|
||||
if (!success) {
|
||||
this.showSmallTip("refresh_coin");
|
||||
this.showSmallTip("refresh_silver", "银币不足");
|
||||
this.updateCoinAndCostUI();
|
||||
mLogger.log(this.debugMode, "MissionCardComp", "draw coin not enough", {
|
||||
currentCoin: MissionEconomy.getCoin(),
|
||||
mLogger.log(this.debugMode, "MissionCardComp", "draw silver not enough", {
|
||||
currentSilver: MissionEconomy.getSilver(),
|
||||
cost
|
||||
});
|
||||
return;
|
||||
@@ -1587,7 +1586,7 @@ export class MissionCardComp extends CCComp {
|
||||
|
||||
mLogger.log(this.debugMode, "MissionCardComp", "click refresh", {
|
||||
cost,
|
||||
leftCoin: MissionEconomy.getCoin()
|
||||
leftSilver: MissionEconomy.getSilver()
|
||||
});
|
||||
this.layoutCardSlots();
|
||||
const cards = this.buildDrawCards();
|
||||
@@ -1626,8 +1625,10 @@ export class MissionCardComp extends CCComp {
|
||||
}
|
||||
// 开局三选一期满后永久隐藏 showHeros(战前限定,不随阶段恢复)
|
||||
this.updateShowHerosVisibility();
|
||||
// 刷新所有刷新按钮的费用显示(含刷新石/金币切换与置灰状态)
|
||||
// 刷新所有刷新按钮的费用显示(含银币置灰状态)
|
||||
this.updateDrawCostUI();
|
||||
// 同步银币数量显示(阶段切换时确保数值最新)
|
||||
this.updateSilverNumUI();
|
||||
// 显示卡牌面板(默认进入准备阶段时展开,缩放放大到 1,点亮按钮 active 高亮)
|
||||
if (this.cardPanNode && this.cardPanNode.isValid) {
|
||||
this.showCardsPanel();
|
||||
@@ -1851,17 +1852,17 @@ export class MissionCardComp extends CCComp {
|
||||
}
|
||||
|
||||
private canDrawCards() {
|
||||
// 有刷新石时可直接刷新,否则校验金币是否足够
|
||||
return MissionEconomy.canRefresh(this.refreshCost);
|
||||
// 银币足够时才可刷新
|
||||
return MissionEconomy.canRefresh();
|
||||
}
|
||||
|
||||
private updateDrawCostUI() {
|
||||
const stones = MissionEconomy.getRefreshStone();
|
||||
const stoneCost = MissionEconomy.getRefreshStoneCost();
|
||||
this.updateOneRefreshBtnUI(this.cards_refresh, stones, stoneCost);
|
||||
this.updateOneRefreshBtnUI(this.equip_refresh, stones, stoneCost);
|
||||
this.updateOneRefreshBtnUI(this.shop_refresh, stones, stoneCost);
|
||||
this.updateOneRefreshBtnUI(this.skill_refresh, stones, stoneCost);
|
||||
const silver = MissionEconomy.getSilver();
|
||||
const silverCost = MissionEconomy.getSilverRefreshCost();
|
||||
this.updateOneRefreshBtnUI(this.cards_refresh, silver, silverCost);
|
||||
this.updateOneRefreshBtnUI(this.equip_refresh, silver, silverCost);
|
||||
this.updateOneRefreshBtnUI(this.shop_refresh, silver, silverCost);
|
||||
this.updateOneRefreshBtnUI(this.skill_refresh, silver, silverCost);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1871,50 +1872,42 @@ export class MissionCardComp extends CCComp {
|
||||
* - 背景 :按钮底图
|
||||
* - nobg :置灰遮罩,不可刷新时激活
|
||||
* - Node/ :费用容器,下含 Label + coin + stone
|
||||
* - coin/ :金币费用(含 num 子节点 Label),刷新石=0 时显示
|
||||
* - stone/ :刷新石费用(含 num 子节点 Label),刷新石>0 时显示
|
||||
* - coin/ :金币费用(含 num 子节点 Label),银币机制下隐藏
|
||||
* - stone/ :银币数量(含 num 子节点 Label),显示当前持有银币数
|
||||
*
|
||||
* @param btnNode 刷新按钮节点
|
||||
* @param stones 当前刷新石数量(外部统一读取,避免 4 次重复访问)
|
||||
* @param stoneCost 单次刷新消耗的刷新石数量
|
||||
* @param silver 当前银币数量(外部统一读取,避免 4 次重复访问)
|
||||
* @param silverCost 单次刷新消耗的银币数量(仅用于判断是否置灰)
|
||||
*/
|
||||
private updateOneRefreshBtnUI(btnNode: Node | null, stones: number, stoneCost: number) {
|
||||
private updateOneRefreshBtnUI(btnNode: Node | null, silver: number, silverCost: number) {
|
||||
if (!btnNode || !btnNode.isValid) return;
|
||||
|
||||
// 刷新石足够一次消耗时走刷新石通道,否则走金币通道
|
||||
const useStone = stones >= stoneCost;
|
||||
// 银币足够一次消耗时走银币通道
|
||||
const useSilver = silver >= silverCost;
|
||||
|
||||
// 置灰遮罩:有刷新石必定可刷新,否则按金币判断
|
||||
// 置灰遮罩:银币不足时置灰
|
||||
const nobg = btnNode.getChildByName("nobg");
|
||||
if (nobg) {
|
||||
nobg.active = useStone ? false : !this.canDrawCards();
|
||||
nobg.active = !useSilver;
|
||||
}
|
||||
|
||||
// 费用容器:按钮下的 Node 子节点(统一结构:背景 + Node[Label/coin/stone])
|
||||
const container = btnNode.getChildByName("Node");
|
||||
if (!container) return;
|
||||
|
||||
// 金币费用节点
|
||||
// 金币费用节点:银币机制下隐藏,不再显示金币费用
|
||||
const coinNode = container.getChildByName("coin");
|
||||
if (coinNode) {
|
||||
coinNode.active = !useStone;
|
||||
if (!useStone) {
|
||||
const numLabel = coinNode.getChildByName("num")?.getComponent(Label);
|
||||
if (numLabel) {
|
||||
numLabel.string = `${MissionEconomy.getRefreshCost(this.refreshCost)}`;
|
||||
}
|
||||
}
|
||||
coinNode.active = false;
|
||||
}
|
||||
|
||||
// 刷新石费用节点(显示单次刷新消耗数量)
|
||||
// 银币费用节点(复用 stone 子节点结构,显示当前持有银币数量)
|
||||
const stoneNode = container.getChildByName("stone");
|
||||
if (stoneNode) {
|
||||
stoneNode.active = useStone;
|
||||
if (useStone) {
|
||||
const numLabel = stoneNode.getChildByName("num")?.getComponent(Label);
|
||||
if (numLabel) {
|
||||
numLabel.string = `${stoneCost}`;
|
||||
}
|
||||
stoneNode.active = true;
|
||||
const numLabel = stoneNode.getChildByName("num")?.getComponent(Label);
|
||||
if (numLabel) {
|
||||
numLabel.string = `${silver}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1930,6 +1923,17 @@ export class MissionCardComp extends CCComp {
|
||||
}
|
||||
}
|
||||
|
||||
/** 刷新银币数量显示(refresh_stone_num_node 下的 num Label),未绑定或节点失效时静默跳过 */
|
||||
private updateSilverNumUI() {
|
||||
if (!this.refresh_stone_num_node || !this.refresh_stone_num_node.isValid) return;
|
||||
const numNode = this.refresh_stone_num_node.getChildByName("num");
|
||||
if (!numNode || !numNode.isValid) return;
|
||||
const label = numNode.getComponent(Label);
|
||||
if (label) {
|
||||
label.string = `${MissionEconomy.getSilver()}`;
|
||||
}
|
||||
}
|
||||
|
||||
private playCoinChangeAnim(isIncrease: boolean) {
|
||||
if (!this.coins_node || !this.coins_node.isValid) return;
|
||||
const icon = this.coins_node.getChildByName("icon");
|
||||
@@ -1941,8 +1945,8 @@ export class MissionCardComp extends CCComp {
|
||||
this.playHeroNumNodePop(num, peak);
|
||||
}
|
||||
|
||||
/** 刷新石计数变化动画(与金币一致的 icon+num 弹跳) */
|
||||
private playRefreshStoneChangeAnim(isIncrease: boolean) {
|
||||
/** 银币计数变化动画(与金币一致的 icon+num 弹跳) */
|
||||
private playSilverChangeAnim(isIncrease: boolean) {
|
||||
if (!this.refresh_stone_num_node || !this.refresh_stone_num_node.isValid) return;
|
||||
const peak = isIncrease ? 1.2 : 1.2;
|
||||
const icon = this.refresh_stone_num_node.getChildByName("icon");
|
||||
|
||||
@@ -830,9 +830,7 @@ export class MissionComp extends CCComp {
|
||||
smc.resetScores();
|
||||
|
||||
smc.vmdata.mission_data.coin = Math.max(0, Math.floor(FightSet.INIT_COIN));
|
||||
// 初始化刷新石数量,并派发事件通知 UI 刷新(MissionStart 早于 data_init,需手动通知)
|
||||
smc.vmdata.mission_data.refresh_stone = Math.max(0, Math.floor(FightSet.INIT_REFRESH_STONE));
|
||||
oops.message.dispatchEvent(GameEvent.RefreshStone, { delta: FightSet.INIT_REFRESH_STONE });
|
||||
// 银币为局外持久货币,每局不重置,仅通过日常积攒,无需初始化
|
||||
// 【评分系统 - 效率分】记录初始获得的金币收入
|
||||
smc.vmdata.scores.gold_earned += smc.vmdata.mission_data.coin;
|
||||
}
|
||||
|
||||
@@ -39,68 +39,45 @@ export class MissionEconomy {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算卡牌刷新费用
|
||||
* @param baseCost 基础费用,默认为1
|
||||
*/
|
||||
static getRefreshCost(baseCost: number = 1): number {
|
||||
return Math.floor(Math.max(0, baseCost));
|
||||
}
|
||||
|
||||
/** 获取当前刷新石数量 */
|
||||
static getRefreshStone(): number {
|
||||
return Math.max(0, Math.floor(smc.vmdata.mission_data.refresh_stone ?? 0));
|
||||
/** 获取当前银币数量(局外持久货币,刷新卡牌消耗) */
|
||||
static getSilver(): number {
|
||||
return Math.max(0, Math.floor(smc.vmdata.silver ?? 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加刷新石
|
||||
* 增加银币
|
||||
* @param amount 增加数量,<=0 时忽略
|
||||
*/
|
||||
static addRefreshStone(amount: number) {
|
||||
static addSilver(amount: number) {
|
||||
if (amount <= 0) return;
|
||||
amount = Math.floor(amount);
|
||||
smc.vmdata.mission_data.refresh_stone = this.getRefreshStone() + amount;
|
||||
|
||||
// 发送 UI 更新事件(复用 RefreshStone 事件通知刷新按钮状态刷新)
|
||||
oops.message.dispatchEvent(GameEvent.RefreshStone, { delta: amount });
|
||||
smc.updateSilver(Math.floor(amount));
|
||||
}
|
||||
|
||||
/** 单次刷新消耗的刷新石数量 */
|
||||
static getRefreshStoneCost(): number {
|
||||
return Math.max(1, Math.floor(FightSet.REFRESH_STONE_COST));
|
||||
/** 单次刷新消耗的银币数量 */
|
||||
static getSilverRefreshCost(): number {
|
||||
return Math.max(1, Math.floor(FightSet.SILVER_REFRESH_COST));
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断当前是否可以执行一次刷新(刷新石足够或金币足够)
|
||||
* 判断当前是否可以执行一次刷新(银币足够)
|
||||
*/
|
||||
static canRefresh(baseCost: number = 1): boolean {
|
||||
if (this.getRefreshStone() >= this.getRefreshStoneCost()) return true;
|
||||
return this.getCoin() >= this.getRefreshCost(baseCost);
|
||||
static canRefresh(): boolean {
|
||||
return this.getSilver() >= this.getSilverRefreshCost();
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行刷新卡牌:
|
||||
* 1. 刷新石足够时优先扣除 REFRESH_STONE_COST 颗刷新石(不消耗金币)。
|
||||
* 2. 刷新石不足时扣除金币(含刷新优惠折扣)。
|
||||
* 银币足够时扣除 SILVER_REFRESH_COST 枚银币,否则刷新失败。
|
||||
* Why: 英雄卡牌只能银币刷新,不能金币刷新,银币为局外持久货币,靠日常积攒。
|
||||
*/
|
||||
static executeRefresh(baseCost: number = 1): boolean {
|
||||
// 优先消耗刷新石
|
||||
const stoneCost = this.getRefreshStoneCost();
|
||||
const stones = this.getRefreshStone();
|
||||
if (stones >= stoneCost) {
|
||||
smc.vmdata.mission_data.refresh_stone = stones - stoneCost;
|
||||
smc.vmdata.scores.refresh_count++;
|
||||
oops.message.dispatchEvent(GameEvent.RefreshStone, { delta: -stoneCost });
|
||||
return true;
|
||||
}
|
||||
static executeRefresh(): boolean {
|
||||
const cost = this.getSilverRefreshCost();
|
||||
const silver = this.getSilver();
|
||||
if (silver < cost) return false;
|
||||
|
||||
// 刷新石不足 → 扣除金币
|
||||
const cost = this.getRefreshCost(baseCost);
|
||||
const success = this.spendCoin(cost);
|
||||
if (success) {
|
||||
smc.vmdata.scores.refresh_count++;
|
||||
}
|
||||
return success;
|
||||
smc.updateSilver(-cost);
|
||||
smc.vmdata.scores.refresh_count++;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user