forked from phenom/healer-man
81 lines
3.8 KiB
TypeScript
81 lines
3.8 KiB
TypeScript
export interface BossBalanceOverride {
|
|
readonly id: string;
|
|
readonly dungeonId: string;
|
|
readonly entityId: string;
|
|
readonly minimumLevel?: number;
|
|
readonly maximumLevel?: number;
|
|
readonly healthScale?: number;
|
|
readonly damageScale?: number;
|
|
readonly reason: string;
|
|
}
|
|
|
|
export interface ResolvedBossBalanceOverride {
|
|
readonly healthScale: number;
|
|
readonly damageScale: number;
|
|
readonly matchedOverrideIds: readonly string[];
|
|
}
|
|
|
|
/**
|
|
* Evidence-based exceptions to the shared boss curve. Entries may cover one
|
|
* level, a bracket, or every level when both bounds are omitted. Multipliers
|
|
* compose so a broad boss correction can coexist with a narrower bracket fix.
|
|
*/
|
|
export const BOSS_BALANCE_OVERRIDES: readonly BossBalanceOverride[] = Object.freeze([
|
|
{ id: "level-80-amanitar-pressure", dungeonId: "ahnkahet-old-kingdom", entityId: "entry-30258",
|
|
minimumLevel: 80, maximumLevel: 80, damageScale: 0.7,
|
|
reason: "Ready-five audit: 100% wipes and 3.14x median incoming pressure." },
|
|
{ id: "level-80-warp-splinter-pressure", dungeonId: "botanica", entityId: "entry-17977",
|
|
minimumLevel: 80, maximumLevel: 80, damageScale: 0.56,
|
|
reason: "Ready-five audit: 100% wipes and 3.90x median incoming pressure." },
|
|
{ id: "level-80-maiden-of-grief-pressure", dungeonId: "halls-of-stone", entityId: "entry-27975",
|
|
minimumLevel: 80, maximumLevel: 80, damageScale: 0.56,
|
|
reason: "Ready-five audit: 100% wipes and 3.93x median incoming pressure." },
|
|
{ id: "level-80-ick-pressure", dungeonId: "pit-of-saron", entityId: "entry-36476",
|
|
minimumLevel: 80, maximumLevel: 80, damageScale: 0.54,
|
|
reason: "Ready-five audit: 100% wipes and 4.11x median incoming pressure." },
|
|
{ id: "level-80-murmur-pressure", dungeonId: "shadow-labyrinth", entityId: "entry-18708",
|
|
minimumLevel: 80, maximumLevel: 80, damageScale: 0.68,
|
|
reason: "Ready-five audit: 100% wipes and 3.22x median incoming pressure." },
|
|
{ id: "level-80-keristrasza-pressure", dungeonId: "the-nexus", entityId: "entry-26723",
|
|
minimumLevel: 80, maximumLevel: 80, damageScale: 0.7,
|
|
reason: "Ready-five audit: 100% wipes and 3.12x median incoming pressure." },
|
|
{ id: "level-80-drakos-pressure", dungeonId: "the-oculus", entityId: "entry-27654",
|
|
minimumLevel: 80, maximumLevel: 80, damageScale: 0.45,
|
|
reason: "Ready-five audit: 100% wipes and 4.89x median incoming pressure." },
|
|
{ id: "level-80-black-knight-phase-3-pressure", dungeonId: "trial-of-the-champion",
|
|
entityId: "wrath-event-black-knight-phase-3", minimumLevel: 80, maximumLevel: 80, damageScale: 0.5,
|
|
reason: "Ready-five audit: 100% wipes and 4.33x median incoming pressure." },
|
|
]);
|
|
|
|
function sourceDungeonId(dungeonId: string, entityId: string): string {
|
|
const prefix = "boss-testing:";
|
|
const suffix = `:${entityId}`;
|
|
return dungeonId.startsWith(prefix) && dungeonId.endsWith(suffix)
|
|
? dungeonId.slice(prefix.length, -suffix.length)
|
|
: dungeonId;
|
|
}
|
|
|
|
function safeScale(value: number | undefined): number {
|
|
return Number.isFinite(value) ? Math.max(0.05, value!) : 1;
|
|
}
|
|
|
|
export function resolveBossBalanceOverride(
|
|
dungeonId: string,
|
|
entityId: string,
|
|
level: number,
|
|
overrides: readonly BossBalanceOverride[] = BOSS_BALANCE_OVERRIDES,
|
|
): ResolvedBossBalanceOverride {
|
|
const sourceId = sourceDungeonId(dungeonId, entityId);
|
|
const matching = overrides.filter((entry) => (
|
|
entry.dungeonId === sourceId
|
|
&& entry.entityId === entityId
|
|
&& level >= (entry.minimumLevel ?? Number.NEGATIVE_INFINITY)
|
|
&& level <= (entry.maximumLevel ?? Number.POSITIVE_INFINITY)
|
|
));
|
|
return Object.freeze({
|
|
healthScale: matching.reduce((scale, entry) => scale * safeScale(entry.healthScale), 1),
|
|
damageScale: matching.reduce((scale, entry) => scale * safeScale(entry.damageScale), 1),
|
|
matchedOverrideIds: Object.freeze(matching.map((entry) => entry.id)),
|
|
});
|
|
}
|