diff --git a/src/game/talentModifiers.test.ts b/src/game/talentModifiers.test.ts index c55b8a37..e7b09f52 100644 --- a/src/game/talentModifiers.test.ts +++ b/src/game/talentModifiers.test.ts @@ -174,6 +174,26 @@ describe("talent runtime modifiers", () => { expect(applyTalentModifierValue(10_000, disciplineModifiers, "cooldown-flat-ms", { abilityName: "Mortal Strike" })).toBe(10_000); }); + it("keeps Blood Frenzy's target-state damage scope broad", () => { + const bloodFrenzy = TALENT_NODES.find((node) => node.id === "talent-1664")!; + expect(bloodFrenzy.rankDescriptions[1]).toBe( + "Increases your melee attack speed by 4%. Rend and Deep Wounds increase all Physical damage caused to that target by 4%. Does not stack with similar effects.", + ); + + const modifiers = talentModifiersForRanks({ [bloodFrenzy.id]: 2 }, "warrior"); + expect(modifiers).toContainEqual(expect.objectContaining({ + kind: "damage-percent", + amount: 4, + scope: "all Physical damage caused to that target", + sourceTalentId: bloodFrenzy.id, + rank: 2, + })); + for (const abilityName of ["Mortal Strike", "Rend", "Deep Wounds"]) { + expect(applyTalentModifierValue(100, modifiers, "damage-percent", { abilityName }), abilityName) + .toBeCloseTo(104); + } + }); + it("keeps Morbidity's Death Coil clauses and Death and Decay cooldown on their named spells", () => { const morbidity = TALENT_NODES.find((node) => node.id === "talent-1933")!; expect(morbidity.name).toBe("Morbidity"); diff --git a/src/game/talentModifiers.ts b/src/game/talentModifiers.ts index 7b19011f..e1a89fd9 100644 --- a/src/game/talentModifiers.ts +++ b/src/game/talentModifiers.ts @@ -451,7 +451,11 @@ export interface TalentModifierContext { function namedModifierTarget(scope: string): string | undefined { const scopeWithoutAmount = scope.replace(/\s+by\s+-?\d+(?:\.\d+)?\s*(?:%|secs?)(?:\s*[.!?])?$/i, ""); - const target = scopeWithoutAmount.match(/\b(?:of|on|with|for|to)\s+(?:your\s+)?([^,.!?]+)$/)?.[1]?.trim(); + // These are the source tooltip forms used for named abilities (for example, + // "cooldown on Death and Decay" and "damage of your Fire Blast"). Other + // prepositions can describe a target condition instead, as in "damage + // caused to that target", and must leave the modifier broadly applicable. + const target = scopeWithoutAmount.match(/\b(?:of|on)\s+(?:your\s+)?([^,.!?]+)$/)?.[1]?.trim(); if (!target) return undefined; // Generic descriptors describe a category of spells, effects, or targets.