Skip to content

Commit

Permalink
Merge branch 'dragonflight' of https://github.com/WoWAnalyzer/WoWAnal…
Browse files Browse the repository at this point in the history
…yzer into Defensives
  • Loading branch information
Krealle committed Apr 1, 2024
2 parents 74d7299 + c74cb12 commit 8c1c628
Show file tree
Hide file tree
Showing 23 changed files with 1,274 additions and 1,014 deletions.
2 changes: 2 additions & 0 deletions src/CHANGELOG.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,13 @@ import SpellLink from 'interface/SpellLink';

// prettier-ignore
export default [
change(date(2024, 3, 27), 'Rewrite events tab in TypeScript.', ToppleTheNun),
change(date(2024, 3, 26), 'Add patch 10.2.6.', ToppleTheNun),
change(date(2024, 3, 26), 'Add Dragonflight season 4 M+ dungeons and zone.', ToppleTheNun),
change(date(2024, 3, 26), 'Remove support for Shadowlands tier sets.', ToppleTheNun),
change(date(2024, 3, 26), 'Add tier set IDs for Dragonflight season 4.', ToppleTheNun),
change(date(2024, 3, 22), 'Update Channeling normalizer to attach fabricated channel events to their associated cast events.', Vollmer),
change(date(2024, 3, 17), <>Implement buffSoonPresent APL condition and fix chain cast issues with APL check.</>, Vollmer),
change(date(2024, 3, 14), 'Correct getBuffStacks method to return the stacks at the given timestamp', Earosselot),
change(date(2024, 3, 14), 'Fix overflow on cooldown bars while using the phase selector.', ToppleTheNun),
change(date(2024, 3, 14), 'Bump opacity on phase selector to 75% from 40%.', ToppleTheNun),
Expand Down
2 changes: 1 addition & 1 deletion src/CONTRIBUTORS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1976,7 +1976,7 @@ export const ToppleTheNun: Contributor = {
nickname: 'ToppleTheNun',
github: 'ToppleTheNun',
avatar: avatar('ToppleTheNun-avatar.jpg'),
discord: 'ToppleTheNun#6969',
discord: 'ToppleTheNun',
mains: [
{
name: 'Toppledh',
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 @@ -6,6 +6,7 @@ import SPELLS from 'common/SPELLS/evoker';
import RESOURCE_TYPES from 'game/RESOURCE_TYPES';

export default [
change(date(2024, 3, 17), 'Update APL Check and timeline cleanup.', Vollmer),
change(date(2024, 3, 7), <>Fix an issue with <SpellLink spell={TALENTS.POTENT_MANA_TALENT} /> module when no <SpellLink spell={TALENTS.SOURCE_OF_MAGIC_TALENT} /> was active during the fight.</>, Vollmer),
change(date(2024, 3, 6), <>Make it more apparent that you can mouseover points in the <SpellLink spell={SPELLS.DISINTEGRATE} /> graph.</>, Vollmer),
change(date(2024, 2, 10), <>Fix crash in <SpellLink spell={TALENTS.SOURCE_OF_MAGIC_TALENT} /> module.</>, Trevor),
Expand Down
2 changes: 1 addition & 1 deletion src/analysis/retail/evoker/devastation/CombatLogParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import Abilities from './modules/Abilities';
import ShatteringStar from './modules/abilities/ShatteringStar';
import Buffs from './modules/Buffs';
import Guide from './Guide';
import AplCheck from './modules/AplCheck';
import AplCheck from './modules/AplCheck/AplCheck';
import Disintegrate from './modules/abilities/Disintegrate';
import EssenceBurst from './modules/abilities/EssenceBurst';
import Burnout from './modules/abilities/Burnout';
Expand Down
2 changes: 2 additions & 0 deletions src/analysis/retail/evoker/devastation/constants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,5 @@ export const DEVA_T31_2PC_MULTIPLER = 0.05;

export const POWER_SWELL_REGEN_FACTOR = 1;
export const DENSE_ENERGY_ESSENCE_REDUCTION = 1;

export const OPTIMAL_EMPOWER_DRAGONRAGE_GAP_ST_MS = 13000;
5 changes: 5 additions & 0 deletions src/analysis/retail/evoker/devastation/modules/Abilities.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import CoreAbilities from 'analysis/retail/evoker/shared/modules/Abilities';
import { SpellbookAbility } from 'parser/core/modules/Ability';
import SPELL_CATEGORY from 'parser/core/SPELL_CATEGORY';
import SPELLS from 'common/SPELLS';
import { BASE_EVOKER_RANGE } from '../../shared';

class Abilities extends CoreAbilities {
spellbook(): SpellbookAbility[] {
Expand All @@ -15,6 +16,7 @@ class Abilities extends CoreAbilities {
gcd: {
base: 1500,
},
range: BASE_EVOKER_RANGE,
enabled: combatant.hasTalent(TALENTS.PYRE_TALENT),
},
{
Expand All @@ -28,6 +30,7 @@ class Abilities extends CoreAbilities {
suggestion: true,
recommendedEfficiency: 0.9,
},
range: BASE_EVOKER_RANGE,
enabled: combatant.hasTalent(TALENTS.FIRESTORM_TALENT),
},
{
Expand All @@ -43,6 +46,7 @@ class Abilities extends CoreAbilities {
suggestion: true,
recommendedEfficiency: 0.95,
},
range: BASE_EVOKER_RANGE,
enabled: combatant.hasTalent(TALENTS.ETERNITY_SURGE_TALENT),
},
{
Expand All @@ -57,6 +61,7 @@ class Abilities extends CoreAbilities {
recommendedEfficiency: 0.9,
extraSuggestion: 'You should aim to use this off CD.',
},
range: BASE_EVOKER_RANGE,
enabled: combatant.hasTalent(TALENTS.SHATTERING_STAR_TALENT),
},
//endregion
Expand Down
106 changes: 106 additions & 0 deletions src/analysis/retail/evoker/devastation/modules/AplCheck/AplCheck.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import SPELLS from 'common/SPELLS/evoker';
import { suggestion } from 'parser/core/Analyzer';
import aplCheck, { Apl, build, CheckResult, PlayerInfo, Rule } from 'parser/shared/metrics/apl';
import annotateTimeline from 'parser/shared/metrics/apl/annotate';
import TALENTS from 'common/TALENTS/evoker';
import { AnyEvent } from 'parser/core/Events';
import Spell from 'common/SPELLS/Spell';
import { getRules, Rules } from './rules';

export type TalentInfo = {
maxEssenceBurst: number;
maxEssence: number;
eternitySurgeSpell: Spell[];
fireBreathSpell: Spell[];
hasEventHorizon: boolean;
hasIridescence: boolean;
hasProtractedTalons: boolean;
};

const default_rotation = (rules: Rules): Rule[] => {
return [
/** Top priority spells */
rules.snapFireFirestorm,
rules.ehEternitySurge,
rules.fireBreath,
rules.aoeEternitySurge,
rules.shatteringStar,
rules.stEternitySurge,
rules.aoeFirestorm,
rules.aoeLivingFlame,
rules.stBurnoutLivingFlame,

/** Spenders */
rules.aoePyre,
rules.threeTargetPyre,
rules.disintegrate,

/** Fillers */
rules.stFirestorm,
rules.aoeAzureStrike,
rules.greenSpells,
rules.dragonRageFillerLivingFlame,
rules.fillerLivingFlame,
SPELLS.AZURE_STRIKE,
];
};

const talentCheck = (info: PlayerInfo): TalentInfo => {
const talentInfo: TalentInfo = {
maxEssenceBurst: 1,
maxEssence: 5,
/** The reason for defining only one version of our empower spell
* is that if we include both font and non font version it will show up as
* "Cast Fire Breath or Fire Breath...", since it then assumes we have both available.
* This looks a bit weird so we try to define the version that is actively talented. */
eternitySurgeSpell: [SPELLS.ETERNITY_SURGE],
fireBreathSpell: [SPELLS.FIRE_BREATH],
/** Below talents have rotational changes */
hasEventHorizon: false,
hasIridescence: false,
hasProtractedTalons: false,
};
if (!info || !info?.combatant) {
/** If we don't know whether the player has font talented or not
* we need to make sure we have both included */
talentInfo.fireBreathSpell = [SPELLS.FIRE_BREATH, SPELLS.FIRE_BREATH_FONT];
talentInfo.eternitySurgeSpell = [SPELLS.ETERNITY_SURGE, SPELLS.ETERNITY_SURGE_FONT];
return talentInfo;
}

const combatant = info.combatant;

talentInfo.maxEssenceBurst = combatant.hasTalent(TALENTS.ESSENCE_ATTUNEMENT_TALENT) ? 2 : 1;
talentInfo.maxEssence = combatant.hasTalent(TALENTS.POWER_NEXUS_TALENT) ? 6 : 5;

if (combatant.hasTalent(TALENTS.FONT_OF_MAGIC_DEVASTATION_TALENT)) {
talentInfo.fireBreathSpell = [SPELLS.FIRE_BREATH_FONT];
talentInfo.eternitySurgeSpell = [SPELLS.ETERNITY_SURGE_FONT];
}

talentInfo.hasEventHorizon = combatant.hasTalent(TALENTS.EVENT_HORIZON_TALENT);
talentInfo.hasIridescence = combatant.hasTalent(TALENTS.IRIDESCENCE_TALENT);
talentInfo.hasProtractedTalons = combatant.hasTalent(TALENTS.PROTRACTED_TALONS_TALENT);

return talentInfo;
};

export const apl = (info: PlayerInfo): Apl => {
const talentInfo = talentCheck(info);

const rules: Rules = getRules(talentInfo);

return build(default_rotation(rules));
};

export const check = (events: AnyEvent[], info: PlayerInfo): CheckResult => {
const check = aplCheck(apl(info));
return check(events, info);
};

export default suggestion((events, info) => {
const { violations } = check(events, info);
annotateTimeline(violations);

return undefined;
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import TALENTS from 'common/TALENTS/evoker';
import RESOURCE_TYPES from 'game/RESOURCE_TYPES';
import * as cnd from 'parser/shared/metrics/apl/conditions';
import SPELLS from 'common/SPELLS/evoker';
import { SpellLink } from 'interface';
import { tenseAlt } from 'parser/shared/metrics/apl';
import { OPTIMAL_EMPOWER_DRAGONRAGE_GAP_ST_MS } from '../../constants';

export const avoidIfDragonRageSoon = (time: number = OPTIMAL_EMPOWER_DRAGONRAGE_GAP_ST_MS) => {
return cnd.describe(
cnd.buffSoonPresent(TALENTS.DRAGONRAGE_TALENT, {
atLeast: time,
}),
(tense) => (
<>
there {tenseAlt(tense, <>is</>, <>was</>)} atleast {time / 1000} seconds left before{' '}
{tenseAlt(tense, <>using</>, <>you used</>)} <SpellLink spell={TALENTS.DRAGONRAGE_TALENT} />
</>
),
);
};

export const hasEssenceRequirement = (resources: number, initial: number) => {
return cnd.always(
cnd.or(
cnd.hasResource(RESOURCE_TYPES.ESSENCE, { atLeast: resources }, initial),
cnd.buffPresent(SPELLS.ESSENCE_BURST_DEV_BUFF),
),
);
};

export const standardEmpowerConditional = cnd.or(
cnd.describe(cnd.buffPresent(TALENTS.DRAGONRAGE_TALENT), (tense) => (
<>
{tenseAlt(tense, <>in</>, <>you were in</>)} <SpellLink spell={TALENTS.DRAGONRAGE_TALENT} />
</>
)),
avoidIfDragonRageSoon(),
);
Loading

0 comments on commit 8c1c628

Please sign in to comment.