import { createMembershipSet, membershipAdd } from '../../../mx/tools/MembershipSet'; import { TableNames } from '../../game/ConfigTableData'; import type { ProjectLevelMonsterConfig } from '../config/LevelMonsterConfig'; import { isDesignDebugEnabled } from './DesignDebug'; const TAG = '[MonsterHp]'; const _loggedKeys = createMembershipSet(); /** 新关卡组装前调用,避免同进程内重复 key 被跳过 */ export function resetMonsterHpDebugLog(): void { _loggedKeys.clear(); } /** 一次章节怪物血量验数 */ export interface MonsterHpCalcDebugInfo { /** 怪物表 id */ monsterId: number; /** 出怪口 */ port: number; /** Monster1 行 */ difficultyRow: number; /** 关卡怪物难度配置 */ config: ProjectLevelMonsterConfig; /** Monster.hp */ monsterHp: number; /** 出怪口倍率 */ portHp: number; /** Monster1 难度系数 */ baseHp: number; /** 战力修正 */ powerCoeff: number; /** 实际参与运算的 hp_multiple */ hpMultiple: number; /** 实际参与运算的 weapon_para */ weaponPara: number; /** 乘积(未 floor) */ raw: number; /** 最终 HP */ finalHp: number; } /** * 打印血量逐步乘算与最终结果。每种 (章+难度+怪+口+M2行) 只打一条。 * @param info 计算中间量 */ export function logChapterMonsterHpCalc(info: MonsterHpCalcDebugInfo): void { if (!isDesignDebugEnabled()) return; const { config, monsterId, port, difficultyRow } = info; const key = `${config.levelId}_${config.difficultyRow}_${monsterId}_p${port}_r${difficultyRow}`; if (_loggedKeys.has(key)) return; membershipAdd(_loggedKeys, key); const monster = gg.data.table.getTableData(TableNames.Monster, monsterId); const monsterName = String(monster?.name ?? monster?.icon ?? '').trim() || String(monsterId); const m1Col = `diffcult${config.monsterGroup}`; const userPower = Math.max(1, gg.data.getCurPower()); const recommend = gg.data.getCurPower(); const ratio = recommend / userPower; const usePowerPara2 = ratio < 1; const powerBranch = usePowerPara2 ? 'power_para2' : 'power_para'; const powerExponent = usePowerPara2 ? config.powerPara2 : config.powerPara; const purpleMaxLv = Math.max(1, gg.data.project.getMaxLevelPurpleWeapon()); const replicaScale = config.specialReplicaHpScale ?? 1; const floored = Math.max(1, Math.floor(info.raw)); let acc = info.monsterHp; const s1 = acc; acc *= info.hpMultiple; const s2 = acc; acc *= info.portHp; const s3 = acc; acc *= info.baseHp; const s4 = acc; acc *= info.powerCoeff; const s5 = acc; acc *= info.weaponPara; const s6 = acc; const lines = [ `${TAG} 战场${config.levelId} 怪${monsterId}「${monsterName}」口${port} Monster1行${difficultyRow}`, ` 公式: floor(monster_hp × hp_multiple × port_hp × basehp × 战力修正 × weapon_para)${replicaScale !== 1 ? ' × 特殊副本倍率' : ''}`, ` 1. Monster.hp = ${info.monsterHp}`, ` 2. × hp_multiple ${info.hpMultiple} → ${s2}`, ` 3. × port_hp[口${port}] ${info.portHp} → ${s3}`, ` 4. × basehp Monster1[${difficultyRow}].${m1Col} = ${info.baseHp} → ${s4}`, ` 5. × 战力修正 ${info.powerCoeff}(推荐=${recommend} 玩家=${userPower} ratio=${ratio} 分支=${powerBranch} 指数=${powerExponent})→ ${s5}`, ` 6. × weapon_para ${info.weaponPara} → ${s6}`, ` 7. floor(${info.raw}) = ${floored}`, ]; if (replicaScale !== 1) { lines.push(` 8. × 特殊副本倍率 ${replicaScale}(紫武最高Lv=${purpleMaxLv}/5)→ floor = ${info.finalHp}`); } lines.push(` 最终 HP = ${info.finalHp}`); console.log(lines.join('\n')); }