Skip to content

Commit

Permalink
[Shadow] Add statistics for several Shadow Talents. (WoWAnalyzer#6747)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
DoxAshe authored and emallson committed May 3, 2024
1 parent e07f419 commit 2a537e2
Show file tree
Hide file tree
Showing 13 changed files with 515 additions and 15 deletions.
1 change: 1 addition & 0 deletions src/analysis/retail/priest/shadow/CHANGELOG.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 <SpellLink spell={TALENTS.VOIDTOUCHED_TALENT}/>, <SpellLink spell={TALENTS.MINDS_EYE_TALENT}/>, <SpellLink spell={TALENTS.DISTORTED_REALITY_TALENT}/>, <SpellLink spell={TALENTS.MADDENING_TOUCH_TALENT}/>, <SpellLink spell={TALENTS.MIND_MELT_TALENT}/>, <SpellLink spell={TALENTS.MASTERMIND_TALENT}/> and <SpellLink spell={TALENTS.DARK_EVANGELISM_TALENT}/> talents</>,DoxAshe),
change(date(2024, 4, 26), <>Add statistics for <SpellLink spell={TALENTS.PSYCHIC_LINK_TALENT}/> 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 <SpellLink spell={SPELLS.DESPERATE_PRAYER} /> when using <SpellLink spell={TALENTS.ANGELS_MERCY_TALENT} />.</>,Arlie),
Expand Down
2 changes: 1 addition & 1 deletion src/analysis/retail/priest/shadow/CONFIG.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,

Expand Down
12 changes: 12 additions & 0 deletions src/analysis/retail/priest/shadow/CombatLogParser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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,
Expand All @@ -110,6 +121,7 @@ class CombatLogParser extends MainCombatLogParser {
tormentedSpirits: TormentedSpirits,
unfurlingDarkness: UnfurlingDarkness,
voidTorrent: VoidTorrent,
voidTouched: VoidTouched,

// Class Talents:
deathAndMadness: DeathAndMadness,
Expand Down
7 changes: 7 additions & 0 deletions src/analysis/retail/priest/shadow/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Original file line number Diff line number Diff line change
@@ -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 (
<Statistic
category={STATISTIC_CATEGORY.TALENTS}
size="flexible"
tooltip="This talent buffs the periodic damage from Vampiric Touch, Shadow Word: Pain, Devouring Plague, Mind Flay, Mind Flay: Insanity and Void Torrent"
>
<BoringSpellValueText spell={TALENTS.DARK_EVANGELISM_TALENT}>
<div>
<ItemDamageDone amount={this.damage} />
</div>
</BoringSpellValueText>
</Statistic>
);
}
static dependencies = {
enemies: Enemies,
};
protected enemies!: Enemies;

get uptime() {
return (
Expand Down
Original file line number Diff line number Diff line change
@@ -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 (
<Statistic
category={STATISTIC_CATEGORY.TALENTS}
size="flexible"
tooltip="Amount of extra Insanity used due to the increased cost"
>
<BoringSpellValueText spell={TALENTS.DISTORTED_REALITY_TALENT}>
<div>
<ItemDamageDone amount={this.damage} />
</div>
<div>
<InsanityIcon /> {formatNumber(this.insanitySpent)} <small> Extra Insanity Cost</small>
</div>
</BoringSpellValueText>
</Statistic>
);
}
}

export default DistortedReality;
Original file line number Diff line number Diff line change
@@ -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 (
<Statistic category={STATISTIC_CATEGORY.TALENTS} size="flexible">
<BoringSpellValueText spell={TALENTS.MADDENING_TOUCH_TALENT}>
<div>
<ItemDamageDone amount={this.damage} />
</div>
<div>
<ItemInsanityGained amount={this.insanityGained} />
</div>
</BoringSpellValueText>
</Statistic>
);
}
}

export default MaddeningTouch;
Loading

0 comments on commit 2a537e2

Please sign in to comment.