Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Essence Burst abstraction #3

Merged
merged 18 commits into from
Apr 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -38,6 +38,8 @@ import T31Augmentation4P from './modules/dragonflight/T31Augmentation4P';
import {
LivingFlameNormalizer,
LivingFlamePrePullNormalizer,
EssenceBurstCastLinkNormalizer,
EssenceBurstRefreshNormalizer,
LeapingFlamesNormalizer,
LeapingFlames,
SpellEssenceCost,
Expand All @@ -57,6 +59,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,7 +2,6 @@ import SPELLS from 'common/SPELLS/evoker';
import TALENTS from 'common/TALENTS/evoker';
import {
ApplyBuffEvent,
ApplyBuffStackEvent,
ApplyDebuffEvent,
CastEvent,
DamageEvent,
Expand All @@ -18,6 +17,8 @@ import {
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
Expand All @@ -34,8 +35,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 EB_FROM_PRESCIENCE = 'ebFromPrescience';

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 @@ -169,12 +168,18 @@ const EVENT_LINKS: EventLink[] = [
anyTarget: true,
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);
return (
encodeEventTargetString(linkingEvent) !== encodeEventTargetString(referencedEvent) &&
!HasRelatedEvent(referencedEvent, LEAPING_FLAMES_HITS)
);
},
},
{
Expand All @@ -187,18 +192,6 @@ const EVENT_LINKS: EventLink[] = [
anyTarget: true,
forwardBufferMs: CAST_BUFFER_MS,
},
{
linkRelation: EB_FROM_PRESCIENCE,
reverseLinkRelation: EB_FROM_PRESCIENCE,
linkingEventId: TALENTS.PRESCIENCE_TALENT.id,
linkingEventType: EventType.Cast,
referencedEventId: SPELLS.ESSENCE_BURST_AUGMENTATION_BUFF.id,
referencedEventType: [EventType.ApplyBuff, EventType.ApplyBuffStack, EventType.RefreshBuff],
anyTarget: true,
forwardBufferMs: CAST_BUFFER_MS,
backwardBufferMs: CAST_BUFFER_MS,
maximumLinks: 1,
},
{
linkRelation: FAILED_EXTENSION_LINK,
reverseLinkRelation: FAILED_EXTENSION_LINK,
Expand Down Expand Up @@ -250,12 +243,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 @@ -329,16 +322,6 @@ export function ebonIsFromBreath(event: ApplyBuffEvent | CastEvent) {
return HasRelatedEvent(event, BREATH_EBON_APPLY_LINK);
}

export function generatedEssenceBurst(event: CastEvent) {
const maybeGenerate = GetRelatedEvent(
event,
EB_FROM_PRESCIENCE,
(e): e is ApplyBuffEvent | ApplyBuffStackEvent =>
e.type === EventType.ApplyBuff || e.type === EventType.ApplyBuffStack,
);
return Boolean(maybeGenerate);
}

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,6 +1,6 @@
import { AnyEvent, EventType } from 'parser/core/Events';
import EventsNormalizer from 'parser/core/EventsNormalizer';
import { isFromTipTheScales } from './CastLinkNormalizer';
import CastLinkNormalizer, { isFromTipTheScales } from './CastLinkNormalizer';

/**
* Empowers cast with Tip the Scales doesn't produce an EmpowerEnd event, only Cast event
Expand All @@ -10,8 +10,10 @@ import { isFromTipTheScales } from './CastLinkNormalizer';
*/

class EmpowerNormalizer extends EventsNormalizer {
// Set lower priority to ensure this runs after our CastLinkNormalizer
priority = 101;
static dependencies = {
...EventsNormalizer.dependencies,
castLinkNormalizer: CastLinkNormalizer,
};
normalize(events: AnyEvent[]): AnyEvent[] {
const fixedEvents: any[] = [];
events.forEach((event) => {
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_ESSCENCE_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
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,
SpellEssenceCost,
Expand All @@ -53,6 +55,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 @@ -10,7 +10,6 @@ export const SNAPFIRE_CONSUME = 'SnapfireConsumption';
export const IRIDESCENCE_RED_CONSUME = 'IridescentRedConsumption';
export const IRIDESCENCE_BLUE_CONSUME = 'IridescentBlueConsumption';
export const DISINTEGRATE_REMOVE_APPLY = 'DisintegrateRemoveApply';
export const EB_FROM_ARCANE_VIGOR = 'ebFromArcaneVigor';

const CAST_BUFFER_MS = 100;
const EVENT_LINKS: EventLink[] = [
Expand Down Expand Up @@ -115,24 +114,6 @@ const EVENT_LINKS: EventLink[] = [
referencedEventType: EventType.ApplyDebuff,
anyTarget: true,
},
{
linkRelation: EB_FROM_ARCANE_VIGOR,
reverseLinkRelation: EB_FROM_ARCANE_VIGOR,
linkingEventId: [SPELLS.SHATTERING_STAR.id],
linkingEventType: EventType.Cast,
referencedEventId: [
TALENTS_EVOKER.RUBY_ESSENCE_BURST_TALENT.id,
SPELLS.ESSENCE_BURST_DEV_BUFF.id,
],
referencedEventType: [EventType.ApplyBuff, EventType.ApplyBuffStack, EventType.RefreshBuff],
anyTarget: true,
forwardBufferMs: CAST_BUFFER_MS,
backwardBufferMs: CAST_BUFFER_MS,
maximumLinks: 1,
isActive(c) {
return c.hasTalent(TALENTS_EVOKER.ARCANE_VIGOR_TALENT);
},
},
];

class CastLinkNormalizer extends EventLinkNormalizer {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ 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 { EB_GENERATION_EVENT_TYPES } from '../../../shared/modules/normalizers/EssenceBurstCastLinkNormalizer';

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 +20,27 @@ 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.
**/
class EssenceBurstNormalizer extends EventOrderNormalizer {
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
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,13 +52,14 @@ import {
LivingFlameNormalizer,
LivingFlamePrePullNormalizer,
LeapingFlamesNormalizer,
EssenceBurstRefreshNormalizer,
EssenceBurstCastLinkNormalizer,
LeapingFlames,
SpellEssenceCost,
EssenceTracker,
SourceOfMagic,
PotentMana,
} from '../shared';
import EBRefreshNormalizer from './normalizers/EBRefreshNormalizer';

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

// Normalizer
ebRefreshNormalizer: EBRefreshNormalizer,
essenceBurstCastLinkNormalizer: EssenceBurstCastLinkNormalizer,
essenceBurstRefreshNormalizer: EssenceBurstRefreshNormalizer,
livingFlameNormalizer: LivingFlameNormalizer,
castLinkNormalizer: CastLinkNormalizer,
hotApplicationNormalizer: HotApplicationNormalizer,
Expand Down
8 changes: 8 additions & 0 deletions src/analysis/retail/evoker/shared/constants.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import SPELLS from 'common/SPELLS/evoker';

export const BASE_ESSENCE_REGEN = 0.2;

export const INNATE_MAGIC_REGEN = 0.05;
Expand All @@ -7,3 +9,9 @@ export const BASE_MAX_ESSENCE = 5;
export const POTENT_MANA_MULTIPLIER = 0.03;

export const BASE_EVOKER_RANGE = 25;

export const EB_BUFF_IDS = [
SPELLS.ESSENCE_BURST_BUFF.id,
SPELLS.ESSENCE_BURST_DEV_BUFF.id,
SPELLS.ESSENCE_BURST_AUGMENTATION_BUFF.id,
];
5 changes: 2 additions & 3 deletions src/analysis/retail/evoker/shared/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
export {
default as LeapingFlamesNormalizer,
eventGeneratedEB,
getGeneratedEBEvents,
isFromLeapingFlames,
getWastedEBEvents,
} from './modules/normalizers/LeapingFlamesNormalizer';
export { default as LivingFlameNormalizer } from './modules/normalizers/LivingFlameNormalizer';
export { default as EssenceBurstCastLinkNormalizer } from './modules/normalizers/EssenceBurstCastLinkNormalizer';
export { default as EssenceBurstRefreshNormalizer } from './modules/normalizers/EssenceBurstRefreshNormalizer';
export { default as LeapingFlames } from './modules/talents/LeapingFlames';
export { default as LivingFlamePrePullNormalizer } from './modules/normalizers/LivingFlamePrePullNormalizer';
export { default as SpellEssenceCost } from './modules/core/essence/SpellEssenceCost';
Expand Down
Loading
Loading