221 lines
11 KiB
TypeScript
221 lines
11 KiB
TypeScript
import type { AbilityDefinition } from "./abilityCatalog";
|
||
import type { AuraDefinition, DamageSchool } from "./combatAuras";
|
||
|
||
export const WOW335_WARLOCK_METAMORPHOSIS_AURA_TAG = "wow335-warlock-metamorphosis";
|
||
export const WOW335_WARLOCK_METAMORPHOSIS_FORM_ID = 22;
|
||
export const WOW335_WARLOCK_METAMORPHOSIS_IMMOLATION_TAG = "wow335-warlock-immolation-aura";
|
||
export const WOW335_WARLOCK_METAMORPHOSIS_IMMOLATION_AP_AURA_TAG = "wow335-warlock-immolation-ap";
|
||
export const WOW335_WARLOCK_METAMORPHOSIS_FORM_ABILITY_IDS = Object.freeze([
|
||
"wow335-warlock-shadow-cleave",
|
||
"wow335-warlock-challenging-howl",
|
||
"wow335-warlock-demon-charge",
|
||
"wow335-warlock-immolation-aura",
|
||
] as const);
|
||
|
||
export interface WarlockMetamorphosisEffects {
|
||
readonly rank: 1;
|
||
readonly durationMs: 30_000;
|
||
readonly cooldownMs: 180_000;
|
||
readonly armorContributionPercent: 130;
|
||
readonly damagePercent: 15;
|
||
readonly meleeCritChanceTakenReductionPercent: 6;
|
||
readonly stunSnareDurationReductionPercent: 25;
|
||
readonly allowedSchools: readonly ["fire", "shadow"];
|
||
/** PvP-only modifier is sourced but has no player-target model here. */
|
||
readonly pvpDamageBonusPercent: null;
|
||
}
|
||
|
||
/**
|
||
* Values come from the generated local Metamorphosis talent-1886 row and its
|
||
* source spells 47241, 54817, and 54879 in the local 3.3.5a talent DBC.
|
||
* The PvP-only +10% damage tooltip rider is omitted because this runtime has
|
||
* no PvP player-target model.
|
||
*/
|
||
export function wow335WarlockMetamorphosisEffectsForRank(rank: number): WarlockMetamorphosisEffects | null {
|
||
if (!Number.isFinite(rank) || Math.trunc(rank) < 1) return null;
|
||
return {
|
||
rank: 1,
|
||
durationMs: 30_000,
|
||
cooldownMs: 180_000,
|
||
armorContributionPercent: 130,
|
||
damagePercent: 15,
|
||
meleeCritChanceTakenReductionPercent: 6,
|
||
stunSnareDurationReductionPercent: 25,
|
||
allowedSchools: ["fire", "shadow"],
|
||
pvpDamageBonusPercent: null,
|
||
};
|
||
}
|
||
|
||
export interface WarlockMetamorphosisAbilityContext {
|
||
readonly school?: DamageSchool;
|
||
readonly schools?: readonly DamageSchool[];
|
||
/** Explicit local metadata for spells that are allowed during shapeshift. */
|
||
readonly usableWhileShapeshifted?: boolean;
|
||
}
|
||
|
||
/** The local Metamorphosis description permits Fire/Shadow or shapeshift-safe spells. */
|
||
export function warlockMetamorphosisAbilityEligible(
|
||
isMetamorphosisActive: boolean,
|
||
ability: WarlockMetamorphosisAbilityContext,
|
||
): boolean {
|
||
const schools = [ability.school, ...(ability.schools ?? [])];
|
||
return !isMetamorphosisActive
|
||
|| ability.usableWhileShapeshifted === true
|
||
|| schools.some((school) => school === "fire" || school === "shadow");
|
||
}
|
||
|
||
/** Gate based only on explicit spell schools or explicit shapeshift-safe text. */
|
||
export function warlockMetamorphosisCanCastAbilityWhileActive(
|
||
ability: Pick<AbilityDefinition, "id" | "description" | "effects" | "castRules">,
|
||
): boolean {
|
||
if ((WOW335_WARLOCK_METAMORPHOSIS_FORM_ABILITY_IDS as readonly string[]).includes(ability.id)) return true;
|
||
const schools: DamageSchool[] = ability.effects.flatMap((effect) => (
|
||
(effect.kind === "damage" || effect.kind === "dot") && effect.school ? [effect.school] : []
|
||
));
|
||
if (ability.castRules?.school) schools.push(ability.castRules.school);
|
||
if (!schools.length && ability.effects.some((effect) => effect.kind === "damage" || effect.kind === "dot")) {
|
||
const text = ability.description.toLowerCase();
|
||
if (/\bshadow\s+(?:damage|spell|magic)\b/.test(text)) schools.push("shadow");
|
||
else if (/\bfire\s+(?:damage|spell|magic)\b/.test(text)) schools.push("fire");
|
||
}
|
||
return warlockMetamorphosisAbilityEligible(true, {
|
||
schools,
|
||
usableWhileShapeshifted: /\busable while shapeshifted\b/i.test(ability.description),
|
||
});
|
||
}
|
||
|
||
export function warlockMetamorphosisFormActionReady(abilityId: string, isFormActive: boolean): boolean {
|
||
return !(WOW335_WARLOCK_METAMORPHOSIS_FORM_ABILITY_IDS as readonly string[]).includes(abilityId)
|
||
|| isFormActive;
|
||
}
|
||
|
||
export function wow335WarlockMetamorphosisControlDuration(
|
||
durationMs: number,
|
||
mechanic: string,
|
||
isFormActive: boolean,
|
||
): number {
|
||
const safeDuration = Math.max(0, Number.isFinite(durationMs) ? durationMs : 0);
|
||
return isFormActive && ["stun", "root", "slow"].includes(mechanic)
|
||
? Math.round(safeDuration * 0.75)
|
||
: safeDuration;
|
||
}
|
||
|
||
/** Spell.dbc Immolated child: tooltip formula is 4.5 × player level − 3. */
|
||
export function wow335WarlockImmolationAttackPowerReduction(level: number): number {
|
||
const safeLevel = Math.max(1, Math.trunc(Number.isFinite(level) ? level : 1));
|
||
return Math.max(0, Math.round(4.5 * safeLevel - 3));
|
||
}
|
||
|
||
export function wow335WarlockImmolationAttackPowerAura(level: number): AuraDefinition {
|
||
const reduction = wow335WarlockImmolationAttackPowerReduction(level);
|
||
return {
|
||
id: `wow335:warlock:immolation-ap:${reduction}`,
|
||
name: "Immolated",
|
||
description: `Reduces attack power by ${reduction} for 30 seconds.`,
|
||
disposition: "debuff",
|
||
durationMs: 30_000,
|
||
maxStacks: 1,
|
||
stackBehavior: "replace",
|
||
uniqueBySource: true,
|
||
utilityTags: [WOW335_WARLOCK_METAMORPHOSIS_IMMOLATION_AP_AURA_TAG],
|
||
modifiers: [{ kind: "stat", stat: "attack-power", operation: "flat", value: -reduction }],
|
||
};
|
||
}
|
||
|
||
/** Numeric modifiers currently expressible by the shared aura resolver. */
|
||
export function wow335WarlockMetamorphosisAuraForRank(rank: number): AuraDefinition | null {
|
||
const effects = wow335WarlockMetamorphosisEffectsForRank(rank);
|
||
if (!effects) return null;
|
||
return {
|
||
id: "wow335:warlock:metamorphosis",
|
||
name: "Metamorphosis",
|
||
description: "Increases armor contribution from cloth and leather by 130% and damage dealt by 15%; reduces melee critical hits against you by 6% and stun and snare durations by 25% while transformed. The PvP-only +10% damage rider is not applied because PvP player targets are unsupported.",
|
||
disposition: "buff",
|
||
durationMs: effects.durationMs,
|
||
maxStacks: 1,
|
||
stackBehavior: "replace",
|
||
uniqueBySource: true,
|
||
exclusiveGroup: "warlock:form",
|
||
utilityTags: ["shapeshift", WOW335_WARLOCK_METAMORPHOSIS_AURA_TAG],
|
||
modifiers: [
|
||
{ kind: "stat", stat: "armor", operation: "percent", value: effects.armorContributionPercent / 100 },
|
||
{ kind: "stat", stat: "incoming-melee-critical-strike", operation: "flat", value: -effects.meleeCritChanceTakenReductionPercent },
|
||
{ kind: "damage", direction: "dealt", operation: "percent", value: effects.damagePercent / 100 },
|
||
],
|
||
};
|
||
}
|
||
|
||
const formOnly = { sourceRankText: "Demon", formOnly: true } as const;
|
||
|
||
/** These rankless buttons are reconstructed from their local Spell.dbc rows and children. */
|
||
export const WOW335_WARLOCK_METAMORPHOSIS_FORM_ABILITIES: readonly AbilityDefinition[] = [
|
||
{
|
||
id: WOW335_WARLOCK_METAMORPHOSIS_FORM_ABILITY_IDS[0], classId: "warlock", dbcSpellId: 50581,
|
||
name: "Shadow Cleave", unlockLevel: 1, sourceUnlockLevel: 1,
|
||
icon: "/assets/ui/spells/spell_shadow_shadowfury.png", sigil: "SC",
|
||
description: "Inflicts 110 Shadow damage to an enemy target and nearby allies, affecting up to 3 targets. Costs 4% base mana.",
|
||
target: "hostile", range: { min: 0, max: 5 }, castMode: "instant", castTimeMs: 0,
|
||
cooldownMs: 6_000, gcdMs: 0,
|
||
cost: { resource: "mana", amount: 4, percentage: true, percentageBasis: "base-mana" },
|
||
effects: [{ kind: "damage", coefficient: 0, school: "shadow", basePoints: 110, dieSides: 1, bonusPowerCoefficient: 1 }],
|
||
targeting: { shape: "chain", maximumTargets: 3 },
|
||
source: "wow335-progression", ...formOnly,
|
||
} as AbilityDefinition,
|
||
{
|
||
id: WOW335_WARLOCK_METAMORPHOSIS_FORM_ABILITY_IDS[1], classId: "warlock", dbcSpellId: 59671,
|
||
name: "Challenging Howl", unlockLevel: 1, sourceUnlockLevel: 1,
|
||
icon: "/assets/ui/spells/ability_warlock_demonicempowerment.png", sigil: "CH",
|
||
description: "Forces all nearby enemies within 10 yards to focus attacks on you for 6 seconds.",
|
||
target: "self", range: { min: 0, max: 0 }, radius: 10, castMode: "instant", castTimeMs: 0,
|
||
cooldownMs: 180_000, gcdMs: 1_500, cost: { resource: "rage", amount: 0 },
|
||
effects: [{ kind: "taunt", durationMs: 6_000 }],
|
||
targeting: { shape: "circle", radius: 10 }, source: "wow335-progression", ...formOnly,
|
||
} as AbilityDefinition,
|
||
{
|
||
id: WOW335_WARLOCK_METAMORPHOSIS_FORM_ABILITY_IDS[2], classId: "warlock", dbcSpellId: 54785,
|
||
name: "Demon Charge", unlockLevel: 1, sourceUnlockLevel: 1,
|
||
icon: "/assets/ui/spells/ability_warlock_demonicempowerment.png", sigil: "DC",
|
||
description: "Charge an enemy, stunning it for 3 seconds. Range 8–25 yards; 45 second cooldown.",
|
||
target: "hostile", range: { min: 8, max: 25 }, castMode: "instant", castTimeMs: 0,
|
||
cooldownMs: 45_000, gcdMs: 1_500, cost: { resource: "mana", amount: 0 },
|
||
effects: [
|
||
{ kind: "movement", movement: "charge", toward: "target" },
|
||
{ kind: "status", status: "stun", durationMs: 3_000 },
|
||
], source: "wow335-progression", ...formOnly,
|
||
} as AbilityDefinition,
|
||
{
|
||
id: WOW335_WARLOCK_METAMORPHOSIS_FORM_ABILITY_IDS[3], classId: "warlock", dbcSpellId: 50589,
|
||
name: "Immolation Aura", unlockLevel: 1, sourceUnlockLevel: 1,
|
||
icon: "/assets/ui/spells/spell_fire_selfdestruct.png", sigil: "IA",
|
||
description: "For 10 seconds, burns nearby enemies for 251 Fire damage plus 11.5 per level and 14.3% spell power every second within 8 yards, reducing their attack power by 4.5 × level − 3 for 30 seconds. Costs 64% base mana.",
|
||
target: "self", range: { min: 0, max: 0 }, radius: 8, castMode: "instant", castTimeMs: 0,
|
||
cooldownMs: 30_000, gcdMs: 1_500,
|
||
cost: { resource: "mana", amount: 64, percentage: true, percentageBasis: "base-mana" },
|
||
effects: [
|
||
{ kind: "dot", coefficient: 0, school: "fire", basePoints: 251, dieSides: 1, pointsPerLevel: 11.5,
|
||
bonusPowerCoefficient: 0.143, sourceLevel: 1, ticks: 10, intervalMs: 1_000, tag: WOW335_WARLOCK_METAMORPHOSIS_IMMOLATION_TAG },
|
||
{ kind: "apply-aura", recipient: "caster", aura: {
|
||
id: "wow335:warlock:immolation-aura", name: "Immolation Aura",
|
||
description: "Emits Fire pulses for 10 seconds. Loss of control suppresses pulses.",
|
||
disposition: "buff", durationMs: 10_000, maxStacks: 1, stackBehavior: "replace",
|
||
utilityTags: [WOW335_WARLOCK_METAMORPHOSIS_IMMOLATION_TAG],
|
||
}, sourceEffectType: 6, sourceAuraType: 23, miscValue: 0, triggerSpellId: 50590 },
|
||
],
|
||
targeting: { shape: "circle", radius: 8 }, source: "wow335-progression", ...formOnly,
|
||
} as AbilityDefinition,
|
||
];
|
||
|
||
export function wow335WarlockMetamorphosisAbility(): AbilityDefinition {
|
||
return {
|
||
id: "wow335-warlock-metamorphosis", classId: "warlock", dbcSpellId: 59672,
|
||
name: "Metamorphosis", unlockLevel: 1, sourceUnlockLevel: 1,
|
||
icon: "/assets/ui/spells/spell_shadow_demonform.png", sigil: "ME",
|
||
description: "Transform into a Demon for 30 seconds. Increases armor contribution from cloth and leather items by 130% and damage dealt by 15%; reduces melee critical chance taken by 6% and stun/snare duration by 25%. Grants four Demon-only abilities. Only Fire/Shadow spells and abilities or spells explicitly usable while shapeshifted may be cast. PvP-only +10% damage is unsupported.",
|
||
target: "self", range: { min: 0, max: 0 }, castMode: "instant", castTimeMs: 0,
|
||
cooldownMs: 180_000, gcdMs: 0, cost: { resource: "mana", amount: 0 },
|
||
effects: [{ kind: "apply-aura", recipient: "caster", aura: wow335WarlockMetamorphosisAuraForRank(1)!,
|
||
sourceEffectType: 6, sourceAuraType: 36, miscValue: WOW335_WARLOCK_METAMORPHOSIS_FORM_ID, triggerSpellId: 0 }],
|
||
talentNodeId: "talent-1886", source: "wow335-progression",
|
||
};
|
||
}
|