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
@@ -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)]),
|
||||
|
||||
Reference in new issue
Block a user