From 2a537e21eb51adc349cb972af6e7c02a0b69e81b Mon Sep 17 00:00:00 2001 From: Sean <103148620+DoxAshe@users.noreply.github.com> Date: Thu, 2 May 2024 18:44:48 -0400 Subject: [PATCH] [Shadow] Add statistics for several Shadow Talents. (#6747) * Add PsychicLink statistic * Update PhantasmalPathogen.tsx * Fix PsychicLink Statistic * Add Voidtouched Statistic * Add Mind's Eye Statistic * Add DistortedReality Statistic * Fix statistics to account for free DevouringPlague * Update CHANGELOG.tsx * Add statistic for Maddening Touch * Update Dark Evangelism Statistic * Fix Mistake in PsychicLink All damage of Devouring plague counts towards Psychic link, not just the non periodic part. * Add Statistic for Mind Melt * Add Mastermind Statistic * Update Mastermind.tsx * Fix Mastermind * Minor fixes to new statistics * Update example report * Update mastermind to be clearer * Update != to !== in DR and ME --- .../retail/priest/shadow/CHANGELOG.tsx | 1 + src/analysis/retail/priest/shadow/CONFIG.tsx | 2 +- .../retail/priest/shadow/CombatLogParser.tsx | 12 +++ .../retail/priest/shadow/constants.ts | 7 ++ .../shadow/modules/talents/DarkEvangelism.tsx | 94 ++++++++++++++++-- .../modules/talents/DistortedReality.tsx | 63 ++++++++++++ .../modules/talents/Maddening Touch.tsx | 60 ++++++++++++ .../shadow/modules/talents/Mastermind.tsx | 96 +++++++++++++++++++ .../shadow/modules/talents/MindMelt.tsx | 86 +++++++++++++++++ .../shadow/modules/talents/MindsEye.tsx | 48 ++++++++++ .../shadow/modules/talents/PsychicLink.tsx | 9 +- .../shadow/modules/talents/VoidTouched.tsx | 41 ++++++++ src/common/SPELLS/priest.ts | 11 +++ 13 files changed, 515 insertions(+), 15 deletions(-) create mode 100644 src/analysis/retail/priest/shadow/modules/talents/DistortedReality.tsx create mode 100644 src/analysis/retail/priest/shadow/modules/talents/Maddening Touch.tsx create mode 100644 src/analysis/retail/priest/shadow/modules/talents/Mastermind.tsx create mode 100644 src/analysis/retail/priest/shadow/modules/talents/MindMelt.tsx create mode 100644 src/analysis/retail/priest/shadow/modules/talents/MindsEye.tsx create mode 100644 src/analysis/retail/priest/shadow/modules/talents/VoidTouched.tsx diff --git a/src/analysis/retail/priest/shadow/CHANGELOG.tsx b/src/analysis/retail/priest/shadow/CHANGELOG.tsx index ca3a96fb1bd..1075897c60d 100644 --- a/src/analysis/retail/priest/shadow/CHANGELOG.tsx +++ b/src/analysis/retail/priest/shadow/CHANGELOG.tsx @@ -5,6 +5,7 @@ import { Arlie, DoxAshe, Havoc, Sref, ToppleTheNun } from 'CONTRIBUTORS'; import { SpellLink } from 'interface'; export default [ + change(date(2024, 4, 30), <>Add statistics for , , , , , and talents,DoxAshe), change(date(2024, 4, 26), <>Add statistics for talent,DoxAshe), change(date(2024, 4, 22), <>Add statistics for the two and four piece Season 4 tier set,DoxAshe), change(date(2024, 4, 20), <>Fix cooldown of when using .,Arlie), diff --git a/src/analysis/retail/priest/shadow/CONFIG.tsx b/src/analysis/retail/priest/shadow/CONFIG.tsx index 197fbfb7e0b..0c33700f48f 100644 --- a/src/analysis/retail/priest/shadow/CONFIG.tsx +++ b/src/analysis/retail/priest/shadow/CONFIG.tsx @@ -39,7 +39,7 @@ const config: Config = { ), // A recent example report to see interesting parts of the spec. Will be shown on the homepage. - exampleReport: 'report/rbM3z4h7F2Wy9JD6/5-Heroic+Volcoross+-+Kill+(2:52)/Doxashe/standard', + exampleReport: 'report/WRBVrQfGyvaJjhzm/2-Heroic+Terros+-+Kill+(4:22)/Doxashe/standard', guideDefault: true, guideOnly: true, diff --git a/src/analysis/retail/priest/shadow/CombatLogParser.tsx b/src/analysis/retail/priest/shadow/CombatLogParser.tsx index 957f4f01f69..aaaf1c75b28 100644 --- a/src/analysis/retail/priest/shadow/CombatLogParser.tsx +++ b/src/analysis/retail/priest/shadow/CombatLogParser.tsx @@ -53,6 +53,12 @@ import AuspiciousSpirits from './modules/talents/AuspiciousSpirits'; import PhantasmalPathogen from './modules/talents/PhantasmalPathogen'; import TormentedSpirits from './modules/talents/TormentedSpirits'; import PsychicLink from './modules/talents/PsychicLink'; +import VoidTouched from './modules/talents/VoidTouched'; +import MindsEye from './modules/talents/MindsEye'; +import DistortedReality from './modules/talents/DistortedReality'; +import MaddeningTouch from './modules/talents/Maddening Touch'; +import MindMelt from './modules/talents/MindMelt'; +import Mastermind from './modules/talents/Mastermind'; import Tier29FourSet from './modules/tier/Tier29ShadowPriest4Set'; import Tier30 from './modules/tier/Tier30ShadowPriest'; @@ -94,14 +100,19 @@ class CombatLogParser extends MainCombatLogParser { darkEvangelism: DarkEvangelism, deathspeaker: Deathspeaker, dispersion: Dispersion, + distortedReality: DistortedReality, idolOfCthun: IdolOfCthun, idolOfNzoth: IdolOfNzoth, idolOfYoggSaron: IdolOfYoggSaron, idolOfYshaarj: IdolOfYshaarj, inescapableTorment: InescapableTorment, insidiousIre: InsidiousIre, + maddeningTouch: MaddeningTouch, + mastermind: Mastermind, mindDevourer: MindDevourer, mindFlayInsanity: MindFlayInsanity, + mindMelt: MindMelt, + mindsEye: MindsEye, mindSpikeInsanity: MindSpikeInsanity, phantasmalPathogen: PhantasmalPathogen, psychicLink: PsychicLink, @@ -110,6 +121,7 @@ class CombatLogParser extends MainCombatLogParser { tormentedSpirits: TormentedSpirits, unfurlingDarkness: UnfurlingDarkness, voidTorrent: VoidTorrent, + voidTouched: VoidTouched, // Class Talents: deathAndMadness: DeathAndMadness, diff --git a/src/analysis/retail/priest/shadow/constants.ts b/src/analysis/retail/priest/shadow/constants.ts index aeffae80c08..98b7a45a1c5 100644 --- a/src/analysis/retail/priest/shadow/constants.ts +++ b/src/analysis/retail/priest/shadow/constants.ts @@ -26,4 +26,11 @@ export const INSIDIOUS_IRE_DAMAGE_PER_RANK = 0.2; export const PHANTASMAL_PATHOGEN_DAMAGE_PER_RANK = 0.75; +export const MADDENING_TOUCH_DAMAGE_PER_RANK = 0.15; + +export const DARK_EVANGELISM_DAMAGE_PER_RANK = 0.01; + +export const MASTERMIND_CRIT_DAMAGE_PER_RANK = 0.2; +export const MASTERMIND_CRIT_CHANCE_PER_RANK = 0.04; + export const MANIPULATION_COOLDOWN_PER_RANK = 0.5; diff --git a/src/analysis/retail/priest/shadow/modules/talents/DarkEvangelism.tsx b/src/analysis/retail/priest/shadow/modules/talents/DarkEvangelism.tsx index 82a0ff6592a..d9a112ea8bc 100644 --- a/src/analysis/retail/priest/shadow/modules/talents/DarkEvangelism.tsx +++ b/src/analysis/retail/priest/shadow/modules/talents/DarkEvangelism.tsx @@ -1,21 +1,103 @@ import TALENTS from 'common/TALENTS/priest'; -import Analyzer, { Options } from 'parser/core/Analyzer'; -import Enemies from 'parser/shared/modules/Enemies'; +import Analyzer, { Options, SELECTED_PLAYER } from 'parser/core/Analyzer'; +import { ApplyBuffStackEvent, DamageEvent } from 'parser/core/Events'; import SPELLS from 'common/SPELLS'; import uptimeBarSubStatistic from 'parser/ui/UptimeBarSubStatistic'; +import Events from 'parser/core/Events'; import { TrackedBuffEvent } from 'parser/core/Entity'; +import Statistic from 'parser/ui/Statistic'; +import STATISTIC_CATEGORY from 'parser/ui/STATISTIC_CATEGORY'; +import BoringSpellValueText from 'parser/ui/BoringSpellValueText'; +import ItemDamageDone from 'parser/ui/ItemDamageDone'; +import { calculateEffectiveDamage } from 'parser/core/EventCalculateLib'; + +import { DARK_EVANGELISM_DAMAGE_PER_RANK } from '../../constants'; const BAR_COLOR = '#6600CC'; class DarkEvangelism extends Analyzer { + damage = 0; + buffStacks = 0; + + multiplierDarkEvangelism = + this.selectedCombatant.getTalentRank(TALENTS.DARK_EVANGELISM_TALENT) * + DARK_EVANGELISM_DAMAGE_PER_RANK; + constructor(options: Options) { super(options); this.active = this.selectedCombatant.hasTalent(TALENTS.DARK_EVANGELISM_TALENT); + + this.addEventListener( + Events.applybuff.by(SELECTED_PLAYER).spell(SPELLS.DARK_EVANGELISM_TALENT_BUFF), + this.onBuffApplied, + ); + this.addEventListener( + Events.applybuffstack.by(SELECTED_PLAYER).spell(SPELLS.DARK_EVANGELISM_TALENT_BUFF), + this.onBuffStack, + ); + this.addEventListener( + Events.removebuff.by(SELECTED_PLAYER).spell(SPELLS.DARK_EVANGELISM_TALENT_BUFF), + this.onBuffRemoved, + ); + + this.addEventListener( + Events.damage.by(SELECTED_PLAYER).spell(TALENTS.DEVOURING_PLAGUE_TALENT), + this.onDamage, + ); + this.addEventListener( + Events.damage.by(SELECTED_PLAYER).spell(SPELLS.VAMPIRIC_TOUCH), + this.onDamage, + ); + this.addEventListener( + Events.damage.by(SELECTED_PLAYER).spell(SPELLS.SHADOW_WORD_PAIN), + this.onDamage, + ); + this.addEventListener( + Events.damage.by(SELECTED_PLAYER).spell(TALENTS.VOID_TORRENT_TALENT), + this.onDamage, + ); + this.addEventListener(Events.damage.by(SELECTED_PLAYER).spell(SPELLS.MIND_FLAY), this.onDamage); + this.addEventListener( + Events.damage.by(SELECTED_PLAYER).spell(SPELLS.MIND_FLAY_INSANITY_TALENT_DAMAGE), + this.onDamage, + ); + } + + onBuffApplied() { + this.buffStacks = 1; + } + onBuffStack(event: ApplyBuffStackEvent) { + this.buffStacks = event.stack; + } + onBuffRemoved() { + this.buffStacks = 0; + } + + //Dark Evangelism buffs the perodic damage of Vampiric Touch, Shadow Word: Pain, Devouring Plague, Void Torrent, Mind Flay, and Mind Flay Insanity. + onDamage(event: DamageEvent) { + if (event.tick) { + this.damage += calculateEffectiveDamage( + event, + this.multiplierDarkEvangelism * this.buffStacks, + ); + } + } + + statistic() { + return ( + + +
+ +
+
+
+ ); } - static dependencies = { - enemies: Enemies, - }; - protected enemies!: Enemies; get uptime() { return ( diff --git a/src/analysis/retail/priest/shadow/modules/talents/DistortedReality.tsx b/src/analysis/retail/priest/shadow/modules/talents/DistortedReality.tsx new file mode 100644 index 00000000000..40a3a1780a6 --- /dev/null +++ b/src/analysis/retail/priest/shadow/modules/talents/DistortedReality.tsx @@ -0,0 +1,63 @@ +import TALENTS from 'common/TALENTS/priest'; +import Analyzer, { Options, SELECTED_PLAYER } from 'parser/core/Analyzer'; +import { CastEvent, DamageEvent } from 'parser/core/Events'; +import Events from 'parser/core/Events'; +import { calculateEffectiveDamage } from 'parser/core/EventCalculateLib'; +import BoringSpellValueText from 'parser/ui/BoringSpellValueText'; +import ItemDamageDone from 'parser/ui/ItemDamageDone'; +import { formatNumber } from 'common/format'; +import InsanityIcon from 'interface/icons/Insanity'; +import Statistic from 'parser/ui/Statistic'; +import STATISTIC_CATEGORY from 'parser/ui/STATISTIC_CATEGORY'; + +class DistortedReality extends Analyzer { + damage = 0; + insanitySpent = 0; // extra insanity requred to cast spell + multiplierDistortedReality = 0.2; //20% + + constructor(options: Options) { + super(options); + this.active = this.selectedCombatant.hasTalent(TALENTS.DISTORTED_REALITY_TALENT); + this.addEventListener( + Events.damage.by(SELECTED_PLAYER).spell(TALENTS.DEVOURING_PLAGUE_TALENT), + this.onDevouringPlagueDamage, + ); + this.addEventListener( + Events.cast.by(SELECTED_PLAYER).spell(TALENTS.DEVOURING_PLAGUE_TALENT), + this.onDevouringPlagueCast, + ); + } + + onDevouringPlagueDamage(event: DamageEvent) { + this.damage += calculateEffectiveDamage(event, this.multiplierDistortedReality); + } + + onDevouringPlagueCast(event: CastEvent) { + const resource = event.classResources?.at(0)?.cost; //Some buffs grant free Devouring Plagues, which do not have a resource cost + if (resource !== undefined) { + //If devouring Plague is free, then we have not spent the extra insanity + this.insanitySpent += 5; + } + } + + statistic() { + return ( + + +
+ +
+
+ {formatNumber(this.insanitySpent)} Extra Insanity Cost +
+
+
+ ); + } +} + +export default DistortedReality; diff --git a/src/analysis/retail/priest/shadow/modules/talents/Maddening Touch.tsx b/src/analysis/retail/priest/shadow/modules/talents/Maddening Touch.tsx new file mode 100644 index 00000000000..80e26310731 --- /dev/null +++ b/src/analysis/retail/priest/shadow/modules/talents/Maddening Touch.tsx @@ -0,0 +1,60 @@ +import TALENTS from 'common/TALENTS/priest'; +import SPELLS from 'common/SPELLS'; +import Analyzer, { Options, SELECTED_PLAYER } from 'parser/core/Analyzer'; +import { ResourceChangeEvent, DamageEvent } from 'parser/core/Events'; +import Events from 'parser/core/Events'; +import { calculateEffectiveDamage } from 'parser/core/EventCalculateLib'; +import BoringSpellValueText from 'parser/ui/BoringSpellValueText'; +import ItemDamageDone from 'parser/ui/ItemDamageDone'; +import ItemInsanityGained from 'analysis/retail/priest/shadow/interface/ItemInsanityGained'; +import Statistic from 'parser/ui/Statistic'; +import STATISTIC_CATEGORY from 'parser/ui/STATISTIC_CATEGORY'; + +import { MADDENING_TOUCH_DAMAGE_PER_RANK } from '../../constants'; + +class MaddeningTouch extends Analyzer { + damage = 0; + insanityGained = 0; + + multiplierMaddeningTouch = + this.selectedCombatant.getTalentRank(TALENTS.MADDENING_TOUCH_TALENT) * + MADDENING_TOUCH_DAMAGE_PER_RANK; + + constructor(options: Options) { + super(options); + this.active = this.selectedCombatant.hasTalent(TALENTS.MADDENING_TOUCH_TALENT); + this.addEventListener( + Events.damage.by(SELECTED_PLAYER).spell(SPELLS.VAMPIRIC_TOUCH), + this.onVampricTouchDamage, + ); + this.addEventListener( + Events.resourcechange.by(SELECTED_PLAYER).spell(SPELLS.MADDENING_TOUCH_RESOURCE), + this.onVampricTouchResource, + ); + } + + onVampricTouchDamage(event: DamageEvent) { + this.damage += calculateEffectiveDamage(event, this.multiplierMaddeningTouch); + } + + onVampricTouchResource(event: ResourceChangeEvent) { + this.insanityGained += event.resourceChange - event.waste; + } + + statistic() { + return ( + + +
+ +
+
+ +
+
+
+ ); + } +} + +export default MaddeningTouch; diff --git a/src/analysis/retail/priest/shadow/modules/talents/Mastermind.tsx b/src/analysis/retail/priest/shadow/modules/talents/Mastermind.tsx new file mode 100644 index 00000000000..fedecc26e95 --- /dev/null +++ b/src/analysis/retail/priest/shadow/modules/talents/Mastermind.tsx @@ -0,0 +1,96 @@ +import TALENTS from 'common/TALENTS/priest'; +import SPELLS from 'common/SPELLS'; +import Analyzer, { Options, SELECTED_PLAYER } from 'parser/core/Analyzer'; +import { DamageEvent } from 'parser/core/Events'; +import Events from 'parser/core/Events'; +import { + calculateEffectiveDamage, + calculateEffectiveDamageFromCritIncrease, +} from 'parser/core/EventCalculateLib'; +import StatTracker from 'parser/shared/modules/StatTracker'; +import BoringSpellValueText from 'parser/ui/BoringSpellValueText'; +import ItemDamageDone from 'parser/ui/ItemDamageDone'; +import Statistic from 'parser/ui/Statistic'; +import STATISTIC_CATEGORY from 'parser/ui/STATISTIC_CATEGORY'; +import HIT_TYPES from 'game/HIT_TYPES'; + +import { MASTERMIND_CRIT_CHANCE_PER_RANK } from '../../constants'; +import { MASTERMIND_CRIT_DAMAGE_PER_RANK } from '../../constants'; + +class Mastermind extends Analyzer { + static dependencies = { + statTracker: StatTracker, + }; + + protected statTracker!: StatTracker; + + damage = 0; + buffStacks = 0; + + mastermindCritChance = + MASTERMIND_CRIT_CHANCE_PER_RANK * + this.selectedCombatant.getTalentRank(TALENTS.MASTERMIND_TALENT); //increase in crit chance + mastermindCritDamage = + MASTERMIND_CRIT_DAMAGE_PER_RANK * + this.selectedCombatant.getTalentRank(TALENTS.MASTERMIND_TALENT); //increase in crit damage + + constructor(options: Options) { + super(options); + this.active = this.selectedCombatant.hasTalent(TALENTS.MASTERMIND_TALENT); + + this.addEventListener(Events.damage.by(SELECTED_PLAYER).spell(SPELLS.MIND_BLAST), this.onSpell); + this.addEventListener( + Events.damage.by(SELECTED_PLAYER).spell(TALENTS.SHADOW_WORD_DEATH_TALENT), + this.onSpell, + ); + this.addEventListener(Events.damage.by(SELECTED_PLAYER).spell(SPELLS.MIND_FLAY), this.onSpell); + this.addEventListener( + Events.damage.by(SELECTED_PLAYER).spell(SPELLS.MIND_FLAY_INSANITY_TALENT_DAMAGE), + this.onSpell, + ); + this.addEventListener( + Events.damage.by(SELECTED_PLAYER).spell(TALENTS.MIND_SPIKE_TALENT), + this.onSpell, + ); + this.addEventListener( + Events.damage.by(SELECTED_PLAYER).spell(SPELLS.MIND_SPIKE_INSANITY_TALENT_DAMAGE), + this.onSpell, + ); + } + + onSpell(event: DamageEvent) { + if (event.hitType === HIT_TYPES.CRIT) { + //only crit events should be sent to effectiveDamageFromCritIncrease, + + this.damage += calculateEffectiveDamageFromCritIncrease( + //Extra damage from having extra crit chance + event, + this.statTracker.currentCritPercentage, + this.mastermindCritChance, + ); + + //Extra damage from having extra crit damage increase + //The increase in crit damage increases amount of extra damage critical hits do (in this case, from 100% to 120% or 140%, depending on talent ranks) + //so the while it increases the critical damage by 20% or 40%, it only increases the total damage of the event by half that amount + this.damage += calculateEffectiveDamage(event, this.mastermindCritDamage / 2); + } + } + + statistic() { + return ( + + +
+ +
+
+
+ ); + } +} + +export default Mastermind; diff --git a/src/analysis/retail/priest/shadow/modules/talents/MindMelt.tsx b/src/analysis/retail/priest/shadow/modules/talents/MindMelt.tsx new file mode 100644 index 00000000000..1154ca05d6a --- /dev/null +++ b/src/analysis/retail/priest/shadow/modules/talents/MindMelt.tsx @@ -0,0 +1,86 @@ +import TALENTS from 'common/TALENTS/priest'; +import SPELLS from 'common/SPELLS'; +import Analyzer, { Options, SELECTED_PLAYER } from 'parser/core/Analyzer'; +import { ApplyBuffStackEvent, DamageEvent } from 'parser/core/Events'; +import Events from 'parser/core/Events'; +import { calculateEffectiveDamageFromCritIncrease } from 'parser/core/EventCalculateLib'; +import StatTracker from 'parser/shared/modules/StatTracker'; +import BoringSpellValueText from 'parser/ui/BoringSpellValueText'; +import ItemDamageDone from 'parser/ui/ItemDamageDone'; +import Statistic from 'parser/ui/Statistic'; +import STATISTIC_CATEGORY from 'parser/ui/STATISTIC_CATEGORY'; +import HIT_TYPES from 'game/HIT_TYPES'; + +class MindMelt extends Analyzer { + static dependencies = { + statTracker: StatTracker, + }; + + protected statTracker!: StatTracker; + + damage = 0; + buffStacks = 0; + multiplierCritMindMelt = 0.2; //20% per stack + + constructor(options: Options) { + super(options); + this.active = this.selectedCombatant.hasTalent(TALENTS.MIND_MELT_TALENT); + + this.addEventListener( + Events.applybuff.by(SELECTED_PLAYER).spell(SPELLS.MIND_MELT_TALENT_BUFF), + this.onBuffApplied, + ); + this.addEventListener( + Events.applybuffstack.by(SELECTED_PLAYER).spell(SPELLS.MIND_MELT_TALENT_BUFF), + this.onBuffStack, + ); + this.addEventListener( + Events.removebuff.by(SELECTED_PLAYER).spell(SPELLS.MIND_MELT_TALENT_BUFF), + this.onBuffRemoved, + ); + + this.addEventListener( + Events.damage.by(SELECTED_PLAYER).spell(SPELLS.MIND_BLAST), + this.onMindBlast, + ); + } + + onBuffApplied() { + this.buffStacks = 1; + } + onBuffStack(event: ApplyBuffStackEvent) { + this.buffStacks = event.stack; + } + onBuffRemoved() { + this.buffStacks = 0; + } + + onMindBlast(event: DamageEvent) { + if (event.hitType === HIT_TYPES.CRIT) { + //only crit events should be sent to effectiveDamageFromCritIncrease, + this.damage += calculateEffectiveDamageFromCritIncrease( + event, + this.statTracker.currentCritPercentage, + this.buffStacks * this.multiplierCritMindMelt, + ); + } + } + + statistic() { + return ( + + +
+ +
+
+
+ ); + } +} + +export default MindMelt; diff --git a/src/analysis/retail/priest/shadow/modules/talents/MindsEye.tsx b/src/analysis/retail/priest/shadow/modules/talents/MindsEye.tsx new file mode 100644 index 00000000000..07419cb69c5 --- /dev/null +++ b/src/analysis/retail/priest/shadow/modules/talents/MindsEye.tsx @@ -0,0 +1,48 @@ +import TALENTS from 'common/TALENTS/priest'; +import Analyzer, { Options, SELECTED_PLAYER } from 'parser/core/Analyzer'; +import Events from 'parser/core/Events'; +import { CastEvent } from 'parser/core/Events'; +import BoringSpellValueText from 'parser/ui/BoringSpellValueText'; +import Statistic from 'parser/ui/Statistic'; +import STATISTIC_CATEGORY from 'parser/ui/STATISTIC_CATEGORY'; +import { formatNumber } from 'common/format'; +import InsanityIcon from 'interface/icons/Insanity'; + +class MindsEye extends Analyzer { + insanitySaved = 0; + + constructor(options: Options) { + super(options); + this.active = this.selectedCombatant.hasTalent(TALENTS.MINDS_EYE_TALENT); + this.addEventListener( + Events.cast.by(SELECTED_PLAYER).spell(TALENTS.DEVOURING_PLAGUE_TALENT), + this.onDevouringPlague, + ); + } + + onDevouringPlague(event: CastEvent) { + const resource = event.classResources?.at(0)?.cost; //Some buffs grant free Devouring Plagues, which do not have a resource cost + if (resource !== undefined) { + //If devouring Plague is free, then we have not saved the extra insanity + this.insanitySaved += 5; + } + } + + statistic() { + return ( + + +
+ {formatNumber(this.insanitySaved)} Insanity Saved +
+
+
+ ); + } +} + +export default MindsEye; diff --git a/src/analysis/retail/priest/shadow/modules/talents/PsychicLink.tsx b/src/analysis/retail/priest/shadow/modules/talents/PsychicLink.tsx index 64c565a344c..960df17d592 100644 --- a/src/analysis/retail/priest/shadow/modules/talents/PsychicLink.tsx +++ b/src/analysis/retail/priest/shadow/modules/talents/PsychicLink.tsx @@ -42,7 +42,7 @@ class PsychicLink extends Analyzer { ); this.addEventListener( Events.damage.by(SELECTED_PLAYER).spell(TALENTS.DEVOURING_PLAGUE_TALENT), - this.onDP, + this.onSpell, ); this.addEventListener( Events.damage.by(SELECTED_PLAYER).spell(TALENTS.MIND_SPIKE_TALENT), @@ -64,13 +64,6 @@ class PsychicLink extends Analyzer { ); } - onDP(event: DamageEvent) { - if (!event.tick) { - //Devouring Plague Ticks cant cause PsychicLink damage (however, Void Torrent does) - this.recentSpell = event.ability.name; - } - } - onSpell(event: DamageEvent) { this.recentSpell = event.ability.name; } diff --git a/src/analysis/retail/priest/shadow/modules/talents/VoidTouched.tsx b/src/analysis/retail/priest/shadow/modules/talents/VoidTouched.tsx new file mode 100644 index 00000000000..0cfc0718277 --- /dev/null +++ b/src/analysis/retail/priest/shadow/modules/talents/VoidTouched.tsx @@ -0,0 +1,41 @@ +import TALENTS from 'common/TALENTS/priest'; +import Analyzer, { Options, SELECTED_PLAYER } from 'parser/core/Analyzer'; +import { DamageEvent } from 'parser/core/Events'; +import Events from 'parser/core/Events'; +import { calculateEffectiveDamage } from 'parser/core/EventCalculateLib'; +import BoringSpellValueText from 'parser/ui/BoringSpellValueText'; +import ItemDamageDone from 'parser/ui/ItemDamageDone'; +import Statistic from 'parser/ui/Statistic'; +import STATISTIC_CATEGORY from 'parser/ui/STATISTIC_CATEGORY'; + +class VoidTouched extends Analyzer { + damage = 0; + multiplierVoidTouched = 0.06; //6% + + constructor(options: Options) { + super(options); + this.active = this.selectedCombatant.hasTalent(TALENTS.VOIDTOUCHED_TALENT); + this.addEventListener( + Events.damage.by(SELECTED_PLAYER).spell(TALENTS.DEVOURING_PLAGUE_TALENT), + this.onDevouringPlague, + ); + } + + onDevouringPlague(event: DamageEvent) { + this.damage += calculateEffectiveDamage(event, this.multiplierVoidTouched); + } + + statistic() { + return ( + + +
+ +
+
+
+ ); + } +} + +export default VoidTouched; diff --git a/src/common/SPELLS/priest.ts b/src/common/SPELLS/priest.ts index e0c8667385c..5a3ae00182a 100644 --- a/src/common/SPELLS/priest.ts +++ b/src/common/SPELLS/priest.ts @@ -611,6 +611,11 @@ const spells = { name: 'Vampiric Touch', icon: 'spell_holy_stoicism', }, + MADDENING_TOUCH_RESOURCE: { + id: 391232, + name: 'Maddening Touch', + icon: 'spell_holy_stoicism', + }, MASTERY_SHADOW_WEAVING: { id: 343690, @@ -762,6 +767,12 @@ const spells = { icon: 'spell_mage_presenceofmind', }, + MIND_MELT_TALENT_BUFF: { + id: 391092, + name: 'Mind Melt', + icon: 'spell_shadow_skull', + }, + // Shadow items: SHADOW_CRASH_TALENT_DAMAGE: {