Release Healer Man 0.1.46

This commit is contained in:
phenom committed 2026-09-16 14:30:58 -04:00
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));