34 lines
1.8 KiB
TypeScript
34 lines
1.8 KiB
TypeScript
import type { AbilityDefinition, AbilityEffect } from "./abilityCatalog";
|
|
|
|
export type PartyBuffScope = "party" | "tank" | "healer";
|
|
export interface PartyBuffRule { readonly abilityId: string; readonly scope: PartyBuffScope }
|
|
export interface PartyBuffPolicy { readonly schemaVersion: 1; readonly rules: readonly PartyBuffRule[] }
|
|
|
|
export const DEFAULT_PARTY_BUFF_POLICY: PartyBuffPolicy = { schemaVersion: 1, rules: [] };
|
|
|
|
export function normalizePartyBuffPolicy(value: unknown): PartyBuffPolicy {
|
|
if (!value || typeof value !== "object") return DEFAULT_PARTY_BUFF_POLICY;
|
|
const policy = value as Partial<PartyBuffPolicy>;
|
|
if (policy.schemaVersion !== 1 || !Array.isArray(policy.rules)) return DEFAULT_PARTY_BUFF_POLICY;
|
|
const seen = new Set<string>();
|
|
return {
|
|
schemaVersion: 1,
|
|
rules: policy.rules.flatMap((rule) => {
|
|
if (!rule || typeof rule.abilityId !== "string" || !/^[a-z0-9][a-z0-9:._-]{0,127}$/i.test(rule.abilityId)
|
|
|| !["party", "tank", "healer"].includes(rule.scope) || seen.has(rule.abilityId)) return [];
|
|
seen.add(rule.abilityId);
|
|
return [{ abilityId: rule.abilityId, scope: rule.scope }];
|
|
}).slice(0, 500),
|
|
};
|
|
}
|
|
|
|
export function permanentBuffEffects(ability: AbilityDefinition): readonly Extract<AbilityEffect, { kind: "apply-aura" }>[] {
|
|
if (ability.passive || ability.target === "hostile" || ability.talentNodeId || ability.talentEntryId !== undefined) return [];
|
|
if (ability.effects.some((effect) => effect.kind !== "apply-aura" && effect.kind !== "unsupported")) return [];
|
|
return ability.effects.filter((effect): effect is Extract<AbilityEffect, { kind: "apply-aura" }> => (
|
|
effect.kind === "apply-aura" && effect.aura.disposition === "buff"
|
|
&& !effect.aura.procs?.length && !effect.aura.controlImmunities?.length
|
|
&& Boolean(effect.aura.modifiers?.length)
|
|
));
|
|
}
|