Update Healer Man server

This commit is contained in:
phenom committed 2026-09-24 18:15:45 -04:00
1 parent 71246e5b75
commit a868401ebc
40 files changed
+1522 -161

No files matched your search

+14 -5
View File
@@ -17,6 +17,10 @@ const cohorts = [
["Mage", "rom-mage", "rom-warlock"],
];
const phases = ["cast-start", "release", "impact", "tick", "aura-start", "aura-end"];
const phaseOrder = (phase) => {
const index = phases.indexOf(phase);
return index < 0 ? phases.length : index;
};
function idsForSkill(skill) {
return [...new Set([skill.sourceSkillId, ...(skill.ranks ?? []).map((rank) => rank.sourceSkillId)])]
@@ -27,10 +31,15 @@ function skillMedia(skill) {
const ids = idsForSkill(skill);
const mapped = ids.map((id) => entries.get(id)).filter(Boolean);
const models = [...new Set(mapped.flatMap((entry) => phases.flatMap((phase) =>
(entry.phases?.[phase] ?? []).map((asset) => `${phase}: ${path.posix.basename(asset.model)}`))))];
(entry.phases?.[phase] ?? []).map((asset) => (
`${phase}: ${path.posix.basename(asset.model)}`
+ (asset.visualCompleteness === "partial" ? " (partial original)" : "")
)))))];
const sounds = [...new Set(mapped.flatMap((entry) => (entry.sounds ?? [])
.filter((sound) => sound.url)
.map((sound) => `${sound.phase ?? "any"}: ${path.posix.basename(sound.sourcePath)}`)))];
.map((sound) => `${sound.phase ?? "any"}: ${path.posix.basename(sound.sourcePath)}`)))].sort((left, right) => (
phaseOrder(left.split(":", 1)[0]) - phaseOrder(right.split(":", 1)[0])
));
const playableVisuals = mapped.flatMap((entry) => Object.values(entry.phases ?? {}).flat())
.filter((asset) => asset.effectGraphUrl).length;
for (const entry of mapped) {
@@ -75,7 +84,7 @@ const lines = [
"",
"Generated by `node scripts/combat-effects/audit-rom-media.mjs --write` from the player catalog and combat effect manifest. The five accepted pairings follow `src/game/romFiveIdentities.ts`. Castable skills are listed; passives have no cast media event.",
"",
`The effect column records original client ROS/RAS references and their cast phase. ${summary.reduce((total, row) => total + row.playableVisuals, 0)} castable skills have browser-playable original phases; other source visuals use the game's generated runtime effect until their controller families are supported. The sound column lists client cues that are packaged and played on their mapped phase. A dash means the source record or matching sound file did not provide that media.`,
`The effect column records original client ROS/RAS references and their cast phase. ${summary.reduce((total, row) => total + row.playableVisuals, 0)} castable skills have browser-playable original phases; other source visuals use the game's generated runtime effect until their controller families are supported. A \`partial original\` phase renders verified source layers and declares its remaining fidelity limit. The sound column lists packaged client cues on their mapped phase. A dash means the source record or matching sound file did not provide that media.`,
"",
"| Primary class | Skill group | Castable skills | With source effect | With packaged sound | With playable original effect |",
"| --- | --- | ---: | ---: | ---: | ---: |",
@@ -85,12 +94,12 @@ const lines = [
"## Decoded particle archive",
"",
particleArchive
? `The particle archive covers ${particleArchive.processedModels} referenced ROS models, with ${particleArchive.decodedModels} fully decoded models and ${particleArchive.partialModels} partial models. ${particleArchive.results.filter((result) => result.rendererReady).length} models are renderer-ready, including the Priest holy cast whose remaining EventTrigger is an audio callback. It exports ${particleArchive.results.reduce((sum, result) => sum + result.spriteControllers, 0)} sprite controllers and ${new Set(particleArchive.results.flatMap((result) => result.graphUrl ? JSON.parse(fs.readFileSync(path.join(projectRoot, "public", result.graphUrl.slice(1)), "utf8")).textures.map((texture) => texture.url) : [])).size} distinct PNG textures. See \`public/assets/game/combat-effects/original/runewaker/manifest.json\` for per-model details.`
? `The particle archive covers ${particleArchive.processedModels} referenced ROS models, with ${particleArchive.decodedModels} fully decoded models and ${particleArchive.partialModels} partial models. ${particleArchive.results.filter((result) => result.rendererReady).length} models are renderer-ready and ${particleArchive.results.filter((result) => result.partialRendererReady).length} has a browser-playable partial original. The Priest holy cast's remaining EventTrigger is an audio callback; Urgent Heal's target renders its source sprites, emitted rune mesh, and animated ground decal. Its terrain-triangle decal projection remains approximated by a level plane. The archive exports ${particleArchive.results.reduce((sum, result) => sum + result.spriteControllers, 0)} sprite controllers and ${new Set(particleArchive.results.flatMap((result) => result.graphUrl ? JSON.parse(fs.readFileSync(path.join(projectRoot, "public", result.graphUrl.slice(1)), "utf8")).textures.map((texture) => texture.url) : [])).size} distinct PNG textures. See \`public/assets/game/combat-effects/original/runewaker/manifest.json\` for per-model details.`
: "The RuneWaker particle archive has not been packaged.",
"",
"## Next conversion step",
"",
"The WebGL sprite renderer plays Priest Urgent Heal, Heal, and Group Heal casting, Knight Charge cast and Whirlwind Shield impact, and Mage Electric Bolt projectile. The Priest holy model's EventTrigger starts a looping 3D WAV and is handled by phase-matched combat audio while its three sprite layers render. Next, verify more spell phases against the source motion and controller semantics before attaching their `effectGraphUrl`. The Direct3D source and packaged ROS data remain the reference for those ports.",
"The WebGL sprite renderer plays Priest Urgent Heal, Heal, and Group Heal casting; Urgent Heal's target impact with its source rune mesh and decal; Rising Tide's cast, projectile release, and target impact; Knight Charge cast and Whirlwind Shield impact; and Mage Electric Bolt projectile. Urgent Heal's holy cast EventTrigger starts a looping 3D WAV, and its target impact triggers the source benedictory heal MP3. Rising Tide retains its packaged cast WAV and now plays its ROS-linked projectile release and target impact MP3s. Impact cues use the target position. Urgent Heal's decal uses a level plane in place of the client's terrain projection. The Direct3D source and packaged ROS data remain the reference for subsequent phases.",
];
const markdown = `${lines.join("\n").trimEnd()}\n`;
if (process.argv.includes("--write")) {