import { writeFile } from "node:fs/promises"; import { fileURLToPath } from "node:url"; import { dirname, join } from "node:path"; import sharp from "sharp"; const outputDir = dirname(fileURLToPath(import.meta.url)); const bosses = [ { name: "Lady Anacondra", copies: "3 copies owned", owned: true, accent: "#69b4ff", shape: "serpent" }, { name: "Lord Cobrahn", copies: "Card not collected", owned: false, accent: "#a5a99b", shape: "serpent" }, { name: "Lord Pythas", copies: "Card not collected", owned: false, accent: "#a5a99b", shape: "serpent" }, { name: "Verdan the Everliving", copies: "5 copies owned", owned: true, accent: "#c493ff", shape: "guardian" }, { name: "Lord Serpentis", copies: "Card not collected", owned: false, accent: "#a5a99b", shape: "serpent" }, { name: "Mutanus the Devourer", copies: "Card not collected", owned: false, accent: "#a5a99b", shape: "mutant" }, ]; const defs = ` `; function rarityMarks(boss, x, y, compact = false) { const size = compact ? 15 : 21; const gap = compact ? 4 : 6; return ["N", "R", "E", "L"].map((label, index) => { const owned = boss.owned && (boss.name.startsWith("Verdan") ? index < 3 : index < 2); const color = ["#ddd8ce", "#69b4ff", "#c493ff", "#e5a757"][index]; return `${label}`; }).join(""); } function largeCard(boss, index) { const x = 88 + index % 3 * 352; const y = 166 + Math.floor(index / 3) * 226; const owned = boss.owned; return ` BOSS ${String(index + 1).padStart(2, "0")} ${owned ? "COLLECTED" : "UNCOLLECTED"} ${boss.name} ${boss.copies} ${rarityMarks(boss, 12, 191)} `; } const countdown = ` ${defs} Wailing Caverns 6 bosses ahead · 2 collected ENTERING IN 05 ${bosses.map(largeCard).join("\n ")} \n`; function compactCard(boss, index) { const x = 180 + index * 169; return ` BOSS ${String(index + 1).padStart(2, "0")} ${boss.owned ? "OWNED" : "MISSING"} ${boss.name} ${boss.owned ? boss.copies : "Not collected"} ${rarityMarks(boss, 8, 148, true)} `; } const pause = ` ${defs} PAUSED + Aria Level 24 · Priest / Discipline BOSS CARDS IN THIS DUNGEON 2 / 6 COLLECTED ${bosses.slice(0, 5).map(compactCard).join("\n ")} SCROLL → Resume game ADVENTURECHARACTERSETTINGSSESSION Party managementDungeon mapInventorySpellbookOptionsKeybindsReturn to entranceMain menu \n`; for (const [name, svg] of [["dungeon-boss-countdown", countdown], ["pause-boss-card-strip", pause]]) { await writeFile(join(outputDir, `${name}.svg`), svg); await sharp(Buffer.from(svg)).png().toFile(join(outputDir, `${name}.png`)); }