From 67b44e96c6ca032bf8c8a98c717bc3b41f5ddf8c Mon Sep 17 00:00:00 2001 From: Putro <29204244+Pewtro@users.noreply.github.com> Date: Thu, 15 Feb 2024 19:46:56 +0100 Subject: [PATCH] [Hunter] Workaround for Volcoross having weird events Volcoross is notoriously bad at having events that make no sense, e.g. https://www.warcraftlogs.com/reports/qpJ4tV8aYZ6CRGrL#fight=10&type=auras&source=45&ability=272790&view=events where Apply Buff events are going out without the buff expiring. This adds a new flag to the buff tracker labelled as experimental because it might have other adverse side effects and uses that to try and work around the weird events --- .../talents/BlisteringScalesStackTracker.tsx | 10 +++++++ .../retail/hunter/beastmastery/CHANGELOG.tsx | 1 + .../rotation/FrenzyBuffStackTracker.tsx | 9 +++++++ .../modules/talents/BarbedShot.tsx | 10 ++++--- src/parser/shared/modules/BuffStackTracker.ts | 27 +++++++++++++++++++ 5 files changed, 54 insertions(+), 3 deletions(-) diff --git a/src/analysis/retail/evoker/augmentation/modules/talents/BlisteringScalesStackTracker.tsx b/src/analysis/retail/evoker/augmentation/modules/talents/BlisteringScalesStackTracker.tsx index 0c2cb73b118..b01c3830dc2 100644 --- a/src/analysis/retail/evoker/augmentation/modules/talents/BlisteringScalesStackTracker.tsx +++ b/src/analysis/retail/evoker/augmentation/modules/talents/BlisteringScalesStackTracker.tsx @@ -39,6 +39,11 @@ export default class BlisteringScalesStackTracker extends Analyzer { ? 20 : 15; + //Unused in this module but exists because this is a custom implementation of BuffStackTracker that is used to render a graph that relies on these values being present + static workaroundWeirdBuffEvents_experimental = false; + buffDuration = 0; + buffActive = false; + constructor(options: Options) { super(options); this.addEventListener( @@ -70,6 +75,11 @@ export default class BlisteringScalesStackTracker extends Analyzer { return ctor.trackedBuff; } + get workaroundWeirdBuffEvents_experimental() { + const ctor = this.constructor as typeof BlisteringScalesStackTracker; + return ctor.workaroundWeirdBuffEvents_experimental; + } + /** The player's buff stack amount at the current timestamp */ get current(): number { const lastUpdate = this.buffStackUpdates.at(-1); diff --git a/src/analysis/retail/hunter/beastmastery/CHANGELOG.tsx b/src/analysis/retail/hunter/beastmastery/CHANGELOG.tsx index 59121b238fa..43bf41e80c8 100644 --- a/src/analysis/retail/hunter/beastmastery/CHANGELOG.tsx +++ b/src/analysis/retail/hunter/beastmastery/CHANGELOG.tsx @@ -5,6 +5,7 @@ import TALENTS from 'common/TALENTS/hunter'; import SPELLS from 'common/SPELLS'; import RESOURCE_TYPES from 'game/RESOURCE_TYPES'; export default [ + change(date(2024, 2, 15), <>Try to workaround weird buff events on bosses like Volcoross for <SpellLink spell={SPELLS.BARBED_SHOT_PET_BUFF} /> </>, Putro), change(date(2023, 11, 21), <>Update when <SpellLink spell={TALENTS.BARBED_SHOT_TALENT} /> are marked as good or bad casts. </>, Putro), change(date(2023, 11, 21), <>Add <SpellLink spell={TALENTS.CALL_OF_THE_WILD_TALENT} /> to the spellbook specifying cooldown and global cooldown. </>, Putro), change(date(2023, 10, 18), <>Enable spec with 10.2 changes</>,Arlie), diff --git a/src/analysis/retail/hunter/beastmastery/modules/guide/sections/rotation/FrenzyBuffStackTracker.tsx b/src/analysis/retail/hunter/beastmastery/modules/guide/sections/rotation/FrenzyBuffStackTracker.tsx index 76ebc787056..7491a8df758 100644 --- a/src/analysis/retail/hunter/beastmastery/modules/guide/sections/rotation/FrenzyBuffStackTracker.tsx +++ b/src/analysis/retail/hunter/beastmastery/modules/guide/sections/rotation/FrenzyBuffStackTracker.tsx @@ -1,13 +1,22 @@ +import { + ORIGINAL_FRENZY_DURATION, + SAVAGERY_FRENZY_DURATION, +} from 'analysis/retail/hunter/beastmastery/constants'; import SPELLS from 'common/SPELLS'; +import { TALENTS_HUNTER } from 'common/TALENTS'; import { Options } from 'parser/core/Analyzer'; import BuffStackTracker from 'parser/shared/modules/BuffStackTracker'; export default class FrenzyBuffStackTracker extends BuffStackTracker { static trackPets = true; static trackedBuff = SPELLS.BARBED_SHOT_PET_BUFF; + static workaroundWeirdBuffEvents_experimental = true; // eslint-disable-next-line @typescript-eslint/no-useless-constructor constructor(options: Options) { super(options); + this.buffDuration = this.selectedCombatant.hasTalent(TALENTS_HUNTER.SAVAGERY_TALENT) + ? SAVAGERY_FRENZY_DURATION + : ORIGINAL_FRENZY_DURATION; } } diff --git a/src/analysis/retail/hunter/beastmastery/modules/talents/BarbedShot.tsx b/src/analysis/retail/hunter/beastmastery/modules/talents/BarbedShot.tsx index 92c8280abd7..7822d164e8e 100644 --- a/src/analysis/retail/hunter/beastmastery/modules/talents/BarbedShot.tsx +++ b/src/analysis/retail/hunter/beastmastery/modules/talents/BarbedShot.tsx @@ -20,7 +20,6 @@ import Events, { } from 'parser/core/Events'; import { ThresholdStyle, When } from 'parser/core/ParseResults'; import { currentStacks } from 'parser/shared/modules/helpers/Stacks'; -import Pets from 'parser/shared/modules/Pets'; import BoringSpellValueText from 'parser/ui/BoringSpellValueText'; import { QualitativePerformance } from 'parser/ui/QualitativePerformance'; import Statistic from 'parser/ui/Statistic'; @@ -44,12 +43,10 @@ import SpellUsable from '../core/SpellUsable'; class BarbedShot extends Analyzer { static dependencies = { spellUsable: SpellUsable, - pets: Pets, globalCooldown: GlobalCooldown, }; protected spellUsable!: SpellUsable; - protected pets!: Pets; protected globalCooldown!: GlobalCooldown; barbedShotStacks: number[][] = []; @@ -162,6 +159,13 @@ class BarbedShot extends Analyzer { return; } this.lastBarbedShotUpdate = event.timestamp; + //Bosses like Volcoross are shit and will trigger ApplyBuffEvents without the buff having expired, and it should have been RefreshBuffEvent instead + if ( + event.type === EventType.ApplyBuff && + event.timestamp < this.lastBarbedShotUpdate + this.frenzyBuffDuration + ) { + return; + } this.lastBarbedShotStack = currentStacks(event); } diff --git a/src/parser/shared/modules/BuffStackTracker.ts b/src/parser/shared/modules/BuffStackTracker.ts index 122695a5147..2c1e997c06f 100644 --- a/src/parser/shared/modules/BuffStackTracker.ts +++ b/src/parser/shared/modules/BuffStackTracker.ts @@ -34,9 +34,18 @@ export default class BuffStackTracker extends Analyzer { /** Whether the module should look at player (default) or at pets when tracking buffs */ static trackPets = false; + /** Experimental feature that makes it so we try and work around weird buff events in the game */ + static workaroundWeirdBuffEvents_experimental = false; + /** Time ordered list of buff stack updates */ buffStackUpdates: BuffStackUpdate[] = []; + /** Duration of the buff */ + buffDuration = 0; + + /** Whether the buff is currently active */ + buffActive = false; + constructor(options: Options) { super(options); const trackTarget = !this.trackPets ? SELECTED_PLAYER : SELECTED_PLAYER_PET; @@ -69,6 +78,11 @@ export default class BuffStackTracker extends Analyzer { return ctor.trackedBuff; } + get workaroundWeirdBuffEvents_experimental() { + const ctor = this.constructor as typeof BuffStackTracker; + return ctor.workaroundWeirdBuffEvents_experimental; + } + /** The player's buff stack amount at the current timestamp */ get current(): number { const lastUpdate = this.buffStackUpdates.at(-1); @@ -80,6 +94,18 @@ export default class BuffStackTracker extends Analyzer { } onApplyBuff(event: ApplyBuffEvent) { + if (this.workaroundWeirdBuffEvents_experimental) { + const lastUpdate = this.buffStackUpdates.at(-1); + //If we are registering an ApplyBuffEvent before it's meant to be expire and we have not seen a RemoveBuffEvent then we should not log and push it as it was most likely a refresh + if ( + this.buffActive && + lastUpdate && + lastUpdate.timestamp < event.timestamp + this.buffDuration + ) { + return; + } + } + this.buffActive = true; this._logAndPushUpdate( { type: event.type, @@ -104,6 +130,7 @@ export default class BuffStackTracker extends Analyzer { } onRemoveBuff(event: RemoveBuffEvent) { + this.buffActive = false; this._logAndPushUpdate( { type: event.type,