diff --git a/assets/script/game/common/SingletonModuleComp.ts b/assets/script/game/common/SingletonModuleComp.ts index 6add3c8f..9168ebb9 100644 --- a/assets/script/game/common/SingletonModuleComp.ts +++ b/assets/script/game/common/SingletonModuleComp.ts @@ -220,12 +220,6 @@ export class SingletonModuleComp extends ecs.Comp { passed_wave_20: false, highest_dmg: 0, - score_combat: 0, - score_output: 0, - score_defense: 0, - score_build: 0, - score_efficiency: 0, - achieved_highlights: [], } as GameScoreStats, @@ -293,11 +287,6 @@ export class SingletonModuleComp extends ecs.Comp { wave_all_alive_count: 0, passed_wave_20: false, highest_dmg: 0, - score_combat: 0, - score_output: 0, - score_defense: 0, - score_build: 0, - score_efficiency: 0, achieved_highlights: [], } as GameScoreStats; } diff --git a/assets/script/game/common/config/GameSet.ts b/assets/script/game/common/config/GameSet.ts index 7b3ccb45..e4296355 100644 --- a/assets/script/game/common/config/GameSet.ts +++ b/assets/script/game/common/config/GameSet.ts @@ -219,14 +219,14 @@ export function getLvColor(lv: number): Color { export const RARITY_BG_COLORS: string[] = ["green", "blue", "purple", "yellow", "red"]; /** - * 战斗结算奖励配置(每局结束后发放:英雄碎片 + 金币 + 天赋经验)。 - * 数值均为"失败基准",胜利时整体乘以 victory_multiplier。 + * 战斗结算奖励配置(每节结束后发放:英雄碎片 + 金币 + 天赋经验)。 + * 胜利奖励随关卡进度(怪物等级 = 大关号)线性增长,整体乘以 victory_multiplier。 */ export const VICTORY_REWARD_SET = { - /** 金币:base + wave_win_count × per_wave */ - gold: { base: 100, per_wave: 50 }, - /** 天赋经验:base + wave_win_count × per_wave */ - talent_exp: { base: 20, per_wave: 10 }, + /** 金币:base + monLv × per_lv */ + gold: { base: 100, per_lv: 50 }, + /** 天赋经验:base + monLv × per_lv */ + talent_exp: { base: 20, per_lv: 10 }, /** 每个出场英雄保底碎片数 */ played_fragment: 1, /** 随机英雄碎片数量(发放给随机抽中的 1 个英雄) */ diff --git a/assets/script/game/common/config/HeroAttrs.ts b/assets/script/game/common/config/HeroAttrs.ts index 22f35e7d..877972cc 100644 --- a/assets/script/game/common/config/HeroAttrs.ts +++ b/assets/script/game/common/config/HeroAttrs.ts @@ -100,13 +100,6 @@ export interface GameScoreStats { passed_wave_20: boolean; // 是否通过第20回合 highest_dmg: number; // 单次最高伤害 - // 最终结算分 - score_combat: number; - score_output: number; - score_defense: number; - score_build: number; - score_efficiency: number; - // 已达成的亮点成就记录 achieved_highlights: any[]; } diff --git a/assets/script/game/map/MissionComp.ts b/assets/script/game/map/MissionComp.ts index 9d37bf5f..3307ed75 100644 --- a/assets/script/game/map/MissionComp.ts +++ b/assets/script/game/map/MissionComp.ts @@ -49,6 +49,7 @@ import { spawningEngine, WAVE_DURATION, BATTLE_TIMEOUT } from "./RogueConfig"; import { MissionMonCompComp } from "./MissionMonComp"; import { getProgressText, + getMonsterLv, } from "../common/config/StageSet"; const { ccclass, property } = _decorator; @@ -638,6 +639,8 @@ export class MissionComp extends CCComp { // 结算类型:小节胜利显示"下一节",末关通关显示"确认退出" + 通关标题 settle_type: this._settleType, settle_title: this._settleTitle, + // 关卡难度度量(= 大关号,驱动胜利奖励随进度增长) + mon_lv: getMonsterLv(this.currentStage), // 失败奖励判定数据:本节坚持时间 + 击杀统计(kills=已刷出-存活) defeat_stats: { clear_time: this.clearTime, diff --git a/assets/script/game/map/VictoryComp.ts b/assets/script/game/map/VictoryComp.ts index cf09e5b4..404c9b25 100644 --- a/assets/script/game/map/VictoryComp.ts +++ b/assets/script/game/map/VictoryComp.ts @@ -180,6 +180,9 @@ export class VictoryComp extends CCComp { /** 失败奖励判定数据(MissionComp 传入:本节坚持时间 + 击杀统计) */ private defeatStats: { clear_time: number; kills: number; total: number } | null = null; + /** 本节怪物等级(= 大关号,驱动胜利奖励随关卡进度增长) */ + private monLv: number = 1; + /** 加载时隐藏 loading 遮罩并绑定按钮事件 */ protected onLoad(): void { this.node.getChildByName("loading").active = false @@ -225,6 +228,7 @@ export class VictoryComp extends CCComp { this.settleType = args.settle_type ?? "defeat"; this.isVictory = !!args.victory; this.defeatStats = args.defeat_stats ?? null; + this.monLv = Math.max(1, Number(args.mon_lv) || 1); // 根据是否可复活决定按钮显示 this.node.getChildByName("btns").getChildByName("next").active = !args.can_revive @@ -312,58 +316,38 @@ export class VictoryComp extends CCComp { * 计算单局总分并更新到 smc.vmdata.scores.score。 * 同时刷新 smc.data.score 历史最高分。 * - * @param isVictory 是否胜利(胜利 +10 分,失败不加分) - * @param allAlive 是否全英雄存活获胜(额外 +5 分) + * 积分规则: + * - 胜利 +10 分,全队存活 +5 分;失败 -10 分 + * - 暴击/闪避/击晕/冰冻每次 +1 分,单项封顶 5 分(不分胜负均计入) + * + * @param isVictory 是否胜利 + * @param allAlive 是否全英雄存活 */ private calculateTotalScore(isVictory: boolean, allAlive: boolean) { const s = smc.vmdata.scores; - // 0. 胜负分:胜利 +10,全英雄存活获胜额外 +5,失败不加分 - let score_result = 0; + // 0. 胜负分:胜利 +10(全队存活再 +5),失败 -10 + let base = 0; if (isVictory) { - score_result = 10; + base = 10; if (allAlive) { - score_result += 5; + base += 5; } + } else { + base = -10; } - // 1. 战绩分:衡量生存能力——活几回合、赢几场。 - s.score_combat = (s.wave_win_count * 100) - - (s.wave_remain_monsters * 15) - + (s.wave_all_alive_count * 50) - + (s.passed_wave_20 ? 500 : 0); + // 1. 战斗行为分:暴击/闪避/击晕/冰冻每次 +1,单项封顶 5 + const critPts = Math.min(5, s.crt_count); + const dodgePts = Math.min(5, s.dod_count); + const stunPts = Math.min(5, s.stun_count); + const freezePts = Math.min(5, s.freeze_count); - // 2. 输出分:衡量伤害能力——团队火力如何。 - s.score_output = Math.floor(s.total_dmg / 100) * 10 - + (s.crt_count * 5) - // 风怒机制已停用: 风怒次数不再计入输出分 - // + (s.wf_count * 5) - + (s.highest_dmg * 2); + // 存储当前局分数 + s.score = Math.floor(base + critPts + dodgePts + stunPts + freezePts); - // 3. 防御分:衡量生存能力——团队多能扛。 - s.score_defense = (s.shield_block_count * 5) - + Math.floor(s.heal_total / 50) * 10 - + (s.dead_trigger_count * 8); - - // 4. 构建分:衡量阵容构建质量——团队配合程度。 - s.score_build = 0; // 待完善 - - // 5. 效率分:衡量资源利用——金币花得值不值。 - const goldRatio = s.gold_earned > 0 ? (s.gold_spent / s.gold_earned) : 0; - const refreshRatio = s.refresh_count > 0 ? (s.refresh_hit_count / s.refresh_count) : 0; - s.score_efficiency = Math.floor(goldRatio * 100) + Math.floor(refreshRatio * 50); - - // 6. 亮点成就额外加分 (按等级叠加) - const achieved = this.getAchievedHighlights(s); - s.achieved_highlights = achieved; // 记录已达成的亮点信息 - - let highlightBonus = 0; - for (const item of achieved) { - highlightBonus += item.config.scoreBonus; - } - - // 取整并存储当前局分数 - s.score = Math.floor(score_result + s.score_combat + s.score_output + s.score_defense + s.score_build + s.score_efficiency + highlightBonus); + // 亮点成就判定:仅作结算页亮点标签展示,不计入总分 + s.achieved_highlights = this.getAchievedHighlights(s); // 记录滚动前的历史最高分(动画起始值) this._prevBestScore = smc.data.score; @@ -384,13 +368,8 @@ export class VictoryComp extends CCComp { (s as any).isNewRecord = isNewRecord; mLogger.log(this.debugMode, 'VictoryComp', `[VictoryComp] 结算总分: ${s.score}`, { - combat: s.score_combat, - output: s.score_output, - defense: s.score_defense, - build: s.score_build, - efficiency: s.score_efficiency, - highlightBonus: highlightBonus, - achievedHighlights: achieved, + base, + critPts, dodgePts, stunPts, freezePts, isNewRecord: isNewRecord, prevBest: this._prevBestScore }); @@ -608,7 +587,9 @@ export class VictoryComp extends CCComp { /** * 计算并发放结算奖励,结果存入 _rewardResult。 - * 胜利:原公式不变(base + wave × per_wave,整体 ×1.2)。 + * 胜利:随关卡进度增长(base + monLv × per_lv,整体 ×1.2)。 + * Why: 无回合概念后 wave_win_count 每节被 resetScores 清零恒为 1, + * 旧的 per_wave 增长失效,改挂怪物等级(= 大关号)随关卡推进线性增长。 * 失败:受"坚持时间 + 击杀比例"限制—— * - 坚持 < 15s 或本节一只怪未杀 → 无任何奖励; * - 达标 → 坚持奖励(固定)+ 击杀比例奖励(基数 × 本节击杀比例), @@ -616,9 +597,7 @@ export class VictoryComp extends CCComp { * @param isVictory 是否胜利 */ private grantRewards(isVictory: boolean) { - const s = smc.vmdata.scores; const cfg = VICTORY_REWARD_SET; - const wave = Math.max(0, s.wave_win_count || 0); // 失败奖励资格判定:坚持时间与击杀数不达标则整场无奖励 let defeatQualified = false; @@ -637,8 +616,8 @@ export class VictoryComp extends CCComp { let talentExp: number; if (isVictory) { const mult = cfg.victory_multiplier; - gold = Math.floor((cfg.gold.base + wave * cfg.gold.per_wave) * mult); - talentExp = Math.floor((cfg.talent_exp.base + wave * cfg.talent_exp.per_wave) * mult); + 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); } else if (defeatQualified) { // 失败达标 = 坚持奖励(固定)+ 击杀比例奖励 gold = Math.floor(cfg.defeat.survive.gold + cfg.defeat.kill.gold * killRatio); @@ -690,7 +669,7 @@ export class VictoryComp extends CCComp { this._rewardResult = { gold, talentExp, silver, diamond, fragments }; mLogger.log(this.debugMode, 'VictoryComp', '[VictoryComp] 结算奖励发放', { - isVictory, wave, gold, talentExp, silver, diamond, fragments, + isVictory, monLv: this.monLv, gold, talentExp, silver, diamond, fragments, defeatStats: this.defeatStats, defeatQualified, killRatio, }); }