Skip to content

Commit

Permalink
[Evoker] Leaping Flames module rework and Essence Burst normalization (
Browse files Browse the repository at this point in the history
…WoWAnalyzer#6719)

* update pupil related links for aug

* add EB_FROM_ARCANE_VIGOR castlink for deva

* rework of LeapingFlamesNormalizer

* Reworked LeapingFlames

* some minor changes

* Essence Burst abstraction (#3)

* Abstract Essence Burst links to new shared file

* Fix missing isActive for PUPIL_OF_ALEXSTRASZA_TALENT cast link

* Move Preservations EBRefreshNormalizer to shared normalizers

* Update import for Preservation

* Update eventGeneratedEB call for Anachronism

* Update function calls for LeapingFlames

* add EssenceBurstCastLinkNormalizer to preservation so LeapingFlames module can function properly

* Update Deva EssenceBurstOrder normalizer to properly catch all leaping EBs

* remove EB_FROM_ARCANE_VIGOR link from deva specific normalizer

* rename EBRefreshNormalizer to EssenceBurstRefreshNormalizer

* Add EB_FROM links to Azure Strike and Emerald Trance

* Add the new castlinks to filter and update variable naming

* add some more documentation

* emerald trance produces first EB after 5seconds

* Emerald trance should take priority over Azure Strike

* jsdoc update

* change logic for leaping hits and pupil links so we can simplify dependencies

* simplify hasNoGenerationLink to make it more streamlined to add future sources

* refactor EssenceBurstRefreshNormalizer so it removes the proper abilities

* update EssenceBurstNormalizer dependencies

* add normalizer dependency for preservation castlinknormalizer

* prettier must be satisfied!

* only check for leaping links if leaping is talented

* implement LeapingFlamesBuffNormalizer

* Implement maxLinks check for LEAPING_FLAMES_HITS cast link check

* add LeapingFlamesBuffNormalizer to combatlogparsers

* add EssenceBurstRefreshNormalizer dep to EssenceBurstCastLinkNormalizer

* remove LeapingFlamesBuffNormalizer in favor of a cast link

* yeet the logs and write some documentation

* yeet some more stuff

* add a lil more info

* yeet this export

* readability changes

* another readability change

* make this variable more descriptive

* changelog

* fix options imports to match PutPuts cleanup
  • Loading branch information
Krealle authored Apr 24, 2024
1 parent 2c56a27 commit 9f2199e
Show file tree
Hide file tree
Showing 20 changed files with 880 additions and 323 deletions.
1 change: 1 addition & 0 deletions src/analysis/retail/evoker/augmentation/CHANGELOG.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import RESOURCE_TYPES from 'game/RESOURCE_TYPES';

export default [
change(date(2024, 4, 17), 'Update modules for 10.2.6.', Vollmer),
change(date(2024, 4, 11), <>Rework <SpellLink spell={SPELLS.LEAPING_FLAMES_BUFF} /> module to increase accuracy.</>, Vollmer),
change(date(2024, 4, 6), 'Normalize Empower behavior to make analysis more consistent.', Vollmer),
change(date(2024, 4, 1), <>Added analysis for <SpellLink spell={TALENTS.RENEWING_BLAZE_TALENT} />, <SpellLink spell={TALENTS.OBSIDIAN_SCALES_TALENT} /> and <SpellLink spell={TALENTS.TWIN_GUARDIAN_TALENT} />.</>, Vollmer),
change(date(2024, 3, 30), <>Fix prepull <SpellLink spell={SPELLS.LIVING_FLAME_CAST} /> casts to properly display channel time.</>, Vollmer),
Expand Down
4 changes: 4 additions & 0 deletions src/analysis/retail/evoker/augmentation/CombatLogParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ import T31Augmentation4P from './modules/dragonflight/T31Augmentation4P';
import {
LivingFlameNormalizer,
LivingFlamePrePullNormalizer,
EssenceBurstCastLinkNormalizer,
EssenceBurstRefreshNormalizer,
LeapingFlamesNormalizer,
LeapingFlames,
EmpowerNormalizer,
Expand Down Expand Up @@ -64,6 +66,8 @@ class CombatLogParser extends MainCombatLogParser {
// Shared
livingFlameNormalizer: LivingFlameNormalizer,
livingFlamePrePullNormalizer: LivingFlamePrePullNormalizer,
essenceBurstRefreshNormalizer: EssenceBurstRefreshNormalizer,
essenceBurstCastLinkNormalizer: EssenceBurstCastLinkNormalizer,
leapingFlamesNormalizer: LeapingFlamesNormalizer,
leapingFlames: LeapingFlames,
spellEssenceCost: SpellEssenceCost,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,23 @@ import {
DamageEvent,
EmpowerEndEvent,
EventType,
GetRelatedEvent,
GetRelatedEvents,
HasRelatedEvent,
HasTarget,
RefreshBuffEvent,
RemoveDebuffEvent,
} from 'parser/core/Events';
import { Options } from 'parser/core/Module';
import EventLinkNormalizer, { EventLink } from 'parser/core/EventLinkNormalizer';
import { encodeEventTargetString } from 'parser/shared/modules/Enemies';
import PrePullCooldowns from 'parser/shared/normalizers/PrePullCooldowns';
import { LEAPING_FLAMES_HITS } from 'analysis/retail/evoker/shared/modules/normalizers/LeapingFlamesNormalizer';

/** So sometimes when Ebon Might should be extended
* it just kinda doesn't? This messes with our analysis so
* let's check if it failed to extend where it should
* See example of this here (upheaval should have extended but didnt):
* See example of this here (upheaval should have extended but didn't):
* https://www.warcraftlogs.com/reports/1JqKrX2vLxb6Zyp9/#fight=8&source=3&pins=2%24Off%24%23244F4B%24expression%24type%20%3D%20%22empowerend%22%20or%20type%3D%22removebuff%22&view=events&start=1402475&end=1408776
*/
export const FAILED_EXTENSION_LINK = 'failedExtensionLink';
Expand All @@ -29,8 +34,6 @@ export const BREATH_EBON_APPLY_LINK = 'breathEbonApplyLink';
export const EBON_MIGHT_BUFF_LINKS = 'ebonMightBuffLinks';
export const EBON_MIGHT_APPLY_REMOVE_LINK = 'ebonMightApplyRemoveLink';

export const ESSENCE_BURST_GENERATED = 'EssenceBurstGenerated';

export const BREATH_OF_EONS_CAST_DEBUFF_APPLY_LINK = 'breathOfEonsCastDebuffApplyLink';
export const BREATH_OF_EONS_CAST_BUFF_LINK = 'breathOfEonsCastBuffLink';
export const BREATH_OF_EONS_DAMAGE_LINK = 'breathOfEonsDamageLink';
Expand Down Expand Up @@ -147,8 +150,21 @@ const EVENT_LINKS: EventLink[] = [
referencedEventId: SPELLS.LIVING_FLAME_DAMAGE.id,
referencedEventType: EventType.Damage,
anyTarget: true,
maximumLinks: 2,
maximumLinks: 1,
forwardBufferMs: PUPIL_OF_ALEXSTRASZA_BUFFER,
isActive(c) {
return c.hasTalent(TALENTS.PUPIL_OF_ALEXSTRASZA_TALENT);
},
additionalCondition(linkingEvent, referencedEvent) {
// No targets so we can't be sure which hit is the correct one, so we just claim it
if (!HasTarget(linkingEvent) && !HasTarget(referencedEvent)) {
return true;
}
return (
encodeEventTargetString(linkingEvent) !== encodeEventTargetString(referencedEvent) &&
!HasRelatedEvent(referencedEvent, LEAPING_FLAMES_HITS)
);
},
},
{
linkRelation: ERUPTION_CAST_DAM_LINK,
Expand All @@ -160,17 +176,6 @@ const EVENT_LINKS: EventLink[] = [
anyTarget: true,
forwardBufferMs: CAST_BUFFER_MS,
},
{
linkRelation: ESSENCE_BURST_GENERATED,
reverseLinkRelation: ESSENCE_BURST_GENERATED,
linkingEventId: TALENTS.PRESCIENCE_TALENT.id,
linkingEventType: EventType.Cast,
referencedEventId: SPELLS.ESSENCE_BURST_AUGMENTATION_BUFF.id,
referencedEventType: [EventType.ApplyBuff, EventType.ApplyBuffStack],
anyTarget: true,
forwardBufferMs: CAST_BUFFER_MS,
backwardBufferMs: CAST_BUFFER_MS,
},
{
linkRelation: FAILED_EXTENSION_LINK,
reverseLinkRelation: FAILED_EXTENSION_LINK,
Expand Down Expand Up @@ -222,12 +227,12 @@ const EVENT_LINKS: EventLink[] = [
];

class CastLinkNormalizer extends EventLinkNormalizer {
// This is set to lower priority than default since
// We depend on prePullCooldowns since
// to create proper links on events fabricated using PrePullCooldownsNormalizer
// We need to ensure this runs after the PrePullCooldownsNormalizer
// We need to ensure this normalizer runs after the PrePullCooldownsNormalizer
// This is necessary if we want BreathOfEons module to function properly
// With pre-pull casts of Breath of Eons
priority = 100;
static dependencies = { ...EventLinkNormalizer.dependencies, prePullCooldowns: PrePullCooldowns };
constructor(options: Options) {
super(options, EVENT_LINKS);
}
Expand Down Expand Up @@ -281,8 +286,8 @@ export function getEruptionDamageEvents(event: CastEvent): DamageEvent[] {
);
}

export function getPupilDamageEvents(event: CastEvent): DamageEvent[] {
return GetRelatedEvents(
export function getPupilDamageEvent(event: CastEvent): DamageEvent | undefined {
return GetRelatedEvent(
event,
PUPIL_OF_ALEXSTRASZA_LINK,
(e): e is DamageEvent => e.type === EventType.Damage,
Expand All @@ -297,10 +302,6 @@ export function ebonIsFromBreath(event: ApplyBuffEvent | CastEvent) {
return HasRelatedEvent(event, BREATH_EBON_APPLY_LINK);
}

export function generatedEssenceBurst(event: CastEvent) {
return HasRelatedEvent(event, ESSENCE_BURST_GENERATED);
}

export function failedEbonMightExtension(event: CastEvent | EmpowerEndEvent) {
return HasRelatedEvent(event, FAILED_EXTENSION_LINK);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { AnyEvent, EventType, HasRelatedEvent } from 'parser/core/Events';
import EventsNormalizer from 'parser/core/EventsNormalizer';
import { EBON_MIGHT_APPLY_REMOVE_LINK, EBON_MIGHT_BUFF_LINKS } from './CastLinkNormalizer';
import CastLinkNormalizer, {
EBON_MIGHT_APPLY_REMOVE_LINK,
EBON_MIGHT_BUFF_LINKS,
} from './CastLinkNormalizer';
import SPELLS from 'common/SPELLS/evoker';

/** This Normalizer fixes an issue that happens very rarely, where external Ebon Might
Expand All @@ -23,10 +26,9 @@ import SPELLS from 'common/SPELLS/evoker';
* */

class EbonMightNormalizer extends EventsNormalizer {
// Set lower priority to ensure this runs after our CastLinkNormalizer
priority = 101;
static dependencies = {
...EventsNormalizer.dependencies,
castLinkNormalizer: CastLinkNormalizer,
};
normalize(events: any[]): any[] {
const fixedEvents: any[] = [];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { AnyEvent, EventType, HasRelatedEvent } from 'parser/core/Events';
import TALENTS from 'common/TALENTS/evoker';
import EventsNormalizer from 'parser/core/EventsNormalizer';
import { PRESCIENCE_APPLY_REMOVE_LINK } from './CastLinkNormalizer';
import CastLinkNormalizer, { PRESCIENCE_APPLY_REMOVE_LINK } from './CastLinkNormalizer';
import Combatants from 'parser/shared/modules/Combatants';
import StatTracker from 'parser/shared/modules/StatTracker';
import {
Expand All @@ -20,10 +20,9 @@ import {
* like to include these in our analysis, so we need to create pre-pull events for it */

class PrescienceNormalizer extends EventsNormalizer {
// Set lower priority to ensure this runs after our CastLinkNormalizer
priority = 101;
static dependencies = {
...EventsNormalizer.dependencies,
castLinkNormalizer: CastLinkNormalizer,
combatants: Combatants,
stats: StatTracker,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import TALENTS from 'common/TALENTS/evoker';

import Analyzer, { Options, SELECTED_PLAYER } from 'parser/core/Analyzer';
import Events, { CastEvent } from 'parser/core/Events';
import { generatedEssenceBurst } from '../normalizers/CastLinkNormalizer';
import { ANACHRONISM_ESSENCE_CHANCE } from '../../constants';

import Statistic from 'parser/ui/Statistic';
Expand All @@ -12,6 +11,10 @@ import STATISTIC_ORDER from 'parser/ui/STATISTIC_ORDER';
import TalentSpellText from 'parser/ui/TalentSpellText';
import { SpellLink } from 'interface';
import { plotOneVariableBinomChart } from 'parser/shared/modules/helpers/Probability';
import {
EBSource,
eventGeneratedEB,
} from '../../../shared/modules/normalizers/EssenceBurstCastLinkNormalizer';

/**
* Prescience has a 35% chance to grant Essence Burst.
Expand All @@ -32,7 +35,7 @@ class Anachronism extends Analyzer {

onCast(event: CastEvent) {
this.prescienceCasts += 1;
if (generatedEssenceBurst(event)) {
if (eventGeneratedEB(event, EBSource.Prescience)) {
this.essenceBurstGenerated += 1;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { formatNumber } from 'common/format';
import Analyzer, { Options, SELECTED_PLAYER } from 'parser/core/Analyzer';
import ItemDamageDone from 'parser/ui/ItemDamageDone';
import Events, { CastEvent } from 'parser/core/Events';
import { getPupilDamageEvents } from '../normalizers/CastLinkNormalizer';
import { getPupilDamageEvent } from '../normalizers/CastLinkNormalizer';

import Statistic from 'parser/ui/Statistic';
import STATISTIC_CATEGORY from 'parser/ui/STATISTIC_CATEGORY';
Expand All @@ -29,12 +29,12 @@ class PupilOfAlexstrasza extends Analyzer {
}

onCast(event: CastEvent) {
const damageEvents = getPupilDamageEvents(event);
if (damageEvents.length > 1) {
damageEvents.forEach((damEvent) => {
this.PupilOfAlexstraszaDamage += damEvent.amount + (damEvent.absorbed ?? 0);
});
const damageEvent = getPupilDamageEvent(event);
if (!damageEvent) {
return;
}

this.PupilOfAlexstraszaDamage += damageEvent.amount + (damageEvent.absorbed ?? 0);
}

statistic() {
Expand All @@ -45,12 +45,12 @@ class PupilOfAlexstrasza extends Analyzer {
category={STATISTIC_CATEGORY.TALENTS}
tooltip={
<>
<li>Damage: {formatNumber(this.PupilOfAlexstraszaDamage / 2)}</li>
<li>Damage: {formatNumber(this.PupilOfAlexstraszaDamage)}</li>
</>
}
>
<TalentSpellText talent={TALENTS.PUPIL_OF_ALEXSTRASZA_TALENT}>
<ItemDamageDone amount={this.PupilOfAlexstraszaDamage / 2} />
<ItemDamageDone amount={this.PupilOfAlexstraszaDamage} />
</TalentSpellText>
</Statistic>
);
Expand Down
1 change: 1 addition & 0 deletions src/analysis/retail/evoker/devastation/CHANGELOG.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import RESOURCE_TYPES from 'game/RESOURCE_TYPES';

export default [
change(date(2024, 4, 19), 'Update modules for 10.2.6', Vollmer),
change(date(2024, 4, 11), <>Rework <SpellLink spell={SPELLS.LEAPING_FLAMES_BUFF} /> module to increase accuracy.</>, Vollmer),
change(date(2024, 4, 6), 'Normalize Empower behavior to make analysis more consistent.', Vollmer),
change(date(2024, 4, 1), <>Added analysis for <SpellLink spell={TALENTS.RENEWING_BLAZE_TALENT} />, <SpellLink spell={TALENTS.OBSIDIAN_SCALES_TALENT} /> and <SpellLink spell={TALENTS.TWIN_GUARDIAN_TALENT} />.</>, Vollmer),
change(date(2024, 3, 30), <>Fix prepull <SpellLink spell={SPELLS.LIVING_FLAME_CAST} /> casts to properly display channel time.</>, Vollmer),
Expand Down
4 changes: 4 additions & 0 deletions src/analysis/retail/evoker/devastation/CombatLogParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ import T31DevaTier from './modules/dragonflight/tier/T31DevaTier';
import {
LivingFlameNormalizer,
LivingFlamePrePullNormalizer,
EssenceBurstCastLinkNormalizer,
EssenceBurstRefreshNormalizer,
LeapingFlamesNormalizer,
LeapingFlames,
EmpowerNormalizer,
Expand Down Expand Up @@ -61,6 +63,8 @@ class CombatLogParser extends MainCombatLogParser {
// Shared
livingFlameNormalizer: LivingFlameNormalizer,
livingFlamePrePullNormalizer: LivingFlamePrePullNormalizer,
essenceBurstRefreshNormalizer: EssenceBurstRefreshNormalizer,
essenceBurstCastLinkNormalizer: EssenceBurstCastLinkNormalizer,
leapingFlamesNormalizer: LeapingFlamesNormalizer,
leapingFlames: LeapingFlames,
spellEssenceCost: SpellEssenceCost,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@ import SPELLS from 'common/SPELLS/evoker';
import EventOrderNormalizer, { EventOrder } from 'parser/core/EventOrderNormalizer';
import { EventType } from 'parser/core/Events';
import { Options } from 'parser/core/Module';
import EssenceBurstCastLinkNormalizer, {
EB_GENERATION_EVENT_TYPES,
} from '../../../shared/modules/normalizers/EssenceBurstCastLinkNormalizer';
import { EssenceBurstRefreshNormalizer } from 'analysis/retail/evoker/shared';

const EVENT_ORDERS: EventOrder[] = [
{
beforeEventId: [SPELLS.SHATTERING_STAR.id, SPELLS.LIVING_FLAME_CAST.id],
beforeEventId: SPELLS.SHATTERING_STAR.id,
beforeEventType: EventType.Cast,
afterEventId: SPELLS.ESSENCE_BURST_DEV_BUFF.id,
afterEventType: [EventType.ApplyBuffStack, EventType.ApplyBuff, EventType.RefreshBuff],
afterEventType: EB_GENERATION_EVENT_TYPES,
bufferMs: 50,
anyTarget: true,
updateTimestamp: true,
Expand All @@ -19,10 +23,34 @@ const EVENT_ORDERS: EventOrder[] = [
* The applybuff from Arcane Vigor is logged before the cast of Shattering Star
* This also happens to Living Flames cast with Burnout
* This normalizes events so that the Shattering Star cast always comes before the EB buff
*
* EventOrderNormalizer only normalizes 1 instance per entry in the EventOrder array
* which means that abilities that can generate multiple EB at once, eg. Living Flame cast with
* Leaping Flames, will only have one event normalized, which can be non ideal. Therefore we will build
* an array with all the different types to make sure we get them all normalized.
* Specifically this messes with the APLCheck due to resources not being applied in the right order.
**/
class EssenceBurstNormalizer extends EventOrderNormalizer {
static dependencies = {
...EventOrderNormalizer.dependencies,
// We need these dependency to ensure we don't mess up our other normalizers
essenceBurstRefreshNormalizer: EssenceBurstRefreshNormalizer,
essenceBurstCastLinkNormalizer: EssenceBurstCastLinkNormalizer,
};
constructor(options: Options) {
super(options, EVENT_ORDERS);

EB_GENERATION_EVENT_TYPES.forEach((ebApplyEventType) => {
EVENT_ORDERS.push({
beforeEventId: SPELLS.LIVING_FLAME_CAST.id,
beforeEventType: EventType.Cast,
afterEventId: SPELLS.ESSENCE_BURST_DEV_BUFF.id,
afterEventType: ebApplyEventType,
bufferMs: 50,
anyTarget: true,
updateTimestamp: true,
});
});
}
}

Expand Down
1 change: 1 addition & 0 deletions src/analysis/retail/evoker/preservation/CHANGELOG.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import RESOURCE_TYPES from 'game/RESOURCE_TYPES';
import { ResourceLink, SpellLink } from 'interface';

export default [
change(date(2024, 4, 11), <>Rework <SpellLink spell={SPELLS.LEAPING_FLAMES_BUFF} /> module to increase accuracy.</>, Vollmer),
change(date(2024, 4, 6), 'Normalize Empower behavior to make analysis more consistent.', Vollmer),
change(date(2024, 3, 30), <>Fix prepull <SpellLink spell={SPELLS.LIVING_FLAME_CAST} /> casts to properly display channel time.</>, Vollmer),
change(date(2024, 3, 12), <>Implement <SpellLink spell={TALENTS_EVOKER.TIME_OF_NEED_TALENT} /> module.</>, Harrek),
Expand Down
6 changes: 4 additions & 2 deletions src/analysis/retail/evoker/preservation/CombatLogParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ import {
LivingFlameNormalizer,
LivingFlamePrePullNormalizer,
LeapingFlamesNormalizer,
EssenceBurstRefreshNormalizer,
EssenceBurstCastLinkNormalizer,
LeapingFlames,
EmpowerNormalizer,
SpellUsable,
Expand All @@ -61,7 +63,6 @@ import {
SourceOfMagic,
PotentMana,
} from '../shared';
import EBRefreshNormalizer from './normalizers/EBRefreshNormalizer';

class CombatLogParser extends CoreCombatLogParser {
static specModules = {
Expand All @@ -70,7 +71,8 @@ class CombatLogParser extends CoreCombatLogParser {
cooldowns: CooldownThroughputTracker,

// Normalizer
ebRefreshNormalizer: EBRefreshNormalizer,
essenceBurstCastLinkNormalizer: EssenceBurstCastLinkNormalizer,
essenceBurstRefreshNormalizer: EssenceBurstRefreshNormalizer,
livingFlameNormalizer: LivingFlameNormalizer,
castLinkNormalizer: CastLinkNormalizer,
hotApplicationNormalizer: HotApplicationNormalizer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,11 @@ import {
} from 'parser/core/Events';
import { DUPLICATION_SPELLS, STASIS_CAST_IDS } from '../constants';
import { TIERS } from 'game/TIERS';
import { LEAPING_FLAMES_HITS } from '../../shared/modules/normalizers/LeapingFlamesNormalizer';
import LeapingFlamesNormalizer, {
LEAPING_FLAMES_HITS,
} from '../../shared/modules/normalizers/LeapingFlamesNormalizer';
import { EMPOWERED_CAST } from '../../shared/modules/normalizers/EmpowerNormalizer';
import { EssenceBurstRefreshNormalizer } from '../../shared';

export const ANCIENT_FLAME = 'AncientFlame'; // links cast to buff apply
export const ANCIENT_FLAME_CONSUME = 'AncientFlameConnsume'; // links buff remove to buff apply
Expand Down Expand Up @@ -825,6 +828,11 @@ const EVENT_LINKS: EventLink[] = [
* This normalizer adds links for Echo and Temporal Anomaly
*/
class CastLinkNormalizer extends EventLinkNormalizer {
static dependencies = {
...EventLinkNormalizer.dependencies,
essenceBurstRefreshNormalizer: EssenceBurstRefreshNormalizer,
leapingFlamesNormalizer: LeapingFlamesNormalizer,
};
constructor(options: Options) {
super(options, EVENT_LINKS);
}
Expand Down
Loading

0 comments on commit 9f2199e

Please sign in to comment.