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 >, Putro),
change(date(2023, 11, 21), <>Update when are marked as good or bad casts. >, Putro),
change(date(2023, 11, 21), <>Add 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,