Files
healer-man/src/game/wailingCavernsServer.ts
T
2026-08-14 15:56:39 -04:00

98 lines
3.0 KiB
TypeScript

import referenceData from "./generated/azerothCoreReference.json";
import {
DEFAULT_ENEMY_ATTACK,
type EnemyAttackDefinition,
type EnemyCombatDefinition,
} from "./enemyAttacks";
import type {
PopulationDefinitionMap,
PopulationEntityDefinition,
} from "./mobPopulation";
import { creatureTemplateReference } from "./azerothCoreReference";
const ENTITY_SERVER_ENTRIES: Readonly<Record<string, number>> = Object.freeze({
"deviate-ravager": 3636,
"deviate-guardian": 3637,
"druid-of-the-fang": 3840,
"evolving-ectoplasm": 3640,
"deviate-crocolisk": 5053,
"deviate-lasher": 5055,
"deviate-shambler": 5761,
"deviate-faerie-dragon": 5912,
"lady-anacondra": 3671,
kresh: 3653,
"lord-cobrahn": 3669,
"lord-pythas": 3670,
skum: 3674,
"lord-serpentis": 3673,
"verdan-the-everliving": 5775,
"mutanus-the-devourer": 3654,
"disciple-of-naralex": 3678,
"nightmare-ectoplasm": 5763,
"deviate-viper": 5755,
"deviate-adder": 5048,
});
interface WailingReferenceShape {
readonly wailingCaverns: {
readonly abilitiesByEntry: Readonly<Record<string, readonly EnemyAttackDefinition[]>>;
readonly unsupportedRequiredBossActions: readonly unknown[];
};
}
const WAILING = (referenceData as unknown as WailingReferenceShape).wailingCaverns;
function serverCombat(
definition: PopulationEntityDefinition,
serverEntry: number,
): EnemyCombatDefinition {
const template = creatureTemplateReference(serverEntry);
const basicAttack: EnemyAttackDefinition = {
...DEFAULT_ENEMY_ATTACK,
cooldownMs: template?.baseAttackTimeMs ?? DEFAULT_ENEMY_ATTACK.cooldownMs,
repeatCooldownMs: [
template?.baseAttackTimeMs ?? DEFAULT_ENEMY_ATTACK.cooldownMs,
template?.baseAttackTimeMs ?? DEFAULT_ENEMY_ATTACK.cooldownMs,
],
initialCooldownMs: [450, 450],
range: definition.kind === "boss" ? 5.2 : 4.3,
};
const scripted = WAILING.abilitiesByEntry[String(serverEntry)] ?? [];
return Object.freeze({
serverEntry,
healthMultiplier: definition.kind === "boss" ? 0.86 : 1,
damageMultiplier: 1,
moveSpeed: definition.combat?.moveSpeed,
leashRange: definition.combat?.leashRange ?? (definition.kind === "boss" ? 55 : 42),
attacks: Object.freeze([basicAttack, ...scripted]),
});
}
/** Adds pinned server combat facts without replacing authored models or placement. */
export function withWailingServerCombat(
definitions: PopulationDefinitionMap,
): PopulationDefinitionMap {
return Object.freeze(Object.fromEntries(
Object.entries(definitions).map(([id, definition]) => {
const serverEntry = ENTITY_SERVER_ENTRIES[id];
if (!serverEntry) return [id, definition];
return [
id,
Object.freeze({
...definition,
combat: serverCombat(definition, serverEntry),
}),
];
}),
));
}
export function wailingServerEntry(entityId: string): number | null {
return ENTITY_SERVER_ENTRIES[entityId] ?? null;
}
export function unsupportedWailingRequiredBossActions(): readonly unknown[] {
return WAILING.unsupportedRequiredBossActions;
}