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

+73 -2
View File
@@ -20,6 +20,7 @@ import type {
PopulationEntityDefinition,
StaticMobSpawnDefinition,
} from "./mobPopulation";
import type { EnemyAttackDefinition } from "./enemyAttacks";
export interface WowWrathEncounterBatchTwoSourceFile {
readonly path: string;
@@ -71,6 +72,43 @@ const UTGARDE_PINNACLE_FILES = Object.freeze([
const GUNDRAK_FILES = Object.freeze([
`${SOURCE_ROOT}/Northrend/Gundrak/instance_gundrak.cpp`,
`${SOURCE_ROOT}/Northrend/Gundrak/gundrak.h`,
`${SOURCE_ROOT}/Northrend/Gundrak/boss_eck.cpp`,
]);
const ECK_ATTACKS: readonly EnemyAttackDefinition[] = Object.freeze([
Object.freeze({
id: "basic-attack", name: "Basic Attack", delivery: "melee", target: "primary",
school: "physical", animation: "attack", range: 4.5, cooldownMs: 2_000,
initialCooldownMs: [450, 450] as const, repeatCooldownMs: [2_000, 2_000] as const, damageMultiplier: 1,
}),
Object.freeze({
id: "spell-55837", name: "Eck Spring Init", spellId: 55_837, delivery: "area", target: "self",
school: "physical", animation: "cast", castTimeMs: 0, range: 0, cooldownMs: 1,
initialCooldownMs: [450, 450] as const, repeatCooldownMs: [1, 1] as const, maximumCasts: 1, damageMultiplier: 0,
effect: { kind: "aura", aura: "eck-spring-init", durationMs: 1_000 } as const,
}),
Object.freeze({
id: "spell-55813", name: "Eck Bite", spellId: 55_813, delivery: "melee", target: "primary",
school: "physical", animation: "attack", range: 5.5, cooldownMs: 10_000,
initialCooldownMs: [5_000, 5_000] as const, repeatCooldownMs: [8_000, 12_000] as const, damageMultiplier: 1.35,
}),
Object.freeze({
id: "spell-55814", name: "Eck Spit", spellId: 55_814, delivery: "projectile", target: "primary",
school: "nature", animation: "cast", castTimeMs: 0, range: 28, cooldownMs: 10_000,
initialCooldownMs: [10_000, 37_000] as const, repeatCooldownMs: [8_000, 12_000] as const, damageMultiplier: 1.35,
}),
Object.freeze({
id: "spell-55815", name: "Eck Spring", spellId: 55_815, delivery: "projectile", target: "random-party",
school: "physical", animation: "cast", castTimeMs: 750, range: 30, cooldownMs: 17_000,
initialCooldownMs: [10_000, 24_000] as const, repeatCooldownMs: [10_000, 24_000] as const, damageMultiplier: 1.35,
telegraph: { shape: "circle", anchor: "target", warningMs: 750, radius: 3 } as const,
}),
Object.freeze({
id: "spell-55816", name: "Eck Berserk", spellId: 55_816, delivery: "area", target: "self",
school: "physical", animation: "cast", castTimeMs: 0, range: 0, cooldownMs: 90_000,
initialCooldownMs: [90_000, 90_000] as const, repeatCooldownMs: [90_000, 90_000] as const, maximumCasts: 1,
damageMultiplier: 0, effect: { kind: "aura", aura: "enrage", durationMs: 0, magnitude: 1 } as const,
}),
]);
export const WOW_WRATH_ENCOUNTER_BATCH_TWO_REVIEWS: readonly WowWrathEncounterBatchTwoReview[] = Object.freeze([
@@ -239,11 +277,20 @@ export const WOW_WRATH_ENCOUNTER_BATCH_TWO_REVIEWS: readonly WowWrathEncounterBa
sha256: "ec0477724b5343879ecfd713060c408796373d3f6fbeaf16dcef84f1393c6356",
anchors: ["boss, altar, statue, bridge, collision, Eck, and Gal'darah door ids (lines 27-73)"],
},
{
path: GUNDRAK_FILES[2],
sha256: "ef6f4736b921c5f654260cb0c61f2590e77270c8e5a4c4f0935db4c5f0478e07",
anchors: [
"Eck Spring initialization and threat handoff (lines 51-72)",
"Bite, Spit, Spring, and 90-second Berserk schedules (lines 75-90)",
],
},
],
reviewedBehavior: "Slad'ran, Moorabi, and the Drakkari Colossus independently enable their exact altars; using all three rotates the exact statues and bridge collision after five seconds, exposing Gal'darah; Moorabi releases the heroic Eck route.",
adaptations: [
"The bridge and statues change discrete procedural states without native rotation animation; the source five-second delay is retained.",
"The optional Eck actor is activated after Moorabi for deterministic recovery rather than after the source Ruins Dweller formation; its actor spawn remains heroic-mask-only, so normal rendering filters it out.",
"Eck keeps the source's independent Bite, Spit, Spring, and 90-second Berserk timings; Spring uses a short target warning because the runtime does not yet execute creature jump motion.",
"Gal'darah's room door closes on engagement and all three source Gal'darah doors open on death; no native door animation is claimed.",
"Exact imported altar, statue, bridge, collision, Eck-door, underwater-gate, and Gal'darah-door rows are replaced by procedural stateful objects at their source transforms.",
],
@@ -1529,9 +1576,33 @@ function buildGundrak(definition: DungeonDefinition): DungeonDefinition {
const galDarah = objectiveForEntry(definition, 29_306);
const eckBase = objectiveForEntry(definition, 29_932);
const eck = eventObjective(definition, eckBase.id);
const entities = ensureEntities(definition, []);
const eckEntityId = entityIdForEntry(entities, 29_932);
const baseEntities = ensureEntities(definition, []);
const eckEntityId = entityIdForEntry(baseEntities, 29_932);
if (!eckEntityId) throw new Error("gundrak is missing Eck the Ferocious entry 29932");
const sourceEck = baseEntities[eckEntityId];
if (!sourceEck.combat) throw new Error("gundrak Eck the Ferocious is missing combat data");
if (!sourceEck.visual.model) throw new Error("gundrak Eck the Ferocious is missing its source model");
const entities = Object.freeze({
...baseEntities,
[eckEntityId]: Object.freeze({
...sourceEck,
visual: Object.freeze({
...sourceEck.visual,
model: Object.freeze({
...sourceEck.visual.model,
// The skinned Oracle bind pose extends far below its animated root.
// Treating that minimum as the floor lifted Eck out of the camera.
groundOffset: 0,
labelHeight: 7,
}),
}),
combat: Object.freeze({
...sourceEck.combat,
mechanicIds: Object.freeze(ECK_ATTACKS.slice(1).map((attack) => attack.id)),
attacks: ECK_ATTACKS,
}),
}),
});
const eckGroup: DungeonEncounterSpawnGroupDefinition = Object.freeze({
id: "gundrak:eck",
spawns: Object.freeze([spawnAt("gundrak:eck-actor", eckEntityId, eck.position, [0, 0], 2)]),