refactor(mission): 重构关卡结算与刷怪统计逻辑
1. 新增整局跨回合刷怪统计与重置能力,替换原小节统计 2. 修改奖励配置为整局5回合累计结算逻辑 3. 调整失败奖励判定为整局维度统计 4. 重构胜利/失败奖励计算逻辑,适配多回合关卡
This commit is contained in:
@@ -177,7 +177,7 @@ export class VictoryComp extends CCComp {
|
||||
/** 是否胜利场(驱动主按钮文案与行为) */
|
||||
private isVictory: boolean = false;
|
||||
|
||||
/** 失败奖励判定数据(MissionComp 传入:本节坚持时间 + 击杀统计) */
|
||||
/** 失败奖励判定数据(MissionComp 传入:整局坚持时间 + 整局击杀统计) */
|
||||
private defeatStats: { clear_time: number; kills: number; total: number } | null = null;
|
||||
|
||||
/** 本节怪物等级(= 大关号,驱动胜利奖励随关卡进度增长) */
|
||||
@@ -585,12 +585,14 @@ export class VictoryComp extends CCComp {
|
||||
|
||||
/**
|
||||
* 计算并发放结算奖励,结果存入 _rewardResult。
|
||||
* 胜利:随关卡进度增长(base + monLv × per_lv,整体 ×1.2)。
|
||||
* Why: 无回合概念后 wave_win_count 每节被 resetScores 清零恒为 1,
|
||||
* 旧的 per_wave 增长失效,改挂怪物等级(= 大关号)随关卡推进线性增长。
|
||||
* 通关:按 5 回合累计发放——
|
||||
* 每回合基础奖励(随 monLv 增长)× 胜利回合数(wave_win_count),
|
||||
* 再按全员存活回合数 × per_wave_bonus 加成。
|
||||
* Why: 一关一局 5 回合后,通关奖励不再是单场,改按"5 回合累计"发放;
|
||||
* scores 统计在整关间保留(data_init 仅在整关开始/重开重置),故可直接累计。
|
||||
* 失败:受"坚持时间 + 击杀比例"限制——
|
||||
* - 坚持 < 15s 或本节一只怪未杀 → 无任何奖励;
|
||||
* - 达标 → 坚持奖励(固定)+ 击杀比例奖励(基数 × 本节击杀比例),
|
||||
* - 坚持 < 15s 或本回合一只怪未杀 → 无任何奖励;
|
||||
* - 达标 → 坚持奖励(固定)+ 击杀比例奖励(基数 × 本回合击杀比例),
|
||||
* 银币/钻石/碎片同样受此门槛限制(不达标不发,达标正常发放)。
|
||||
* @param isVictory 是否胜利
|
||||
*/
|
||||
@@ -609,13 +611,19 @@ export class VictoryComp extends CCComp {
|
||||
killRatio = total > 0 ? Math.min(1, kills / total) : 0;
|
||||
}
|
||||
|
||||
// 5 回合累计:胜利回合数与全员存活回合数(scores 跨回合累计,整关重置)
|
||||
const winWaves = Math.max(1, Math.floor(smc.vmdata.scores.wave_win_count || 0));
|
||||
const aliveWaves = Math.max(0, Math.floor(smc.vmdata.scores.wave_all_alive_count || 0));
|
||||
// 全员存活回合加成:每个全员存活回合额外 +per_wave_bonus(线性叠加于累计基础)
|
||||
const aliveBonus = 1 + aliveWaves * cfg.per_wave_bonus;
|
||||
|
||||
// 1. 金币 / 天赋经验
|
||||
let gold: number;
|
||||
let talentExp: number;
|
||||
if (isVictory) {
|
||||
const mult = cfg.victory_multiplier;
|
||||
gold = Math.floor((cfg.gold.base + this.monLv * cfg.gold.per_lv) * mult);
|
||||
talentExp = Math.floor((cfg.talent_exp.base + this.monLv * cfg.talent_exp.per_lv) * mult);
|
||||
// 通关:每回合基础 × 胜利回合数 × 全员存活加成
|
||||
gold = Math.floor((cfg.gold.base + this.monLv * cfg.gold.per_lv) * winWaves * aliveBonus);
|
||||
talentExp = Math.floor((cfg.talent_exp.base + this.monLv * cfg.talent_exp.per_lv) * winWaves * aliveBonus);
|
||||
} else if (defeatQualified) {
|
||||
// 失败达标 = 坚持奖励(固定)+ 击杀比例奖励
|
||||
gold = Math.floor(cfg.defeat.survive.gold + cfg.defeat.kill.gold * killRatio);
|
||||
@@ -625,25 +633,31 @@ export class VictoryComp extends CCComp {
|
||||
talentExp = 0;
|
||||
}
|
||||
|
||||
// 1.5 银币固定发放;钻石按输赢在 [min, max] 内随机(失败不达标时同样清零)
|
||||
const silver = !isVictory && !defeatQualified ? 0 : cfg.silver;
|
||||
// 1.5 银币 / 钻石:通关按胜利回合数累计;失败不达标清零
|
||||
const silverBase = !isVictory && !defeatQualified ? 0 : cfg.silver;
|
||||
const silver = isVictory ? Math.floor(silverBase * winWaves) : silverBase;
|
||||
let diamond = 0;
|
||||
if (isVictory || defeatQualified) {
|
||||
const dRange = isVictory ? cfg.diamond.victory : cfg.diamond.defeat;
|
||||
if (isVictory) {
|
||||
const dRange = cfg.diamond.victory;
|
||||
const perWave = dRange.min + Math.floor(Math.random() * (dRange.max - dRange.min + 1));
|
||||
diamond = perWave * winWaves;
|
||||
} else if (defeatQualified) {
|
||||
const dRange = cfg.diamond.defeat;
|
||||
diamond = dRange.min + Math.floor(Math.random() * (dRange.max - dRange.min + 1));
|
||||
}
|
||||
|
||||
// 2. 英雄碎片:出场英雄各保底 + 1 个随机英雄(失败不达标时不发)
|
||||
// 2. 英雄碎片:出场英雄各保底 + 1 个随机英雄(通关 × 胜利回合数累计;失败不达标时不发)
|
||||
const fragments: FragmentReward[] = [];
|
||||
if (isVictory || defeatQualified) {
|
||||
const playedUuids = this.collectPlayedHeroUuids();
|
||||
const playedSet = new Set(playedUuids);
|
||||
const fragMult = isVictory ? winWaves : 1;
|
||||
for (const uuid of playedUuids) {
|
||||
fragments.push({ uuid, count: cfg.played_fragment, isPlayed: true });
|
||||
fragments.push({ uuid, count: cfg.played_fragment * fragMult, isPlayed: true });
|
||||
}
|
||||
const randomUuid = this.pickRandomHeroUuid(playedSet);
|
||||
if (randomUuid > 0) {
|
||||
fragments.push({ uuid: randomUuid, count: cfg.random_fragment, isPlayed: false });
|
||||
fragments.push({ uuid: randomUuid, count: cfg.random_fragment * fragMult, isPlayed: false });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -667,7 +681,8 @@ export class VictoryComp extends CCComp {
|
||||
this._rewardResult = { gold, talentExp, silver, diamond, fragments };
|
||||
|
||||
mLogger.log(this.debugMode, 'VictoryComp', '[VictoryComp] 结算奖励发放', {
|
||||
isVictory, monLv: this.monLv, gold, talentExp, silver, diamond, fragments,
|
||||
isVictory, monLv: this.monLv, winWaves, aliveWaves, aliveBonus,
|
||||
gold, talentExp, silver, diamond, fragments,
|
||||
defeatStats: this.defeatStats, defeatQualified, killRatio,
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user