Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
Krealle committed Aug 13, 2024
2 parents 4aba6f7 + 86271db commit 1877c12
Show file tree
Hide file tree
Showing 90 changed files with 801 additions and 2,267 deletions.
1 change: 1 addition & 0 deletions src/CHANGELOG.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import SpellLink from 'interface/SpellLink';

// prettier-ignore
export default [
change(date(2024, 8, 10), <>Implement buffAndNextCastChannelSpec for channeling normalizer</>, Vollmer),
change(date(2024, 8, 9), <>Fix the haste bonus of <SpellLink spell={SPELLS.BERSERKING.id} /> in Classic Cataclysm.</>, emallson),
change(date(2024, 8, 7), 'Prepare for cleanup of Dragonflight items.', ToppleTheNun),
change(date(2024, 8, 6), 'Update Priest spells for Classic Cataclysm', jazminite),
Expand Down
13 changes: 12 additions & 1 deletion src/CONTRIBUTORS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2075,9 +2075,14 @@ export const Squided: Contributor = {
mains: [
{
name: 'Squided',
spec: SPECS.HOLY_PRIEST,
spec: SPECS.HOLY_PALADIN,
link: 'https://worldofwarcraft.com/en-us/character/us/area-52/Squided',
},
{
name: 'Squidkid',
spec: SPECS.HOLY_PRIEST,
link: 'https://worldofwarcraft.com/en-us/character/us/area-52/Squidkid',
},
],
};

Expand Down Expand Up @@ -2443,3 +2448,9 @@ export const Ethelis: Contributor = {
nickname: 'Ethelis',
github: 'ethelis',
};

export const Lithix: Contributor = {
nickname: 'Lithix',
github: 'Yitaarli',
discord: 'lithix#0749',
};
3 changes: 3 additions & 0 deletions src/analysis/retail/deathknight/blood/CHANGELOG.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { change, date } from 'common/changelog';
import talents from 'common/TALENTS/deathknight';
import { emallson } from 'CONTRIBUTORS';
import SpellLink from 'interface/SpellLink';

// prettier-ignore
export default [
change(date(2024, 8, 12), <>Fix crash when <SpellLink spell={talents.RAPID_DECOMPOSITION_TALENT} /> was not selected.</>, emallson),
change(date(2024, 7, 28), 'Basic updates for The War Within', emallson),
];
10 changes: 4 additions & 6 deletions src/analysis/retail/deathknight/blood/modules/Abilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,12 +223,10 @@ class Abilities extends CoreAbilities {
base: 1500,
},
cooldown: 15,
castEfficiency: combatant.hasTalent(TALENTS.RAPID_DECOMPOSITION_TALENT)
? {
suggestion: true,
recommendedEfficiency: 0.8, //reduced because of proc resets
}
: undefined,
castEfficiency: {
suggestion: true,
recommendedEfficiency: 0.8, //reduced because of proc resets
},
charges: combatant.hasTalent(TALENTS.DEATHS_ECHO_TALENT) ? 2 : 1,
timelineSortIndex: 5,
},
Expand Down
2 changes: 2 additions & 0 deletions src/analysis/retail/evoker/augmentation/CHANGELOG.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import TALENTS from 'common/TALENTS/evoker';

