58 lines
2.3 KiB
TypeScript
58 lines
2.3 KiB
TypeScript
import type { AbilityDefinition } from "./abilityCatalog";
|
|
import { targetingRulesForAbility } from "./abilityRules";
|
|
import { ROM_PHYSICAL_DARK_DAMAGE_PROFILE } from "./combatDamageProfile";
|
|
import type { CombatDamageProfile } from "./combatDamageProfile";
|
|
|
|
export const ROM_PSYCHIC_WARRIOR_PASSIVE_ID = 499868;
|
|
export const ROM_PSYCHIC_WARRIOR_PRIMARY_CLASS_ID = "rom-warlock";
|
|
export const ROM_PSYCHIC_WARRIOR_SECONDARY_CLASS_ID = "rom-warrior";
|
|
|
|
export interface RomPsychicWarriorCasterContext {
|
|
readonly primaryClassId: AbilityDefinition["classId"];
|
|
readonly secondaryClassId: AbilityDefinition["classId"] | null;
|
|
readonly learnedPassiveSpellIds: readonly number[];
|
|
/** True only when the triggering action is a CoA-style magical spell. */
|
|
readonly isMagicalSpell: boolean;
|
|
}
|
|
|
|
export interface RomPsychicWarriorWeaponRider {
|
|
readonly damageProfile: CombatDamageProfile;
|
|
readonly targetMode: "area" | "single-target";
|
|
readonly weaponHand: "main-hand";
|
|
/** Coefficient passed to the combat engine's main-hand weapon-DPS scaling. */
|
|
readonly weaponDpsCoefficient: number;
|
|
}
|
|
|
|
/**
|
|
* Resolve CoA Psychic Warrior's quantified weapon choice for a damaging
|
|
* Warlock spell. The combat model has no integrated Physical Dark composite
|
|
* damage type yet, so this descriptor preserves both tags and must not be
|
|
* collapsed to one DamageSchool by a caller.
|
|
*/
|
|
export function describeRomPsychicWarriorWeaponRider(
|
|
ability: AbilityDefinition,
|
|
caster: RomPsychicWarriorCasterContext,
|
|
): RomPsychicWarriorWeaponRider | null {
|
|
if (caster.primaryClassId !== ROM_PSYCHIC_WARRIOR_PRIMARY_CLASS_ID
|
|
|| caster.secondaryClassId !== ROM_PSYCHIC_WARRIOR_SECONDARY_CLASS_ID
|
|
|| !caster.learnedPassiveSpellIds.includes(ROM_PSYCHIC_WARRIOR_PASSIVE_ID)
|
|
|| !caster.isMagicalSpell
|
|
|| ability.source !== "runewaker"
|
|
|| ability.classId !== "rom-warlock"
|
|
|| ability.passive
|
|
|| !ability.effects.some((effect) => effect.kind === "damage")) {
|
|
return null;
|
|
}
|
|
|
|
const targeting = targetingRulesForAbility(ability);
|
|
const isAreaDamage = targeting.shape !== "unit"
|
|
|| (targeting.maximumTargets ?? 0) > 1
|
|
|| (targeting.radius ?? 0) > 0;
|
|
return {
|
|
damageProfile: ROM_PHYSICAL_DARK_DAMAGE_PROFILE,
|
|
targetMode: isAreaDamage ? "area" : "single-target",
|
|
weaponHand: "main-hand",
|
|
weaponDpsCoefficient: isAreaDamage ? 1.875 : 10.5,
|
|
};
|
|
}
|