Skip to content

Commit

Permalink
[Aug/Deva] Implement Wingleader module (WoWAnalyzer#7002)
Browse files Browse the repository at this point in the history
* add constants

* add missing "supportID" prop for "DamageEvent" interface

* implement Wingleader module

* enable for aug & deva

* changelogs

* core changelog
  • Loading branch information
Krealle authored Sep 10, 2024
1 parent 4c34d83 commit 612f302
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/CHANGELOG.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import SpellLink from 'interface/SpellLink';
export default [
change(date(2024, 9, 9), 'Fix character search showing UNKNOWN instead of THE WAR WITHIN.', ToppleTheNun),
change(date(2024, 9, 8), "Add Nerub'ar Palace bosses and season 1 M+ dungeons.", ToppleTheNun),
change(date(2024, 9, 6), "Add missing supportID property to DamageEvent interface", Vollmer),
change(date(2024, 9, 5), 'Update Rogue spells for Classic Cataclysm', jazminite),
change(date(2024, 9, 4), 'Updates to Active Time calculation to avoid cases where overcount could occur.', Sref),
change(date(2024, 9, 3), "Fixed a bug where the Death Recap wouldn't detect some defensive buffs", Sref),
Expand Down
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 @@ -4,6 +4,7 @@ import { SpellLink } from 'interface';
import TALENTS from 'common/TALENTS/evoker';

export default [
change(date(2024, 9, 6), <>Implement <SpellLink spell={TALENTS.WINGLEADER_TALENT}/> module</>, Vollmer),
change(date(2024, 9, 6), <>Update MajorDefensive module for <SpellLink spell={TALENTS.LIFECINDERS_TALENT}/> and <SpellLink spell={TALENTS.HARDENED_SCALES_TALENT}/></>, Vollmer),
change(date(2024, 9, 6), <>Implement <SpellLink spell={TALENTS.SLIPSTREAM_TALENT}/> module</>, Vollmer),
change(date(2024, 9, 6), <>Implement <SpellLink spell={TALENTS.EXTENDED_BATTLE_TALENT}/> module</>, Vollmer),
Expand Down
2 changes: 2 additions & 0 deletions src/analysis/retail/evoker/augmentation/CombatLogParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import {
ExtendedBattle,
DivertedPower,
UnrelentingSiege,
Wingleader,
Slipstream,
} from 'analysis/retail/evoker/shared';

Expand Down Expand Up @@ -131,6 +132,7 @@ class CombatLogParser extends MainCombatLogParser {
extendedBattle: ExtendedBattle,
divertedPower: DivertedPower,
unrelentingSiege: UnrelentingSiege,
wingLeader: Wingleader,
slipstream: Slipstream,

// Features
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 @@ -5,6 +5,7 @@ import { TALENTS_EVOKER } from 'common/TALENTS/evoker';
import SPELLS from 'common/SPELLS/evoker';

export default [
change(date(2024, 9, 6), <>Implement <SpellLink spell={TALENTS_EVOKER.WINGLEADER_TALENT}/> module</>, Vollmer),
change(date(2024, 9, 6), <>Update MajorDefensive module for <SpellLink spell={TALENTS_EVOKER.LIFECINDERS_TALENT}/> and <SpellLink spell={TALENTS_EVOKER.HARDENED_SCALES_TALENT}/></>, Vollmer),
change(date(2024, 9, 6), <>Implement <SpellLink spell={TALENTS_EVOKER.SLIPSTREAM_TALENT}/> module</>, Vollmer),
change(date(2024, 9, 6), <>Implement <SpellLink spell={TALENTS_EVOKER.EXTENDED_BATTLE_TALENT}/> module</>, Vollmer),
Expand Down
2 changes: 2 additions & 0 deletions src/analysis/retail/evoker/devastation/CombatLogParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ import {
ExtendedBattle,
DivertedPower,
UnrelentingSiege,
Wingleader,
Slipstream,
} from 'analysis/retail/evoker/shared';
import ExpandedLungs from '../shared/modules/talents/hero/flameshaper/ExpandedLungs';
Expand Down Expand Up @@ -141,6 +142,7 @@ class CombatLogParser extends MainCombatLogParser {
extendedBattle: ExtendedBattle,
divertedPower: DivertedPower,
unrelentingSiege: UnrelentingSiege,
wingLeader: Wingleader,
slipstream: Slipstream,

// core abilities
Expand Down
3 changes: 3 additions & 0 deletions src/analysis/retail/evoker/shared/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,6 @@ export const HARDENED_SCALES_MITIGATION = 0.1;
export const MASS_DISINTEGRATE_MULTIPLIER_PER_MISSING_TARGET = 0.15;
export const MASS_ERUPTION_MULTIPLIER_PER_MISSING_TARGET =
MASS_DISINTEGRATE_MULTIPLIER_PER_MISSING_TARGET;

export const WINGLEADER_CDR_PER_HIT_MS = 1_000;
export const WINGLEADER_MAX_HITS = 3;
1 change: 1 addition & 0 deletions src/analysis/retail/evoker/shared/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@ export { default as MightOfTheBlackDragonflight } from './modules/talents/hero/s
export { default as ExtendedBattle } from './modules/talents/hero/scalecommander/ExtendedBattle';
export { default as DivertedPower } from './modules/talents/hero/scalecommander/DivertedPower';
export { default as UnrelentingSiege } from './modules/talents/hero/scalecommander/UnrelentingSiege';
export { default as Wingleader } from './modules/talents/hero/scalecommander/Wingleader';
export { default as Slipstream } from './modules/talents/hero/scalecommander/Slipstream';
export * from './constants';
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import Analyzer, { Options, SELECTED_PLAYER } from 'parser/core/Analyzer';
import SPELLS from 'common/SPELLS/evoker';
import TALENTS from 'common/TALENTS/evoker';
import Events, { DamageEvent } from 'parser/core/Events';
import {
WINGLEADER_CDR_PER_HIT_MS,
WINGLEADER_MAX_HITS,
} from 'analysis/retail/evoker/shared/constants';
import SpellUsable from 'parser/shared/modules/SpellUsable';
import SPECS from 'game/SPECS';
import STATISTIC_ORDER from 'parser/ui/STATISTIC_ORDER';
import Statistic from 'parser/ui/Statistic';
import STATISTIC_CATEGORY from 'parser/ui/STATISTIC_CATEGORY';
import SpellLink from 'interface/SpellLink';
import DonutChart from 'parser/ui/DonutChart';
import Spell from 'common/SPELLS/Spell';

const BUFFER = 50;

/** Bombardments reduce the cooldown of Deep Breath by 1 sec for each target struck,
* up to 3 sec. */
class Wingleader extends Analyzer {
static dependencies = {
spellUsable: SpellUsable,
};
protected spellUsable!: SpellUsable;

damageRecord: Record<
number,
{
initialTimestamp: number;
hits: number;
}
> = {};

effectiveCDR = 0;
wastedCDR = 0;
breathSpell: Spell;

constructor(options: Options) {
super(options);
this.active = this.selectedCombatant.hasTalent(TALENTS.WINGLEADER_TALENT);

this.breathSpell =
this.owner.selectedCombatant.specId === SPECS.DEVASTATION_EVOKER.id
? SPELLS.DEEP_BREATH_SCALECOMMANDER
: SPELLS.BREATH_OF_EONS_SCALECOMMANDER;

this.addEventListener(
Events.damage.by(SELECTED_PLAYER).spell(SPELLS.BOMBARDMENTS_DAMAGE),
this.onDamage,
);
}

onDamage(event: DamageEvent) {
/** When you proc Bombas yourself, you will get both the
* natty damage event and the supportID damage event.
* We only want to track one of them.
* We track the natty event since sometimes the supportID event doesn't
* show up */
if (event.supportID === this.owner.selectedCombatant.id) {
return;
}

const sourceId = event.supportID ?? this.owner.selectedCombatant.id;

if (!this.damageRecord[sourceId]) {
this.damageRecord[sourceId] = {
initialTimestamp: event.timestamp,
hits: 0,
};
}

const record = this.damageRecord[sourceId];

if (event.timestamp - record.initialTimestamp > BUFFER) {
record.initialTimestamp = event.timestamp;
record.hits = 0;
}

if (record.hits === WINGLEADER_MAX_HITS) {
return;
}

record.hits += 1;
const effectiveCDR = this.spellUsable.reduceCooldown(
this.breathSpell.id,
WINGLEADER_CDR_PER_HIT_MS,
);
const wastedCDR = WINGLEADER_CDR_PER_HIT_MS - effectiveCDR;

this.effectiveCDR += effectiveCDR / 1000;
this.wastedCDR += wastedCDR / 1000;
}

statistic() {
const donutItems = [
{
color: 'rgb(123,188,93)',
label: 'Effective CDR',
valueTooltip: this.effectiveCDR.toFixed(2) + 's effective CDR',
value: this.effectiveCDR,
},
{
color: 'rgb(216,59,59)',
label: 'Wasted CDR',
valueTooltip:
this.wastedCDR.toFixed(2) + `s CDR wasted whilst ${this.breathSpell.name} was ready`,
value: this.wastedCDR,
},
];

return (
<Statistic
position={STATISTIC_ORDER.CORE(60)}
category={STATISTIC_CATEGORY.HERO_TALENTS}
size="flexible"
>
<div className="pad">
<label>
<SpellLink spell={TALENTS.WINGLEADER_TALENT} /> usage
</label>
<strong>CDR efficiency:</strong>
<DonutChart items={donutItems} />
</div>
</Statistic>
);
}
}

export default Wingleader;
1 change: 1 addition & 0 deletions src/parser/core/Events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,7 @@ export interface DamageEvent extends Event<EventType.Damage> {
overkill?: number;
blocked?: number; // does this exist?
subtractsFromSupportedActor?: boolean;
supportID?: number;
}

export interface BuffEvent<T extends string> extends Event<T> {
Expand Down

0 comments on commit 612f302

Please sign in to comment.