export default [
change(date(2024, 8, 11), <>Implement <SpellLink spell={TALENTS.MELT_ARMOR_TALENT}/> module</>, Vollmer),
change(date(2024, 8, 11), <>Implement <SpellLink spell={TALENTS.MIGHT_OF_THE_BLACK_DRAGONFLIGHT_TALENT}/> module</>, Vollmer),
change(date(2024, 8, 11), <>Implement <SpellLink spell={TALENTS.MASS_ERUPTION_TALENT}/> module</>, Vollmer),
change(date(2024, 7, 22), <>Update <SpellLink spell={TALENTS.REACTIVE_HIDE_TALENT}/> multiplier</>, Vollmer),
change(date(2024, 7, 21), <>Implement <SpellLink spell={TALENTS.RUMBLING_EARTH_TALENT}/> module</>, Vollmer),
change(date(2024, 7, 21), <>Implement <SpellLink spell={TALENTS.IMMINENT_DESTRUCTION_AUGMENTATION_TALENT}/> module</>, Vollmer),
Expand Down
5 changes: 5 additions & 0 deletions src/analysis/retail/evoker/augmentation/CombatLogParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ import {
RenewingBlaze,
ImminentDestruction,
MeltArmor,
MassDisintegrate,
MightOfTheBlackDragonflight,
} from 'analysis/retail/evoker/shared';

class CombatLogParser extends MainCombatLogParser {
Expand Down Expand Up @@ -86,6 +88,7 @@ class CombatLogParser extends MainCombatLogParser {
defensiveNormalizer: DefensiveNormalizer,
twinGuardian: TwinGuardian,
renewingBlaze: RenewingBlaze,
massDisintegrate: MassDisintegrate,

// Normalizers
castLinkNormalizer: CastLinkNormalizer,
Expand Down Expand Up @@ -118,6 +121,8 @@ class CombatLogParser extends MainCombatLogParser {
moltenEmbers: MoltenEmbers,
rumblingEarth: RumblingEarth,

// hero talents
mightOfTheBlackDragonflight: MightOfTheBlackDragonflight,
meltArmor: MeltArmor,

// Features
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ export const UPHEAVAL_RUMBLING_EARTH_LINK = 'upheavalRumblingEarthLink';
// Tier
export const TREMBLING_EARTH_DAM_LINK = 'tremblingEarthDamLink';

export const MASS_ERUPTION_DAM_LINK = 'massEruptionDamLink';
export const MASS_ERUPTION_CONSUME = 'massEruptionConsume';
const MASS_ERUPTION_DAMAGE_BUFFER = 1000; // These have very spooky delay

const PRESCIENCE_BUFFER = 150;
const CAST_BUFFER_MS = 100;
const BREATH_EBON_BUFFER = 250;
Expand Down Expand Up @@ -256,6 +260,30 @@ const EVENT_LINKS: EventLink[] = [
return !HasRelatedEvent(referencedEvent, UPHEAVAL_CAST_DAM_LINK);
},
},
{
linkRelation: MASS_ERUPTION_CONSUME,
reverseLinkRelation: MASS_ERUPTION_CONSUME,
linkingEventId: TALENTS.ERUPTION_TALENT.id,
linkingEventType: EventType.Cast,
referencedEventId: SPELLS.MASS_ERUPTION_BUFF.id,
referencedEventType: [EventType.RemoveBuff, EventType.RemoveBuffStack],
anyTarget: true,
forwardBufferMs: CAST_BUFFER_MS,
backwardBufferMs: CAST_BUFFER_MS,
isActive: (C) => C.hasTalent(TALENTS.MASS_ERUPTION_TALENT),
maximumLinks: 1,
},
{
linkRelation: MASS_ERUPTION_DAM_LINK,
reverseLinkRelation: MASS_ERUPTION_DAM_LINK,
linkingEventId: TALENTS.ERUPTION_TALENT.id,
linkingEventType: EventType.Cast,
referencedEventId: SPELLS.MASS_ERUPTION_DAMAGE.id,
referencedEventType: EventType.Damage,
anyTarget: true,
forwardBufferMs: MASS_ERUPTION_DAMAGE_BUFFER,
isActive: (C) => C.hasTalent(TALENTS.MASS_ERUPTION_TALENT),
},
];

class CastLinkNormalizer extends EventLinkNormalizer {
Expand Down Expand Up @@ -346,4 +374,16 @@ function upheavalHitIsUnique(castEvent: EmpowerEndEvent, damageEvent: DamageEven
);
}

export function isFromMassEruption(event: CastEvent) {
return HasRelatedEvent(event, MASS_ERUPTION_CONSUME);
}

export function getMassEruptionDamageEvents(event: CastEvent): DamageEvent[] {
return GetRelatedEvents(
event,
MASS_ERUPTION_DAM_LINK,
(e): e is DamageEvent => e.type === EventType.Damage,
);
}

export default CastLinkNormalizer;
3 changes: 3 additions & 0 deletions src/analysis/retail/evoker/devastation/CHANGELOG.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import SPELLS from 'common/SPELLS/evoker';

export default [
change(date(2024, 8, 11), <>Implement <SpellLink spell={TALENTS_EVOKER.MELT_ARMOR_TALENT}/> module</>, Vollmer),
change(date(2024, 8, 11), <>Implement <SpellLink spell={TALENTS_EVOKER.MIGHT_OF_THE_BLACK_DRAGONFLIGHT_TALENT}/> module</>, Vollmer),
change(date(2024, 8, 11), <>Implement <SpellLink spell={TALENTS_EVOKER.MASS_DISINTEGRATE_TALENT}/> module</>, Vollmer),
change(date(2024, 8, 10), <>Add Always Be Casting guide section</>, Vollmer),
change(date(2024, 7, 22), <>Update <SpellLink spell={TALENTS_EVOKER.HEAT_WAVE_TALENT}/> and <SpellLink spell={TALENTS_EVOKER.HONED_AGGRESSION_TALENT}/> multipliers</>, Vollmer),
change(date(2024, 7, 21), <>Implement <SpellLink spell={TALENTS_EVOKER.SCORCHING_EMBERS_TALENT} /> module</>, Vollmer),
change(date(2024, 7, 21), <>Implement <SpellLink spell={TALENTS_EVOKER.IMMINENT_DESTRUCTION_DEVASTATION_TALENT}/> module</>, Vollmer),
Expand Down
2 changes: 1 addition & 1 deletion src/analysis/retail/evoker/devastation/CONFIG.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const config: Config = {
contributors: [Vireve, Tyndi, Vollmer],
branch: GameBranch.Retail,
// The WoW client patch this spec was last updated.
patchCompatibility: '10.2.7',
patchCompatibility: '11.0.0',
supportLevel: SupportLevel.MaintainedFull,
// Explain the status of this spec's analysis here. Try to mention how complete it is, and perhaps show links to places users can learn more.
// If this spec's analysis does not show a complete picture please mention this in the `<Warning>` component.
Expand Down
8 changes: 8 additions & 0 deletions src/analysis/retail/evoker/devastation/CombatLogParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ import T31DevaTier from './modules/dragonflight/tier/T31DevaTier';
import Pyre from './modules/abilities/Pyre';
import EternitySurgeNormalizer from './modules/normalizers/EternitySurgeNormalizer';
import ScorchingEmbers from './modules/talents/ScorchingEmbers';
import AlwaysBeCasting from 'parser/shared/modules/AlwaysBeCasting';
import CancelledCasts from 'parser/shared/modules/CancelledCasts';

// Shared
import {
Expand All @@ -58,6 +60,8 @@ import {
Engulf,
ImminentDestruction,
MeltArmor,
MassDisintegrate,
MightOfTheBlackDragonflight,
} from 'analysis/retail/evoker/shared';
import ExpandedLungs from '../shared/modules/talents/hero/flameshaper/ExpandedLungs';
import FanTheFlames from '../shared/modules/talents/hero/flameshaper/FanTheFlames';
Expand Down Expand Up @@ -102,6 +106,8 @@ class CombatLogParser extends MainCombatLogParser {
// features
apls: AplCheck,
cooldownThroughputTracker: CooldownThroughputTracker,
alwaysBeCasting: AlwaysBeCasting,
cancelledCasts: CancelledCasts,

// talents
catalyze: Catalyze,
Expand All @@ -126,6 +132,8 @@ class CombatLogParser extends MainCombatLogParser {
fanTheFlames: FanTheFlames,
redHot: RedHot,
meltArmor: MeltArmor,
massDisintegrate: MassDisintegrate,
mightOfTheBlackDragonflight: MightOfTheBlackDragonflight,

// core abilities
disintegrate: Disintegrate,
Expand Down
4 changes: 2 additions & 2 deletions src/analysis/retail/evoker/devastation/Guide.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import PreparationSection from 'interface/guide/components/Preparation/Preparati
import { CooldownSection } from './modules/guide/Cooldown';
import { CoreRotation } from './modules/guide/CoreRotation';
import { DamageEfficiency } from './modules/guide/DamageEfficiencySection';
import { EssenceGraphSection } from './modules/guide/EssenceGraphSection';
import { CoreSection } from './modules/guide/CoreSection';
import { DragonRageSection } from './modules/guide/DragonRageSection';
import { IntroSection } from './modules/guide/IntroSection';
import MajorDefensives from '../shared/modules/MajorDefensives/DefensivesGuide';
Expand All @@ -13,7 +13,7 @@ export default function Guide({ modules, events, info }: GuideProps<typeof Comba
return (
<>
<IntroSection />
<EssenceGraphSection modules={modules} info={info} events={events} />
<CoreSection modules={modules} info={info} events={events} />
<CooldownSection modules={modules} info={info} events={events} />
<DragonRageSection modules={modules} info={info} events={events} />
<DamageEfficiency modules={modules} info={info} events={events} />
Expand Down
112 changes: 112 additions & 0 deletions src/analysis/retail/evoker/devastation/modules/guide/CoreSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import CombatLogParser from '../../CombatLogParser';
import { GuideProps, Section, SubSection } from 'interface/guide';
import { QualitativePerformance } from 'parser/ui/QualitativePerformance';
import PerformancePercentage from './PerformancePercentage';
import { ResourceLink, SpellLink, Tooltip } from 'interface';
import RESOURCE_TYPES from 'game/RESOURCE_TYPES';
import { TIERS } from 'game/TIERS';
import { InformationIcon } from 'interface/icons';
import SPELLS from 'common/SPELLS/evoker';
import PerformanceStrong from 'interface/PerformanceStrong';
import { formatPercentage } from 'common/format';
import ActiveTimeGraph from 'parser/ui/ActiveTimeGraph';

export function CoreSection({ modules, events, info }: GuideProps<typeof CombatLogParser>) {
const hasT31 = info.combatant.has4PieceByTier(TIERS.DF3);
const percentAtCap = modules.essenceTracker.percentAtCap;
const essenceWasted = modules.essenceTracker.wasted;

const perfectTimeAtEssenceCap = 0.1 + (hasT31 ? 0.05 : 0);
const goodTimeAtEssenceCap = 0.15 + (hasT31 ? 0.05 : 0);
const okTimeAtEssenceCap = 0.2 + (hasT31 ? 0.05 : 0);

const percentAtCapPerformance =
percentAtCap <= perfectTimeAtEssenceCap
? QualitativePerformance.Perfect
: percentAtCap <= goodTimeAtEssenceCap
? QualitativePerformance.Good
: percentAtCap <= okTimeAtEssenceCap
? QualitativePerformance.Ok
: QualitativePerformance.Fail;

return (
<Section title="Core">
<SubSection title="Essence Graph">
<p>
Your primary resource is <ResourceLink id={RESOURCE_TYPES.ESSENCE.id} />. You should avoid
overcapping <ResourceLink id={RESOURCE_TYPES.ESSENCE.id} /> - lost{' '}
<ResourceLink id={RESOURCE_TYPES.ESSENCE.id} /> generation is lost DPS. Sometimes it will
be impossible to avoid overcapping <ResourceLink id={RESOURCE_TYPES.ESSENCE.id} /> - due
to handling mechanics, high rolling <SpellLink spell={SPELLS.ESSENCE_BURST_DEV_BUFF} />{' '}
procs or during intermission phases.
</p>
<p>
The chart below shows your <ResourceLink id={RESOURCE_TYPES.ESSENCE.id} /> over the course
of the encounter. You wasted{' '}
<PerformancePercentage
performance={percentAtCapPerformance}
perfectPercentage={perfectTimeAtEssenceCap}
goodPercentage={goodTimeAtEssenceCap}
okPercentage={okTimeAtEssenceCap}
percentage={percentAtCap}
flatAmount={essenceWasted}
/>{' '}
of your <ResourceLink id={RESOURCE_TYPES.ESSENCE.id} />.
{hasT31 && (
<>
{' '}
<Tooltip
content={
<div>
Since you have T31 4pc an extra 5% grace period is added, as it is expected that
more <ResourceLink id={RESOURCE_TYPES.ESSENCE.id} /> will go to waste, due to
the extra amount of <SpellLink spell={SPELLS.ESSENCE_BURST_DEV_BUFF} />{' '}
generated.
</div>
}
>
<div style={{ display: 'inline' }}>
<InformationIcon style={{ fontSize: '1.4em' }} />
</div>
</Tooltip>
</>
)}
</p>
{modules.essenceGraph.plot}
</SubSection>
<SubSection title="Always be Casting">
<p>
<em>
<b>
Continuously chaining casts throughout an encounter is the single most important thing
for achieving good DPS as a caster.
</b>
</em>
<br />
There should be no delay at all between your spell casts, it's better to start casting the
wrong spell than to think for a few seconds and then cast the right spell. You should be
able to handle a fight's mechanics with the minimum possible interruption to your casting.
Some fights have unavoidable downtime due to phase transitions and the like, so in these
cases 0% downtime will not be possible - do the best you can.
</p>
<p>
Active Time:{' '}
<PerformanceStrong performance={modules.alwaysBeCasting.DowntimePerformance}>
{formatPercentage(modules.alwaysBeCasting.activeTimePercentage, 1)}%
</PerformanceStrong>{' '}
Cancelled Casts:{' '}
<PerformanceStrong performance={modules.cancelledCasts.CancelledPerformance}>
{formatPercentage(modules.cancelledCasts.cancelledPercentage, 1)}%
</PerformanceStrong>{' '}
</p>
<p>
<ActiveTimeGraph
activeTimeSegments={modules.alwaysBeCasting.activeTimeSegments}
fightStart={info.fightStart}
fightEnd={info.fightEnd}
/>
</p>
</SubSection>
</Section>
);
}
Loading

0 comments on commit 1877c12

Please sign in to comment.