diff --git a/src/analysis/retail/hunter/beastmastery/CHANGELOG.tsx b/src/analysis/retail/hunter/beastmastery/CHANGELOG.tsx index 90ccd5f25e4..d745f31088b 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(2023, 10, 3), <>Add as a trackable talent. , Putro), change(date(2023, 7, 29), 'Mark Beast Mastery as compatible for 10.1.5', Putro), change(date(2023, 7, 3), 'Update SpellLink usage.', ToppleTheNun), change(date(2023, 7, 3), 'Added support for Tier 30 2piece and 4piece', Putro), diff --git a/src/analysis/retail/hunter/beastmastery/CombatLogParser.ts b/src/analysis/retail/hunter/beastmastery/CombatLogParser.ts index 936964b6c66..5f3094ae60b 100644 --- a/src/analysis/retail/hunter/beastmastery/CombatLogParser.ts +++ b/src/analysis/retail/hunter/beastmastery/CombatLogParser.ts @@ -15,7 +15,8 @@ import { WailingArrow, WailingArrowPrepullNormalizer, TranquilizingShot, -} from 'analysis/retail/hunter/shared'; + SteelTrap, +} from '../shared'; import CoreCombatLogParser from 'parser/core/CombatLogParser'; import Abilities from './modules/Abilities'; import Buffs from './modules/Buffs'; @@ -127,6 +128,7 @@ class CombatLogParser extends CoreCombatLogParser { bloodshed: Bloodshed, direPack: DirePack, tranquilizingShot: TranquilizingShot, + steeltrap: SteelTrap, //Items t292p: T29BMTier2P, diff --git a/src/analysis/retail/hunter/beastmastery/constants.ts b/src/analysis/retail/hunter/beastmastery/constants.ts index 4fb1fe21548..c156029a495 100644 --- a/src/analysis/retail/hunter/beastmastery/constants.ts +++ b/src/analysis/retail/hunter/beastmastery/constants.ts @@ -91,11 +91,11 @@ export const BASE_BM_FOCUS_REGEN = 5; //Beast Mastery has 120 focus at start export const BASE_BM_FOCUS_MAX = 100; //Minor threshold for focus wastage on focus generators -export const FOCUS_THRESHOLD_MINOR = 0.025; +export const FOCUS_THRESHOLD_MINOR = 0.05; //Average threshold for focus wastage on focus generators -export const FOCUS_THRESHOLD_AVG = 0.05; +export const FOCUS_THRESHOLD_AVG = 0.075; //Major threshold for focus wastage on focus generators -export const FOCUS_THRESHOLD_MAJOR = 0.1; +export const FOCUS_THRESHOLD_MAJOR = 0.125; //The 8 focus regen buffs connected to Barbed Shot export const BARBED_SHOT_FOCUS_REGEN_BUFFS = [ SPELLS.BARBED_SHOT_BUFF, diff --git a/src/analysis/retail/hunter/beastmastery/modules/Abilities.tsx b/src/analysis/retail/hunter/beastmastery/modules/Abilities.tsx index 58739b25a39..7f1411216a7 100644 --- a/src/analysis/retail/hunter/beastmastery/modules/Abilities.tsx +++ b/src/analysis/retail/hunter/beastmastery/modules/Abilities.tsx @@ -172,6 +172,19 @@ class Abilities extends CoreAbilities { recommendedEfficiency: 0.9, }, }, + { + spell: TALENTS.STEEL_TRAP_TALENT.id, + category: SPELL_CATEGORY.ROTATIONAL, + cooldown: 30, + enabled: combatant.hasTalent(TALENTS.STEEL_TRAP_TALENT), + gcd: { + base: 1500, + }, + castEfficiency: { + suggestion: true, + recommendedEfficiency: 0.85, + }, + }, //endregion //region Baseline Defensives diff --git a/src/analysis/retail/hunter/marksmanship/CHANGELOG.tsx b/src/analysis/retail/hunter/marksmanship/CHANGELOG.tsx index 7e7e2775f12..6e9877f73db 100644 --- a/src/analysis/retail/hunter/marksmanship/CHANGELOG.tsx +++ b/src/analysis/retail/hunter/marksmanship/CHANGELOG.tsx @@ -4,6 +4,7 @@ import { ItemLink, SpellLink } from 'interface'; import TALENTS from 'common/TALENTS/hunter'; import ITEMS from 'common/ITEMS'; export default [ + change(date(2023, 10, 3), <>Add as a trackable talent. , Putro), change(date(2023, 7, 3), 'Update SpellLink usage.', ToppleTheNun), change(date(2023, 6, 4), <>Add module to hunter, Trevor), change(date(2023, 5, 9), <>Added support for T29 tier sets, Swolorno), diff --git a/src/analysis/retail/hunter/marksmanship/CombatLogParser.ts b/src/analysis/retail/hunter/marksmanship/CombatLogParser.ts index c8b92c2537b..b584088cd26 100644 --- a/src/analysis/retail/hunter/marksmanship/CombatLogParser.ts +++ b/src/analysis/retail/hunter/marksmanship/CombatLogParser.ts @@ -1,28 +1,28 @@ import { - Channeling, - DeathTracker, - NaturalMending, - Trailblazer, - Barrage, AMurderOfCrows, - BornToBeWild, + Barrage, BindingShot, - KillShot, - FocusTracker, - FocusDetails, - SpellFocusCost, + BornToBeWild, + CancelledCasts, + Channeling, DeathChakrams, + DeathTracker, + FocusDetails, + FocusTracker, + KillShot, + NaturalMending, RejuvenatingWind, - CancelledCasts, + SpellFocusCost, + SteelTrap, + Trailblazer, + TranquilizingShot, WailingArrow, WailingArrowPrepullNormalizer, - TranquilizingShot, -} from 'analysis/retail/hunter/shared'; +} from '../shared'; import CoreCombatLogParser from 'parser/core/CombatLogParser'; import ArcaneTorrent from 'parser/shared/modules/racials/bloodelf/ArcaneTorrent'; import Abilities from './modules/Abilities'; -import AplCheck from './modules/apl/AplCheck'; import Buffs from './modules/Buffs'; import Checklist from './modules/checklist/Module'; import GlobalCooldown from './modules/core/GlobalCooldown'; @@ -35,7 +35,7 @@ import SurgingShots from './modules/talents/SurgingShots'; import Focus from './modules/resources/Focus'; import MarksmanshipFocusCapTracker from './modules/resources/MarksmanshipFocusCapTracker'; import MarksmanshipFocusUsage from './modules/resources/MarksmanshipFocusUsage'; -import AimedShot from './modules/spells/AimedShot'; +import AimedShot from './modules/talents/AimedShot'; import LoneWolf from './modules/spells/LoneWolf'; import PreciseShots from './modules/spells/PreciseShots'; import RapidFire from './modules/spells/RapidFire'; @@ -90,18 +90,16 @@ class CombatLogParser extends CoreCombatLogParser { trueshot: Trueshot, loneWolf: LoneWolf, preciseShots: PreciseShots, - aimedShot: AimedShot, rapidFire: RapidFire, steadyShot: SteadyShot, killShot: KillShot, bindingShot: BindingShot, //Talents + aimedShot: AimedShot, volley: Volley, lockAndLoad: LockAndLoad, - barrage: Barrage, callingTheShots: CallingTheShots, - serpentSting: SerpentSting, steadyFocus: SteadyFocus, carefulAim: CarefulAim, chimaeraShot: ChimaeraShot, @@ -122,6 +120,9 @@ class CombatLogParser extends CoreCombatLogParser { explosiveShot: ExplosiveShot, masterMarksman: MasterMarksman, wailingArrow: WailingArrow, + steelTrap: SteelTrap, + serpentSting: SerpentSting, + barrage: Barrage, // items t292p: T29MMTier2P, @@ -129,9 +130,6 @@ class CombatLogParser extends CoreCombatLogParser { // There's no throughput benefit from casting Arcane Torrent on cooldown arcaneTorrent: [ArcaneTorrent, { castEfficiency: null }] as const, - - // apl - apl: AplCheck, }; } diff --git a/src/analysis/retail/hunter/marksmanship/constants.ts b/src/analysis/retail/hunter/marksmanship/constants.ts index fc76437b78b..9c5300cc788 100644 --- a/src/analysis/retail/hunter/marksmanship/constants.ts +++ b/src/analysis/retail/hunter/marksmanship/constants.ts @@ -30,7 +30,7 @@ export const START_LONE_WOLF_MODIFIER = 0; export const LONE_WOLF_AFFECTED_SPELLS = [ SPELLS.AUTO_SHOT, SPELLS.MULTISHOT_MM, - SPELLS.AIMED_SHOT, + TALENTS.AIMED_SHOT_TALENT, SPELLS.STEADY_SHOT, TALENTS.BARRAGE_TALENT, SPELLS.A_MURDER_OF_CROWS_DEBUFF, diff --git a/src/analysis/retail/hunter/marksmanship/modules/Abilities.tsx b/src/analysis/retail/hunter/marksmanship/modules/Abilities.tsx index d587c6fe933..0299ab30916 100644 --- a/src/analysis/retail/hunter/marksmanship/modules/Abilities.tsx +++ b/src/analysis/retail/hunter/marksmanship/modules/Abilities.tsx @@ -18,7 +18,8 @@ class Abilities extends CoreAbilities { */ //region Baseline Rotational { - spell: SPELLS.AIMED_SHOT.id, + spell: TALENTS.AIMED_SHOT_TALENT.id, + enabled: this.selectedCombatant.hasTalent(TALENTS.AIMED_SHOT_TALENT), category: SPELL_CATEGORY.ROTATIONAL, cooldown: (haste: number) => 12 / (1 + haste), charges: 2, @@ -163,6 +164,19 @@ class Abilities extends CoreAbilities { base: 1500, }, }, + { + spell: TALENTS.STEEL_TRAP_TALENT.id, + category: SPELL_CATEGORY.ROTATIONAL, + cooldown: 30, + enabled: combatant.hasTalent(TALENTS.STEEL_TRAP_TALENT), + gcd: { + base: 1500, + }, + castEfficiency: { + suggestion: true, + recommendedEfficiency: 0.85, + }, + }, //endregion //region Baseline Defensives diff --git a/src/analysis/retail/hunter/marksmanship/modules/Buffs.tsx b/src/analysis/retail/hunter/marksmanship/modules/Buffs.tsx index cf4c7d70244..df6a8756f64 100644 --- a/src/analysis/retail/hunter/marksmanship/modules/Buffs.tsx +++ b/src/analysis/retail/hunter/marksmanship/modules/Buffs.tsx @@ -14,7 +14,7 @@ class Buffs extends CoreAuras { { spellId: SPELLS.PRECISE_SHOTS.id, timelineHighlight: true, - triggeredBySpellId: SPELLS.AIMED_SHOT.id, + triggeredBySpellId: TALENTS_HUNTER.AIMED_SHOT_TALENT.id, }, { spellId: SPELLS.LOCK_AND_LOAD_BUFF.id, diff --git a/src/analysis/retail/hunter/marksmanship/modules/apl/AplCheck.tsx b/src/analysis/retail/hunter/marksmanship/modules/apl/AplCheck.tsx deleted file mode 100644 index 132d6500356..00000000000 --- a/src/analysis/retail/hunter/marksmanship/modules/apl/AplCheck.tsx +++ /dev/null @@ -1,120 +0,0 @@ -import SPELLS from 'common/SPELLS'; -import { TALENTS_HUNTER } from 'common/TALENTS'; -import RESOURCE_TYPES from 'game/RESOURCE_TYPES'; -import { suggestion } from 'parser/core/Analyzer'; -import { EventType } from 'parser/core/Events'; -import aplCheck, { build } from 'parser/shared/metrics/apl'; -import annotateTimeline from 'parser/shared/metrics/apl/annotate'; -import { - and, - buffMissing, - buffPresent, - debuffMissing, - hasResource, - hasTalent, - inExecute, - lastSpellCast, - or, - targetsHit, -} from 'parser/shared/metrics/apl/conditions'; - -export const apl = build([ - { - spell: SPELLS.STEADY_SHOT, - condition: and( - hasTalent(TALENTS_HUNTER.STEADY_FOCUS_TALENT), - lastSpellCast(SPELLS.STEADY_SHOT), - buffMissing(SPELLS.STEADY_FOCUS_BUFF, { timeRemaining: 5000, duration: 15000 }), - ), - }, - { - spell: SPELLS.STEADY_SHOT, - condition: and( - hasTalent(TALENTS_HUNTER.STEADY_FOCUS_TALENT), - buffMissing(SPELLS.STEADY_FOCUS_BUFF), - ), - }, - { - spell: SPELLS.KILL_SHOT_MM_BM, - condition: inExecute(0.2), - }, - TALENTS_HUNTER.EXPLOSIVE_SHOT_TALENT, - { - spell: TALENTS_HUNTER.DEATH_CHAKRAM_TALENT, - condition: hasTalent(TALENTS_HUNTER.DEATH_CHAKRAM_TALENT), - }, - { - spell: TALENTS_HUNTER.WAILING_ARROW_TALENT, - condition: hasTalent(TALENTS_HUNTER.WAILING_ARROW_TALENT), - }, - { - spell: TALENTS_HUNTER.VOLLEY_TALENT, - condition: hasTalent(TALENTS_HUNTER.VOLLEY_TALENT), - }, - { - spell: SPELLS.RAPID_FIRE, - condition: and( - hasTalent(TALENTS_HUNTER.SURGING_SHOTS_TALENT), - hasTalent(TALENTS_HUNTER.STREAMLINE_TALENT), - ), - }, - { - spell: SPELLS.AIMED_SHOT, - condition: or(buffMissing(SPELLS.PRECISE_SHOTS), buffPresent(SPELLS.TRUESHOT)), - }, - { - spell: SPELLS.AIMED_SHOT, - condition: and( - buffPresent(SPELLS.TRICK_SHOTS_BUFF), - targetsHit( - { atLeast: 2 }, - { lookahead: 1000, targetType: EventType.Damage, targetSpell: SPELLS.AIMED_SHOT }, - ), - ), - }, - { - spell: SPELLS.RAPID_FIRE, - condition: hasResource(RESOURCE_TYPES.FOCUS, { atMost: 80 }), - }, - { - spell: TALENTS_HUNTER.CHIMAERA_SHOT_TALENT, - condition: and( - hasTalent(TALENTS_HUNTER.CHIMAERA_SHOT_TALENT), - or(buffPresent(SPELLS.PRECISE_SHOTS), hasResource(RESOURCE_TYPES.FOCUS, { atLeast: 55 })), - ), - }, - { - spell: SPELLS.ARCANE_SHOT, - condition: or( - buffPresent(SPELLS.PRECISE_SHOTS), - hasResource(RESOURCE_TYPES.FOCUS, { atLeast: 55 }), - ), - }, - { - spell: TALENTS_HUNTER.SERPENT_STING_TALENT, - condition: and( - hasTalent(TALENTS_HUNTER.SERPENT_STING_TALENT), - debuffMissing(TALENTS_HUNTER.SERPENT_STING_TALENT, { timeRemaining: 6000, duration: 18000 }), - ), - }, - { - spell: TALENTS_HUNTER.BARRAGE_TALENT, - condition: and( - hasTalent(TALENTS_HUNTER.BARRAGE_TALENT), - targetsHit( - { atLeast: 2 }, - { lookahead: 1000, targetType: EventType.Damage, targetSpell: SPELLS.BARRAGE_DAMAGE }, - ), - ), - }, - SPELLS.STEADY_SHOT, -]); - -export const check = aplCheck(apl); - -export default suggestion((events, info) => { - const { violations } = check(events, info); - annotateTimeline(violations); - - return undefined; -}); diff --git a/src/analysis/retail/hunter/marksmanship/modules/checklist/Component.tsx b/src/analysis/retail/hunter/marksmanship/modules/checklist/Component.tsx index bf0d289a50b..94b58f729a6 100644 --- a/src/analysis/retail/hunter/marksmanship/modules/checklist/Component.tsx +++ b/src/analysis/retail/hunter/marksmanship/modules/checklist/Component.tsx @@ -2,7 +2,6 @@ import SPELLS from 'common/SPELLS'; import { TALENTS_HUNTER } from 'common/TALENTS'; import { SpellLink } from 'interface'; import PreparationRule from 'parser/retail/modules/features/Checklist/PreparationRule'; -import AplRule, { AplRuleProps } from 'parser/shared/metrics/apl/ChecklistRule'; import Checklist from 'parser/shared/modules/features/Checklist'; import { AbilityRequirementProps, @@ -13,7 +12,7 @@ import Requirement from 'parser/shared/modules/features/Checklist/Requirement'; import Rule from 'parser/shared/modules/features/Checklist/Rule'; import TalentCastEfficiencyRequirement from 'parser/shared/modules/features/Checklist/TalentCastEfficiencyRequirement'; -const MarksmanshipChecklist = (props: ChecklistProps & AplRuleProps) => { +const MarksmanshipChecklist = (props: ChecklistProps) => { const { combatant, castEfficiency, thresholds } = props; const AbilityRequirement = (props: AbilityRequirementProps) => ( { } > - + @@ -155,7 +154,6 @@ const MarksmanshipChecklist = (props: ChecklistProps & AplRuleProps) => { /> - ); diff --git a/src/analysis/retail/hunter/marksmanship/modules/checklist/Module.tsx b/src/analysis/retail/hunter/marksmanship/modules/checklist/Module.tsx index d127292df1d..213dd003232 100644 --- a/src/analysis/retail/hunter/marksmanship/modules/checklist/Module.tsx +++ b/src/analysis/retail/hunter/marksmanship/modules/checklist/Module.tsx @@ -8,7 +8,6 @@ import CastEfficiency from 'parser/shared/modules/CastEfficiency'; import Combatants from 'parser/shared/modules/Combatants'; import BaseChecklist from 'parser/shared/modules/features/Checklist/Module'; -import { apl, check as aplCheck } from '../apl/AplCheck'; import AlwaysBeCasting from '../features/AlwaysBeCasting'; import Component from './Component'; @@ -65,11 +64,8 @@ class Checklist extends BaseChecklist { //endregion render() { - const checkResults = aplCheck(this.owner.eventHistory, this.owner.info); return ( - Try to keep focus below max by using ,{' '} + Try to keep focus below max by using ,{' '} {this.selectedCombatant.hasTalent(TALENTS_HUNTER.CHIMAERA_SHOT_TALENT) ? ( ) : ( @@ -27,16 +27,16 @@ class Focus extends Analyzer { ); resourceSuggest(when, this.focusTracker, { spell: SPELLS.STEADY_SHOT_FOCUS, - minor: 0.025, - avg: 0.05, - major: 0.1, + minor: 0.05, + avg: 0.075, + major: 0.125, extraSuggestion: mmFocusExtraSuggestion, }); resourceSuggest(when, this.focusTracker, { spell: SPELLS.RAPID_FIRE_FOCUS, - minor: 0.025, - avg: 0.05, - major: 0.1, + minor: 0.05, + avg: 0.075, + major: 0.125, extraSuggestion: mmFocusExtraSuggestion, }); } diff --git a/src/analysis/retail/hunter/marksmanship/modules/spells/Trueshot.tsx b/src/analysis/retail/hunter/marksmanship/modules/spells/Trueshot.tsx index 100dae8c6fc..5a12bff69ff 100644 --- a/src/analysis/retail/hunter/marksmanship/modules/spells/Trueshot.tsx +++ b/src/analysis/retail/hunter/marksmanship/modules/spells/Trueshot.tsx @@ -5,6 +5,7 @@ import SteadyShot from 'analysis/retail/hunter/marksmanship/modules/spells/Stead import { HUNTER_BASE_FOCUS_MAX, MS_BUFFER_100 } from 'analysis/retail/hunter/shared/constants'; import { formatNumber } from 'common/format'; import SPELLS from 'common/SPELLS'; +import { TALENTS_HUNTER } from 'common/TALENTS'; import RESOURCE_TYPES from 'game/RESOURCE_TYPES'; import { ResourceIcon } from 'interface'; import { SpellIcon } from 'interface'; @@ -45,7 +46,7 @@ class Trueshot extends Analyzer { constructor(options: Options) { super(options); this.addEventListener( - Events.cast.by(SELECTED_PLAYER).spell(SPELLS.AIMED_SHOT), + Events.cast.by(SELECTED_PLAYER).spell(TALENTS_HUNTER.AIMED_SHOT_TALENT), this.onAimedShotCast, ); this.addEventListener( @@ -133,8 +134,8 @@ class Trueshot extends Analyzer { return ( - {this.averageAimedShots.toFixed(1)}{' '} - per Trueshot + {' '} + {this.averageAimedShots.toFixed(1)} per Trueshot
{this.effectiveFocus}/ {this.possibleFocus} Focus gained diff --git a/src/analysis/retail/hunter/marksmanship/modules/spells/AimedShot.tsx b/src/analysis/retail/hunter/marksmanship/modules/talents/AimedShot.tsx similarity index 90% rename from src/analysis/retail/hunter/marksmanship/modules/spells/AimedShot.tsx rename to src/analysis/retail/hunter/marksmanship/modules/talents/AimedShot.tsx index 1d50fbfd3ad..df456f2da85 100644 --- a/src/analysis/retail/hunter/marksmanship/modules/spells/AimedShot.tsx +++ b/src/analysis/retail/hunter/marksmanship/modules/talents/AimedShot.tsx @@ -1,5 +1,6 @@ import { TRUESHOT_AIMED_SHOT_RECHARGE_INCREASE } from 'analysis/retail/hunter/marksmanship/constants'; import SPELLS from 'common/SPELLS'; +import { TALENTS_HUNTER } from 'common/TALENTS'; import Analyzer, { Options, SELECTED_PLAYER } from 'parser/core/Analyzer'; import Events, { AnyEvent, @@ -39,8 +40,13 @@ class AimedShot extends Analyzer { constructor(options: Options) { super(options); + this.active = this.selectedCombatant.hasTalent(TALENTS_HUNTER.AIMED_SHOT_TALENT); + this.addEventListener(Events.any, this.onEvent); - this.addEventListener(Events.cast.by(SELECTED_PLAYER).spell(SPELLS.AIMED_SHOT), this.onCast); + this.addEventListener( + Events.cast.by(SELECTED_PLAYER).spell(TALENTS_HUNTER.AIMED_SHOT_TALENT), + this.onCast, + ); this.addEventListener( Events.applybuff.by(SELECTED_PLAYER).spell([SPELLS.TRUESHOT]), this.onAffectingBuffChange, @@ -59,7 +65,7 @@ class AimedShot extends Analyzer { if (!this.selectedCombatant.hasBuff(SPELLS.TRUESHOT.id)) { return; } - if (!this.spellUsable.isOnCooldown(SPELLS.AIMED_SHOT.id)) { + if (!this.spellUsable.isOnCooldown(TALENTS_HUNTER.AIMED_SHOT_TALENT.id)) { return; } if (this.lastReductionTimestamp === 0 || event.timestamp <= this.lastReductionTimestamp) { @@ -89,7 +95,7 @@ class AimedShot extends Analyzer { maxReductionMs / 1000 + ' seconds since last event', ); const effectiveReductionMs: number = this.spellUsable.reduceCooldown( - SPELLS.AIMED_SHOT.id, + TALENTS_HUNTER.AIMED_SHOT_TALENT.id, maxReductionMs, event.timestamp, ); @@ -106,7 +112,7 @@ class AimedShot extends Analyzer { onCast(event: CastEvent) { const expectedCooldownDuration = this.abilities.getExpectedCooldownDuration( - SPELLS.AIMED_SHOT.id, + TALENTS_HUNTER.AIMED_SHOT_TALENT.id, ); if (expectedCooldownDuration) { this.totalCooldown += expectedCooldownDuration; diff --git a/src/analysis/retail/hunter/marksmanship/modules/talents/CarefulAim.tsx b/src/analysis/retail/hunter/marksmanship/modules/talents/CarefulAim.tsx index 669e5c3e7f8..65cf09064f6 100644 --- a/src/analysis/retail/hunter/marksmanship/modules/talents/CarefulAim.tsx +++ b/src/analysis/retail/hunter/marksmanship/modules/talents/CarefulAim.tsx @@ -1,7 +1,6 @@ import { CA_MODIFIER, CAREFUL_AIM_THRESHOLD } from 'analysis/retail/hunter/marksmanship/constants'; import { abbreviateBossNames } from 'common/abbreviateLongNames'; import { formatDuration, formatNumber } from 'common/format'; -import SPELLS from 'common/SPELLS'; import { TALENTS_HUNTER } from 'common/TALENTS'; import { Options, SELECTED_PLAYER } from 'parser/core/Analyzer'; import { calculateEffectiveDamage } from 'parser/core/EventCalculateLib'; @@ -29,7 +28,7 @@ class CarefulAim extends ExecuteHelper { enemies: Enemies, }; - static executeSpells = [SPELLS.AIMED_SHOT]; + static executeSpells = [TALENTS_HUNTER.AIMED_SHOT_TALENT]; static executeSources = SELECTED_PLAYER; static upperThreshold = CAREFUL_AIM_THRESHOLD; static modifiesDamage = true; @@ -108,7 +107,7 @@ class CarefulAim extends ExecuteHelper { } else { target = 'Adds'; } - if (spellId !== SPELLS.AIMED_SHOT.id || outsideCarefulAim) { + if (spellId !== TALENTS_HUNTER.AIMED_SHOT_TALENT.id || outsideCarefulAim) { return; } const damageFromCA = calculateEffectiveDamage(event, CA_MODIFIER); diff --git a/src/analysis/retail/hunter/marksmanship/modules/talents/LockAndLoad.tsx b/src/analysis/retail/hunter/marksmanship/modules/talents/LockAndLoad.tsx index 498f5c744b1..c6abcca4182 100644 --- a/src/analysis/retail/hunter/marksmanship/modules/talents/LockAndLoad.tsx +++ b/src/analysis/retail/hunter/marksmanship/modules/talents/LockAndLoad.tsx @@ -45,7 +45,7 @@ class LockAndLoad extends Analyzer { this.autoshotDamage, ); this.addEventListener( - Events.cast.by(SELECTED_PLAYER).spell(SPELLS.AIMED_SHOT), + Events.cast.by(SELECTED_PLAYER).spell(TALENTS_HUNTER.AIMED_SHOT_TALENT), this.onAimedCast, ); this.addEventListener( @@ -76,14 +76,15 @@ class LockAndLoad extends Analyzer { onLNLApplication(event: ApplyBuffEvent) { this.totalProcs += 1; this.hasLnLBuff = true; - if (this.spellUsable.isOnCooldown(SPELLS.AIMED_SHOT.id)) { + if (this.spellUsable.isOnCooldown(TALENTS_HUNTER.AIMED_SHOT_TALENT.id)) { const expectedCooldownDuration = this.abilities.getExpectedCooldownDuration( - SPELLS.AIMED_SHOT.id, + TALENTS_HUNTER.AIMED_SHOT_TALENT.id, ); if (expectedCooldownDuration) { const newChargeCDR = - expectedCooldownDuration - this.spellUsable.cooldownRemaining(SPELLS.AIMED_SHOT.id); - this.spellUsable.reduceCooldown(SPELLS.AIMED_SHOT.id, newChargeCDR); + expectedCooldownDuration - + this.spellUsable.cooldownRemaining(TALENTS_HUNTER.AIMED_SHOT_TALENT.id); + this.spellUsable.reduceCooldown(TALENTS_HUNTER.AIMED_SHOT_TALENT.id, newChargeCDR); } } } diff --git a/src/analysis/retail/hunter/marksmanship/modules/talents/SerpentstalkersTrickery.tsx b/src/analysis/retail/hunter/marksmanship/modules/talents/SerpentstalkersTrickery.tsx index 44d8b2c2b3e..1222f972b94 100644 --- a/src/analysis/retail/hunter/marksmanship/modules/talents/SerpentstalkersTrickery.tsx +++ b/src/analysis/retail/hunter/marksmanship/modules/talents/SerpentstalkersTrickery.tsx @@ -1,4 +1,3 @@ -import SPELLS from 'common/SPELLS'; import TALENTS from 'common/TALENTS/hunter'; import Analyzer, { Options, SELECTED_PLAYER } from 'parser/core/Analyzer'; import Events, { CastEvent, DamageEvent, HasTarget, RemoveDebuffEvent } from 'parser/core/Events'; @@ -28,7 +27,7 @@ class SerpentstalkersTrickery extends Analyzer { this.onSerpentStingDamage, ); this.addEventListener( - Events.cast.by(SELECTED_PLAYER).spell(SPELLS.AIMED_SHOT), + Events.cast.by(SELECTED_PLAYER).spell(TALENTS.AIMED_SHOT_TALENT), this.onAimedShotCast, ); this.addEventListener( diff --git a/src/analysis/retail/hunter/marksmanship/modules/talents/SteadyFocus.tsx b/src/analysis/retail/hunter/marksmanship/modules/talents/SteadyFocus.tsx index 7b0616c6b70..c3c001d1505 100644 --- a/src/analysis/retail/hunter/marksmanship/modules/talents/SteadyFocus.tsx +++ b/src/analysis/retail/hunter/marksmanship/modules/talents/SteadyFocus.tsx @@ -44,9 +44,9 @@ class SteadyFocus extends Analyzer { return { actual: this.uptime, isLessThan: { - minor: 0.9, - average: 0.85, - major: 0.8, + minor: 0.7, + average: 0.6, + major: 0.5, }, style: ThresholdStyle.PERCENTAGE, }; diff --git a/src/analysis/retail/hunter/marksmanship/modules/talents/Streamline.tsx b/src/analysis/retail/hunter/marksmanship/modules/talents/Streamline.tsx index 8c1ada6802f..9014ecc0305 100644 --- a/src/analysis/retail/hunter/marksmanship/modules/talents/Streamline.tsx +++ b/src/analysis/retail/hunter/marksmanship/modules/talents/Streamline.tsx @@ -42,7 +42,7 @@ class Streamline extends Analyzer { this.onRapidFireDamage, ); this.addEventListener( - Events.cast.by(SELECTED_PLAYER).spell(SPELLS.AIMED_SHOT), + Events.cast.by(SELECTED_PLAYER).spell(TALENTS_HUNTER.AIMED_SHOT_TALENT), this.onAimedShotCast, ); } diff --git a/src/analysis/retail/hunter/marksmanship/modules/talents/SurgingShots.tsx b/src/analysis/retail/hunter/marksmanship/modules/talents/SurgingShots.tsx index 9b51108c1e4..f6690a8fba1 100644 --- a/src/analysis/retail/hunter/marksmanship/modules/talents/SurgingShots.tsx +++ b/src/analysis/retail/hunter/marksmanship/modules/talents/SurgingShots.tsx @@ -40,7 +40,7 @@ class SurgingShots extends Analyzer { this.onRapidFireDamage, ); this.addEventListener( - Events.cast.by(SELECTED_PLAYER).spell(SPELLS.AIMED_SHOT), + Events.cast.by(SELECTED_PLAYER).spell(TALENTS.AIMED_SHOT_TALENT), this.onAimedShotCast, ); } @@ -69,7 +69,7 @@ class SurgingShots extends Analyzer { )}

Likelihood of getting exactly as many procs as estimated on a fight given - your number of casts. + your number of casts.

diff --git a/src/analysis/retail/hunter/marksmanship/normalizers/AimedShotPrepullNormalizer.js b/src/analysis/retail/hunter/marksmanship/normalizers/AimedShotPrepullNormalizer.js index b7ff6a2c9fd..ff0d1ae1585 100644 --- a/src/analysis/retail/hunter/marksmanship/normalizers/AimedShotPrepullNormalizer.js +++ b/src/analysis/retail/hunter/marksmanship/normalizers/AimedShotPrepullNormalizer.js @@ -1,4 +1,4 @@ -import SPELLS from 'common/SPELLS'; +import { TALENTS_HUNTER } from 'common/TALENTS'; import { EventType } from 'parser/core/Events'; import EventsNormalizer from 'parser/core/EventsNormalizer'; @@ -17,7 +17,7 @@ class AimedShotPrepullNormalizer extends EventsNormalizer { events.forEach((event) => { if ( (event.type === EventType.BeginCast || event.type === EventType.Cast) && - event.ability.guid === SPELLS.AIMED_SHOT.id + event.ability.guid === TALENTS_HUNTER.AIMED_SHOT_TALENT.id ) { if (event.type === EventType.BeginCast) { lastBeginCastTimestamp = event.timestamp; diff --git a/src/analysis/retail/hunter/shared/SpellFocusCost.tsx b/src/analysis/retail/hunter/shared/SpellFocusCost.tsx index 2c3252c1a6d..24f6b3de866 100644 --- a/src/analysis/retail/hunter/shared/SpellFocusCost.tsx +++ b/src/analysis/retail/hunter/shared/SpellFocusCost.tsx @@ -22,7 +22,7 @@ class SpellFocusCost extends SpellResourceCost { if ( this.lockAndLoad && this.selectedCombatant.hasBuff(SPELLS.LOCK_AND_LOAD_BUFF.id) && - spellId === SPELLS.AIMED_SHOT.id + spellId === TALENTS.AIMED_SHOT_TALENT.id ) { return cost * LNL_COST_MULTIPLIER; } diff --git a/src/analysis/retail/hunter/shared/index.ts b/src/analysis/retail/hunter/shared/index.ts index 5a433e4d7c6..a5f8582c201 100644 --- a/src/analysis/retail/hunter/shared/index.ts +++ b/src/analysis/retail/hunter/shared/index.ts @@ -4,17 +4,20 @@ export { default as BindingShot } from './talents/BindingShot'; export { default as BornToBeWild } from './talents/BornToBeWild'; export { default as CancelledCasts } from './CancelledCasts'; export { default as Channeling } from 'parser/shared/normalizers/Channeling'; +export { default as DeathChakrams } from './talents/DeathChakrams'; export { default as DeathTracker } from './DeathTracker'; export { default as FocusCapTracker } from './FocusCapTracker'; export { default as FocusDetails } from './FocusDetails'; export { default as FocusTracker } from './FocusTracker'; export { default as FocusUsage } from './FocusUsage'; export { default as KillShot } from './talents/KillShot'; +export { default as MasterMarksman } from './talents/MasterMarksman'; export { default as NaturalMending } from './talents/NaturalMending'; +export { default as RejuvenatingWind } from './talents/RejuvenatingWind'; +export { default as SerpentSting } from './talents/SerpentSting'; export { default as SpellFocusCost } from './SpellFocusCost'; +export { default as SteelTrap } from './talents/SteelTrap'; export { default as Trailblazer } from './talents/Trailblazer'; export { default as TranquilizingShot } from './talents/TranquilizingShot'; -export { default as RejuvenatingWind } from './talents/RejuvenatingWind'; -export { default as DeathChakrams } from './talents/DeathChakrams'; export { default as WailingArrow } from './talents/WailingArrow'; export { default as WailingArrowPrepullNormalizer } from './talents/WailingArrowPrepullNormalizer'; diff --git a/src/analysis/retail/hunter/survival/modules/talents/SteelTrap.tsx b/src/analysis/retail/hunter/shared/talents/SteelTrap.tsx similarity index 100% rename from src/analysis/retail/hunter/survival/modules/talents/SteelTrap.tsx rename to src/analysis/retail/hunter/shared/talents/SteelTrap.tsx diff --git a/src/analysis/retail/hunter/survival/CHANGELOG.tsx b/src/analysis/retail/hunter/survival/CHANGELOG.tsx index 9a4ca169c98..a9e5f3cd5fe 100644 --- a/src/analysis/retail/hunter/survival/CHANGELOG.tsx +++ b/src/analysis/retail/hunter/survival/CHANGELOG.tsx @@ -4,6 +4,7 @@ import { Putro, Arlie, ToppleTheNun } from 'CONTRIBUTORS'; import { SpellLink } from 'interface'; export default [ + change(date(2023, 10, 3), 'Remove old references to Chakrams', Putro), change(date(2023, 9, 25), <>Fix issues with registering casts., Putro), change(date(2023, 7, 3), 'Update SpellLink usage.', ToppleTheNun), change(date(2022, 12, 16), 'Re-enable log parser.', ToppleTheNun), diff --git a/src/analysis/retail/hunter/survival/CombatLogParser.ts b/src/analysis/retail/hunter/survival/CombatLogParser.ts index 52fa66d1557..a845d539745 100644 --- a/src/analysis/retail/hunter/survival/CombatLogParser.ts +++ b/src/analysis/retail/hunter/survival/CombatLogParser.ts @@ -1,51 +1,49 @@ +import CoreCombatLogParser from 'parser/core/CombatLogParser'; +import ArcaneTorrent from 'parser/shared/modules/racials/bloodelf/ArcaneTorrent'; import { - DeathTracker, - NaturalMending, - Trailblazer, AMurderOfCrows, - BornToBeWild, BindingShot, - KillShot, - FocusTracker, - FocusDetails, - SpellFocusCost, + BornToBeWild, DeathChakrams, + DeathTracker, + FocusDetails, + FocusTracker, + KillShot, + MasterMarksman, + NaturalMending, RejuvenatingWind, + SerpentSting, + SpellFocusCost, + SteelTrap, + Trailblazer, TranquilizingShot, -} from 'analysis/retail/hunter/shared'; -import CoreCombatLogParser from 'parser/core/CombatLogParser'; -import ArcaneTorrent from 'parser/shared/modules/racials/bloodelf/ArcaneTorrent'; -import MasterMarksman from '../shared/talents/MasterMarksman'; -import SerpentSting from '../shared/talents/SerpentSting'; - +} from '../shared'; import Abilities from './modules/Abilities'; -import Buffs from './modules/Buffs'; -import Checklist from './modules/checklist/Module'; -import GlobalCooldown from './modules/core/GlobalCooldown'; -import AlwaysBeCasting from './modules/features/AlwaysBeCasting'; -import CooldownThroughputTracker from './modules/features/CooldownThroughputTracker'; -import Focus from './modules/resources/Focus'; -import SurvivalFocusCapTracker from './modules/resources/SurvivalFocusCapTracker'; -import SurvivalFocusUsage from './modules/resources/SurvivalFocusUsage'; -import ButcheryCarve from './modules/spells/ButcheryCarve'; -import CoordinatedAssault from './modules/spells/CoordinatedAssault'; -import KillCommand from './modules/spells/KillCommand'; -import RaptorStrike from './modules/spells/RaptorStrike'; -import WildfireBomb from './modules/spells/WildfireBomb'; import AlphaPredator from './modules/talents/AlphaPredator'; +import AlwaysBeCasting from './modules/features/AlwaysBeCasting'; import BirdOfPrey from './modules/talents/BirdOfPrey'; import Bloodseeker from './modules/talents/Bloodseeker'; -import Chakrams from './modules/talents/Chakrams'; +import Buffs from './modules/Buffs'; +import ButcheryCarve from './modules/talents/ButcheryCarve'; +import Checklist from './modules/checklist/Module'; +import CooldownThroughputTracker from './modules/features/CooldownThroughputTracker'; +import CoordinatedAssault from './modules/talents/CoordinatedAssault'; import FlankingStrike from './modules/talents/FlankingStrike'; +import Focus from './modules/resources/Focus'; +import GlobalCooldown from './modules/core/GlobalCooldown'; import GuerrillaTactics from './modules/talents/GuerrillaTactics'; import HydrasBite from './modules/talents/HydrasBite'; +import KillCommand from './modules/talents/KillCommand'; import MongooseBite from './modules/talents/MongooseBite'; -import SteelTrap from './modules/talents/SteelTrap'; -import TipOfTheSpear from './modules/talents/TipOfTheSpear'; import PheromoneBomb from './modules/talents/WildfireInfusion/PheromoneBomb'; +import RaptorStrike from './modules/talents/RaptorStrike'; import ShrapnelBomb from './modules/talents/WildfireInfusion/ShrapnelBomb'; -import VolatileBomb from './modules/talents/WildfireInfusion/VolatileBomb'; +import SurvivalFocusCapTracker from './modules/resources/SurvivalFocusCapTracker'; +import SurvivalFocusUsage from './modules/resources/SurvivalFocusUsage'; +import TipOfTheSpear from './modules/talents/TipOfTheSpear'; import TipOfTheSpearNormalizer from './normalizers/TipOfTheSpear'; +import VolatileBomb from './modules/talents/WildfireInfusion/VolatileBomb'; +import WildfireBomb from './modules/talents/WildfireBomb'; class CombatLogParser extends CoreCombatLogParser { static specModules = { @@ -74,39 +72,36 @@ class CombatLogParser extends CoreCombatLogParser { deathTracker: DeathTracker, //Spells - killCommand: KillCommand, + alphaPredator: AlphaPredator, + birdOfPrey: BirdOfPrey, + bloodseeker: Bloodseeker, butcheryCarve: ButcheryCarve, coordinatedAssault: CoordinatedAssault, - wildfireBomb: WildfireBomb, - raptorStrike: RaptorStrike, - killShot: KillShot, - - //Talents - naturalMending: NaturalMending, - trailblazer: Trailblazer, - aMurderOfCrows: AMurderOfCrows, - mongooseBite: MongooseBite, - steelTrap: SteelTrap, + flankingStrike: FlankingStrike, guerrillaTactics: GuerrillaTactics, - chakrams: Chakrams, - birdOfPrey: BirdOfPrey, - bornToBeWild: BornToBeWild, - bindingShot: BindingShot, - alphaPredator: AlphaPredator, - bloodseeker: Bloodseeker, hydrasBite: HydrasBite, - flankingStrike: FlankingStrike, - tipOfTheSpear: TipOfTheSpear, + killCommand: KillCommand, + mongooseBite: MongooseBite, pheromoneBomb: PheromoneBomb, + raptorStrike: RaptorStrike, shrapnelBomb: ShrapnelBomb, + tipOfTheSpear: TipOfTheSpear, volatileBomb: VolatileBomb, - deathChakrams: DeathChakrams, - serpentSting: SerpentSting, - masterMarksman: MasterMarksman, - tranquilizingShot: TranquilizingShot, + wildfireBomb: WildfireBomb, //Shared Talents + aMurderOfCrows: AMurderOfCrows, + bindingShot: BindingShot, + bornToBeWild: BornToBeWild, + deathChakrams: DeathChakrams, + killShot: KillShot, + masterMarksman: MasterMarksman, + naturalMending: NaturalMending, rejuvenatingWind: RejuvenatingWind, + serpentSting: SerpentSting, + steelTrap: SteelTrap, + trailblazer: Trailblazer, + tranquilizingShot: TranquilizingShot, // Survival's throughput benefit isn't as big as for other classes arcaneTorrent: [ArcaneTorrent, { castEfficiency: 0.5 }] as const, diff --git a/src/analysis/retail/hunter/survival/modules/resources/Focus.tsx b/src/analysis/retail/hunter/survival/modules/resources/Focus.tsx index fc7b796cf77..1c028d722ad 100644 --- a/src/analysis/retail/hunter/survival/modules/resources/Focus.tsx +++ b/src/analysis/retail/hunter/survival/modules/resources/Focus.tsx @@ -16,8 +16,8 @@ class Focus extends Analyzer { suggestions(when: When) { resourceSuggest(when, this.focusTracker, { spell: TALENTS.KILL_COMMAND_SURVIVAL_TALENT, - minor: 0.025, - avg: 0.05, + minor: 0.05, + avg: 0.075, major: 0.1, extraSuggestion: ( <> diff --git a/src/analysis/retail/hunter/survival/modules/spells/ButcheryCarve.tsx b/src/analysis/retail/hunter/survival/modules/talents/ButcheryCarve.tsx similarity index 100% rename from src/analysis/retail/hunter/survival/modules/spells/ButcheryCarve.tsx rename to src/analysis/retail/hunter/survival/modules/talents/ButcheryCarve.tsx diff --git a/src/analysis/retail/hunter/survival/modules/talents/Chakrams.tsx b/src/analysis/retail/hunter/survival/modules/talents/Chakrams.tsx deleted file mode 100644 index 30d68b66a68..00000000000 --- a/src/analysis/retail/hunter/survival/modules/talents/Chakrams.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import { SURVIVAL_CHAKRAM_TYPES } from 'analysis/retail/hunter/survival/constants'; -import TALENTS from 'common/TALENTS/hunter'; -import Analyzer, { Options, SELECTED_PLAYER } from 'parser/core/Analyzer'; -import Events, { DamageEvent } from 'parser/core/Events'; -import { encodeTargetString } from 'parser/shared/modules/Enemies'; -import SpellUsable from 'parser/shared/modules/SpellUsable'; -import AverageTargetsHit from 'parser/ui/AverageTargetsHit'; -import BoringSpellValueText from 'parser/ui/BoringSpellValueText'; -import Statistic from 'parser/ui/Statistic'; -import STATISTIC_CATEGORY from 'parser/ui/STATISTIC_CATEGORY'; -import STATISTIC_ORDER from 'parser/ui/STATISTIC_ORDER'; - -/** - * Throw a pair of chakrams at your target, slicing all enemies in the chakrams' path for (40% of Attack power) Physical damage. The chakrams will return to you, damaging enemies again. - * - * Example log: - * https://www.warcraftlogs.com/reports/VGNkQ6BFbcdPvMDX#fight=20&type=damage-done&source=169&ability=-259391 - */ - -class Chakrams extends Analyzer { - static dependencies = { - spellUsable: SpellUsable, - }; - casts = 0; - targetsHit = 0; - uniqueTargets: string[] = []; - protected spellUsable!: SpellUsable; - - constructor(options: Options) { - super(options); - - this.active = this.selectedCombatant.hasTalent(TALENTS.DEATH_CHAKRAM_TALENT); - - this.addEventListener( - Events.cast.by(SELECTED_PLAYER).spell(TALENTS.DEATH_CHAKRAM_TALENT), - this.onCast, - ); - this.addEventListener( - Events.damage.by(SELECTED_PLAYER).spell(SURVIVAL_CHAKRAM_TYPES), - this.onDamage, - ); - } - - onCast() { - this.uniqueTargets = []; - this.casts += 1; - } - - onDamage(event: DamageEvent) { - if (this.casts === 0) { - this.casts += 1; - this.spellUsable.beginCooldown(event, TALENTS.DEATH_CHAKRAM_TALENT.id); - } - const damageTarget: string = encodeTargetString(event.targetID, event.targetInstance); - if (!this.uniqueTargets.includes(damageTarget)) { - this.targetsHit += 1; - this.uniqueTargets.push(damageTarget); - } - } - - statistic() { - return ( - - - <> - - - - - ); - } -} - -export default Chakrams; diff --git a/src/analysis/retail/hunter/survival/modules/spells/CoordinatedAssault.tsx b/src/analysis/retail/hunter/survival/modules/talents/CoordinatedAssault.tsx similarity index 100% rename from src/analysis/retail/hunter/survival/modules/spells/CoordinatedAssault.tsx rename to src/analysis/retail/hunter/survival/modules/talents/CoordinatedAssault.tsx diff --git a/src/analysis/retail/hunter/survival/modules/spells/KillCommand.tsx b/src/analysis/retail/hunter/survival/modules/talents/KillCommand.tsx similarity index 100% rename from src/analysis/retail/hunter/survival/modules/spells/KillCommand.tsx rename to src/analysis/retail/hunter/survival/modules/talents/KillCommand.tsx diff --git a/src/analysis/retail/hunter/survival/modules/spells/RaptorStrike.tsx b/src/analysis/retail/hunter/survival/modules/talents/RaptorStrike.tsx similarity index 100% rename from src/analysis/retail/hunter/survival/modules/spells/RaptorStrike.tsx rename to src/analysis/retail/hunter/survival/modules/talents/RaptorStrike.tsx diff --git a/src/analysis/retail/hunter/survival/modules/spells/WildfireBomb.tsx b/src/analysis/retail/hunter/survival/modules/talents/WildfireBomb.tsx similarity index 100% rename from src/analysis/retail/hunter/survival/modules/spells/WildfireBomb.tsx rename to src/analysis/retail/hunter/survival/modules/talents/WildfireBomb.tsx diff --git a/src/common/SPELLS/hunter.ts b/src/common/SPELLS/hunter.ts index 9ce61ae3a52..16c8450c641 100644 --- a/src/common/SPELLS/hunter.ts +++ b/src/common/SPELLS/hunter.ts @@ -120,11 +120,6 @@ const spells = { //endregion //region Marksmanship - AIMED_SHOT: { - id: 19434, - name: 'Aimed Shot', - icon: 'inv_spear_07', - }, STEADY_SHOT_FOCUS: { id: 77443, name: 'Steady Shot',