93 lines
2.8 KiB
TypeScript
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,
|
|
])];
|
|
}
|