Files
pixelheros/assets/script/game/map/MissionEconomy.ts
panFD 4eba1c8ad8 feat: 重构英雄成长系统,支持差异化成长曲线与无限升级
1. 新增英雄成长类型枚举与系数表,实现坦克/战士/刺客等差异化成长
2. 替换旧的固定指数成长逻辑,改用线性累计成长公式
3. 移除英雄等级上限,改为技能等级封顶,调整升级/出售金币计算逻辑
4. 重构属性计算与UI展示逻辑,统一成长计算入口
5. 优化技能文案展示与英雄配置格式
2026-08-10 23:33:06 +08:00

175 lines
6.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { smc } from "../common/SingletonModuleComp";
import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops";
import { GameEvent } from "../common/config/GameEvent";
import { FightSet } from "../common/config/GameSet";
import { FieldSkillType } from "../common/config/SkillSet";
import { FieldSkillHelper } from "../hero/FieldSkillHelper";
/**
* 局内经济统一管理类
* 负责统一处理金币的增减、各种费用的计算以及战绩评分中的金币统计。
*/
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 = FieldSkillHelper.getFieldSkillTotalValue(FieldSkillType.RefreshDiscount);
cost = Math.max(0, cost - discount);
return Math.floor(cost);
}
/** 获取当前刷新石数量 */
static getRefreshStone(): number {
return Math.max(0, Math.floor(smc.vmdata.mission_data.refresh_stone ?? 0));
}
/**
* 增加刷新石
* @param amount 增加数量,<=0 时忽略
*/
static addRefreshStone(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 });
}
/** 单次刷新消耗的刷新石数量 */
static getRefreshStoneCost(): number {
return Math.max(1, Math.floor(FightSet.REFRESH_STONE_COST));
}
/**
* 判断当前是否可以执行一次刷新(刷新石足够或金币足够)
*/
static canRefresh(baseCost: number = 1): boolean {
if (this.getRefreshStone() >= this.getRefreshStoneCost()) return true;
return this.getCoin() >= this.getRefreshCost(baseCost);
}
/**
* 执行刷新卡牌:
* 1. 刷新石足够时优先扣除 REFRESH_STONE_COST 颗刷新石(不消耗金币)。
* 2. 刷新石不足时扣除金币(含刷新优惠折扣)。
*/
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;
}
// 刷新石不足 → 扣除金币
const cost = this.getRefreshCost(baseCost);
const success = this.spendCoin(cost);
if (success) {
smc.vmdata.scores.refresh_count++;
}
return success;
}
/**
* 计算英雄升级金币消耗指数递增5×2^(lv-1),无限升级下指数控速)
* @param heroLevel 当前英雄等级(升级前)
*/
static getUpgradeCost(heroLevel: number = 1): number {
const lv = Math.max(1, Math.floor(heroLevel));
return Math.floor(5 * Math.pow(2, lv - 1));
}
/**
* 执行英雄升级扣费
* @param heroLevel 当前英雄等级(升级前)
* @returns true = 扣费成功(金币足够)
*/
static executeUpgradeCost(heroLevel: number = 1): boolean {
return this.spendCoin(this.getUpgradeCost(heroLevel));
}
/**
* 计算英雄出售金币(按累计升级投入的 50% 折算,无限升级自动缩放)。
* 累计投入 = 等比数列求和 Σ5×2^(i-1)i=1..lv-1= 5×(2^(lv-1) - 1)。
*/
static getSellGold(heroLevel: number = 1): number {
const lv = Math.max(1, Math.floor(heroLevel));
// 基础出售价 3保底招募残值+ 累计升级投入的 50%
const investTotal = 5 * (Math.pow(2, lv - 1) - 1);
const baseSellGold = 3 + Math.floor(investTotal * 0.5);
// 驻场英雄带来的"出售金币"加成(包含原 SellBonus 语义,统一在 SellGold 中)
const goldBoost = FieldSkillHelper.getFieldSkillTotalValue(FieldSkillType.SellGold);
const totalSellGold = baseSellGold + goldBoost;
return Math.floor(totalSellGold);
}
/**
* 执行出售英雄并增加金币
*/
static executeSellHero(heroLevel: number = 1): number {
const gold = this.getSellGold(heroLevel);
this.addCoin(gold);
return gold;
}
/**
* 计算每回合基础金币收益
*/
static getWaveGold(baseReward: number): number {
let reward = Math.max(0, Math.floor(baseReward));
const goldBoost = FieldSkillHelper.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;
}
}