Files
healer-man/src/game/manastormChaoticLink.ts
T
2026-08-18 16:22:19 -04:00

93 lines
2.8 KiB
TypeScript

import type { MobCombatState } from "./combatStore";
import type {
ManastormEncounterDefinition,
ManastormPhase,
} from "./manastorm";
/**
* Ascension's published Chapter 2 tuning: each remaining Chaotic Link stack
* grants roughly 25% boss health and 10% boss damage. The number of stacks is
* approximately half of the creatures between the party and the boss.
*/
export const MANASTORM_CHAOTIC_LINK_HEALTH_PER_STACK = 0.25;
export const MANASTORM_CHAOTIC_LINK_DAMAGE_PER_STACK = 0.10;
export interface ManastormChaoticLinkState {
readonly guardianCount: number;
readonly defeatedGuardians: number;
readonly requiredGuardianKills: number;
readonly activeStacks: number;
readonly broken: boolean;
readonly bossHealthMultiplier: number;
readonly bossDamageMultiplier: number;
}
function uniqueGuardianIds(
encounter: ManastormEncounterDefinition,
): readonly string[] {
return [...new Set(
(encounter.trashRuntimeIds ?? [])
.filter((runtimeId) => Boolean(runtimeId) && runtimeId !== encounter.bossRuntimeId),
)];
}
/**
* Missing guardian registrations count as alive. This prevents a partially
* mounted scene from prematurely breaking the link before its actors exist.
*/
export function manastormChaoticLinkState(
encounter: ManastormEncounterDefinition,
mobs: Readonly<Record<string, MobCombatState>>,
): ManastormChaoticLinkState {
const guardianIds = uniqueGuardianIds(encounter);
const guardianCount = guardianIds.length;
const defeatedGuardians = guardianIds.filter(
(runtimeId) => mobs[runtimeId]?.dead === true,
).length;
const requiredGuardianKills = encounter.chaoticLinkEnabled === false
? 0
: Math.max(
0,
Math.min(
guardianCount,
Math.trunc(encounter.requiredGuardianKills ?? Math.ceil(guardianCount / 2)),
),
);
const activeStacks = Math.max(0, requiredGuardianKills - defeatedGuardians);
return Object.freeze({
guardianCount,
defeatedGuardians,
requiredGuardianKills,
activeStacks,
broken: activeStacks === 0,
bossHealthMultiplier:
1 + activeStacks * MANASTORM_CHAOTIC_LINK_HEALTH_PER_STACK,
bossDamageMultiplier:
1 + activeStacks * MANASTORM_CHAOTIC_LINK_DAMAGE_PER_STACK,
});
}
/**
* Chaotic Link requires the boss and its linked creatures to coexist. The boss
* may be challenged immediately at full strength; killing approximately half
* of the linked guardians first removes the aura.
*/
export function manastormChaoticLinkRuntimeIds(
encounter: ManastormEncounterDefinition | null,
phase: ManastormPhase,
): readonly string[] {
if (
!encounter
|| phase === "idle"
|| phase === "next"
|| phase === "failed"
|| phase === "complete"
) {
return [];
}
return [...new Set([
...(encounter.trashRuntimeIds ?? []),
encounter.bossRuntimeId,
])];
}