forked from phenom/healer-man
Release Healer Man 0.1.46
This commit is contained in:
1 parent
f82daf1c13
commit
9ff574ac0b
73 files changed
+33486
-174
No files matched your search
@@ -0,0 +1,79 @@
|
||||
#!/usr/bin/env node
|
||||
import { writeFile } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import {
|
||||
BOSS_PRESSURE_PARTY_SIZE,
|
||||
BOSS_PRESSURE_WINDOW_MS,
|
||||
rankBossPartyPressure,
|
||||
} from "../../src/game/bossPressure";
|
||||
|
||||
const projectRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
||||
const playerLevel = Math.max(1, Math.min(80, Number(process.env.BOSS_PRESSURE_LEVEL) || 80));
|
||||
const { DUNGEON_DEFINITIONS } = await import("../../src/game/dungeonRegistry");
|
||||
const wowDefinitions = DUNGEON_DEFINITIONS.filter((dungeon) => dungeon.expansion !== "runewaker");
|
||||
const ranking = rankBossPartyPressure(wowDefinitions, playerLevel);
|
||||
const median = ranking.length ? ranking[Math.floor(ranking.length / 2)].partyDamagePerSecond : 0;
|
||||
const entries = ranking.map((entry, index) => ({
|
||||
rank: index + 1,
|
||||
pressureVsMedian: median > 0 ? entry.partyDamagePerSecond / median : 0,
|
||||
...entry,
|
||||
}));
|
||||
const eck = entries.find((entry) => entry.serverEntry === 29_932) ?? null;
|
||||
const report = {
|
||||
schemaVersion: 1,
|
||||
generatedAt: new Date().toISOString(),
|
||||
assumptions: {
|
||||
playerLevel,
|
||||
enemyLevelOffset: 2,
|
||||
durationSeconds: BOSS_PRESSURE_WINDOW_MS / 1_000,
|
||||
partySize: BOSS_PRESSURE_PARTY_SIZE,
|
||||
partyLayout: "all five actors inside nearby-party effects",
|
||||
metric: "unmitigated direct damage from the live boss attack catalog",
|
||||
excludes: [
|
||||
"armor and resistance",
|
||||
"avoidable movement and interrupts",
|
||||
"summoned creature damage",
|
||||
"damage-amplifying debuffs",
|
||||
"healing and absorbs",
|
||||
"mutually exclusive phase uptime",
|
||||
],
|
||||
},
|
||||
bosses: entries.length,
|
||||
medianPartyDamagePerSecond: median,
|
||||
eck,
|
||||
entries,
|
||||
};
|
||||
|
||||
const number = (value: number): string => Math.round(value).toLocaleString("en-US");
|
||||
const decimal = (value: number): string => value.toFixed(1);
|
||||
const top = entries.slice(0, 30);
|
||||
const markdown = `# WoW boss party-pressure audit
|
||||
|
||||
Generated ${report.generatedAt}. This is a deterministic comparison at player level ${playerLevel}: ${BOSS_PRESSURE_PARTY_SIZE} grouped party members, ${BOSS_PRESSURE_WINDOW_MS / 1_000} seconds, and live boss attack definitions. It is a pressure ceiling, not a combat-log prediction: mitigation, movement, interrupts, summons, debuff amplification, and phase uptime are excluded.
|
||||
|
||||
| Rank | Boss | Dungeon | Party DPS | Tank DPS | Random DPS | Groupwide DPS | vs median |
|
||||
| ---: | --- | --- | ---: | ---: | ---: | ---: | ---: |
|
||||
${top.map((entry) => `| ${entry.rank} | ${entry.boss} | ${entry.dungeonTitle} | ${number(entry.partyDamagePerSecond)} | ${number(entry.tankDamage / entry.windowSeconds)} | ${number(entry.randomTargetDamage / entry.windowSeconds)} | ${number(entry.groupwideDamage / entry.windowSeconds)} | ${decimal(entry.pressureVsMedian)}x |`).join("\n")}
|
||||
|
||||
## Eck the Ferocious
|
||||
|
||||
${eck ? `Eck ranks **${eck.rank} of ${entries.length}** at **${number(eck.partyDamagePerSecond)} raw party DPS** (**${decimal(eck.pressureVsMedian)}x** the median). His corrected schedule contains one 2-second melee swing, Bite every 8–12 seconds, Spit every 8–12 seconds after its delayed opener, Spring every 10–24 seconds against a random party member, and a non-damaging Berserk at 90 seconds.` : "Eck was not found in the runtime catalog."}
|
||||
|
||||
The complete machine-readable ranking and per-attack breakdown are in \`dungeon-pipeline/WOW_BOSS_PRESSURE_REPORT.json\`.
|
||||
`;
|
||||
|
||||
const jsonPath = path.join(projectRoot, "dungeon-pipeline", "WOW_BOSS_PRESSURE_REPORT.json");
|
||||
const markdownPath = path.join(projectRoot, "dungeon-pipeline", "WOW_BOSS_PRESSURE_REPORT.md");
|
||||
await Promise.all([
|
||||
writeFile(jsonPath, `${JSON.stringify(report, null, 2)}\n`, "utf8"),
|
||||
writeFile(markdownPath, markdown, "utf8"),
|
||||
]);
|
||||
console.log(JSON.stringify({
|
||||
status: "complete",
|
||||
bosses: entries.length,
|
||||
playerLevel,
|
||||
medianPartyDamagePerSecond: Number(median.toFixed(2)),
|
||||
eck: eck ? { rank: eck.rank, partyDamagePerSecond: Number(eck.partyDamagePerSecond.toFixed(2)), pressureVsMedian: Number(eck.pressureVsMedian.toFixed(2)) } : null,
|
||||
outputs: [path.relative(projectRoot, jsonPath), path.relative(projectRoot, markdownPath)],
|
||||
}, null, 2));
|
||||
Reference in new issue
Block a user