feat(map,economy): 重做游戏经济与卡牌平衡系统

本次提交重构了英雄出售、抽卡、波次金币的数值体系:
1. 调整英雄出售价格按等级计算,1/2/3级分别为3/10/25金币
2. 修改抽卡刷新费用为2,初始金币调整为10
3. 重做波次金币公式,基础收益改为10,每波增长4
4. 调整卡池卡牌消耗与特殊卡牌的定价
5. 优化卡牌抽取消耗的计算逻辑,使用指数增长替代线性计算
This commit is contained in:
walkpan
2026-05-23 19:03:48 +08:00
parent f49831bf9e
commit 92836c14b6
5 changed files with 43 additions and 39 deletions

View File

@@ -70,7 +70,7 @@ export const CardsUpSet: Record<number, number> = {
}
/**初始coin数 */
export const CardInitCoins = 11
export const CardInitCoins = 10
/** 卡池升级每波减免金额 */
export const CARD_POOL_UPGRADE_DISCOUNT_PER_WAVE = 10
/** 卡池默认初始等级 */
@@ -90,7 +90,7 @@ HeroList.forEach(uuid => {
const basePoolLv = hero.pool_lv || 1;
const baseHeroLv = hero.lv || 1;
const baseCost = 10;
const baseCost = 5;
const baseWeight = 25;
// 生成从 basePoolLv 到 CARD_POOL_MAX_LEVEL 的卡牌
@@ -103,10 +103,10 @@ HeroList.forEach(uuid => {
break;
}
// cost = 原始的cost*MERGE_NEED*hero_lv
// cost = baseCost * 3^(lv-1): Lv1=5, Lv2=15, Lv3=45
let cost = baseCost;
if (targetHeroLv > 1) {
cost = baseCost * FightSet.MERGE_NEED * targetHeroLv;
cost = baseCost * Math.pow(FightSet.MERGE_NEED, targetHeroLv - 1);
}
CardPoolList.push({
@@ -124,14 +124,14 @@ HeroList.forEach(uuid => {
// 添加非英雄卡牌 (技能、功能卡)
CardPoolList.push(
// 技能卡牌 (以增益/辅助为主,因为在备战期没有敌人)
{ uuid: 6401, type: CardType.Skill, cost: 10, weight: 20, pool_lv: 1, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6401"), info: t("skill_info_6401"), is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6402, type: CardType.Skill, cost: 10, weight: 20, pool_lv: 1, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6402"), info: t("skill_info_6402"), is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6403, type: CardType.Skill, cost: 10, weight: 20, pool_lv: 1, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6403"), info: t("skill_info_6403"), is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6404, type: CardType.Skill, cost: 10, weight: 20, pool_lv: 1, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6404"), info: t("skill_info_6404"), is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6405, type: CardType.Skill, cost: 10, weight: 20, pool_lv: 2, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6405"), info: t("skill_info_6405"), is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6406, type: CardType.Skill, cost: 10, weight: 20, pool_lv: 2, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6406"), info: t("skill_info_6406"), is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6304, type: CardType.Skill, cost: 10, weight: 20, pool_lv: 3, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6304"), info: t("skill_info_6304"), is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6305, type: CardType.Skill, cost: 10, weight: 20, pool_lv: 3, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6305"), info: t("skill_info_6305"), is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6401, type: CardType.Skill, cost: 8, weight: 20, pool_lv: 1, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6401"), info: t("skill_info_6401"), is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6402, type: CardType.Skill, cost: 8, weight: 20, pool_lv: 1, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6402"), info: t("skill_info_6402"), is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6403, type: CardType.Skill, cost: 8, weight: 20, pool_lv: 1, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6403"), info: t("skill_info_6403"), is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6404, type: CardType.Skill, cost: 8, weight: 20, pool_lv: 1, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6404"), info: t("skill_info_6404"), is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6405, type: CardType.Skill, cost: 8, weight: 20, pool_lv: 2, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6405"), info: t("skill_info_6405"), is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6406, type: CardType.Skill, cost: 8, weight: 20, pool_lv: 2, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6406"), info: t("skill_info_6406"), is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6304, type: CardType.Skill, cost: 8, weight: 20, pool_lv: 3, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6304"), info: t("skill_info_6304"), is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6305, type: CardType.Skill, cost: 8, weight: 20, pool_lv: 3, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6305"), info: t("skill_info_6305"), is_inst: true, t_times: 1, t_inv: 0 },
);
@@ -162,22 +162,22 @@ export interface SpecialRefreshCardConfig extends CardConfig {
export const SpecialUpgradeCardList: Record<number, SpecialUpgradeCardConfig> = {
7001: { uuid: 7001,type: CardType.SpecialUpgrade,cost: 6,weight: 16,pool_lv: CardLV.LV1,kind:CKind.Card,name:t("scard_name_7001"),info:t("scard_info_7001"),
7001: { uuid: 7001,type: CardType.SpecialUpgrade,cost: 10,weight: 16,pool_lv: CardLV.LV1,kind:CKind.Card,name:t("scard_name_7001"),info:t("scard_info_7001"),
currentLv: 1, targetLv: 2,
},
7002: { uuid: 7002,type: CardType.SpecialUpgrade,cost: 6,weight: 14,pool_lv: CardLV.LV2,kind:CKind.Card,name:t("scard_name_7002"),info:t("scard_info_7002"),
7002: { uuid: 7002,type: CardType.SpecialUpgrade,cost: 28,weight: 14,pool_lv: CardLV.LV2,kind:CKind.Card,name:t("scard_name_7002"),info:t("scard_info_7002"),
currentLv: 2, targetLv: 3,
},
}
export const SpecialRefreshCardList: Record<number, SpecialRefreshCardConfig> = {
7101: { uuid: 7101,type: CardType.SpecialRefresh,cost: 4,weight: 14,pool_lv: CardLV.LV1,kind:CKind.Card,name:t("scard_name_7101"),info:t("scard_info_7101"),
7101: { uuid: 7101,type: CardType.SpecialRefresh,cost: 3,weight: 14,pool_lv: CardLV.LV1,kind:CKind.Card,name:t("scard_name_7101"),info:t("scard_info_7101"),
refreshLv: 0, refreshHeroType: SpecialRefreshHeroType.Melee,
},
7102: { uuid: 7102,type: CardType.SpecialRefresh,cost: 4,weight: 14,pool_lv: CardLV.LV1,kind:CKind.Card,name:t("scard_name_7102"),info:t("scard_info_7102"),
7102: { uuid: 7102,type: CardType.SpecialRefresh,cost: 3,weight: 14,pool_lv: CardLV.LV1,kind:CKind.Card,name:t("scard_name_7102"),info:t("scard_info_7102"),
refreshLv: 0, refreshHeroType: SpecialRefreshHeroType.Ranged,
},
7103: { uuid: 7103,type: CardType.SpecialRefresh,cost: 5,weight: 12,pool_lv: CardLV.LV2,kind:CKind.Card,name:t("scard_name_7103"),info:t("scard_info_7103"),
7103: { uuid: 7103,type: CardType.SpecialRefresh,cost: 4,weight: 12,pool_lv: CardLV.LV2,kind:CKind.Card,name:t("scard_name_7103"),info:t("scard_info_7103"),
refreshLv: 3, refreshHeroType: SpecialRefreshHeroType.Any,
},
}

View File

@@ -304,17 +304,19 @@ export class HInfoComp extends CCComp {
*/
private onSellHero(event?: Event) {
if (!this.eid) return;
const heroLv = Math.max(1, Math.floor(this.model?.lv ?? 1));
const removed = Hero.removeByEid(this.eid);
mLogger.log(this.debugMode, "HInfoComp", "onSellHero", {
eid: this.eid,
heroLv,
isAlive: this.isModelAlive(),
removed
});
if (!removed) return;
// 使用统一经济管理入口出售英雄
MissionEconomy.executeSellHero();
// 使用统一经济管理入口出售英雄(按等级计算卖价)
MissionEconomy.executeSellHero(heroLv);
oops.gui.remove(UIID.IBox);
}

View File

@@ -74,7 +74,7 @@ export class MissionCardComp extends CCComp {
/** 按钮弹起缩放(峰值) */
private readonly buttonClickScale: number = 1.06;
/** 抽卡(刷新)费用 */
refreshCost: number = 1;
refreshCost: number = 2;
/** 卡牌面板展开/收起动画时长(秒) */
cardsPanelMoveDuration: number = 0.2;

View File

@@ -87,10 +87,10 @@ export class MissionComp extends CCComp {
private maxMonsterCount: number = 50;
/** 怪物数量恢复阈值(降至此值以下恢复刷怪) */
private resumeMonsterCount: number = 30;
/** 新一波金币奖励基础值(现已固定,不再随波次增长) */
private prepareBaseCoinReward: number = 25;
/** 每一波金币增长值(固定收益设为0 */
private prepareCoinWaveGrow: number = 0;
/** 新一波金币奖励基础值 */
private prepareBaseCoinReward: number = 10;
/** 每一波金币增长值(公式: base + (wave-1) * growth */
private prepareCoinWaveGrow: number = 4;
/** 金币奖励上限(固定收益,此值不再生效) */
private prepareCoinRewardCap: number = 100;
/** 卡池升级波次配置:达到对应波次时,推送卡池升级事件 */
@@ -788,12 +788,13 @@ export class MissionComp extends CCComp {
private grantPrepareCoinByWave(wave: number) {
if (wave <= 1) return;
if (wave <= this.lastPrepareCoinWave) return;
// 使用统一经济管理入口发放每波金币
const reward = MissionEconomy.executeWaveGold(this.prepareBaseCoinReward);
// 波次金币公式: baseReward + (wave-1) * waveGrow
const waveReward = this.prepareBaseCoinReward + (wave - 1) * this.prepareCoinWaveGrow;
const reward = MissionEconomy.executeWaveGold(waveReward);
this.lastPrepareCoinWave = wave;
mLogger.log(this.debugMode, "MissionComp", "grantPrepareCoinByWave", { wave, reward, coin: smc.vmdata.mission_data.coin });
mLogger.log(this.debugMode, "MissionComp", "grantPrepareCoinByWave", { wave, waveReward, reward, coin: smc.vmdata.mission_data.coin });
}
// ======================== 怪物数量管理 ========================

View File

@@ -66,11 +66,12 @@ export class MissionEconomy {
return success;
}
/**
* 计算英雄出售金币
/**
* 计算英雄出售金币(按英雄等级缩放)
*/
static getSellGold(): number {
const baseSellGold = 1; // 基础卖出金币
static getSellGold(heroLevel: number = 1): number {
const sellByLevel: Record<number, number> = { 1: 3, 2: 10, 3: 25 };
const baseSellGold = sellByLevel[heroLevel] || 3;
const goldBoost = FieldSkillHelper.getFieldSkillTotalValue(FieldSkillType.SellGold);
let totalSellGold = baseSellGold + goldBoost;
// 应用天赋 SellBonus (增加数值)
@@ -81,11 +82,11 @@ export class MissionEconomy {
return Math.floor(totalSellGold);
}
/**
* 执行出售英雄并增加金币
/**
* 执行出售英雄并增加金币
*/
static executeSellHero(): number {
const gold = this.getSellGold();
static executeSellHero(heroLevel: number = 1): number {
const gold = this.getSellGold(heroLevel);
this.addCoin(gold);
return gold;
}