From e96990bad502e84555bb368585492b819c4a1d32 Mon Sep 17 00:00:00 2001 From: James Tanner Date: Fri, 29 Dec 2023 11:18:02 +0900 Subject: [PATCH 01/28] Remove legacy rotation code from UI --- proto/priest.proto | 6 +- proto/ui.proto | 8 +- ui/balance_druid/inputs.ts | 137 +------ ui/balance_druid/presets.ts | 17 - ui/balance_druid/sim.ts | 4 - .../custom_rotation_picker.ts | 135 ------- .../individual_sim_ui/rotation_tab.ts | 41 +- .../individual_sim_ui/settings_tab.ts | 68 +--- ui/core/components/input_helpers.ts | 33 -- ui/core/individual_sim_ui.ts | 19 +- ui/core/launched_sims.ts | 25 -- ui/core/player.ts | 119 ++---- ui/core/proto_utils/utils.ts | 22 -- ui/deathknight/inputs.ts | 360 +----------------- ui/deathknight/presets.ts | 79 ---- ui/deathknight/sim.ts | 7 - ui/elemental_shaman/inputs.ts | 95 +---- ui/elemental_shaman/presets.ts | 20 - ui/elemental_shaman/sim.ts | 5 - ui/enhancement_shaman/inputs.ts | 215 ----------- ui/enhancement_shaman/presets.ts | 44 +-- ui/enhancement_shaman/sim.ts | 4 - ui/feral_druid/inputs.ts | 5 - ui/feral_druid/sim.ts | 2 - ui/feral_tank_druid/inputs.ts | 6 - ui/feral_tank_druid/sim.ts | 4 +- ui/healing_priest/inputs.ts | 37 -- ui/healing_priest/presets.ts | 29 -- ui/healing_priest/sim.ts | 4 - ui/holy_paladin/inputs.ts | 4 - ui/holy_paladin/presets.ts | 4 - ui/holy_paladin/sim.ts | 4 - ui/hunter/inputs.ts | 7 +- ui/hunter/presets.ts | 4 +- ui/hunter/sim.ts | 4 +- ui/mage/sim.ts | 2 - ui/protection_paladin/inputs.ts | 4 - ui/protection_paladin/presets.ts | 23 -- ui/protection_paladin/sim.ts | 4 - ui/protection_warrior/inputs.ts | 59 --- ui/protection_warrior/presets.ts | 27 +- ui/protection_warrior/sim.ts | 4 - ui/restoration_druid/inputs.ts | 11 +- ui/restoration_druid/presets.ts | 4 - ui/restoration_druid/sim.ts | 4 - ui/restoration_shaman/inputs.ts | 74 +--- ui/restoration_shaman/presets.ts | 20 - ui/restoration_shaman/sim.ts | 5 +- ui/retribution_paladin/inputs.ts | 146 +------ ui/retribution_paladin/presets.ts | 46 --- ui/retribution_paladin/sim.ts | 21 - ui/rogue/inputs.ts | 138 ------- ui/rogue/presets.ts | 20 - ui/rogue/sim.ts | 123 ------ .../_custom_rotation_picker.scss | 33 -- .../individual_sim_ui/_settings_tab.scss | 1 - ui/shadow_priest/inputs.ts | 43 --- ui/shadow_priest/presets.ts | 7 - ui/shadow_priest/sim.ts | 9 - ui/smite_priest/inputs.ts | 33 +- ui/smite_priest/presets.ts | 8 - ui/smite_priest/sim.ts | 5 - ui/tank_deathknight/inputs.ts | 3 - ui/tank_deathknight/presets.ts | 15 - ui/tank_deathknight/sim.ts | 3 - ui/warlock/inputs.ts | 218 +---------- ui/warlock/presets.ts | 40 +- ui/warlock/sim.ts | 6 - ui/warrior/inputs.ts | 197 ---------- ui/warrior/presets.ts | 41 -- ui/warrior/sim.ts | 4 - 71 files changed, 91 insertions(+), 2887 deletions(-) delete mode 100644 ui/core/components/individual_sim_ui/custom_rotation_picker.ts delete mode 100644 ui/scss/core/components/individual_sim_ui/_custom_rotation_picker.scss diff --git a/proto/priest.proto b/proto/priest.proto index 9e04269f47..d275e525bd 100644 --- a/proto/priest.proto +++ b/proto/priest.proto @@ -162,10 +162,10 @@ message ShadowPriest { InnerFire = 1; } - bool use_shadowfiend = 1; + bool use_shadowfiend = 1 [deprecated = true]; Armor armor = 2; - bool use_mind_blast = 4; - bool use_shadow_word_death = 5; + bool use_mind_blast = 4 [deprecated = true]; + bool use_shadow_word_death = 5 [deprecated = true]; UnitReference power_infusion_target = 6; double latency = 7 [deprecated = true]; // Latency between actions } diff --git a/proto/ui.proto b/proto/ui.proto index 1d6b7cfe6a..ae1b928691 100644 --- a/proto/ui.proto +++ b/proto/ui.proto @@ -290,8 +290,8 @@ message SavedSettings { IndividualBuffs player_buffs = 3; Consumes consumes = 4; Race race = 5; - Cooldowns cooldowns = 6; - string rotation_json = 8; + Cooldowns cooldowns = 6 [deprecated = true]; + string rotation_json = 8 [deprecated = true]; repeated Profession professions = 9; bool enable_item_swap = 18; ItemSwap item_swap = 17; @@ -313,8 +313,8 @@ message SavedTalents { message SavedRotation { APLRotation rotation = 1; - string spec_rotation_options_json = 2; - Cooldowns cooldowns = 3; + string spec_rotation_options_json = 2 [deprecated = true]; + Cooldowns cooldowns = 3 [deprecated = true]; } message BlessingsAssignment { diff --git a/ui/balance_druid/inputs.ts b/ui/balance_druid/inputs.ts index 71ee7a5896..5bcab559e6 100644 --- a/ui/balance_druid/inputs.ts +++ b/ui/balance_druid/inputs.ts @@ -2,21 +2,10 @@ import { UnitReference, UnitReference_Type as UnitType } from '../core/proto/com import { Spec } from '../core/proto/common.js'; import { ActionId } from '../core/proto_utils/action_id.js'; import { Player } from '../core/player.js'; -import { EventID, TypedEvent } from '../core/typed_event.js'; +import { EventID } from '../core/typed_event.js'; import * as InputHelpers from '../core/components/input_helpers.js'; -import { - BalanceDruid_Options as DruidOptions, - BalanceDruid_Rotation_Type as RotationType, - BalanceDruid_Rotation_MfUsage as MfUsage, - BalanceDruid_Rotation_MfExtension as MfExtension, - BalanceDruid_Rotation_IsUsage as IsUsage, - BalanceDruid_Rotation_WrathUsage as WrathUsage, - BalanceDruid_Rotation_EclipsePrio as EclipsePrio, -} from '../core/proto/druid.js'; - - // Configuration for spec-specific UI elements on the settings tab. // These don't need to be in a separate file but it keeps things cleaner. @@ -43,127 +32,3 @@ export const OkfUptime = InputHelpers.makeSpecOptionsNumberInput({ - fieldName: 'type', - label: 'Type', - labelTooltip: 'Set to \'Manual\', to manage eclipses, spells, CDs and DoTs usage.', - values: [ - { - name: 'Default', value: RotationType.Default, - tooltip: 'The default rotation.', - }, - { - name: 'Manual', value: RotationType.Manual, - tooltip: 'Allows custom selection of which spells to use, dot management and CD usage.', - }, - ], - }), - InputHelpers.makeRotationEnumInput({ - fieldName: 'eclipsePrio', - label: 'Eclipse priority', - labelTooltip: 'Defines which eclipse will get prioritized in the rotation.', - values: [ - { name: 'Lunar', value: EclipsePrio.Lunar }, - { name: 'Solar', value: EclipsePrio.Solar }, - ], - showWhen: (player: Player) => player.getRotation().type == RotationType.Manual, - }), - InputHelpers.makeRotationEnumInput({ - fieldName: 'mfUsage', - label: 'Moonfire Usage', - labelTooltip: 'Defines how Moonfire will be used in the rotation.', - values: [ - { name: 'Unused', value: MfUsage.NoMf }, - { name: 'Before lunar', value: MfUsage.BeforeLunar }, - { name: 'Maximize', value: MfUsage.MaximizeMf }, - { name: 'Multidot', value: MfUsage.MultidotMf }, - ], - showWhen: (player: Player) => player.getRotation().type == RotationType.Manual, - }), - InputHelpers.makeRotationEnumInput({ - fieldName: 'mfExtension', - label: 'Moonfire Extension', - labelTooltip: 'When should the rotation try to extend Moonfire on the main target.', - values: [ - { name: 'Extend always', value: MfExtension.ExtendAlways }, - { name: 'Extend outside solar', value: MfExtension.ExtendOutsideSolar }, - { name: 'Do not extend', value: MfExtension.DontExtend }, - ], - showWhen: (player: Player) => player.getRotation().type == RotationType.Manual, - }), - InputHelpers.makeRotationEnumInput({ - fieldName: 'isUsage', - label: 'Insect Swarm Usage', - labelTooltip: 'Defines how Insect Swarm will be used in the rotation.', - values: [ - { name: 'Unused', value: IsUsage.NoIs }, - { name: 'Before solar', value: IsUsage.BeforeSolar }, - { name: 'Optimize', value: IsUsage.OptimizeIs }, - { name: 'Multidot', value: IsUsage.MultidotIs }, - ], - showWhen: (player: Player) => player.getRotation().type == RotationType.Manual, - }), - InputHelpers.makeRotationEnumInput({ - fieldName: 'wrathUsage', - label: 'Wrath usage', - labelTooltip: 'Defines how Wrath will be used in the rotation.', - values: [ - { name: 'Unused', value: WrathUsage.NoWrath }, - { name: 'Fishing for Lunar', value: WrathUsage.FishingForLunar }, - { name: 'Regular', value: WrathUsage.RegularWrath }, - ], - showWhen: (player: Player) => player.getRotation().type == RotationType.Manual, - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'useStarfire', - label: 'Use Starfire', - labelTooltip: 'Should the rotation use Starfire.', - showWhen: (player: Player) => player.getRotation().type == RotationType.Manual, - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'useSmartCooldowns', - label: 'Smart Cooldowns usage', - labelTooltip: 'The rotation will use cooldowns during eclipses, avoiding Haste CDs in solar and Crit CDs in lunar', - showWhen: (player: Player) => player.getRotation().type == RotationType.Manual, - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'snapshotMf', - label: 'Snapshot Moonfire', - labelTooltip: 'The rotation will try to snapshot Moonfire with SP procs', - showWhen: (player: Player) => player.getRotation().type == RotationType.Manual, - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'eclipseShuffling', - label: 'Eclipse Shuffling', - labelTooltip: 'Should the rotation alternate Starfire and Wrath when both eclipses are available.', - showWhen: (player: Player) => player.getRotation().type == RotationType.Manual, - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'useTyphoon', - label: 'Use Typhoon', - labelTooltip: 'Should the rotation use Typhoon.', - showWhen: (player: Player) => player.getRotation().type == RotationType.Manual, - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'useHurricane', - label: 'Use Hurricane', - labelTooltip: 'Should the rotation use Hurricane.', - showWhen: (player: Player) => player.getRotation().type == RotationType.Manual, - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'useBattleRes', - label: 'Use Battle Res', - labelTooltip: 'Cast Battle Res on an ally sometime during the encounter.', - showWhen: (player: Player) => player.getRotation().type == RotationType.Manual, - }), - InputHelpers.makeRotationNumberInput({ - fieldName: 'playerLatency', - label: 'Player latency', - labelTooltip: 'Time before the player reacts to an eclipse proc, in milliseconds.', - showWhen: (player: Player) => player.getRotation().type == RotationType.Manual, - }), - ], -}; diff --git a/ui/balance_druid/presets.ts b/ui/balance_druid/presets.ts index 794cebb306..b11e50dd42 100644 --- a/ui/balance_druid/presets.ts +++ b/ui/balance_druid/presets.ts @@ -18,11 +18,6 @@ import { SavedTalents } from '../core/proto/ui.js'; import { BalanceDruid_Options as BalanceDruidOptions, - BalanceDruid_Rotation as BalanceDruidRotation, - BalanceDruid_Rotation_IsUsage, - BalanceDruid_Rotation_MfUsage, - BalanceDruid_Rotation_Type as RotationType, - BalanceDruid_Rotation_WrathUsage, DruidMajorGlyph, DruidMinorGlyph, } from '../core/proto/druid.js'; @@ -117,18 +112,6 @@ export const Phase4Talents = { }), }; -export const DefaultRotation = BalanceDruidRotation.create({ - type: RotationType.Default, - maintainFaerieFire: true, - useSmartCooldowns: true, - mfUsage: BalanceDruid_Rotation_MfUsage.BeforeLunar, - isUsage: BalanceDruid_Rotation_IsUsage.OptimizeIs, - wrathUsage: BalanceDruid_Rotation_WrathUsage.RegularWrath, - useStarfire: true, - useBattleRes: false, - playerLatency: 200, -}); - export const DefaultOptions = BalanceDruidOptions.create({ innervateTarget: UnitReference.create(), }); diff --git a/ui/balance_druid/sim.ts b/ui/balance_druid/sim.ts index 768be09c72..1190eb4579 100644 --- a/ui/balance_druid/sim.ts +++ b/ui/balance_druid/sim.ts @@ -65,8 +65,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecBalanceDruid, { }), // Default consumes settings. consumes: Presets.DefaultConsumes, - // Default rotation settings. - rotation: Presets.DefaultRotation, // Default talents. talents: Presets.Phase3Talents.data, // Default spec-specific settings. @@ -83,8 +81,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecBalanceDruid, { playerIconInputs: [ DruidInputs.SelfInnervate, ], - // Inputs to include in the 'Rotation' section on the settings tab. - rotationInputs: DruidInputs.BalanceDruidRotationConfig, // Buff and Debuff inputs to include/exclude, overriding the EP-based defaults. includeBuffDebuffInputs: [ IconInputs.MeleeHasteBuff, diff --git a/ui/core/components/individual_sim_ui/custom_rotation_picker.ts b/ui/core/components/individual_sim_ui/custom_rotation_picker.ts deleted file mode 100644 index 7014d6edfa..0000000000 --- a/ui/core/components/individual_sim_ui/custom_rotation_picker.ts +++ /dev/null @@ -1,135 +0,0 @@ -import { Spec } from '../../proto/common.js'; -import { CustomRotation, CustomSpell } from '../../proto/common.js'; -import { EventID } from '../../typed_event.js'; -import { Player } from '../../player.js'; -import { IconEnumPicker, IconEnumValueConfig } from '../icon_enum_picker.js'; -import { ListItemPickerConfig, ListPicker } from '../list_picker.js'; -import { NumberPicker } from '../number_picker.js'; - -import { Component } from '../component.js'; -import { Input } from '../input.js'; -import { SimUI } from 'ui/core/sim_ui.js'; - -export interface CustomRotationPickerConfig { - getValue: (player: Player) => CustomRotation, - setValue: (eventID: EventID, player: Player, newValue: CustomRotation) => void, - - numColumns: number, - extraCssClasses?: string[]; - showCastsPerMinute?: boolean, - values: Array, T>>; - - showWhen?: (player: Player) => boolean, -} - -export class CustomRotationPicker extends Component { - constructor(parent: HTMLElement, simUI: SimUI, modPlayer: Player, config: CustomRotationPickerConfig) { - super(parent, 'custom-rotation-picker-root'); - - if (config.extraCssClasses) - this.rootElem.classList.add(...config.extraCssClasses); - - new ListPicker, CustomSpell>(this.rootElem, modPlayer, { - extraCssClasses: ['custom-spells-picker'], - title: 'Spell Priority', - titleTooltip: 'Spells at the top of the list are prioritized first. Safely ignores untalented options.', - itemLabel: 'Spell', - changedEvent: (player: Player) => player.changeEmitter, - getValue: (player: Player) => config.getValue(player).spells, - setValue: (eventID: EventID, player: Player, newValue: Array) => { - config.setValue(eventID, player, CustomRotation.create({ - spells: newValue, - })); - }, - newItem: () => CustomSpell.create(), - copyItem: (oldItem: CustomSpell) => CustomSpell.clone(oldItem), - newItemPicker: (parent: HTMLElement, listPicker: ListPicker, CustomSpell>, index: number, itemConfig: ListItemPickerConfig, CustomSpell>) => new CustomSpellPicker(parent, modPlayer, index, itemConfig, listPicker, config), - inlineMenuBar: true, - showWhen: config.showWhen, - }); - } -} - -class CustomSpellPicker extends Input, CustomSpell> { - private readonly player: Player; - private readonly listPicker: ListPicker, CustomSpell>; - private readonly spellIndex: number; - - private readonly spellPicker: Input; - private readonly cpmPicker: Input | null; - - getSpell(): CustomSpell { - return this.listPicker.config.getValue(this.player)[this.spellIndex] || CustomSpell.create(); - } - - constructor(parent: HTMLElement, player: Player, spellIndex: number, config: ListItemPickerConfig, CustomSpell>, listPicker: ListPicker, CustomSpell>, crConfig: CustomRotationPickerConfig) { - super(parent, 'custom-spell-picker-root', player, config); - this.player = player; - this.listPicker = listPicker; - this.spellIndex = spellIndex; - - this.spellPicker = new IconEnumPicker(this.rootElem, null, { - numColumns: crConfig.numColumns, - values: crConfig.values.map(value => { - if (value.showWhen) { - const oldShowWhen = value.showWhen; - value.showWhen = (() => oldShowWhen(player)) as unknown as ((player: Player) => boolean); - } - return value; - }) as unknown as Array>, - equals: (a: number, b: number) => a == b, - zeroValue: 0, - changedEvent: () => player.changeEmitter, - getValue: () => this.getSpell().spell, - setValue: (eventID: EventID, _: null, newValue: number) => { - const spell = this.getSpell(); - spell.spell = newValue; - this.setSpell(eventID, spell); - }, - }); - - this.cpmPicker = null; - if (crConfig.showCastsPerMinute) { - this.cpmPicker = new NumberPicker(this.rootElem, null, { - label: 'CPM', - labelTooltip: 'Desired Casts-Per-Minute for this spell.', - float: true, - positive: true, - changedEvent: () => player.changeEmitter, - getValue: () => this.getSpell().castsPerMinute, - setValue: (eventID: EventID, _: null, newValue: number) => { - const spell = this.getSpell(); - spell.castsPerMinute = newValue; - this.setSpell(eventID, spell); - }, - }); - } - } - - getInputElem(): HTMLElement | null { - return this.rootElem; - } - - getInputValue(): CustomSpell { - return CustomSpell.create({ - spell: this.spellPicker.getInputValue(), - castsPerMinute: this.cpmPicker?.getInputValue(), - }); - } - - setInputValue(newValue: CustomSpell) { - if (!newValue) { - return; - } - this.spellPicker.setInputValue(newValue.spell); - if (this.cpmPicker) { - this.cpmPicker.setInputValue(newValue.castsPerMinute); - } - } - - private setSpell(eventID: EventID, spell: CustomSpell) { - const customSpells = this.listPicker.config.getValue(this.player); - customSpells[this.spellIndex] = CustomSpell.clone(spell); - this.listPicker.config.setValue(eventID, this.player, customSpells); - } -} diff --git a/ui/core/components/individual_sim_ui/rotation_tab.ts b/ui/core/components/individual_sim_ui/rotation_tab.ts index 74c6ff3ce6..e962848ee1 100644 --- a/ui/core/components/individual_sim_ui/rotation_tab.ts +++ b/ui/core/components/individual_sim_ui/rotation_tab.ts @@ -12,7 +12,6 @@ import { } from "../../proto/ui"; import { EventID, TypedEvent } from "../../typed_event"; import { Player } from "../../player"; -import { aplLaunchStatuses, LaunchStatus } from '../../launched_sims'; import { ContentBlock } from "../content_block"; import { SimTab } from "../sim_tab"; @@ -21,7 +20,6 @@ import { BooleanPicker } from "../boolean_picker"; import { EnumPicker } from "../enum_picker"; import { Input } from "../input"; import { CooldownsPicker } from "./cooldowns_picker"; -import { CustomRotationPicker } from "./custom_rotation_picker"; import { SavedDataManager } from "../saved_data_manager"; import * as IconInputs from '../icon_inputs.js'; @@ -59,7 +57,7 @@ export class RotationTab extends SimTab { this.buildAutoContent(); this.buildAplContent(); - this.buildSimpleOrLegacyContent(this.simUI.player.hasSimpleRotationGenerator()); + this.buildSimpleContent(); this.buildSavedDataPickers(); } @@ -87,20 +85,11 @@ export class RotationTab extends SimTab { header.classList.add('rotation-tab-header'); this.leftPanel.appendChild(header); - const aplLaunchStatus = aplLaunchStatuses[this.simUI.player.spec]; - new EnumPicker(header, this.simUI.player, { label: 'Rotation Type', labelTooltip: 'Which set of options to use for specifying the rotation.', inline: true, - values: aplLaunchStatus == LaunchStatus.Alpha ? [ - { value: APLRotationType.TypeLegacy, name: 'Legacy' }, - { value: APLRotationType.TypeAPL, name: 'APL' }, - ] : aplLaunchStatus == LaunchStatus.Beta ? [ - { value: APLRotationType.TypeAuto, name: 'Auto' }, - { value: APLRotationType.TypeAPL, name: 'APL' }, - { value: APLRotationType.TypeLegacy, name: 'Legacy' }, - ] : this.simUI.player.hasSimpleRotationGenerator() ? [ + values: this.simUI.player.hasSimpleRotationGenerator() ? [ { value: APLRotationType.TypeAuto, name: 'Auto' }, { value: APLRotationType.TypeSimple, name: 'Simple' }, { value: APLRotationType.TypeAPL, name: 'APL' }, @@ -132,11 +121,11 @@ export class RotationTab extends SimTab { new APLRotationPicker(content, this.simUI, this.simUI.player); } - private buildSimpleOrLegacyContent(isSimple: boolean) { - if (!isSimple && aplLaunchStatuses[this.simUI.player.spec] == LaunchStatus.Launched) { + private buildSimpleContent() { + if (!this.simUI.player.hasSimpleRotationGenerator() || !this.simUI.individualConfig.rotationInputs) { return; } - const cssClass = isSimple ? 'rotation-tab-simple' : 'rotation-tab-legacy'; + const cssClass = 'rotation-tab-simple'; const contentBlock = new ContentBlock(this.leftPanel, 'rotation-settings', { header: { title: 'Rotation' } @@ -177,8 +166,6 @@ export class RotationTab extends SimTab { new BooleanPicker(sectionElem, this.simUI.player, { ...inputConfig, ...{ cssScheme: this.simUI.cssScheme } }); } else if (inputConfig.type == 'enum') { new EnumPicker(sectionElem, this.simUI.player, inputConfig); - } else if (inputConfig.type == 'customRotation') { - new CustomRotationPicker(sectionElem, this.simUI, this.simUI.player, inputConfig); } }); } @@ -196,32 +183,18 @@ export class RotationTab extends SimTab { } private buildSavedDataPickers() { - const aplIsLaunched = aplLaunchStatuses[this.simUI.player.spec] == LaunchStatus.Launched; - const savedRotationsManager = new SavedDataManager, SavedRotation>(this.rightPanel, this.simUI.player, { label: 'Rotation', header: { title: 'Saved Rotations' }, storageKey: this.simUI.getSavedRotationStorageKey(), getData: (player: Player) => SavedRotation.create({ rotation: APLRotation.clone(player.aplRotation), - specRotationOptionsJson: aplIsLaunched ? '{}' : JSON.stringify(player.specTypeFunctions.rotationToJson(player.getRotation())), - cooldowns: aplIsLaunched ? Cooldowns.create() : player.getCooldowns(), + specRotationOptionsJson: '{}', + cooldowns: Cooldowns.create(), }), setData: (eventID: EventID, player: Player, newRotation: SavedRotation) => { TypedEvent.freezeAllAndDo(() => { player.setAplRotation(eventID, newRotation.rotation || APLRotation.create()); - if (!aplIsLaunched) { - if (newRotation.specRotationOptionsJson) { - try { - const json = JSON.parse(newRotation.specRotationOptionsJson); - const specRot = player.specTypeFunctions.rotationFromJson(json); - player.setRotation(eventID, specRot); - } catch (e) { - console.warn('Error parsing rotation spec options: ' + e); - } - } - player.setCooldowns(eventID, newRotation.cooldowns || Cooldowns.create()); - } }); }, changeEmitters: [this.simUI.player.rotationChangeEmitter, this.simUI.player.cooldownsChangeEmitter, this.simUI.player.talentsChangeEmitter], diff --git a/ui/core/components/individual_sim_ui/settings_tab.ts b/ui/core/components/individual_sim_ui/settings_tab.ts index c5e59348de..f313fbdf81 100644 --- a/ui/core/components/individual_sim_ui/settings_tab.ts +++ b/ui/core/components/individual_sim_ui/settings_tab.ts @@ -1,7 +1,6 @@ import { IndividualSimUI, InputSection, StatOption } from "../../individual_sim_ui"; import { Consumes, - Cooldowns, Debuffs, HealingModel, IndividualBuffs, @@ -20,7 +19,6 @@ import { SavedEncounter, SavedSettings } from "../../proto/ui"; import { EventID, TypedEvent } from "../../typed_event"; import { getEnumValues } from "../../utils"; import { Player } from "../../player"; -import { aplLaunchStatuses, LaunchStatus } from '../../launched_sims'; import { ContentBlock } from "../content_block"; import { EncounterPicker } from '../encounter_picker.js'; @@ -34,8 +32,6 @@ import { MultiIconPicker } from "../multi_icon_picker"; import { IconPickerConfig } from "../icon_picker"; import { TypedIconPickerConfig } from "../input_helpers"; -import { CustomRotationPicker } from "./custom_rotation_picker"; -import { CooldownsPicker } from "./cooldowns_picker"; import { ConsumesPicker } from "./consumes_picker"; import * as IconInputs from '../icon_inputs.js'; @@ -84,16 +80,9 @@ export class SettingsTab extends SimTab { this.buildEncounterSettings(); } - if (aplLaunchStatuses[this.simUI.player.spec] == LaunchStatus.Unlaunched) { - this.buildRotationSettings(); - } - this.buildPlayerSettings(); this.buildCustomSettingsSections(); this.buildConsumesSection(); - if (aplLaunchStatuses[this.simUI.player.spec] == LaunchStatus.Unlaunched) { - this.buildCooldownSettings(); - } this.buildOtherSettings(); if (!this.simUI.isWithinRaidSim) { @@ -114,32 +103,8 @@ export class SettingsTab extends SimTab { new EncounterPicker(contentBlock.bodyElement, this.simUI.sim.encounter, this.simUI.individualConfig.encounterPicker, this.simUI); } - private buildRotationSettings() { - const contentBlock = new ContentBlock(this.column1, 'rotation-settings', { - header: { title: 'Rotation' } - }); - - const rotationIconGroup = Input.newGroupContainer(); - rotationIconGroup.classList.add('rotation-icon-group', 'icon-group'); - contentBlock.bodyElement.appendChild(rotationIconGroup); - - if (this.simUI.individualConfig.rotationIconInputs?.length) { - this.configureIconSection( - rotationIconGroup, - this.simUI.individualConfig.rotationIconInputs.map(iconInput => IconInputs.buildIconInput(rotationIconGroup, this.simUI.player, iconInput)), - true - ); - } - - this.configureInputSection(contentBlock.bodyElement, this.simUI.individualConfig.rotationInputs); - - contentBlock.bodyElement.querySelectorAll('.input-root').forEach(elem => { - elem.classList.add('input-inline'); - }) - } - private buildPlayerSettings() { - const column = aplLaunchStatuses[this.simUI.player.spec] == LaunchStatus.Unlaunched ? this.column2 : this.column1; + const column = this.column1; const contentBlock = new ContentBlock(column, 'player-settings', { header: { title: 'Player' } }); @@ -155,7 +120,7 @@ export class SettingsTab extends SimTab { ); const races = specToEligibleRaces[this.simUI.player.spec]; - const racePicker = new EnumPicker(contentBlock.bodyElement, this.simUI.player, { + const _racePicker = new EnumPicker(contentBlock.bodyElement, this.simUI.player, { label: 'Race', values: races.map(race => { return { @@ -176,7 +141,7 @@ export class SettingsTab extends SimTab { contentBlock.bodyElement.appendChild(professionGroup); const professions = getEnumValues(Profession) as Array; - const profession1Picker = new EnumPicker(professionGroup, this.simUI.player, { + const _profession1Picker = new EnumPicker(professionGroup, this.simUI.player, { label: 'Profession 1', values: professions.map(p => { return { @@ -189,7 +154,7 @@ export class SettingsTab extends SimTab { setValue: (eventID, sim, newValue) => sim.setProfession1(eventID, newValue), }); - const profession2Picker = new EnumPicker(professionGroup, this.simUI.player, { + const _profession2Picker = new EnumPicker(professionGroup, this.simUI.player, { label: 'Profession 2', values: professions.map(p => { return { @@ -219,17 +184,7 @@ export class SettingsTab extends SimTab { new ConsumesPicker(contentBlock.bodyElement, this, this.simUI); } - private buildCooldownSettings() { - const column = (this.simUI.isWithinRaidSim ? this.column4 : this.column2) as HTMLElement; - const contentBlock = new ContentBlock(column, 'cooldown-settings', { - header: { title: 'Cooldowns', tooltip: Tooltips.COOLDOWNS_SECTION } - }); - - new CooldownsPicker(contentBlock.bodyElement, this.simUI.player); - } - private buildOtherSettings() { - const column = this.simUI.isWithinRaidSim ? this.column4 : this.column2; const settings = this.simUI.individualConfig.otherInputs?.inputs.filter(inputs => !inputs.extraCssClasses?.includes('within-raid-sim-hide') || true ) @@ -412,8 +367,6 @@ export class SettingsTab extends SimTab { distanceFromTarget: player.getDistanceFromTarget(), healingModel: player.getHealingModel(), nibelungAverageCasts: player.getNibelungAverageCasts(), - cooldowns: aplLaunchStatuses[simUI.player.spec] == LaunchStatus.Unlaunched ? player.getCooldowns() : undefined, - rotationJson: aplLaunchStatuses[simUI.player.spec] == LaunchStatus.Unlaunched ? JSON.stringify(player.specTypeFunctions.rotationToJson(player.getRotation())) : undefined, }); }, setData: (eventID: EventID, simUI: IndividualSimUI, newSettings: SavedSettings) => { @@ -436,12 +389,6 @@ export class SettingsTab extends SimTab { simUI.player.setDistanceFromTarget(eventID, newSettings.distanceFromTarget); simUI.player.setHealingModel(eventID, newSettings.healingModel || HealingModel.create()); simUI.player.setNibelungAverageCasts(eventID, newSettings.nibelungAverageCasts) - if (aplLaunchStatuses[simUI.player.spec] == LaunchStatus.Unlaunched) { - simUI.player.setCooldowns(eventID, newSettings.cooldowns || Cooldowns.create()); - if (newSettings.rotationJson) { - simUI.player.setRotation(eventID, simUI.player.specTypeFunctions.rotationFromJson(JSON.parse(newSettings.rotationJson))); - } - } }); }, changeEmitters: [ @@ -457,10 +404,7 @@ export class SettingsTab extends SimTab { this.simUI.player.inFrontOfTargetChangeEmitter, this.simUI.player.distanceFromTargetChangeEmitter, this.simUI.player.healingModelChangeEmitter, - ].concat(aplLaunchStatuses[this.simUI.player.spec] == LaunchStatus.Unlaunched ? [ - this.simUI.player.cooldownsChangeEmitter, - this.simUI.player.rotationChangeEmitter, - ] : []), + ], equals: (a: SavedSettings, b: SavedSettings) => SavedSettings.equals(a, b), toJson: (a: SavedSettings) => SavedSettings.toJson(a), fromJson: (obj: any) => SavedSettings.fromJson(obj), @@ -480,8 +424,6 @@ export class SettingsTab extends SimTab { new BooleanPicker(sectionElem, this.simUI.player, { ...inputConfig, ...{ cssScheme: this.simUI.cssScheme } }); } else if (inputConfig.type == 'enum') { new EnumPicker(sectionElem, this.simUI.player, inputConfig); - } else if (inputConfig.type == 'customRotation') { - new CustomRotationPicker(sectionElem, this.simUI, this.simUI.player, inputConfig); } }); }; diff --git a/ui/core/components/input_helpers.ts b/ui/core/components/input_helpers.ts index 6feced79b3..4058200c79 100644 --- a/ui/core/components/input_helpers.ts +++ b/ui/core/components/input_helpers.ts @@ -1,10 +1,8 @@ import { ActionId } from '../proto_utils/action_id.js'; -import { CustomRotation } from '../proto/common.js'; import { Spec } from '../proto/common.js'; import { Player } from '../player.js'; import { EventID, TypedEvent } from '../typed_event.js'; import { SpecOptions, SpecRotation } from '../proto_utils/utils.js'; -import { CustomRotationPickerConfig } from './individual_sim_ui/custom_rotation_picker.js'; import { IconPickerConfig } from './icon_picker.js'; import { IconEnumPickerConfig, IconEnumValueConfig } from './icon_enum_picker.js'; import { EnumPickerConfig, EnumValueConfig } from './enum_picker.js'; @@ -446,34 +444,3 @@ export function makeRotationEnumIconInput(config: Play extraCssClasses: config.extraCssClasses, }); } - -export interface TypedCustomRotationPickerConfig extends CustomRotationPickerConfig { - type: 'customRotation', -} - -interface WrappedCustomRotationInputConfig { - fieldName: keyof SpecRotation, - getValue?: (player: Player) => CustomRotation, - setValue?: (eventID: EventID, player: Player, newValue: CustomRotation) => void, - - numColumns: number, - showCastsPerMinute?: boolean, - values: Array, T>>; - - showWhen?: (player: Player) => boolean, -} -export function makeCustomRotationInput(config: WrappedCustomRotationInputConfig): TypedCustomRotationPickerConfig { - return { - type: 'customRotation', - getValue: config.getValue || ((player: Player) => (player.getRotation()[config.fieldName] as unknown as CustomRotation) || CustomRotation.create()), - setValue: config.setValue || ((eventID: EventID, player: Player, newValue: CustomRotation) => { - const rotation = player.getRotation(); - (rotation[config.fieldName] as unknown as CustomRotation) = newValue; - player.setRotation(eventID, rotation); - }), - showWhen: config.showWhen, - numColumns: config.numColumns, - showCastsPerMinute: config.showCastsPerMinute || false, - values: config.values, - } -} diff --git a/ui/core/individual_sim_ui.ts b/ui/core/individual_sim_ui.ts index b1a26e633c..08502d6d36 100644 --- a/ui/core/individual_sim_ui.ts +++ b/ui/core/individual_sim_ui.ts @@ -1,4 +1,4 @@ -import { aplLaunchStatuses, LaunchStatus, simLaunchStatuses } from './launched_sims'; +import { simLaunchStatuses } from './launched_sims'; import { Player, PlayerConfig, registerSpecConfig as registerPlayerConfig } from './player'; import { SimUI, SimWarning } from './sim_ui'; import { EventID, TypedEvent } from './typed_event'; @@ -47,7 +47,6 @@ import { isHealingSpec, isTankSpec, SpecOptions, - SpecRotation, specToEligibleRaces, specToLocalStorageKey, } from './proto_utils/utils'; @@ -70,8 +69,7 @@ const SAVED_TALENTS_STORAGE_KEY = '__savedTalents__'; export type InputConfig = ( InputHelpers.TypedBooleanPickerConfig | InputHelpers.TypedNumberPickerConfig | - InputHelpers.TypedEnumPickerConfig | - InputHelpers.TypedCustomRotationPickerConfig + InputHelpers.TypedEnumPickerConfig ); export interface InputSection { @@ -121,7 +119,6 @@ export interface IndividualSimUIConfig extends PlayerConf gear: EquipmentSpec, epWeights: Stats, consumes: Consumes, - rotation: SpecRotation, talents: SavedTalents, specOptions: SpecOptions, @@ -137,7 +134,7 @@ export interface IndividualSimUIConfig extends PlayerConf playerInputs?: InputSection, playerIconInputs: Array, any>>, petConsumeInputs?: Array, any>>, - rotationInputs: InputSection; + rotationInputs?: InputSection; rotationIconInputs?: Array, any>>; includeBuffDebuffInputs: Array, excludeBuffDebuffInputs: Array, @@ -198,7 +195,6 @@ export abstract class IndividualSimUI extends SimUI { spec: player.spec, knownIssues: config.knownIssues, launchStatus: simLaunchStatuses[player.spec], - noticeText: aplLaunchStatuses[player.spec] == LaunchStatus.Alpha ? 'Rotation settings have been moved to the \'Rotation\' tab, where experimental APL options are also available. Try them out!' : undefined, }); this.rootElem.classList.add('individual-sim-ui'); this.player = player; @@ -293,9 +289,7 @@ export abstract class IndividualSimUI extends SimUI { this.bt = this.addBulkTab(); this.addSettingsTab(); this.addTalentsTab(); - if (aplLaunchStatuses[this.player.spec] != LaunchStatus.Unlaunched) { - this.addRotationTab(); - } + this.addRotationTab(); if (!this.isWithinRaidSim) { this.addDetailedResultsTab(); @@ -415,11 +409,6 @@ export abstract class IndividualSimUI extends SimUI { this.player.setRace(eventID, specToEligibleRaces[this.player.spec][0]); this.player.setGear(eventID, this.sim.db.lookupEquipmentSpec(this.individualConfig.defaults.gear)); this.player.setConsumes(eventID, this.individualConfig.defaults.consumes); - if (aplLaunchStatuses[this.player.spec] < LaunchStatus.Beta) { - this.player.setRotation(eventID, this.individualConfig.defaults.rotation); - } else if (aplLaunchStatuses[this.player.spec] == LaunchStatus.Beta) { - this.player.setRotation(eventID, this.player.specTypeFunctions.rotationCreate()); - } this.player.setTalentsString(eventID, this.individualConfig.defaults.talents.talentsString); this.player.setGlyphs(eventID, this.individualConfig.defaults.talents.glyphs || Glyphs.create()); this.player.setSpecOptions(eventID, this.individualConfig.defaults.specOptions); diff --git a/ui/core/launched_sims.ts b/ui/core/launched_sims.ts index 47d45e1755..61ed8e65c6 100644 --- a/ui/core/launched_sims.ts +++ b/ui/core/launched_sims.ts @@ -38,31 +38,6 @@ export const simLaunchStatuses: Record = { [Spec.SpecTankDeathknight]: LaunchStatus.Launched, }; -// Alpha and Beta show an info notice at the top of the page. -export const aplLaunchStatuses: Record = { - [Spec.SpecBalanceDruid]: LaunchStatus.Beta, - [Spec.SpecFeralDruid]: LaunchStatus.Launched, - [Spec.SpecFeralTankDruid]: LaunchStatus.Launched, - [Spec.SpecRestorationDruid]: LaunchStatus.Launched, - [Spec.SpecElementalShaman]: LaunchStatus.Beta, - [Spec.SpecEnhancementShaman]: LaunchStatus.Beta, - [Spec.SpecRestorationShaman]: LaunchStatus.Launched, - [Spec.SpecHunter]: LaunchStatus.Launched, - [Spec.SpecMage]: LaunchStatus.Launched, - [Spec.SpecRogue]: LaunchStatus.Beta, - [Spec.SpecHolyPaladin]: LaunchStatus.Launched, - [Spec.SpecProtectionPaladin]: LaunchStatus.Launched, - [Spec.SpecRetributionPaladin]: LaunchStatus.Beta, - [Spec.SpecHealingPriest]: LaunchStatus.Launched, - [Spec.SpecShadowPriest]: LaunchStatus.Beta, - [Spec.SpecSmitePriest]: LaunchStatus.Launched, - [Spec.SpecWarlock]: LaunchStatus.Beta, - [Spec.SpecWarrior]: LaunchStatus.Launched, - [Spec.SpecProtectionWarrior]: LaunchStatus.Launched, - [Spec.SpecDeathknight]: LaunchStatus.Beta, - [Spec.SpecTankDeathknight]: LaunchStatus.Beta, -}; - // Meme specs are excluded from title drop-down menu. export const memeSpecs: Array = [ Spec.SpecSmitePriest, diff --git a/ui/core/player.ts b/ui/core/player.ts index 0c64a544c5..3a5e80b252 100644 --- a/ui/core/player.ts +++ b/ui/core/player.ts @@ -46,7 +46,6 @@ import { Player as PlayerProto } from './proto/api.js'; import { StatWeightsResult } from './proto/api.js'; import { ActionId } from './proto_utils/action_id.js'; import { EquippedItem, getWeaponDPS } from './proto_utils/equipped_item.js'; -import { aplLaunchStatuses, LaunchStatus } from './launched_sims'; import { playerTalentStringToProto } from './talents/factory.js'; import { Gear, ItemSwapGear } from './proto_utils/gear.js'; @@ -321,7 +320,7 @@ export class Player { throw new Error('Could not find spec config for spec: ' + this.spec); } this.autoRotationGenerator = specConfig.autoRotation; - if (aplLaunchStatuses[this.spec] == LaunchStatus.Launched && specConfig.simpleRotation) { + if (specConfig.simpleRotation) { this.simpleRotationGenerator = specConfig.simpleRotation; } else { this.simpleRotationGenerator = null; @@ -600,27 +599,18 @@ export class Player { getCooldowns(): Cooldowns { // Make a defensive copy - if (aplLaunchStatuses[this.spec] == LaunchStatus.Launched) { - return Cooldowns.clone(this.aplRotation.simple?.cooldowns || Cooldowns.create()); - } else { - return Cooldowns.clone(this.cooldowns); - } + return Cooldowns.clone(this.aplRotation.simple?.cooldowns || Cooldowns.create()); } setCooldowns(eventID: EventID, newCooldowns: Cooldowns) { if (Cooldowns.equals(this.getCooldowns(), newCooldowns)) return; - if (aplLaunchStatuses[this.spec] == LaunchStatus.Launched) { - if (!this.aplRotation.simple) { - this.aplRotation.simple = SimpleRotation.create(); - } - this.aplRotation.simple.cooldowns = newCooldowns; - this.rotationChangeEmitter.emit(eventID); - } else { - // Make a defensive copy - this.cooldowns = Cooldowns.clone(newCooldowns); + if (!this.aplRotation.simple) { + this.aplRotation.simple = SimpleRotation.create(); } + this.aplRotation.simple.cooldowns = newCooldowns; + this.rotationChangeEmitter.emit(eventID); this.cooldownsChangeEmitter.emit(eventID); } @@ -762,21 +752,17 @@ export class Player { } getRotation(): SpecRotation { - if (aplLaunchStatuses[this.spec] == LaunchStatus.Launched) { - const jsonStr = this.aplRotation.simple?.specRotationJson || ''; - if (!jsonStr) { - return this.specTypeFunctions.rotationCreate(); - } + const jsonStr = this.aplRotation.simple?.specRotationJson || ''; + if (!jsonStr) { + return this.specTypeFunctions.rotationCreate(); + } - try { - const json = JSON.parse(jsonStr); - return this.specTypeFunctions.rotationFromJson(json); - } catch (e) { - console.warn(`Error parsing rotation spec options: ${e}\n\nSpec options: '${jsonStr}'`); - return this.specTypeFunctions.rotationCreate(); - } - } else { - return this.specTypeFunctions.rotationCopy(this.rotation); + try { + const json = JSON.parse(jsonStr); + return this.specTypeFunctions.rotationFromJson(json); + } catch (e) { + console.warn(`Error parsing rotation spec options: ${e}\n\nSpec options: '${jsonStr}'`); + return this.specTypeFunctions.rotationCreate(); } } @@ -784,14 +770,10 @@ export class Player { if (this.specTypeFunctions.rotationEquals(newRotation, this.getRotation())) return; - if (aplLaunchStatuses[this.spec] == LaunchStatus.Launched) { - if (!this.aplRotation.simple) { - this.aplRotation.simple = SimpleRotation.create(); - } - this.aplRotation.simple.specRotationJson = JSON.stringify(this.specTypeFunctions.rotationToJson(newRotation)); - } else { - this.rotation = this.specTypeFunctions.rotationCopy(newRotation); + if (!this.aplRotation.simple) { + this.aplRotation.simple = SimpleRotation.create(); } + this.aplRotation.simple.specRotationJson = JSON.stringify(this.specTypeFunctions.rotationToJson(newRotation)); this.rotationChangeEmitter.emit(eventID); } @@ -1337,7 +1319,6 @@ export class Player { || exportCategories.length == 0 || exportCategories.includes(cat); - const aplIsLaunched = aplLaunchStatuses[this.spec] == LaunchStatus.Launched; const gear = this.getGear(); const aplRotation = forSimming ? this.getResolvedAplRotation() : this.aplRotation; @@ -1361,9 +1342,7 @@ export class Player { } if (exportCategory(SimSettingCategories.Rotation)) { PlayerProto.mergePartial(player, { - cooldowns: (aplIsLaunched || (forSimming && aplRotation.type == APLRotationType.TypeAPL)) - ? Cooldowns.create({ hpPercentForDefensives: this.getCooldowns().hpPercentForDefensives }) - : this.getCooldowns(), + cooldowns: Cooldowns.create({ hpPercentForDefensives: this.getCooldowns().hpPercentForDefensives }), rotation: aplRotation, }); } @@ -1386,21 +1365,14 @@ export class Player { nibelungAverageCasts: this.getNibelungAverageCasts(), nibelungAverageCastsSet: this.nibelungAverageCastsSet, }); + player = withSpecProto(this.spec, player, this.getSpecOptions()); } if (exportCategory(SimSettingCategories.External)) { PlayerProto.mergePartial(player, { buffs: this.getBuffs(), }); } - return withSpecProto( - this.spec, - player, - (aplIsLaunched || (forSimming && aplRotation.type == APLRotationType.TypeAPL) || !exportCategory(SimSettingCategories.Rotation)) - ? this.specTypeFunctions.rotationCreate() - : this.getRotation(), - exportCategory(SimSettingCategories.Miscellaneous) - ? this.getSpecOptions() - : this.specTypeFunctions.optionsCreate()); + return player; } fromProto(eventID: EventID, proto: PlayerProto, includeCategories?: Array) { @@ -1424,24 +1396,22 @@ export class Player { } } - if (aplLaunchStatuses[this.spec] == LaunchStatus.Launched) { - const rot = this.specTypeFunctions.rotationFromPlayer(proto); - if (rot && !this.specTypeFunctions.rotationEquals(rot, this.specTypeFunctions.rotationCreate())) { - if (proto.rotation?.type == APLRotationType.TypeAPL) { - // Do nothing - } else if (this.simpleRotationGenerator) { - proto.rotation = APLRotation.create({ - type: APLRotationType.TypeSimple, - simple: { - specRotationJson: JSON.stringify(this.specTypeFunctions.rotationToJson(rot)), - cooldowns: proto.cooldowns, - }, - }); - } else { - proto.rotation = APLRotation.create({ - type: APLRotationType.TypeAuto, - }); - } + const rot = this.specTypeFunctions.rotationFromPlayer(proto); + if (rot && !this.specTypeFunctions.rotationEquals(rot, this.specTypeFunctions.rotationCreate())) { + if (proto.rotation?.type == APLRotationType.TypeAPL) { + // Do nothing + } else if (this.simpleRotationGenerator) { + proto.rotation = APLRotation.create({ + type: APLRotationType.TypeSimple, + simple: { + specRotationJson: JSON.stringify(this.specTypeFunctions.rotationToJson(rot)), + cooldowns: proto.cooldowns, + }, + }); + } else { + proto.rotation = APLRotation.create({ + type: APLRotationType.TypeAuto, + }); } } @@ -1458,16 +1428,11 @@ export class Player { this.setGlyphs(eventID, proto.glyphs || Glyphs.create()); } if (loadCategory(SimSettingCategories.Rotation)) { - if (aplLaunchStatuses[this.spec] == LaunchStatus.Launched) { - if (proto.rotation?.type == APLRotationType.TypeUnknown || proto.rotation?.type == APLRotationType.TypeLegacy) { - if (!proto.rotation) { - proto.rotation = APLRotation.create(); - } - proto.rotation.type = APLRotationType.TypeAuto; + if (proto.rotation?.type == APLRotationType.TypeUnknown || proto.rotation?.type == APLRotationType.TypeLegacy) { + if (!proto.rotation) { + proto.rotation = APLRotation.create(); } - } else { - this.setCooldowns(eventID, proto.cooldowns || Cooldowns.create()); - this.setRotation(eventID, this.specTypeFunctions.rotationFromPlayer(proto)); + proto.rotation.type = APLRotationType.TypeAuto; } this.setAplRotation(eventID, proto.rotation || APLRotation.create()) } diff --git a/ui/core/proto_utils/utils.ts b/ui/core/proto_utils/utils.ts index 650c413a41..8a6be3a96a 100644 --- a/ui/core/proto_utils/utils.ts +++ b/ui/core/proto_utils/utils.ts @@ -1318,7 +1318,6 @@ export const specToLocalStorageKey: Record = { export function withSpecProto( spec: Spec, player: Player, - rotation: SpecRotation, specOptions: SpecOptions): Player { const copy = Player.clone(player); @@ -1327,7 +1326,6 @@ export function withSpecProto( copy.spec = { oneofKind: 'balanceDruid', balanceDruid: BalanceDruid.create({ - rotation: rotation as BalanceDruidRotation, options: specOptions as BalanceDruidOptions, }), }; @@ -1336,7 +1334,6 @@ export function withSpecProto( copy.spec = { oneofKind: 'feralDruid', feralDruid: FeralDruid.create({ - rotation: rotation as FeralDruidRotation, options: specOptions as FeralDruidOptions, }), }; @@ -1345,7 +1342,6 @@ export function withSpecProto( copy.spec = { oneofKind: 'feralTankDruid', feralTankDruid: FeralTankDruid.create({ - rotation: rotation as FeralTankDruidRotation, options: specOptions as FeralTankDruidOptions, }), }; @@ -1354,7 +1350,6 @@ export function withSpecProto( copy.spec = { oneofKind: 'restorationDruid', restorationDruid: RestorationDruid.create({ - rotation: rotation as RestorationDruidRotation, options: specOptions as RestorationDruidOptions, }), }; @@ -1363,7 +1358,6 @@ export function withSpecProto( copy.spec = { oneofKind: 'elementalShaman', elementalShaman: ElementalShaman.create({ - rotation: rotation as ElementalShamanRotation, options: specOptions as ElementalShamanOptions, }), }; @@ -1372,7 +1366,6 @@ export function withSpecProto( copy.spec = { oneofKind: 'enhancementShaman', enhancementShaman: EnhancementShaman.create({ - rotation: rotation as EnhancementShamanRotation, options: specOptions as ElementalShamanOptions, }), }; @@ -1381,7 +1374,6 @@ export function withSpecProto( copy.spec = { oneofKind: 'restorationShaman', restorationShaman: RestorationShaman.create({ - rotation: rotation as RestorationShamanRotation, options: specOptions as RestorationShamanOptions, }), }; @@ -1390,7 +1382,6 @@ export function withSpecProto( copy.spec = { oneofKind: 'hunter', hunter: Hunter.create({ - rotation: rotation as HunterRotation, options: specOptions as HunterOptions, }), }; @@ -1399,7 +1390,6 @@ export function withSpecProto( copy.spec = { oneofKind: 'mage', mage: Mage.create({ - rotation: rotation as MageRotation, options: specOptions as MageOptions, }), }; @@ -1408,7 +1398,6 @@ export function withSpecProto( copy.spec = { oneofKind: 'holyPaladin', holyPaladin: HolyPaladin.create({ - rotation: rotation as HolyPaladinRotation, options: specOptions as HolyPaladinOptions, }), }; @@ -1417,7 +1406,6 @@ export function withSpecProto( copy.spec = { oneofKind: 'protectionPaladin', protectionPaladin: ProtectionPaladin.create({ - rotation: rotation as ProtectionPaladinRotation, options: specOptions as ProtectionPaladinOptions, }), }; @@ -1426,7 +1414,6 @@ export function withSpecProto( copy.spec = { oneofKind: 'retributionPaladin', retributionPaladin: RetributionPaladin.create({ - rotation: rotation as RetributionPaladinRotation, options: specOptions as RetributionPaladinOptions, }), }; @@ -1435,7 +1422,6 @@ export function withSpecProto( copy.spec = { oneofKind: 'rogue', rogue: Rogue.create({ - rotation: rotation as RogueRotation, options: specOptions as RogueOptions, }), }; @@ -1444,7 +1430,6 @@ export function withSpecProto( copy.spec = { oneofKind: 'healingPriest', healingPriest: HealingPriest.create({ - rotation: rotation as HealingPriestRotation, options: specOptions as HealingPriestOptions, }), }; @@ -1453,7 +1438,6 @@ export function withSpecProto( copy.spec = { oneofKind: 'shadowPriest', shadowPriest: ShadowPriest.create({ - rotation: rotation as ShadowPriestRotation, options: specOptions as ShadowPriestOptions, }), }; @@ -1462,7 +1446,6 @@ export function withSpecProto( copy.spec = { oneofKind: 'smitePriest', smitePriest: SmitePriest.create({ - rotation: rotation as SmitePriestRotation, options: specOptions as SmitePriestOptions, }), }; @@ -1471,7 +1454,6 @@ export function withSpecProto( copy.spec = { oneofKind: 'warlock', warlock: Warlock.create({ - rotation: rotation as WarlockRotation, options: specOptions as WarlockOptions, }), }; @@ -1480,7 +1462,6 @@ export function withSpecProto( copy.spec = { oneofKind: 'warrior', warrior: Warrior.create({ - rotation: rotation as WarriorRotation, options: specOptions as WarriorOptions, }), }; @@ -1489,7 +1470,6 @@ export function withSpecProto( copy.spec = { oneofKind: 'protectionWarrior', protectionWarrior: ProtectionWarrior.create({ - rotation: rotation as ProtectionWarriorRotation, options: specOptions as ProtectionWarriorOptions, }), }; @@ -1498,7 +1478,6 @@ export function withSpecProto( copy.spec = { oneofKind: 'deathknight', deathknight: Deathknight.create({ - rotation: rotation as DeathknightRotation, options: specOptions as DeathknightOptions, }), }; @@ -1507,7 +1486,6 @@ export function withSpecProto( copy.spec = { oneofKind: 'tankDeathknight', tankDeathknight: TankDeathknight.create({ - rotation: rotation as TankDeathknightRotation, options: specOptions as TankDeathknightOptions, }), }; diff --git a/ui/deathknight/inputs.ts b/ui/deathknight/inputs.ts index 84e520a551..71df139b96 100644 --- a/ui/deathknight/inputs.ts +++ b/ui/deathknight/inputs.ts @@ -1,22 +1,7 @@ -import { ItemSlot, Spec } from '../core/proto/common.js'; +import { Spec } from '../core/proto/common.js'; import { UnitReference, UnitReference_Type as UnitType } from '../core/proto/common.js'; -import { ActionId } from '../core/proto_utils/action_id.js'; import { - DeathknightTalents as DeathKnightTalents, - Deathknight_Rotation_ArmyOfTheDead as ArmyOfTheDead, - Deathknight_Rotation_DrwDiseases as DrwDiseases, - Deathknight_Rotation_BloodOpener as BloodOpener, - Deathknight_Rotation_BloodSpell as BloodSpell, - Deathknight_Rotation_FirstDisease as FirstDisease, - Deathknight_Rotation_DeathAndDecayPrio as DeathAndDecayPrio, - Deathknight_Rotation_Presence as StartingPresence, - Deathknight_Rotation_BloodRuneFiller as BloodRuneFiller, - Deathknight_Rotation_BloodTap as BloodTap, - Deathknight_Rotation_FrostRotationType as FrostRotationType, - Deathknight_Rotation_CustomSpellOption as CustomSpellOption, - Deathknight_Rotation as DeathKnightRotation, - Deathknight_Options as DeathKnightOptions, DeathknightMajorGlyph, } from '../core/proto/deathknight.js'; @@ -79,301 +64,14 @@ export const DrwPestiApply = InputHelpers.makeSpecOptionsBooleanInput) => !player.getRotation().autoRotation && player.getTalentTree() == 0 && (player.getGlyphs().major1 == DeathknightMajorGlyph.GlyphOfDisease || player.getGlyphs().major2 == DeathknightMajorGlyph.GlyphOfDisease || player.getGlyphs().major3 == DeathknightMajorGlyph.GlyphOfDisease), + showWhen: (player: Player) => player.getTalentTree() == 0 && (player.getGlyphs().major1 == DeathknightMajorGlyph.GlyphOfDisease || player.getGlyphs().major2 == DeathknightMajorGlyph.GlyphOfDisease || player.getGlyphs().major3 == DeathknightMajorGlyph.GlyphOfDisease), changeEmitter: (player: Player) => TypedEvent.onAny([player.specOptionsChangeEmitter, player.rotationChangeEmitter, player.talentsChangeEmitter]), }); -export const DiseaseRefreshDuration = InputHelpers.makeRotationNumberInput({ - fieldName: 'diseaseRefreshDuration', - label: 'Disease Refresh Duration', - labelTooltip: 'Minimum duration for refreshing a disease.', -}); - -export const UseDeathAndDecay = InputHelpers.makeRotationBooleanInput({ - fieldName: 'useDeathAndDecay', - label: 'Death and Decay', - labelTooltip: 'Use Death and Decay based rotation.', - showWhen: (player: Player) => (player.getTalents().summonGargoyle && player.getTalents().scourgeStrike && !player.getRotation().autoRotation) || (!player.getTalents().epidemic && !player.getRotation().desyncRotation && player.getTalentTree() == 1 && player.sim.encounter.targets.length >= 3), - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter, player.sim.encounter.targetsChangeEmitter]), -}); - -export const SetDeathAndDecayPrio = InputHelpers.makeRotationEnumInput({ - fieldName: 'deathAndDecayPrio', - label: 'Death and Decay Prio', - labelTooltip: '

Chose how to prioritize death and decay usage:

\ -

Max Rune Downtime: Prioritizes spending runes over holding them for death and decay

\ -

Max Dnd Uptime: Prioritizes dnd uptime and can hold runes for longer then rune grace

', - values: [ - { name: 'Max Rune Downtime', value: DeathAndDecayPrio.MaxRuneDowntime }, - { name: 'Max Dnd Uptime', value: DeathAndDecayPrio.MaxDndUptime }, - ], - showWhen: (player: Player) => player.getTalents().summonGargoyle && (player.getRotation().useDeathAndDecay || !player.getTalents().scourgeStrike) && !player.getRotation().autoRotation, - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), -}) - -export const UseEmpowerRuneWeapon = InputHelpers.makeRotationBooleanInput({ - fieldName: 'useEmpowerRuneWeapon', - label: 'Empower Rune Weapon', - labelTooltip: 'Use Empower Rune Weapon in rotation.', - showWhen: (player: Player) => !player.getRotation().autoRotation && player.getTalentTree() != 0 && player.getRotation().frostRotationType != FrostRotationType.Custom, -}); - -export const UseGargoyle = InputHelpers.makeRotationBooleanInput({ - fieldName: 'useGargoyle', - label: 'Summon Gargoyle', - labelTooltip: 'Use Summon Gargoyle in rotation.', - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), - showWhen: (player: Player) => player.getTalents().summonGargoyle && !player.getRotation().autoRotation, -}); - -export const HoldErwArmy = InputHelpers.makeRotationBooleanInput({ - fieldName: 'holdErwArmy', - label: 'Hold ERW for AotD', - labelTooltip: 'Hold Empower Rune Weapon for after Summon Gargoyle to guarantee maximized snapshot for Army of the Dead.', - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), - showWhen: (player: Player) => !player.getRotation().autoRotation && player.getRotation().useEmpowerRuneWeapon && player.getRotation().armyOfTheDead == ArmyOfTheDead.AsMajorCd && player.getTalentTree() != 0, -}); - -export const BloodlustPresence = InputHelpers.makeRotationEnumInput({ - fieldName: 'blPresence', - label: 'Bloodlust Presence', - labelTooltip: 'Presence during bloodlust.', - values: [ - { name: 'Blood', value: StartingPresence.Blood }, - { name: 'Unholy', value: StartingPresence.Unholy }, - ], - showWhen: (player: Player) => player.getTalents().summonGargoyle && !player.getRotation().autoRotation, - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), -}); - -export const GargoylePresence = InputHelpers.makeRotationEnumInput({ - fieldName: 'gargoylePresence', - label: 'Gargoyle Presence', - labelTooltip: 'Presence during Gargoyle.', - values: [ - { name: 'Blood', value: StartingPresence.Blood }, - { name: 'Unholy', value: StartingPresence.Unholy }, - ], - showWhen: (player: Player) => player.getTalents().summonGargoyle && !player.getRotation().autoRotation && !player.getRotation().preNerfedGargoyle, - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), -}); - -export const BloodTapGhoulFrenzy = InputHelpers.makeRotationBooleanInput({ - fieldName: 'btGhoulFrenzy', - label: 'BT Ghoul Frenzy', - labelTooltip: 'Use Ghoul Frenzy only with Blood Tap.', - showWhen: (player: Player) => player.getTalents().ghoulFrenzy && !player.getRotation().autoRotation, - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), -}); - -export const FirstDiseaseInput = InputHelpers.makeRotationEnumInput({ - fieldName: 'firstDisease', - label: 'First Disease', - labelTooltip: 'Chose which disease to apply first.', - values: [ - { name: 'Frost Fever', value: FirstDisease.FrostFever }, - { name: 'Blood Plague', value: FirstDisease.BloodPlague }, - ], - showWhen: (player: Player) => player.getTalents().summonGargoyle && !player.getRotation().autoRotation, - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), -}) - -export const ArmyOfTheDeadInput = InputHelpers.makeRotationEnumInput({ - fieldName: 'armyOfTheDead', - label: 'Army of the Dead', - labelTooltip: 'Chose how to use Army of the Dead.', - values: [ - { name: 'Do not use', value: ArmyOfTheDead.DoNotUse }, - { name: 'Pre pull', value: ArmyOfTheDead.PreCast }, - { name: 'As Major CD', value: ArmyOfTheDead.AsMajorCd }, - ], - showWhen: (player: Player) => !player.getRotation().autoRotation, - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), -}); - -export const StartingPresenceInput = InputHelpers.makeRotationEnumInput({ - fieldName: 'startingPresence', - label: 'Starting Presence', - labelTooltip: 'Chose the presence you start combat in.', - values: [ - { name: 'Blood', value: StartingPresence.Blood }, - { name: 'Unholy', value: StartingPresence.Unholy }, - ], - showWhen: (player: Player) => player.getTalents().summonGargoyle && !player.getRotation().autoRotation, - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), -}) - -export const FightPresence = InputHelpers.makeRotationEnumInput({ - fieldName: 'presence', - label: 'Fight Presence', - labelTooltip: 'Presence to be in during the encounter.', - values: [ - { name: 'Blood', value: StartingPresence.Blood }, - { name: 'Unholy', value: StartingPresence.Unholy }, - ], - showWhen: (player: Player) => player.getTalents().summonGargoyle && !player.getRotation().autoRotation, - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), -}); - -export const BloodRuneFillerInput = InputHelpers.makeRotationEnumInput({ - fieldName: 'bloodRuneFiller', - label: 'Blood Rune Filler', - labelTooltip: 'Chose what to spend your free blood runes on.', - values: [ - { name: 'Blood Strike', value: BloodRuneFiller.BloodStrike }, - { name: 'Blood Boil', value: BloodRuneFiller.BloodBoil }, - ], - showWhen: (player: Player) => player.getTalents().summonGargoyle && !player.getRotation().autoRotation, - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), -}) - -export const PreNerfedGargoyleInput = InputHelpers.makeRotationBooleanInput({ - fieldName: 'preNerfedGargoyle', - label: 'Pre-Nerfed Gargoyle (haste snapshot)', - labelTooltip: "Use old Gargoyle that snapshots haste", - showWhen: (player: Player) => player.getTalents().summonGargoyle && !player.getRotation().autoRotation && player.sim.getShowExperimental(), - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), -}) - -export const BloodTapInput = InputHelpers.makeRotationEnumInput({ - fieldName: 'bloodTap', - label: 'Blood Tap', - labelTooltip: 'Chose what to spend your Blood Tap on.', - values: [ - { name: 'Ghoul Frenzy', value: BloodTap.GhoulFrenzy }, - { name: 'Icy Touch', value: BloodTap.IcyTouch }, - { name: 'Blood Strike', value: BloodTap.BloodStrikeBT }, - { name: 'Blood Boil', value: BloodTap.BloodBoilBT }, - ], - showWhen: (player: Player) => player.getTalents().summonGargoyle && !player.getRotation().autoRotation, - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), -}) - -export const UseAMSInput = InputHelpers.makeRotationBooleanInput({ - fieldName: 'useAms', - label: 'Use AMS', - labelTooltip: 'Use AMS around predicted damage for a RP gain.', - showWhen: (player: Player) => player.getTalents().howlingBlast && !player.getRotation().autoRotation && player.getRotation().frostRotationType != FrostRotationType.Custom, - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), -}); - -export const AvgAMSSuccessRateInput = InputHelpers.makeRotationNumberInput({ - fieldName: 'avgAmsSuccessRate', - label: 'Avg AMS Success %', - labelTooltip: 'Chance for damage to be taken during the 5 second window of AMS.', - showWhen: (player: Player) => player.getRotation().useAms == true && !player.getRotation().autoRotation && player.getTalents().howlingBlast && player.getRotation().frostRotationType != FrostRotationType.Custom, - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), -}); - -export const AvgAMSHitInput = InputHelpers.makeRotationNumberInput({ - fieldName: 'avgAmsHit', - label: 'Avg AMS Hit', - labelTooltip: 'How much on average (+-10%) the character is hit for when AMS is successful.', - showWhen: (player: Player) => player.getRotation().useAms == true && !player.getRotation().autoRotation && player.getTalents().howlingBlast && player.getRotation().frostRotationType != FrostRotationType.Custom, - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), -}); - -export const UseAutoRotation = InputHelpers.makeRotationBooleanInput({ - fieldName: 'autoRotation', - label: 'Automatic Rotation', - labelTooltip: 'Have sim automatically adjust rotation based on the scenario. This is still in development and currently only works for Unholy.', - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), - showWhen: (player: Player) => !player.getTalents().howlingBlast, -}); - -export const DesyncRotation = InputHelpers.makeRotationBooleanInput({ - fieldName: 'desyncRotation', - label: 'Use Desync Rotation', - labelTooltip: 'Use the Desync Rotation.', - showWhen: (player: Player) => player.getTalents().howlingBlast && !player.getTalents().epidemic && !player.getRotation().autoRotation, - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), -}); - -export const Presence = InputHelpers.makeRotationEnumInput({ - fieldName: 'presence', - label: 'Presence', - labelTooltip: 'Presence to be in during the encounter.', - values: [ - { name: 'Blood', value: StartingPresence.Blood }, - { name: 'Frost', value: StartingPresence.Frost }, - { name: 'Unholy', value: StartingPresence.Unholy }, - ], - showWhen: (player: Player) => player.getTalents().howlingBlast && !player.getRotation().autoRotation, - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), -}); - -export const BloodSpenderInput = InputHelpers.makeRotationEnumInput({ - fieldName: 'bloodSpender', - label: 'Blood Spender', - labelTooltip: 'Chose how to use Blood Runes.', - values: [ - { name: 'Heart Strike', value: BloodSpell.HS }, - { name: 'Blood Boil', value: BloodSpell.BB }, - { name: 'Blood Strike', value: BloodSpell.BS }, - ], - showWhen: (player: Player) => !player.getRotation().autoRotation && player.getTalentTree() == 0, - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), -}); - -export const UseDancingRuneWeapon = InputHelpers.makeRotationBooleanInput({ - fieldName: 'useDancingRuneWeapon', - label: 'Dancing Rune Weapon', - labelTooltip: 'Use Dancing Rune Weapon.', - showWhen: (player: Player) => player.getTalents().dancingRuneWeapon && !player.getRotation().autoRotation, - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), -}); - -export const DrwDiseasesInput = InputHelpers.makeRotationEnumInput({ - fieldName: 'drwDiseases', - label: 'DRW Disease', - labelTooltip: 'Chose how to apply diseases for Dancing Rune Weapon.', - values: [ - { name: 'Do not apply', value: DrwDiseases.DoNotApply }, - { name: 'IT + PS', value: DrwDiseases.Normal }, - { name: 'Pestilence', value: DrwDiseases.Pestilence }, - ], - showWhen: (player: Player) => player.getRotation().useDancingRuneWeapon && !player.getRotation().autoRotation && player.getTalents().dancingRuneWeapon && player.getRotation().bloodOpener == BloodOpener.Standard, - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), -}); - -export const BloodOpenerInput = InputHelpers.makeRotationEnumInput({ - fieldName: 'bloodOpener', - label: 'Opener', - labelTooltip: 'Chose which opener to use.', - values: [ - { name: 'Standard', value: BloodOpener.Standard }, - { name: 'Incan', value: BloodOpener.Experimental_1 }, - ], - showWhen: (player: Player) => !player.getRotation().autoRotation && player.getTalentTree() == 0, - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), -}); - -export const FrostCustomRotation = InputHelpers.makeCustomRotationInput({ - fieldName: 'frostCustomRotation', - numColumns: 4, - values: [ - { actionId: ActionId.fromSpellId(49909), value: CustomSpellOption.CustomIcyTouch }, - { actionId: ActionId.fromSpellId(49921), value: CustomSpellOption.CustomPlagueStrike }, - { actionId: ActionId.fromSpellId(50842), value: CustomSpellOption.CustomPestilence }, - { actionId: ActionId.fromSpellId(51425), value: CustomSpellOption.CustomObliterate }, - { actionId: ActionId.fromSpellId(51411), value: CustomSpellOption.CustomHowlingBlast }, - { actionId: ActionId.fromSpellId(59052), value: CustomSpellOption.CustomHowlingBlastRime }, - { actionId: ActionId.fromSpellId(49941), value: CustomSpellOption.CustomBloodBoil }, - { actionId: ActionId.fromSpellId(49930), value: CustomSpellOption.CustomBloodStrike }, - { actionId: ActionId.fromSpellId(49938), value: CustomSpellOption.CustomDeathAndDecay }, - { actionId: ActionId.fromSpellId(57623), value: CustomSpellOption.CustomHornOfWinter }, - { actionId: ActionId.fromSpellId(51271), value: CustomSpellOption.CustomUnbreakableArmor }, - { actionId: ActionId.fromSpellId(45529), value: CustomSpellOption.CustomBloodTap }, - { actionId: ActionId.fromSpellId(47568), value: CustomSpellOption.CustomEmpoweredRuneWeapon }, - { actionId: ActionId.fromSpellId(55268), value: CustomSpellOption.CustomFrostStrike }, - ], - showWhen: (player: Player) => player.getRotation().frostRotationType == FrostRotationType.Custom, -}); - export const NewDrwInput = InputHelpers.makeSpecOptionsBooleanInput({ fieldName: 'newDrw', label: 'PTR DRW Scaling', - showWhen: (player: Player) => player.getTalents().dancingRuneWeapon && player.getRotation().useDancingRuneWeapon, + showWhen: (player: Player) => player.getTalents().dancingRuneWeapon, changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), }) @@ -381,56 +79,6 @@ export const DiseaseDowntime = InputHelpers.makeSpecOptionsNumberInput) => !player.getRotation().autoRotation && player.getTalentTree() == 2, + showWhen: (player: Player) => player.getTalentTree() == 2, changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), }); - -export const VirulenceRefreshTime = InputHelpers.makeRotationNumberInput({ - fieldName: 'virulenceRefresh', - label: 'Virulence Refresh', - labelTooltip: 'How long to wait after ICD is ready before trying to refresh buff with strike (0-10 seconds range).', - showWhen: (player: Player) => player.sim.getShowExperimental() && !player.getRotation().autoRotation && player.getTalentTree() == 2 && player.getEquippedItem(ItemSlot.ItemSlotRanged)?._item.id == 47673, - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter, player.gearChangeEmitter]), -}); - -export const DeathKnightRotationConfig = { - inputs: [ - InputHelpers.makeRotationEnumInput({ - fieldName: 'frostRotationType', - label: 'Rotation Type', - values: [ - { name: 'Single Target', value: FrostRotationType.SingleTarget }, - { name: 'Custom', value: FrostRotationType.Custom }, - ], - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), - showWhen: (player: Player) => player.getTalents().howlingBlast && !player.getRotation().autoRotation, - }), - Presence, - UseAutoRotation, - BloodTapGhoulFrenzy, - UseGargoyle, - UseEmpowerRuneWeapon, - UseDancingRuneWeapon, - //NewDrwInput, - HoldErwArmy, - BloodTapInput, - BloodSpenderInput, - ArmyOfTheDeadInput, - //BloodOpenerInput, - DrwDiseasesInput, - FirstDiseaseInput, - StartingPresenceInput, - GargoylePresence, - BloodlustPresence, - FightPresence, - BloodRuneFillerInput, - UseDeathAndDecay, - UseAMSInput, - AvgAMSSuccessRateInput, - AvgAMSHitInput, - DesyncRotation, - FrostCustomRotation, - PreNerfedGargoyleInput, - VirulenceRefreshTime, - ], -}; diff --git a/ui/deathknight/presets.ts b/ui/deathknight/presets.ts index f29f1149a8..d73bd8b94d 100644 --- a/ui/deathknight/presets.ts +++ b/ui/deathknight/presets.ts @@ -1,7 +1,5 @@ import { Consumes, - CustomRotation, - CustomSpell, Explosive, Flask, Food, @@ -9,22 +7,13 @@ import { PetFood, Potions, UnitReference, - Spec } from '../core/proto/common.js'; import { SavedTalents } from '../core/proto/ui.js'; import { Deathknight_Options as DeathKnightOptions, - Deathknight_Rotation as DeathKnightRotation, - Deathknight_Rotation_ArmyOfTheDead, - Deathknight_Rotation_BloodRuneFiller, - Deathknight_Rotation_CustomSpellOption as CustomSpellOption, - Deathknight_Rotation_FrostRotationType, - Deathknight_Rotation_Presence, DeathknightMajorGlyph, DeathknightMinorGlyph, - Deathknight_Rotation_DrwDiseases, - Deathknight_Rotation_BloodSpell, } from '../core/proto/deathknight.js'; import * as PresetUtils from '../core/preset_utils.js'; @@ -70,74 +59,6 @@ export const P3_UNHOLY_DW_PRESET = PresetUtils.makePresetGear('P3 DW Unholy', P3 import P4UhDwGear from './gear_sets/p4_uh_dw.gear.json'; export const P4_UNHOLY_DW_PRESET = PresetUtils.makePresetGear('P4 DW Unholy', P4UhDwGear, { talentTree: 2 }); -export const DefaultUnholyRotation = DeathKnightRotation.create({ - useDeathAndDecay: true, - btGhoulFrenzy: true, - refreshHornOfWinter: false, - useGargoyle: true, - useEmpowerRuneWeapon: true, - holdErwArmy: false, - preNerfedGargoyle: false, - armyOfTheDead: Deathknight_Rotation_ArmyOfTheDead.AsMajorCd, - startingPresence: Deathknight_Rotation_Presence.Unholy, - blPresence: Deathknight_Rotation_Presence.Blood, - presence: Deathknight_Rotation_Presence.Blood, - gargoylePresence: Deathknight_Rotation_Presence.Unholy, - bloodRuneFiller: Deathknight_Rotation_BloodRuneFiller.BloodBoil, - useAms: false, - drwDiseases: Deathknight_Rotation_DrwDiseases.Pestilence, - bloodSpender: Deathknight_Rotation_BloodSpell.HS, - useDancingRuneWeapon: true -}); - -export const DefaultFrostRotation = DeathKnightRotation.create({ - useDeathAndDecay: false, - btGhoulFrenzy: false, - refreshHornOfWinter: false, - useEmpowerRuneWeapon: true, - preNerfedGargoyle: false, - startingPresence: Deathknight_Rotation_Presence.Blood, - presence: Deathknight_Rotation_Presence.Blood, - bloodRuneFiller: Deathknight_Rotation_BloodRuneFiller.BloodBoil, - useAms: false, - avgAmsSuccessRate: 1.0, - avgAmsHit: 10000.0, - drwDiseases: Deathknight_Rotation_DrwDiseases.Pestilence, - frostRotationType: Deathknight_Rotation_FrostRotationType.SingleTarget, - armyOfTheDead: Deathknight_Rotation_ArmyOfTheDead.PreCast, - frostCustomRotation: CustomRotation.create({ - spells: [ - CustomSpell.create({ spell: CustomSpellOption.CustomDeathAndDecay }), - CustomSpell.create({ spell: CustomSpellOption.CustomIcyTouch }), - CustomSpell.create({ spell: CustomSpellOption.CustomPlagueStrike }), - CustomSpell.create({ spell: CustomSpellOption.CustomPestilence }), - CustomSpell.create({ spell: CustomSpellOption.CustomHowlingBlastRime }), - CustomSpell.create({ spell: CustomSpellOption.CustomHowlingBlast }), - CustomSpell.create({ spell: CustomSpellOption.CustomBloodBoil }), - CustomSpell.create({ spell: CustomSpellOption.CustomObliterate }), - CustomSpell.create({ spell: CustomSpellOption.CustomFrostStrike }), - ], - }), -}); - -export const DefaultBloodRotation = DeathKnightRotation.create({ - refreshHornOfWinter: false, - useEmpowerRuneWeapon: true, - preNerfedGargoyle: false, - startingPresence: Deathknight_Rotation_Presence.Blood, - bloodRuneFiller: Deathknight_Rotation_BloodRuneFiller.BloodStrike, - armyOfTheDead: Deathknight_Rotation_ArmyOfTheDead.PreCast, - holdErwArmy: false, - useAms: false, - drwDiseases: Deathknight_Rotation_DrwDiseases.Pestilence, - bloodSpender: Deathknight_Rotation_BloodSpell.HS, - useDancingRuneWeapon: true, -}); - -export const BLOOD_ROTATION_PRESET_LEGACY_DEFAULT = PresetUtils.makePresetLegacyRotation('Blood Legacy', Spec.SpecDeathknight, DefaultBloodRotation, { talentTree: 0 }); -export const FROST_ROTATION_PRESET_LEGACY_DEFAULT = PresetUtils.makePresetLegacyRotation('Frost Legacy', Spec.SpecDeathknight, DefaultFrostRotation, { talentTree: 1 }); -export const UNHOLY_DW_ROTATION_PRESET_LEGACY_DEFAULT = PresetUtils.makePresetLegacyRotation('Unholy DW Legacy', Spec.SpecDeathknight, DefaultUnholyRotation, { talentTree: 2 }); - import BloodDPSApl from './apls/blood_dps.apl.json'; export const BLOOD_DPS_ROTATION_PRESET_DEFAULT = PresetUtils.makePresetAPLRotation('Blood DPS', BloodDPSApl, { talentTree: 0 }); import BloodPestiAoeApl from './apls/blood_pesti_aoe.apl.json'; diff --git a/ui/deathknight/sim.ts b/ui/deathknight/sim.ts index 0aebcc9f37..afd9a0f956 100644 --- a/ui/deathknight/sim.ts +++ b/ui/deathknight/sim.ts @@ -90,8 +90,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecDeathknight, { }), // Default consumes settings. consumes: Presets.DefaultConsumes, - // Default rotation settings. - rotation: Presets.DefaultUnholyRotation, // Default talents. talents: Presets.UnholyDualWieldTalents.data, // Default spec-specific settings. @@ -168,8 +166,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecDeathknight, { // IconInputs to include in the 'Player' section on the settings tab. playerIconInputs: [ ], - // Inputs to include in the 'Rotation' section on the settings tab. - rotationInputs: DeathKnightInputs.DeathKnightRotationConfig, petConsumeInputs: [ IconInputs.SpicedMammothTreats, ], @@ -218,9 +214,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecDeathknight, { ], // Preset rotations that the user can quickly select. rotations: [ - Presets.BLOOD_ROTATION_PRESET_LEGACY_DEFAULT, - Presets.FROST_ROTATION_PRESET_LEGACY_DEFAULT, - Presets.UNHOLY_DW_ROTATION_PRESET_LEGACY_DEFAULT, Presets.BLOOD_DPS_ROTATION_PRESET_DEFAULT, Presets.BLOOD_PESTI_AOE_ROTATION_PRESET_DEFAULT, Presets.FROST_BL_PESTI_ROTATION_PRESET_DEFAULT, diff --git a/ui/elemental_shaman/inputs.ts b/ui/elemental_shaman/inputs.ts index d3963843fd..4fe31b5180 100644 --- a/ui/elemental_shaman/inputs.ts +++ b/ui/elemental_shaman/inputs.ts @@ -1,13 +1,10 @@ -import { IconPickerConfig } from '../core/components/icon_picker.js'; -import { ElementalShaman_Options_ThunderstormRange, ElementalShaman_Rotation_BloodlustUse, ElementalShaman_Rotation_RotationType as RotationType, ShamanShield, ShamanTotems } from '../core/proto/shaman.js'; -import { ElementalShaman_Options as ShamanOptions } from '../core/proto/shaman.js'; -import { AirTotem } from '../core/proto/shaman.js'; +import { ElementalShaman_Options_ThunderstormRange, ShamanShield } from '../core/proto/shaman.js'; import { Spec } from '../core/proto/common.js'; import { ActionId } from '../core/proto_utils/action_id.js'; import { Player } from '../core/player.js'; import * as InputHelpers from '../core/components/input_helpers.js'; -import { EventID, TypedEvent } from 'ui/core/typed_event.js'; +import { EventID } from 'ui/core/typed_event.js'; // Configuration for spec-specific UI elements on the settings tab. // These don't need to be in a separate file but it keeps things cleaner. @@ -37,91 +34,3 @@ export const ShamanShieldInput = InputHelpers.makeSpecOptionsEnumIconInput({ - fieldName: 'type', - label: 'Type', - values: [ - { - name: 'Adaptive', value: RotationType.Adaptive, - tooltip: 'Dynamically adapts based on available mana to maximize CL casts without going OOM.', - }, - { - name: 'Manual', value: RotationType.Manual, - tooltip: 'Allows custom selection of which spells to use and to modify cast conditions.', - }, - ], - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'bloodlust', - label: 'Use Bloodlust', - labelTooltip: 'Player will cast bloodlust', - getValue: (player: Player) => player.getRotation().bloodlust == ElementalShaman_Rotation_BloodlustUse.UseBloodlust, - setValue: (eventID: EventID, player: Player, newValue: boolean) => { - const newRotation = player.getRotation(); - if (newValue) { - newRotation.bloodlust = ElementalShaman_Rotation_BloodlustUse.UseBloodlust; - } else { - newRotation.bloodlust = ElementalShaman_Rotation_BloodlustUse.NoBloodlust; - } - player.setRotation(eventID, newRotation); - }, - }), - InputHelpers.makeRotationNumberInput({ - fieldName: 'lvbFsWaitMs', - label: 'Max wait for LvB/FS (ms)', - labelTooltip: 'Amount of time the sim will wait if FS is about to fall off or LvB CD is about to come up. Setting to 0 will default to 175ms', - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'useChainLightning', - label: 'Use Chain Lightning in Rotation', - labelTooltip: 'Use Chain Lightning in rotation', - enableWhen: (player: Player) => player.getRotation().type == RotationType.Manual, - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'useClOnlyGap', - label: 'Use CL only as gap filler', - labelTooltip: 'Use CL to fill short gaps in LvB CD instead of on CD.', - enableWhen: (player: Player) => player.getRotation().type == RotationType.Manual && player.getRotation().useChainLightning, - }), - InputHelpers.makeRotationNumberInput({ - fieldName: 'clMinManaPer', - label: 'Min mana percent to use Chain Lightning', - labelTooltip: 'Customize minimum mana level to cast Chain Lightning. 0 will spam until OOM.', - enableWhen: (player: Player) => player.getRotation().type == RotationType.Manual && player.getRotation().useChainLightning, - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'useFireNova', - label: 'Use Fire Nova in Rotation', - labelTooltip: 'Fire Nova will hit all targets when cast.', - enableWhen: (player: Player) => player.getRotation().type == RotationType.Manual, - }), - InputHelpers.makeRotationNumberInput({ - fieldName: 'fnMinManaPer', - label: 'Min mana percent to use FireNova', - labelTooltip: 'Customize minimum mana level to cast Fire Nova. 0 will spam until OOM.', - enableWhen: (player: Player) => player.getRotation().type == RotationType.Manual && player.getRotation().useFireNova, - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'overwriteFlameshock', - label: 'Allow Flameshock to be overwritten', - labelTooltip: 'Will use flameshock at the end of the duration even if its still ticking if there isn\'t enough time to cast lavaburst before expiring.', - enableWhen: (player: Player) => player.getRotation().type == RotationType.Manual, - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'alwaysCritLvb', - label: 'Only cast Lavaburst with FS', - labelTooltip: 'Will only cast Lavaburst if Flameshock will be active when the cast finishes.', - enableWhen: (player: Player) => player.getRotation().type == RotationType.Manual, - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'useThunderstorm', - label: 'Allow Thunderstorm to be cast.', - labelTooltip: 'Disabling this will stop thunderstorm from being cast entirely.', - enableWhen: (player: Player) => player.getRotation().type == RotationType.Manual, - showWhen: (player: Player) => player.getTalents().thunderstorm, - }), - ], -}; diff --git a/ui/elemental_shaman/presets.ts b/ui/elemental_shaman/presets.ts index fba358df48..d41b815709 100644 --- a/ui/elemental_shaman/presets.ts +++ b/ui/elemental_shaman/presets.ts @@ -6,13 +6,10 @@ import { Glyphs, Potions, Profession, - Spec, } from '../core/proto/common.js'; import { SavedTalents } from '../core/proto/ui.js'; import { - ElementalShaman_Rotation_RotationType as RotationType, - ElementalShaman_Rotation as ElementalShamanRotation, ElementalShaman_Options as ElementalShamanOptions, ShamanShield, ShamanMajorGlyph, @@ -43,23 +40,6 @@ export const P3_PRESET_HORDE = PresetUtils.makePresetGear('P3 Preset [H]', P3Hor import P4Gear from './gear_sets/p4.gear.json'; export const P4_PRESET = PresetUtils.makePresetGear('P4 Preset', P4Gear); -export const DefaultRotation = ElementalShamanRotation.create({ - totems: ShamanTotems.create({ - earth: EarthTotem.StrengthOfEarthTotem, - air: AirTotem.WrathOfAirTotem, - fire: FireTotem.TotemOfWrath, - water: WaterTotem.ManaSpringTotem, - useFireElemental: true, - }), - type: RotationType.Adaptive, - fnMinManaPer: 66, - clMinManaPer: 33, - useChainLightning: false, - useFireNova: false, - useThunderstorm: true, -}); - -export const ROTATION_PRESET_LEGACY = PresetUtils.makePresetLegacyRotation('Legacy', Spec.SpecElementalShaman, DefaultRotation); import DefaultApl from './apls/default.apl.json'; export const ROTATION_PRESET_DEFAULT = PresetUtils.makePresetAPLRotation('Default', DefaultApl); import AdvancedApl from './apls/advanced.apl.json'; diff --git a/ui/elemental_shaman/sim.ts b/ui/elemental_shaman/sim.ts index 5162287ceb..6bbaf3bef6 100644 --- a/ui/elemental_shaman/sim.ts +++ b/ui/elemental_shaman/sim.ts @@ -95,8 +95,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecElementalShaman, { }), // Default consumes settings. consumes: Presets.DefaultConsumes, - // Default rotation settings. - rotation: Presets.DefaultRotation, // Default talents. talents: Presets.StandardTalents.data, // Default spec-specific settings. @@ -132,8 +130,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecElementalShaman, { playerIconInputs: [ ShamanInputs.ShamanShieldInput, ], - // Inputs to include in the 'Rotation' section on the settings tab. - rotationInputs: ShamanInputs.ElementalShamanRotationConfig, // Buff and Debuff inputs to include/exclude, overriding the EP-based defaults. includeBuffDebuffInputs: [ ], @@ -162,7 +158,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecElementalShaman, { ], // Preset rotations that the user can quickly select. rotations: [ - Presets.ROTATION_PRESET_LEGACY, Presets.ROTATION_PRESET_DEFAULT, Presets.ROTATION_PRESET_ADVANCED, ], diff --git a/ui/enhancement_shaman/inputs.ts b/ui/enhancement_shaman/inputs.ts index 63b07fa739..891084ebbf 100644 --- a/ui/enhancement_shaman/inputs.ts +++ b/ui/enhancement_shaman/inputs.ts @@ -1,25 +1,12 @@ import { - AirTotem, - EarthTotem, - FireTotem, - WaterTotem, - EnhancementShaman_Options as ShamanOptions, - ShamanTotems, ShamanShield, ShamanImbue, ShamanSyncType, - EnhancementShaman_Rotation_PrimaryShock as PrimaryShock, - EnhancementShaman_Rotation_RotationType as RotationType, - EnhancementShaman_Rotation_CustomRotationSpell as CustomRotationSpell, - EnhancementShaman_Rotation, - EnhancementShaman_Rotation_BloodlustUse } from '../core/proto/shaman.js'; import { Spec } from '../core/proto/common.js'; import { ActionId } from '../core/proto_utils/action_id.js'; -import { Player } from '../core/player.js'; import * as InputHelpers from '../core/components/input_helpers.js'; -import { EventID } from 'ui/core/typed_event.js'; // Configuration for spec-specific UI elements on the settings tab. // These don't need to be in a separate file but it keeps things cleaner. @@ -73,205 +60,3 @@ export const SyncTypeInput = InputHelpers.makeSpecOptionsEnumInput({ - fieldName: 'rotationType', - label: 'Type', - labelTooltip: - `
    -
  • -
    Standard: Priority Rotation
    -
  • -
  • -
    Custom: Highest spell that is ready will be cast.
    -
  • -
`, - values: [ - { name: 'Standard', value: RotationType.Priority }, - { name: 'Custom', value: RotationType.Custom }, - ], - }), - InputHelpers.makeCustomRotationInput({ - fieldName: 'customRotation', - numColumns: 2, - values: [ - { actionId: ActionId.fromSpellId(49238), value: CustomRotationSpell.LightningBolt }, - { actionId: ActionId.fromSpellId(49238), value: CustomRotationSpell.LightningBoltWeave, text: "Weave" }, - { actionId: ActionId.fromSpellId(49238), value: CustomRotationSpell.LightningBoltDelayedWeave, text: "Delay" }, - { actionId: ActionId.fromSpellId(49271), value: CustomRotationSpell.ChainLightning }, - { actionId: ActionId.fromSpellId(17364), value: CustomRotationSpell.StormstrikeDebuffMissing, text: "Debuff" }, - { actionId: ActionId.fromSpellId(17364), value: CustomRotationSpell.Stormstrike }, - { actionId: ActionId.fromSpellId(49233), value: CustomRotationSpell.FlameShock }, - { actionId: ActionId.fromSpellId(49231), value: CustomRotationSpell.EarthShock }, - { actionId: ActionId.fromSpellId(58734), value: CustomRotationSpell.MagmaTotem }, - { actionId: ActionId.fromSpellId(61657), value: CustomRotationSpell.FireNova }, - { actionId: ActionId.fromSpellId(60103), value: CustomRotationSpell.LavaLash }, - { actionId: ActionId.fromSpellId(49281), value: CustomRotationSpell.LightningShield }, - { actionId: ActionId.fromSpellId(60043), value: CustomRotationSpell.LavaBurst, text: "Weave" }, - { actionId: ActionId.fromSpellId(49236), value: CustomRotationSpell.FrostShock }, - ], - showWhen: (player: Player) => player.getRotation().rotationType == RotationType.Custom, - }), - InputHelpers.makeRotationEnumInput({ - fieldName: 'primaryShock', - label: 'Primary Shock', - values: [ - { name: 'None', value: PrimaryShock.None }, - { name: 'Earth Shock', value: PrimaryShock.Earth }, - { name: 'Frost Shock', value: PrimaryShock.Frost }, - ], - showWhen: (player: Player) => player.getRotation().rotationType != RotationType.Custom - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'weaveFlameShock', - label: 'Weave Flame Shock', - labelTooltip: 'Use Flame Shock whenever the target does not already have the DoT.', - showWhen: (player: Player) => player.getRotation().rotationType != RotationType.Custom - }), - InputHelpers.makeRotationNumberInput({ - fieldName: 'flameShockClipTicks', - label: 'Refresh Flame Shock at ticks remaining', - labelTooltip: 'Set to 0 to require the debuff be missing. A tick is 3s, affected by spell haste', - enableWhen: (player: Player) => player.getRotation().weaveFlameShock, - showWhen: (player: Player) => { - if (player.getRotation().rotationType == RotationType.Custom) { - return player.getRotation().customRotation?.spells.find(customSpell => customSpell.spell == CustomRotationSpell.FlameShock) != undefined - } - - return player.getRotation().weaveFlameShock - } - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'lightningboltWeave', - label: 'Enable Weaving Lightning Bolt', - labelTooltip: 'Will provide a DPS increase, but is harder to execute', - enableWhen: (player: Player) => player.getTalents().maelstromWeapon > 0, - showWhen: (player: Player) => player.getRotation().rotationType != RotationType.Custom - }), - InputHelpers.makeRotationEnumInput({ - fieldName: 'maelstromweaponMinStack', - label: 'Minimum Maelstrom Stacks to Weave', - labelTooltip: '3 stacks is the most realistic, however there are cases where lower might be possible, just much harder to do in practice', - values: [ - { name: '1', value: 1 }, - { name: '2', value: 2 }, - { name: '3', value: 3 }, - { name: '4', value: 4 }, - ], - enableWhen: (player: Player) => { - if (player.getRotation().rotationType == RotationType.Custom) { - return player.getRotation().customRotation?.spells.find(customSpell => customSpell.spell == CustomRotationSpell.LightningBoltWeave) != undefined - } - - return player.getRotation().lightningboltWeave - }, - showWhen: (player: Player) => { - if (player.getRotation().rotationType == RotationType.Custom) { - return player.getRotation().customRotation?.spells.find(customSpell => customSpell.spell == CustomRotationSpell.LightningBoltWeave) != undefined - } - - return true - } - }), - InputHelpers.makeRotationNumberInput({ - fieldName: 'autoWeaveDelay', - label: 'Weaving Delay After Auto Attack', - labelTooltip: 'The amount of time to wait after an auto attack before weaveing, in milliseconds', - enableWhen: (player: Player) => { - if (player.getRotation().rotationType == RotationType.Custom) { - return player.getRotation().customRotation?.spells.find(customSpell => customSpell.spell == CustomRotationSpell.LightningBoltWeave) != undefined - } - - return player.getRotation().lightningboltWeave - }, - showWhen: (player: Player) => { - if (player.getRotation().rotationType == RotationType.Custom) { - return player.getRotation().customRotation?.spells.find(customSpell => customSpell.spell == CustomRotationSpell.LightningBoltWeave) != undefined - } - - return true - }, - }), InputHelpers.makeRotationNumberInput({ - fieldName: 'delayGcdWeave', - label: 'Delay LL to Weave', - labelTooltip: 'The amount of time to hold Lava Lash to weave in milliseconds. Setting to 0 will disable delaying', - enableWhen: (player: Player) => { - if (player.getRotation().rotationType == RotationType.Custom) { - return false - } - - return player.getRotation().lightningboltWeave - }, - showWhen: (player: Player) => { - if (player.getRotation().rotationType == RotationType.Custom) { - return false - } - - return true - }, - }), - InputHelpers.makeRotationNumberInput({ - fieldName: 'delayGcdWeave', - label: 'Delay Weave Time', - labelTooltip: 'The amount of time to hold a GCD to weave in milliseconds. Setting to 0 will disable delaying', - enableWhen: (player: Player) => { - if (player.getRotation().rotationType == RotationType.Custom) { - return player.getRotation().customRotation?.spells.find(customSpell => customSpell.spell == CustomRotationSpell.LightningBoltDelayedWeave) != undefined - } - - return false - }, - showWhen: (player: Player) => { - if (player.getRotation().rotationType == RotationType.Custom) { - return player.getRotation().customRotation?.spells.find(customSpell => customSpell.spell == CustomRotationSpell.LightningBoltDelayedWeave) != undefined - } - - return false - }, - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'lavaburstWeave', - label: 'Enable Weaving Lava Burst', - labelTooltip: 'Not particularily useful for dual wield, mostly a 2h option', - enableWhen: (player: Player) => player.getRotation().lightningboltWeave, - showWhen: (player: Player) => player.getRotation().rotationType != RotationType.Custom - }), - InputHelpers.makeRotationNumberInput({ - fieldName: 'firenovaManaThreshold', - label: 'Minimum mana to cast Fire Nova', - labelTooltip: 'Fire Nova will not be cast when mana is below this value. Set this medium-low, it has a bad mana-to-damage ratio', - showWhen: (player: Player) => { - if (player.getRotation().rotationType == RotationType.Custom) { - return player.getRotation().customRotation?.spells.find(customSpell => customSpell.spell == CustomRotationSpell.FireNova) != undefined - } - - return true - }, - }), - InputHelpers.makeRotationNumberInput({ - fieldName: 'shamanisticRageManaThreshold', - label: 'Mana % to use Shamanistic Rage', - enableWhen: (player: Player) => player.getTalents().shamanisticRage, - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'bloodlust', - label: 'Use Bloodlust', - labelTooltip: 'Player will cast bloodlust', - getValue: (player: Player) => player.getRotation().bloodlust == EnhancementShaman_Rotation_BloodlustUse.UseBloodlust, - setValue: (eventID: EventID, player: Player, newValue: boolean) => { - const newRotation = player.getRotation(); - if (newValue) { - newRotation.bloodlust = EnhancementShaman_Rotation_BloodlustUse.UseBloodlust; - } else { - newRotation.bloodlust = EnhancementShaman_Rotation_BloodlustUse.NoBloodlust; - } - player.setRotation(eventID, newRotation); - }, - }), - ], -}; - - diff --git a/ui/enhancement_shaman/presets.ts b/ui/enhancement_shaman/presets.ts index 43421f6e1b..1d4174bec1 100644 --- a/ui/enhancement_shaman/presets.ts +++ b/ui/enhancement_shaman/presets.ts @@ -7,13 +7,10 @@ import { RaidBuffs, TristateEffect, Debuffs, - CustomRotation, - CustomSpell, Faction, } from '../core/proto/common.js'; import { SavedTalents } from '../core/proto/ui.js'; -import { EnhancementShaman_Rotation as EnhancementShamanRotation, EnhancementShaman_Options as EnhancementShamanOptions, ShamanShield } from '../core/proto/shaman.js'; import { AirTotem, EarthTotem, @@ -21,11 +18,10 @@ import { WaterTotem, ShamanTotems, ShamanImbue, + ShamanShield, ShamanSyncType, ShamanMajorGlyph, - EnhancementShaman_Rotation_PrimaryShock as PrimaryShock, - EnhancementShaman_Rotation_RotationType as RotationType, - EnhancementShaman_Rotation_CustomRotationSpell as CustomRotationSpell + EnhancementShaman_Options as EnhancementShamanOptions, } from '../core/proto/shaman.js'; import * as PresetUtils from '../core/preset_utils.js'; @@ -51,42 +47,6 @@ export const P4_PRESET_FT = PresetUtils.makePresetGear('P4 Preset FT', P4FtGear) import P4WfGear from './gear_sets/p4_wf.gear.json'; export const P4_PRESET_WF = PresetUtils.makePresetGear('P4 Preset WF', P4WfGear); -export const DefaultRotation = EnhancementShamanRotation.create({ - totems: ShamanTotems.create({ - earth: EarthTotem.StrengthOfEarthTotem, - air: AirTotem.WindfuryTotem, - fire: FireTotem.MagmaTotem, - water: WaterTotem.ManaSpringTotem, - useFireElemental: true, - }), - maelstromweaponMinStack: 3, - lightningboltWeave: true, - autoWeaveDelay: 500, - delayGcdWeave: 750, - lavaburstWeave: false, - firenovaManaThreshold: 3000, - shamanisticRageManaThreshold: 25, - primaryShock: PrimaryShock.Earth, - weaveFlameShock: true, - rotationType: RotationType.Priority, - customRotation: CustomRotation.create({ - spells: [ - CustomSpell.create({ spell: CustomRotationSpell.LightningBolt }), - CustomSpell.create({ spell: CustomRotationSpell.StormstrikeDebuffMissing }), - CustomSpell.create({ spell: CustomRotationSpell.LightningBoltWeave }), - CustomSpell.create({ spell: CustomRotationSpell.Stormstrike }), - CustomSpell.create({ spell: CustomRotationSpell.FlameShock }), - CustomSpell.create({ spell: CustomRotationSpell.EarthShock }), - CustomSpell.create({ spell: CustomRotationSpell.MagmaTotem }), - CustomSpell.create({ spell: CustomRotationSpell.LightningShield }), - CustomSpell.create({ spell: CustomRotationSpell.FireNova }), - CustomSpell.create({ spell: CustomRotationSpell.LightningBoltDelayedWeave }), - CustomSpell.create({ spell: CustomRotationSpell.LavaLash }), - ], - }), -}); - - import DefaultFt from './apls/default_ft.apl.json'; export const ROTATION_FT_DEFAULT = PresetUtils.makePresetAPLRotation('Default FT', DefaultFt); import DefaultWf from './apls/default_wf.apl.json'; diff --git a/ui/enhancement_shaman/sim.ts b/ui/enhancement_shaman/sim.ts index 92e3cd8466..f0451ec3bc 100644 --- a/ui/enhancement_shaman/sim.ts +++ b/ui/enhancement_shaman/sim.ts @@ -98,8 +98,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecEnhancementShaman, { }), // Default consumes settings. consumes: Presets.DefaultConsumes, - // Default rotation settings. - rotation: Presets.DefaultRotation, // Default talents. talents: Presets.StandardTalents.data, // Default spec-specific settings. @@ -123,8 +121,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecEnhancementShaman, { ShamanInputs.ShamanImbueMH, ShamanInputs.ShamanImbueOH, ], - // Inputs to include in the 'Rotation' section on the settings tab. - rotationInputs: ShamanInputs.EnhancementShamanRotationConfig, // Buff and Debuff inputs to include/exclude, overriding the EP-based defaults. includeBuffDebuffInputs: [ IconInputs.ReplenishmentBuff, diff --git a/ui/feral_druid/inputs.ts b/ui/feral_druid/inputs.ts index 9f2c94e515..03e89d8fa6 100644 --- a/ui/feral_druid/inputs.ts +++ b/ui/feral_druid/inputs.ts @@ -7,13 +7,8 @@ import { EventID, TypedEvent } from '../core/typed_event.js'; import * as InputHelpers from '../core/components/input_helpers.js'; import { - FeralDruid, - FeralDruid_Rotation as DruidRotation, FeralDruid_Rotation_AplType as AplType, - FeralDruid_Rotation_BearweaveType as BearweaveType, FeralDruid_Rotation_BiteModeType as BiteModeType, - FeralDruid_Options as DruidOptions, - FeralDruid_Rotation_BiteModeType } from '../core/proto/druid.js'; // Configuration for spec-specific UI elements on the settings tab. diff --git a/ui/feral_druid/sim.ts b/ui/feral_druid/sim.ts index 8d0b45bc50..b6643b34a0 100644 --- a/ui/feral_druid/sim.ts +++ b/ui/feral_druid/sim.ts @@ -93,8 +93,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecFeralDruid, { }), // Default consumes settings. consumes: Presets.DefaultConsumes, - // Default rotation settings. - rotation: Presets.DefaultRotation, // Default talents. talents: Presets.StandardTalents.data, // Default spec-specific settings. diff --git a/ui/feral_tank_druid/inputs.ts b/ui/feral_tank_druid/inputs.ts index 86a3bd3869..02ab793660 100644 --- a/ui/feral_tank_druid/inputs.ts +++ b/ui/feral_tank_druid/inputs.ts @@ -2,12 +2,6 @@ import { Spec } from '../core/proto/common.js'; import * as InputHelpers from '../core/components/input_helpers.js'; -import { - FeralTankDruid, - FeralTankDruid_Rotation as DruidRotation, - FeralTankDruid_Options as DruidOptions -} from '../core/proto/druid.js'; - // Configuration for spec-specific UI elements on the settings tab. // These don't need to be in a separate file but it keeps things cleaner. diff --git a/ui/feral_tank_druid/sim.ts b/ui/feral_tank_druid/sim.ts index a42a25c005..8197bfee6d 100644 --- a/ui/feral_tank_druid/sim.ts +++ b/ui/feral_tank_druid/sim.ts @@ -112,8 +112,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecFeralTankDruid, { }), // Default consumes settings. consumes: Presets.DefaultConsumes, - // Default rotation settings. - rotation: Presets.DefaultSimpleRotation, // Default talents. talents: Presets.StandardTalents.data, // Default spec-specific settings. @@ -280,6 +278,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecFeralTankDruid, { export class FeralTankDruidSimUI extends IndividualSimUI { constructor(parentElem: HTMLElement, player: Player) { super(parentElem, player, SPEC_CONFIG); - const gemOptimizer = new TankGemOptimizer(this); + const _gemOptimizer = new TankGemOptimizer(this); } } diff --git a/ui/healing_priest/inputs.ts b/ui/healing_priest/inputs.ts index 4632ca8ad7..2288765e74 100644 --- a/ui/healing_priest/inputs.ts +++ b/ui/healing_priest/inputs.ts @@ -4,13 +4,6 @@ import { ActionId } from '../core/proto_utils/action_id.js'; import { Player } from '../core/player.js'; import { EventID, TypedEvent } from '../core/typed_event.js'; -import { - HealingPriest, - HealingPriest_Rotation as PriestRotation, - HealingPriest_Rotation_RotationType as RotationType, - HealingPriest_Rotation_SpellOption as SpellOption, -} from '../core/proto/priest.js'; - import * as InputHelpers from '../core/components/input_helpers.js'; // Configuration for spec-specific UI elements on the settings tab. @@ -50,33 +43,3 @@ export const RapturesPerMinute = InputHelpers.makeSpecOptionsNumberInput) => player.getTalents().rapture > 0, changeEmitter: (player: Player) => TypedEvent.onAny([player.specOptionsChangeEmitter, player.talentsChangeEmitter]), }); - -export const HealingPriestRotationConfig = { - inputs: [ - InputHelpers.makeRotationEnumInput({ - fieldName: 'type', - label: 'Type', - values: [ - { name: 'Cycle', value: RotationType.Cycle }, - { name: 'Custom', value: RotationType.Custom }, - ], - }), - InputHelpers.makeCustomRotationInput({ - fieldName: 'customRotation', - numColumns: 2, - showCastsPerMinute: true, - values: [ - { actionId: ActionId.fromSpellId(48063), value: SpellOption.GreaterHeal }, - { actionId: ActionId.fromSpellId(48071), value: SpellOption.FlashHeal }, - { actionId: ActionId.fromSpellId(48068), value: SpellOption.Renew }, - { actionId: ActionId.fromSpellId(48066), value: SpellOption.PowerWordShield }, - { actionId: ActionId.fromSpellId(48089), value: SpellOption.CircleOfHealing }, - { actionId: ActionId.fromSpellId(48072), value: SpellOption.PrayerOfHealing }, - { actionId: ActionId.fromSpellId(48113), value: SpellOption.PrayerOfMending }, - { actionId: ActionId.fromSpellId(53007), value: SpellOption.Penance }, - { actionId: ActionId.fromSpellId(48120), value: SpellOption.BindingHeal }, - ], - showWhen: (player: Player) => player.getRotation().type == RotationType.Custom, - }), - ], -}; diff --git a/ui/healing_priest/presets.ts b/ui/healing_priest/presets.ts index 14e144e116..8bb3ab74bc 100644 --- a/ui/healing_priest/presets.ts +++ b/ui/healing_priest/presets.ts @@ -1,7 +1,5 @@ import { Consumes, - CustomRotation, - CustomSpell, Debuffs, IndividualBuffs, Flask, @@ -15,9 +13,6 @@ import { import { SavedTalents } from '../core/proto/ui.js'; import { - HealingPriest_Rotation as Rotation, - HealingPriest_Rotation_RotationType as RotationType, - HealingPriest_Rotation_SpellOption as SpellOption, HealingPriest_Options as Options, PriestMajorGlyph as MajorGlyph, PriestMinorGlyph as MinorGlyph, @@ -50,30 +45,6 @@ import P4HolyGear from './gear_sets/p4_holy.gear.json'; export const DISC_P4_PRESET = PresetUtils.makePresetGear('Disc P4 Preset', P4DiscGear, { talentTree: 0 }); export const HOLY_P4_PRESET = PresetUtils.makePresetGear('Holy P4 Preset', P4HolyGear, { talentTree: 1 }); -export const DiscDefaultRotation = Rotation.create({ - type: RotationType.Cycle, - customRotation: CustomRotation.create({ - spells: [ - CustomSpell.create({ spell: SpellOption.PowerWordShield, castsPerMinute: 18 }), - CustomSpell.create({ spell: SpellOption.Penance, castsPerMinute: 4 }), - CustomSpell.create({ spell: SpellOption.PrayerOfMending, castsPerMinute: 2 }), - CustomSpell.create({ spell: SpellOption.GreaterHeal, castsPerMinute: 1 }), - ], - }), -}); - -export const HolyDefaultRotation = Rotation.create({ - type: RotationType.Cycle, - customRotation: CustomRotation.create({ - spells: [ - CustomSpell.create({ spell: SpellOption.GreaterHeal, castsPerMinute: 10 }), - CustomSpell.create({ spell: SpellOption.CircleOfHealing, castsPerMinute: 5 }), - CustomSpell.create({ spell: SpellOption.Renew, castsPerMinute: 10 }), - CustomSpell.create({ spell: SpellOption.PrayerOfMending, castsPerMinute: 2 }), - ], - }), -}); - import DiscApl from './apls/disc.apl.json'; export const ROTATION_PRESET_DISC = PresetUtils.makePresetAPLRotation('Disc', DiscApl); import HolyApl from './apls/holy.apl.json'; diff --git a/ui/healing_priest/sim.ts b/ui/healing_priest/sim.ts index ec5c3f207d..07219c342e 100644 --- a/ui/healing_priest/sim.ts +++ b/ui/healing_priest/sim.ts @@ -64,8 +64,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecHealingPriest, { }), // Default consumes settings. consumes: Presets.DefaultConsumes, - // Default rotation settings. - rotation: Presets.DiscDefaultRotation, // Default talents. talents: Presets.DiscTalents.data, // Default spec-specific settings. @@ -83,8 +81,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecHealingPriest, { HealingPriestInputs.InnerFire, HealingPriestInputs.Shadowfiend, ], - // Inputs to include in the 'Rotation' section on the settings tab. - rotationInputs: HealingPriestInputs.HealingPriestRotationConfig, // Buff and Debuff inputs to include/exclude, overriding the EP-based defaults. includeBuffDebuffInputs: [ ], diff --git a/ui/holy_paladin/inputs.ts b/ui/holy_paladin/inputs.ts index d900336243..df39fb9664 100644 --- a/ui/holy_paladin/inputs.ts +++ b/ui/holy_paladin/inputs.ts @@ -9,10 +9,6 @@ import * as InputHelpers from '../core/components/input_helpers.js'; // Configuration for spec-specific UI elements on the settings tab. // These don't need to be in a separate file but it keeps things cleaner. -export const HolyPaladinRotationConfig = { - inputs: [ - ], -} export const AuraSelection = InputHelpers.makeSpecOptionsEnumInput({ fieldName: 'aura', diff --git a/ui/holy_paladin/presets.ts b/ui/holy_paladin/presets.ts index 05ab8e31ab..40f8a11b4c 100644 --- a/ui/holy_paladin/presets.ts +++ b/ui/holy_paladin/presets.ts @@ -11,7 +11,6 @@ import { PaladinMajorGlyph, PaladinMinorGlyph, PaladinJudgement, - HolyPaladin_Rotation as HolyPaladinRotation, HolyPaladin_Options as HolyPaladinOptions, } from '../core/proto/paladin.js'; @@ -50,9 +49,6 @@ export const StandardTalents = { }), }; -export const DefaultRotation = HolyPaladinRotation.create({ -}); - export const DefaultOptions = HolyPaladinOptions.create({ aura: PaladinAura.DevotionAura, judgement: PaladinJudgement.NoJudgement, diff --git a/ui/holy_paladin/sim.ts b/ui/holy_paladin/sim.ts index f2eaa896bb..726cf95491 100644 --- a/ui/holy_paladin/sim.ts +++ b/ui/holy_paladin/sim.ts @@ -67,8 +67,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecHolyPaladin, { }), // Default consumes settings. consumes: Presets.DefaultConsumes, - // Default rotation settings. - rotation: Presets.DefaultRotation, // Default talents. talents: Presets.StandardTalents.data, // Default spec-specific settings. @@ -122,8 +120,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecHolyPaladin, { // IconInputs to include in the 'Player' section on the settings tab. playerIconInputs: [ ], - // Inputs to include in the 'Rotation' section on the settings tab. - rotationInputs: HolyPaladinInputs.HolyPaladinRotationConfig, // Buff and Debuff inputs to include/exclude, overriding the EP-based defaults. includeBuffDebuffInputs: [ ], diff --git a/ui/hunter/inputs.ts b/ui/hunter/inputs.ts index 377348b303..e28f2091da 100644 --- a/ui/hunter/inputs.ts +++ b/ui/hunter/inputs.ts @@ -1,20 +1,15 @@ import { Spec } from '../core/proto/common.js'; import { ActionId } from '../core/proto_utils/action_id.js'; import { Player } from '../core/player.js'; -import { EventID, TypedEvent } from '../core/typed_event.js'; +import { TypedEvent } from '../core/typed_event.js'; import { makePetTypeInputConfig } from '../core/talents/hunter_pet.js'; import * as InputHelpers from '../core/components/input_helpers.js'; import { - Hunter, - Hunter_Rotation as HunterRotation, Hunter_Rotation_RotationType as RotationType, Hunter_Rotation_StingType as StingType, - Hunter_Rotation_SpellOption as SpellOption, - Hunter_Options as HunterOptions, Hunter_Options_Ammo as Ammo, - Hunter_Options_PetType as PetType, } from '../core/proto/hunter.js'; // Configuration for spec-specific UI elements on the settings tab. diff --git a/ui/hunter/presets.ts b/ui/hunter/presets.ts index 2f4772a3a8..274b062756 100644 --- a/ui/hunter/presets.ts +++ b/ui/hunter/presets.ts @@ -52,7 +52,7 @@ export const SV_P4_PRESET = PresetUtils.makePresetGear('SV P4 Preset', P4SVGear, import P5SVGear from './gear_sets/p5_sv.gear.json'; export const SV_P5_PRESET = PresetUtils.makePresetGear('SV P5 Preset', P5SVGear, { talentTree: 2 }); -export const DefaultRotation = HunterRotation.create({ +export const DefaultSimpleRotation = HunterRotation.create({ type: RotationType.SingleTarget, sting: StingType.SerpentSting, trapWeave: true, @@ -62,7 +62,7 @@ export const DefaultRotation = HunterRotation.create({ allowExplosiveShotDownrank: true, }); -export const ROTATION_PRESET_SIMPLE_DEFAULT = PresetUtils.makePresetSimpleRotation('Simple Default', Spec.SpecHunter, DefaultRotation); +export const ROTATION_PRESET_SIMPLE_DEFAULT = PresetUtils.makePresetSimpleRotation('Simple Default', Spec.SpecHunter, DefaultSimpleRotation); import BmApl from './apls/bm.apl.json'; export const ROTATION_PRESET_BM = PresetUtils.makePresetAPLRotation('BM', BmApl, { talentTree: 0 }); import MmApl from './apls/mm.apl.json'; diff --git a/ui/hunter/sim.ts b/ui/hunter/sim.ts index 67c8b34dd0..5d68f55091 100644 --- a/ui/hunter/sim.ts +++ b/ui/hunter/sim.ts @@ -171,8 +171,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecHunter, { }), // Default consumes settings. consumes: Presets.DefaultConsumes, - // Default rotation settings. - rotation: Presets.DefaultRotation, // Default talents. talents: Presets.SurvivalTalents.data, // Default spec-specific settings. @@ -465,7 +463,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecHunter, { export class HunterSimUI extends IndividualSimUI { constructor(parentElem: HTMLElement, player: Player) { super(parentElem, player, SPEC_CONFIG); - const gemOptimizer = new HunterGemOptimizer(this); + const _gemOptimizer = new HunterGemOptimizer(this); } } diff --git a/ui/mage/sim.ts b/ui/mage/sim.ts index 964ada82ba..ff702df22d 100644 --- a/ui/mage/sim.ts +++ b/ui/mage/sim.ts @@ -75,8 +75,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecMage, { }), // Default consumes settings. consumes: Presets.DefaultFireConsumes, - // Default rotation settings. - rotation: Presets.DefaultSimpleRotation, // Default talents. talents: Presets.Phase3FireTalents.data, // Default spec-specific settings. diff --git a/ui/protection_paladin/inputs.ts b/ui/protection_paladin/inputs.ts index a7da711739..dfa50143fc 100644 --- a/ui/protection_paladin/inputs.ts +++ b/ui/protection_paladin/inputs.ts @@ -10,10 +10,6 @@ import * as InputHelpers from '../core/components/input_helpers.js'; // Configuration for spec-specific UI elements on the settings tab. // These don't need to be in a separate file but it keeps things cleaner. -export const ProtectionPaladinRotationConfig = { - inputs: [ - ], -} export const AuraSelection = InputHelpers.makeSpecOptionsEnumInput({ fieldName: 'aura', diff --git a/ui/protection_paladin/presets.ts b/ui/protection_paladin/presets.ts index 6e02f8b2d6..2403c329fa 100644 --- a/ui/protection_paladin/presets.ts +++ b/ui/protection_paladin/presets.ts @@ -1,7 +1,5 @@ import { Consumes, - CustomRotation, - CustomSpell, Flask, Food, Potions, @@ -13,8 +11,6 @@ import { PaladinMajorGlyph, PaladinMinorGlyph, PaladinJudgement as PaladinJudgement, - ProtectionPaladin_Rotation_SpellOption as SpellOption, - ProtectionPaladin_Rotation as ProtectionPaladinRotation, ProtectionPaladin_Options as ProtectionPaladinOptions, } from '../core/proto/paladin.js'; @@ -37,25 +33,6 @@ export const P3_PRESET = PresetUtils.makePresetGear('P3 Preset', P3Gear); import P4Gear from './gear_sets/p4.gear.json'; export const P4_PRESET = PresetUtils.makePresetGear('P4 Preset', P4Gear); -export const DefaultRotation = ProtectionPaladinRotation.create({ - hammerFirst: false, - squeezeHolyWrath: true, - waitSlack: 300, - useCustomPrio: false, - customRotation: CustomRotation.create({ - spells: [ - CustomSpell.create({ spell: SpellOption.ShieldOfRighteousness }), - CustomSpell.create({ spell: SpellOption.HammerOfTheRighteous }), - CustomSpell.create({ spell: SpellOption.HolyShield }), - CustomSpell.create({ spell: SpellOption.HammerOfWrath }), - CustomSpell.create({ spell: SpellOption.Consecration }), - CustomSpell.create({ spell: SpellOption.AvengersShield }), - CustomSpell.create({ spell: SpellOption.JudgementOfWisdom }), - CustomSpell.create({ spell: SpellOption.Exorcism }) - ], - }), -}); - import DefaultApl from './apls/default.apl.json'; export const ROTATION_DEFAULT = PresetUtils.makePresetAPLRotation('Default (969)', DefaultApl); diff --git a/ui/protection_paladin/sim.ts b/ui/protection_paladin/sim.ts index 9ffd66c852..89161b19f3 100644 --- a/ui/protection_paladin/sim.ts +++ b/ui/protection_paladin/sim.ts @@ -136,8 +136,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecProtectionPaladin, { }), // Default consumes settings. consumes: Presets.DefaultConsumes, - // Default rotation settings. - rotation: Presets.DefaultRotation, // Default talents. talents: Presets.GenericAoeTalents.data, // Default spec-specific settings. @@ -191,8 +189,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecProtectionPaladin, { // IconInputs to include in the 'Player' section on the settings tab. playerIconInputs: [ ], - // Inputs to include in the 'Rotation' section on the settings tab. - rotationInputs: ProtectionPaladinInputs.ProtectionPaladinRotationConfig, // Buff and Debuff inputs to include/exclude, overriding the EP-based defaults. includeBuffDebuffInputs: [ IconInputs.HealthBuff, diff --git a/ui/protection_warrior/inputs.ts b/ui/protection_warrior/inputs.ts index e4699dc043..3e9a79b798 100644 --- a/ui/protection_warrior/inputs.ts +++ b/ui/protection_warrior/inputs.ts @@ -3,18 +3,9 @@ import { ActionId } from '../core/proto_utils/action_id.js'; import { WarriorShout, - WarriorTalents as WarriorTalents, - ProtectionWarrior, - ProtectionWarrior_Rotation as ProtectionWarriorRotation, - ProtectionWarrior_Rotation_DemoShoutChoice as DemoShoutChoice, - ProtectionWarrior_Rotation_ThunderClapChoice as ThunderClapChoice, - ProtectionWarrior_Options as ProtectionWarriorOptions, - ProtectionWarrior_Rotation_SpellOption as SpellOption, } from '../core/proto/warrior.js'; import * as InputHelpers from '../core/components/input_helpers.js'; -import * as Presets from './presets.js'; -import { SimUI } from '../core/sim_ui.js'; // Configuration for spec-specific UI elements on the settings tab. // These don't need to be in a separate file but it keeps things cleaner. @@ -38,53 +29,3 @@ export const ShatteringThrow = InputHelpers.makeSpecOptionsBooleanIconInput({ - // fieldName: 'customRotation', - // numColumns: 3, - // values: [ - // { actionId: ActionId.fromSpellId(57823), value: SpellOption.Revenge }, - // { actionId: ActionId.fromSpellId(47488), value: SpellOption.ShieldSlam }, - // { actionId: ActionId.fromSpellId(47440), value: SpellOption.Shout }, - // { actionId: ActionId.fromSpellId(47502), value: SpellOption.ThunderClap }, - // { actionId: ActionId.fromSpellId(25203), value: SpellOption.DemoralizingShout }, - // { actionId: ActionId.fromSpellId(47486), value: SpellOption.MortalStrike }, - // { actionId: ActionId.fromSpellId(47498), value: SpellOption.Devastate }, - // { actionId: ActionId.fromSpellId(47467), value: SpellOption.SunderArmor }, - // { actionId: ActionId.fromSpellId(12809), value: SpellOption.ConcussionBlow }, - // { actionId: ActionId.fromSpellId(46968), value: SpellOption.Shockwave }, - // ], - // }), - // InputHelpers.makeRotationNumberInput({ - // fieldName: 'hsRageThreshold', - // label: 'HS rage threshold', - // labelTooltip: 'Heroic Strike when rage is above:', - // }), - // InputHelpers.makeRotationBooleanInput({ - // fieldName: 'prioSslamOnShieldBlock', - // label: 'Prio SSlam on Shield Block', - // labelTooltip: 'The rotation code will prio SSlam over Revenge during active shield block windows.', - // }), - // InputHelpers.makeRotationEnumInput({ - // fieldName: 'demoShoutChoice', - // label: 'Demo Shout', - // values: [ - // { name: 'Never', value: DemoShoutChoice.DemoShoutChoiceNone }, - // { name: 'Maintain Debuff', value: DemoShoutChoice.DemoShoutChoiceMaintain }, - // { name: 'Filler', value: DemoShoutChoice.DemoShoutChoiceFiller }, - // ], - // }), - // InputHelpers.makeRotationEnumInput({ - // fieldName: 'thunderClapChoice', - // label: 'Thunder Clap', - // values: [ - // { name: 'Never', value: ThunderClapChoice.ThunderClapChoiceNone }, - // { name: 'Maintain Debuff', value: ThunderClapChoice.ThunderClapChoiceMaintain }, - // { name: 'On CD', value: ThunderClapChoice.ThunderClapChoiceOnCD }, - // ], - // }), - ], -}; diff --git a/ui/protection_warrior/presets.ts b/ui/protection_warrior/presets.ts index 0ebe1f039f..65bd5d80d8 100644 --- a/ui/protection_warrior/presets.ts +++ b/ui/protection_warrior/presets.ts @@ -1,8 +1,6 @@ import { BattleElixir, Consumes, - CustomRotation, - CustomSpell, Explosive, Food, Glyphs, @@ -15,10 +13,7 @@ import { SavedTalents } from '../core/proto/ui.js'; import { WarriorShout, ProtectionWarrior_Rotation as ProtectionWarriorRotation, - ProtectionWarrior_Rotation_DemoShoutChoice as DemoShoutChoice, - ProtectionWarrior_Rotation_ThunderClapChoice as ThunderClapChoice, ProtectionWarrior_Options as ProtectionWarriorOptions, - ProtectionWarrior_Rotation_SpellOption as SpellOption, WarriorMajorGlyph, WarriorMinorGlyph, } from '../core/proto/warrior.js'; @@ -42,29 +37,9 @@ export const P3_PRESET = PresetUtils.makePresetGear('P3 Preset', P3Gear); import P4Gear from './gear_sets/p4.gear.json'; export const P4_PRESET = PresetUtils.makePresetGear('P4 Preset', P4Gear); -export const DefaultRotation = ProtectionWarriorRotation.create({ - customRotation: CustomRotation.create({ - spells: [ - CustomSpell.create({ spell: SpellOption.ShieldSlam }), - CustomSpell.create({ spell: SpellOption.Revenge }), - CustomSpell.create({ spell: SpellOption.Shout }), - CustomSpell.create({ spell: SpellOption.ThunderClap }), - CustomSpell.create({ spell: SpellOption.DemoralizingShout }), - CustomSpell.create({ spell: SpellOption.MortalStrike }), - CustomSpell.create({ spell: SpellOption.Devastate }), - CustomSpell.create({ spell: SpellOption.SunderArmor }), - CustomSpell.create({ spell: SpellOption.ConcussionBlow }), - CustomSpell.create({ spell: SpellOption.Shockwave }), - ], - }), - demoShoutChoice: DemoShoutChoice.DemoShoutChoiceNone, - thunderClapChoice: ThunderClapChoice.ThunderClapChoiceNone, - hsRageThreshold: 30, -}); - import DefaultApl from './apls/default.apl.json'; export const ROTATION_DEFAULT = PresetUtils.makePresetAPLRotation('Default APL', DefaultApl); -export const ROTATION_PRESET_SIMPLE = PresetUtils.makePresetSimpleRotation('Simple Cooldowns', Spec.SpecProtectionWarrior, DefaultRotation); +export const ROTATION_PRESET_SIMPLE = PresetUtils.makePresetSimpleRotation('Simple Cooldowns', Spec.SpecProtectionWarrior, ProtectionWarriorRotation.create()); // Default talents. Uses the wowhead calculator format, make the talents on diff --git a/ui/protection_warrior/sim.ts b/ui/protection_warrior/sim.ts index e63f82bd7a..bd0251091f 100644 --- a/ui/protection_warrior/sim.ts +++ b/ui/protection_warrior/sim.ts @@ -119,8 +119,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecProtectionWarrior, { }), // Default consumes settings. consumes: Presets.DefaultConsumes, - // Default rotation settings. - rotation: Presets.DefaultRotation, // Default talents. talents: Presets.StandardTalents.data, // Default spec-specific settings. @@ -167,8 +165,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecProtectionWarrior, { ProtectionWarriorInputs.ShoutPicker, ProtectionWarriorInputs.ShatteringThrow, ], - // Inputs to include in the 'Rotation' section on the settings tab. - rotationInputs: ProtectionWarriorInputs.ProtectionWarriorRotationConfig, // Buff and Debuff inputs to include/exclude, overriding the EP-based defaults. includeBuffDebuffInputs: [ IconInputs.HealthBuff, diff --git a/ui/restoration_druid/inputs.ts b/ui/restoration_druid/inputs.ts index e44dea933d..f965272dc7 100644 --- a/ui/restoration_druid/inputs.ts +++ b/ui/restoration_druid/inputs.ts @@ -2,14 +2,10 @@ import { UnitReference, UnitReference_Type as UnitType } from '../core/proto/com import { Spec } from '../core/proto/common.js'; import { ActionId } from '../core/proto_utils/action_id.js'; import { Player } from '../core/player.js'; -import { EventID, TypedEvent } from '../core/typed_event.js'; +import { EventID } from '../core/typed_event.js'; import * as InputHelpers from '../core/components/input_helpers.js'; -import { - RestorationDruid_Options as DruidOptions, -} from '../core/proto/druid.js'; - // Configuration for spec-specific UI elements on the settings tab. // These don't need to be in a separate file but it keeps things cleaner. @@ -30,8 +26,3 @@ export const SelfInnervate = InputHelpers.makeSpecOptionsBooleanIconInput({ - fieldName: 'primaryHeal', - label: 'Primary Heal', - labelTooltip: 'Set to \'AutoHeal\', to automatically swap based on best heal.', - values: [ - { - name: "Auto Heal", - value: ShamanHealSpell.AutoHeal - }, - { - name: "Lesser Healing Wave", - value: ShamanHealSpell.LesserHealingWave // actionId: ActionId.fromSpellId(49276), - }, - { - name: "Healing Wave", - value: ShamanHealSpell.HealingWave // actionId: ActionId.fromSpellId(49273), - }, - { - name: "Chain Heal", - value: ShamanHealSpell.ChainHeal // actionId: ActionId.fromSpellId(55459), - }, - ] -}); - - -export const UseRiptide = InputHelpers.makeRotationBooleanInput({ - fieldName: 'useRiptide', - label: 'Use Riptide', - labelTooltip: 'Causes riptide to be cast on primary target when CD is available and not already on.', - showWhen: (player: Player) => player.getTalents().riptide, - changeEmitter: (player: Player) => TypedEvent.onAny([player.specOptionsChangeEmitter, player.rotationChangeEmitter, player.talentsChangeEmitter]), -}); - -export const UseEarthShield = InputHelpers.makeRotationBooleanInput({ - fieldName: 'useEarthShield', - label: 'Use Earth Shield', - labelTooltip: 'Causes earth shield to be cast on healing target.', - showWhen: (player: Player) => player.getTalents().earthShield, - changeEmitter: (player: Player) => TypedEvent.onAny([player.specOptionsChangeEmitter, player.rotationChangeEmitter, player.talentsChangeEmitter]), -}); - export const TriggerEarthShield = InputHelpers.makeSpecOptionsNumberInput({ fieldName: 'earthShieldPPM', label: 'Earth Shield PPM', labelTooltip: 'How many times Earth Shield should be triggered per minute.', - showWhen: (player: Player) => player.getTalents().earthShield && player.getRotation().useEarthShield, + showWhen: (player: Player) => player.getTalents().earthShield, changeEmitter: (player: Player) => TypedEvent.onAny([player.specOptionsChangeEmitter, player.rotationChangeEmitter, player.talentsChangeEmitter]), }); -export const RestorationShamanRotationConfig = { - inputs: [ - PrimaryHealInput, - UseRiptide, - UseEarthShield, - TriggerEarthShield, - InputHelpers.makeRotationBooleanInput({ - fieldName: 'bloodlust', - label: 'Use Bloodlust', - labelTooltip: 'Player will cast bloodlust', - getValue: (player: Player) => player.getRotation().bloodlust == RestorationShaman_Rotation_BloodlustUse.UseBloodlust, - setValue: (eventID: EventID, player: Player, newValue: boolean) => { - const newRotation = player.getRotation(); - if (newValue) { - newRotation.bloodlust = RestorationShaman_Rotation_BloodlustUse.UseBloodlust; - } else { - newRotation.bloodlust = RestorationShaman_Rotation_BloodlustUse.NoBloodlust; - } - player.setRotation(eventID, newRotation); - }, - }), - ], -}; - diff --git a/ui/restoration_shaman/presets.ts b/ui/restoration_shaman/presets.ts index 35632299c5..c1b8631e04 100644 --- a/ui/restoration_shaman/presets.ts +++ b/ui/restoration_shaman/presets.ts @@ -8,21 +8,12 @@ import { import { SavedTalents } from '../core/proto/ui.js'; import { - RestorationShaman_Rotation as RestorationShamanRotation, RestorationShaman_Options as RestorationShamanOptions, ShamanShield, ShamanMajorGlyph, ShamanMinorGlyph, } from '../core/proto/shaman.js'; -import { - AirTotem, - EarthTotem, - FireTotem, - WaterTotem, - ShamanTotems, -} from '../core/proto/shaman.js'; - import * as PresetUtils from '../core/preset_utils.js'; // Preset options for this spec. @@ -40,17 +31,6 @@ export const P3_PRESET = PresetUtils.makePresetGear('P3 Preset', P3Gear); import P4Gear from './gear_sets/p4.gear.json'; export const P4_PRESET = PresetUtils.makePresetGear('P4 Preset', P4Gear); -export const DefaultRotation = RestorationShamanRotation.create({ - totems: ShamanTotems.create({ - earth: EarthTotem.StrengthOfEarthTotem, - air: AirTotem.WrathOfAirTotem, - fire: FireTotem.FlametongueTotem, - water: WaterTotem.HealingStreamTotem, - }), - useEarthShield: true, - useRiptide: true, -}); - // Default talents. Uses the wowhead calculator format, make the talents on // https://wowhead.com/wotlk/talent-calc and copy the numbers in the url. export const TankHealingTalents = { diff --git a/ui/restoration_shaman/sim.ts b/ui/restoration_shaman/sim.ts index 19304a0084..daa42081f7 100644 --- a/ui/restoration_shaman/sim.ts +++ b/ui/restoration_shaman/sim.ts @@ -79,8 +79,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecRestorationShaman, { }), // Default consumes settings. consumes: Presets.DefaultConsumes, - // Default rotation settings. - rotation: Presets.DefaultRotation, // Default talents. talents: Presets.RaidHealingTalents.data, // Default spec-specific settings. @@ -112,8 +110,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecRestorationShaman, { playerIconInputs: [ ShamanInputs.ShamanShieldInput, ], - // Inputs to include in the 'Rotation' section on the settings tab. - rotationInputs: ShamanInputs.RestorationShamanRotationConfig, // Buff and Debuff inputs to include/exclude, overriding the EP-based defaults. includeBuffDebuffInputs: [ ], @@ -122,6 +118,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecRestorationShaman, { // Inputs to include in the 'Other' section on the settings tab. otherInputs: { inputs: [ + ShamanInputs.TriggerEarthShield, OtherInputs.TankAssignment ], }, diff --git a/ui/retribution_paladin/inputs.ts b/ui/retribution_paladin/inputs.ts index 945b907ba0..7faecd52a0 100644 --- a/ui/retribution_paladin/inputs.ts +++ b/ui/retribution_paladin/inputs.ts @@ -1,22 +1,18 @@ -import { Spec, ItemSlot } from '../core/proto/common.js'; +import { Spec } from '../core/proto/common.js'; import { Player } from '../core/player.js'; -import { EventID } from '../core/typed_event.js'; -import { IndividualSimUI } from '../core/individual_sim_ui.js'; import { ActionId } from '../core/proto_utils/action_id.js'; -import { CustomRotation } from '../core/proto/common.js'; import { PaladinAura as PaladinAura, - RetributionPaladin_Rotation as RetributionPaladinRotation, - RetributionPaladin_Options as RetributionPaladinOptions, - RetributionPaladin_Rotation_SpellOption as SpellOption, - RetributionPaladin_Rotation_RotationType as RotationType, PaladinJudgement as PaladinJudgement, PaladinSeal, } from '../core/proto/paladin.js'; import * as InputHelpers from '../core/components/input_helpers.js'; +// Configuration for spec-specific UI elements on the settings tab. +// These don't need to be in a separate file but it keeps things cleaner. + export const AuraSelection = InputHelpers.makeSpecOptionsEnumIconInput({ fieldName: 'aura', values: [ @@ -44,138 +40,4 @@ export const JudgementSelection = InputHelpers.makeSpecOptionsEnumIconInput({ - fieldName: "exoSlack", - label: "Exo Slack (MS)", - labelTooltip: "Amount of extra time in MS to give main abilities to come off cooldown before using Exorcism on single target", - positive: true, - showWhen: (player: Player) => player.getRotation().type == RotationType.Standard, -}) - -export const RetributionPaladinRotationConsSlackConfig = InputHelpers.makeRotationNumberInput({ - fieldName: "consSlack", - label: "Cons Slack (MS)", - labelTooltip: "Amount of extra time in MS to give main abilities to come off cooldown before using Consecration on single target", - positive: true, - showWhen: (player: Player) => player.getRotation().type == RotationType.Standard, -}) - - -export const RetributionPaladinRotationDivinePleaSelection = InputHelpers.makeRotationBooleanInput({ - fieldName: 'useDivinePlea', - label: 'Use Divine Plea', - labelTooltip: 'Whether or not to maintain Divine Plea', - showWhen: (player: Player) => player.getRotation().type == RotationType.Standard, -}); - -// Reuse field name, but different tooltip. -export const RetributionPaladinRotationDivinePleaSelectionAlternate = InputHelpers.makeRotationBooleanInput({ - fieldName: 'useDivinePlea', - label: 'Use Divine Plea - Out of Sequence', - labelTooltip: 'Whether or not to maintain Divine Plea, this happens OUTSIDE of the cast sequence', - showWhen: (player: Player) => player.getRotation().type == RotationType.CastSequence -}); - -export const RetributionPaladinRotationDivinePleaPercentageConfig = InputHelpers.makeRotationNumberInput({ - fieldName: "divinePleaPercentage", - label: "Divine Plea Mana Threshold %", - labelTooltip: "% of max mana left before beginning to use Divine Plea", - percent: true, - positive: true, -}) - -export const RetributionPaladinRotationHolyWrathConfig = InputHelpers.makeRotationNumberInput({ - fieldName: "holyWrathThreshold", - label: "Holy Wrath Threshold", - labelTooltip: "Minimum number of Demon and Undead units before Holy Wrath is considered viable to add to an AOE rotation.", - positive: true, - showWhen: (player: Player) => player.getRotation().type == RotationType.Standard, -}) - -export const RetributionPaladinSoVTargets = InputHelpers.makeRotationNumberInput({ - fieldName: "sovTargets", - label: "Max SoV Targets", - labelTooltip: "The maximum number of targets to keep the SoV debuff on.", - positive: true, - showWhen: (player: Player) => player.getSpecOptions().seal == PaladinSeal.Vengeance, - changeEmitter: (player: Player) => player.changeEmitter, -}) - -export const RetributionPaladinRotationAvoidClippingConsecration = InputHelpers.makeRotationBooleanInput({ - fieldName: 'avoidClippingConsecration', - label: 'Avoid Clipping Consecration', - labelTooltip: 'Avoid clipping consecration at the end of a fight.', - showWhen: (player: Player) => (player.getRotation().type == RotationType.Standard) || (player.getRotation().type == RotationType.Custom), -}); - -export const RetributionPaladinRotationHoldLastAvengingWrathUntilExecution = InputHelpers.makeRotationBooleanInput({ - fieldName: 'holdLastAvengingWrathUntilExecution', - label: 'Hold Avenging Wrath Until Execution', - labelTooltip: 'Hold last Avenging Wrath usage until the execution phase. This currently does not work if specific Avenging Wrath CD usage times are specified.', - showWhen: (player: Player) => (player.getRotation().type == RotationType.Standard) || (player.getRotation().type == RotationType.Custom), -}); - -export const RetributionPaladinRotationCancelChaosBane = InputHelpers.makeRotationBooleanInput({ - fieldName: 'cancelChaosBane', - label: 'Cancel Chaos Bane Buff From Shadowmourne', - labelTooltip: 'Cancels the buff provided when Shadowmourne soul shard buff reaches 10 stacks.', - showWhen: (player: Player) => player.getEquippedItem(ItemSlot.ItemSlotMainHand)?.item.name == "Shadowmourne", -}); - -export const RetributionPaladinRotationPriorityConfig = InputHelpers.makeCustomRotationInput({ - fieldName: 'customRotation', - numColumns: 2, - values: [ - { actionId: ActionId.fromSpellId(53408), value: SpellOption.JudgementOfWisdom }, - { actionId: ActionId.fromSpellId(53385), value: SpellOption.DivineStorm }, - { actionId: ActionId.fromSpellId(48806), value: SpellOption.HammerOfWrath }, - { actionId: ActionId.fromSpellId(48819), value: SpellOption.Consecration }, - { actionId: ActionId.fromSpellId(48817), value: SpellOption.HolyWrath }, - { actionId: ActionId.fromSpellId(35395), value: SpellOption.CrusaderStrike }, - { actionId: ActionId.fromSpellId(48801), value: SpellOption.Exorcism }, - { actionId: ActionId.fromSpellId(54428), value: SpellOption.DivinePlea } - ], - showWhen: (player: Player) => player.getRotation().type == RotationType.Custom, -}); - -export const RetributionPaladinCastSequenceConfig = InputHelpers.makeCustomRotationInput({ - fieldName: 'customCastSequence', - numColumns: 2, - values: [ - { actionId: ActionId.fromSpellId(53408), value: SpellOption.JudgementOfWisdom }, - { actionId: ActionId.fromSpellId(53385), value: SpellOption.DivineStorm }, - { actionId: ActionId.fromSpellId(48806), value: SpellOption.HammerOfWrath }, - { actionId: ActionId.fromSpellId(48819), value: SpellOption.Consecration }, - { actionId: ActionId.fromSpellId(48817), value: SpellOption.HolyWrath }, - { actionId: ActionId.fromSpellId(35395), value: SpellOption.CrusaderStrike }, - { actionId: ActionId.fromSpellId(48801), value: SpellOption.Exorcism }, - { actionId: ActionId.fromSpellId(54428), value: SpellOption.DivinePlea } - ], - showWhen: (player: Player) => player.getRotation().type == RotationType.CastSequence, -}); - -export const RotationSelector = InputHelpers.makeRotationEnumInput({ - fieldName: 'type', - label: 'Type', - labelTooltip: - `
    -
  • -
    Standard: All-in-one rotation for single target and aoe.
    -
  • -
  • -
    Custom: Highest spell that is ready will be cast.
    -
  • -
  • -
    Cast Sequence: Spells will be cast in the order of the list. (Like 1-button-macro)
    -
  • -
`, - values: [ - { name: 'Standard', value: RotationType.Standard }, - { name: 'Custom', value: RotationType.Custom }, - { name: 'Cast Sequence', value: RotationType.CastSequence }, - ], }); \ No newline at end of file diff --git a/ui/retribution_paladin/presets.ts b/ui/retribution_paladin/presets.ts index 1ab4367313..3487c45c7d 100644 --- a/ui/retribution_paladin/presets.ts +++ b/ui/retribution_paladin/presets.ts @@ -1,23 +1,17 @@ import { Conjured, Consumes, - CustomRotation, - CustomSpell, Flask, Food, Glyphs, Potions, - Spec, } from '../core/proto/common.js'; import { SavedTalents } from '../core/proto/ui.js'; import { PaladinAura as PaladinAura, PaladinJudgement as PaladinJudgement, - RetributionPaladin_Rotation as RetributionPaladinRotation, RetributionPaladin_Options as RetributionPaladinOptions, - RetributionPaladin_Rotation_RotationType as RotationType, - RetributionPaladin_Rotation_SpellOption as SpellOption, PaladinMajorGlyph, PaladinMinorGlyph, } from '../core/proto/paladin.js'; @@ -41,46 +35,6 @@ export const P4_PRESET = PresetUtils.makePresetGear('P4 Preset', P4Gear); import P5Gear from './gear_sets/p5.gear.json'; export const P5_PRESET = PresetUtils.makePresetGear('P5 Preset', P5Gear); -export const DefaultRotation = RetributionPaladinRotation.create({ - type: RotationType.Standard, - exoSlack: 500, - consSlack: 500, - useDivinePlea: true, - avoidClippingConsecration: true, - holdLastAvengingWrathUntilExecution: false, - cancelChaosBane: false, - divinePleaPercentage: 0.75, - holyWrathThreshold: 4, - sovTargets: 1, - customRotation: CustomRotation.create({ - spells: [ - CustomSpell.create({ spell: SpellOption.HammerOfWrath }), - CustomSpell.create({ spell: SpellOption.JudgementOfWisdom }), - CustomSpell.create({ spell: SpellOption.CrusaderStrike }), - CustomSpell.create({ spell: SpellOption.DivineStorm }), - CustomSpell.create({ spell: SpellOption.Consecration }), - CustomSpell.create({ spell: SpellOption.Exorcism }), - CustomSpell.create({ spell: SpellOption.HolyWrath }), - ], - }), - customCastSequence: CustomRotation.create({ - spells: [ - CustomSpell.create({ spell: SpellOption.JudgementOfWisdom }), - CustomSpell.create({ spell: SpellOption.CrusaderStrike }), - CustomSpell.create({ spell: SpellOption.DivineStorm }), - CustomSpell.create({ spell: SpellOption.Consecration }), - CustomSpell.create({ spell: SpellOption.CrusaderStrike }), - CustomSpell.create({ spell: SpellOption.Exorcism }), - CustomSpell.create({ spell: SpellOption.JudgementOfWisdom }), - CustomSpell.create({ spell: SpellOption.CrusaderStrike }), - CustomSpell.create({ spell: SpellOption.DivineStorm }), - CustomSpell.create({ spell: SpellOption.Consecration }), - CustomSpell.create({ spell: SpellOption.CrusaderStrike }), - ], - }), -}); - -export const ROTATION_PRESET_LEGACY_DEFAULT = PresetUtils.makePresetLegacyRotation('Legacy Default', Spec.SpecRetributionPaladin, DefaultRotation); import DefaultApl from './apls/default.apl.json'; export const ROTATION_PRESET_DEFAULT = PresetUtils.makePresetAPLRotation('Default', DefaultApl); diff --git a/ui/retribution_paladin/sim.ts b/ui/retribution_paladin/sim.ts index 578bd9b224..d70127cba4 100644 --- a/ui/retribution_paladin/sim.ts +++ b/ui/retribution_paladin/sim.ts @@ -114,8 +114,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecRetributionPaladin, { }), // Default consumes settings. consumes: Presets.DefaultConsumes, - // Default rotation settings. - rotation: Presets.DefaultRotation, // Default talents. talents: Presets.AuraMasteryTalents.data, // Default spec-specific settings. @@ -167,24 +165,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecRetributionPaladin, { RetributionPaladinInputs.JudgementSelection, RetributionPaladinInputs.StartingSealSelection, ], - // Inputs to include in the 'Rotation' section on the settings tab. - rotationInputs: { - inputs: [ - RetributionPaladinInputs.RotationSelector, - RetributionPaladinInputs.RetributionPaladinRotationDivinePleaSelection, - RetributionPaladinInputs.RetributionPaladinRotationAvoidClippingConsecration, - RetributionPaladinInputs.RetributionPaladinRotationHoldLastAvengingWrathUntilExecution, - RetributionPaladinInputs.RetributionPaladinRotationCancelChaosBane, - RetributionPaladinInputs.RetributionPaladinRotationDivinePleaSelectionAlternate, - RetributionPaladinInputs.RetributionPaladinRotationDivinePleaPercentageConfig, - RetributionPaladinInputs.RetributionPaladinRotationConsSlackConfig, - RetributionPaladinInputs.RetributionPaladinRotationExoSlackConfig, - RetributionPaladinInputs.RetributionPaladinRotationHolyWrathConfig, - RetributionPaladinInputs.RetributionPaladinSoVTargets, - RetributionPaladinInputs.RetributionPaladinRotationPriorityConfig, - RetributionPaladinInputs.RetributionPaladinCastSequenceConfig - ] - }, // Buff and Debuff inputs to include/exclude, overriding the EP-based defaults. includeBuffDebuffInputs: [ IconInputs.ReplenishmentBuff, @@ -205,7 +185,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecRetributionPaladin, { presets: { rotations: [ - Presets.ROTATION_PRESET_LEGACY_DEFAULT, Presets.ROTATION_PRESET_DEFAULT, ], // Preset talents that the user can quickly select. diff --git a/ui/rogue/inputs.ts b/ui/rogue/inputs.ts index ef29f8d92b..2b9d964f1a 100644 --- a/ui/rogue/inputs.ts +++ b/ui/rogue/inputs.ts @@ -5,12 +5,6 @@ import { Player } from '../core/player.js'; import * as InputHelpers from '../core/components/input_helpers.js'; import { - Rogue_Rotation_AssassinationPriority as AssassinationPriority, - Rogue_Rotation_CombatPriority as CombatPriority, - Rogue_Rotation_CombatBuilder as CombatBuilder, - Rogue_Rotation_SubtletyBuilder as SubtletyBuilder, - Rogue_Rotation_SubtletyPriority as SubtletyPriority, - Rogue_Rotation_Frequency as Frequency, Rogue_Options_PoisonImbue as Poison, } from '../core/proto/rogue.js'; @@ -74,135 +68,3 @@ export const ApplyPoisonsManually = InputHelpers.makeSpecOptionsBooleanInput({ - fieldName: 'exposeArmorFrequency', - label: 'Expose Armor', - labelTooltip: 'Frequency of Expose Armor casts.', - values: [ - { name: 'Never', value: Frequency.Never }, - { name: 'Cast Once', value: Frequency.Once }, - { name: 'Maintain', value: Frequency.Maintain }, - ], - }), - InputHelpers.makeRotationNumberInput({ - fieldName: 'minimumComboPointsExposeArmor', - label: 'Minimum CP (Expose Armor)', - labelTooltip: 'Minimum number of combo points for Expose Armor when only cast once.', - showWhen: (player: Player) => player.getRotation().exposeArmorFrequency == Frequency.Once, - }), - InputHelpers.makeRotationEnumInput({ - fieldName: 'tricksOfTheTradeFrequency', - label: 'Tricks of the Trade', - labelTooltip: 'Frequency of Tricks of the Trade usage.', - values: [ - { name: 'Never', value: Frequency.Never }, - { name: 'Maintain', value: Frequency.Maintain }, - ], - }), - InputHelpers.makeRotationEnumInput({ - fieldName: 'combatBuilder', - label: "Builder", - labelTooltip: 'Use Sinister Strike, Backstab, or Hemorrhage as builder.', - values: [ - { name: "Sinister Strike", value: CombatBuilder.SinisterStrike }, - { name: "Backstab", value: CombatBuilder.Backstab }, - { name: "Hemorrhage", value: CombatBuilder.HemorrhageCombat }, - ], - showWhen: (player: Player) => player.getTalents().combatPotency > 0 - }), - InputHelpers.makeRotationEnumInput({ - fieldName: 'combatFinisherPriority', - label: 'Finisher Priority', - labelTooltip: 'The finisher that will be cast with highest priority.', - values: [ - { name: 'Rupture', value: CombatPriority.RuptureEviscerate }, - { name: 'Eviscerate', value: CombatPriority.EviscerateRupture }, - ], - showWhen: (player: Player) => player.getTalents().combatPotency > 0 - }), - InputHelpers.makeRotationEnumInput({ - fieldName: 'assassinationFinisherPriority', - label: 'Finisher Priority', - labelTooltip: 'The finisher that will be cast with highest priority.', - values: [ - { name: 'Rupture', value: AssassinationPriority.RuptureEnvenom }, - { name: 'Envenom', value: AssassinationPriority.EnvenomRupture }, - ], - showWhen: (player: Player) => player.getTalents().mutilate - }), - InputHelpers.makeRotationEnumInput({ - fieldName: 'subtletyBuilder', - label: "Builder", - labelTooltip: 'Use Hemorrhage or Backstab as builder.', - values: [ - { name: "Hemorrhage", value: SubtletyBuilder.Hemorrhage }, - { name: "Backstab", value: SubtletyBuilder.BackstabSub }, - ], - showWhen: (player: Player) => player.getTalents().honorAmongThieves > 0 - }), - InputHelpers.makeRotationEnumInput({ - fieldName: 'subtletyFinisherPriority', - label: "Finisher Priority", - labelTooltip: 'The finisher that will be cast with highest priority.', - values: [ - { name: "Eviscerate", value: SubtletyPriority.SubtletyEviscerate }, - { name: "Envenom", value: SubtletyPriority.SubtletyEnvenom }, - ], - showWhen: (player: Player) => player.getTalents().honorAmongThieves > 0 - }), - InputHelpers.makeRotationEnumInput({ - fieldName: 'multiTargetSliceFrequency', - label: 'Multi-Target S&D', - labelTooltip: 'Frequency of Slice and Dice cast in multi-target scenarios.', - values: [ - { name: 'Never', value: Frequency.Never }, - { name: 'Once', value: Frequency.Once }, - { name: 'Maintain', value: Frequency.Maintain }, - ], - showWhen: (player: Player) => player.getRotation().multiTargetSliceFrequency != Frequency.FrequencyUnknown - }), - InputHelpers.makeRotationNumberInput({ - fieldName: 'minimumComboPointsMultiTargetSlice', - label: 'Minimum CP (Slice)', - labelTooltip: 'Minimum number of combo points spent if Slice and Dice has frequency: Once', - showWhen: (player: Player) => player.getRotation().multiTargetSliceFrequency == Frequency.Once - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'openWithGarrote', - label: 'Open with Garrote', - labelTooltip: 'Open the encounter by casting Garrote.', - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'openWithShadowstep', - label: 'Open with Shadowstep', - labelTooltip: 'Open the encounter by casting Shadowstep.', - showWhen: (player: Player) => player.getTalents().shadowstep - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'openWithPremeditation', - label: 'Open with Premeditation', - labelTooltip: 'Open the encounter by casting Premeditation.', - showWhen: (player: Player) => player.getTalents().premeditation - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'useFeint', - label: 'Use Feint', - labelTooltip: 'Cast Feint on cooldown. Mainly useful when using the associate glyph.' - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: "useGhostlyStrike", - label: 'Use Ghostly Strike', - labelTooltip: 'Use Ghostly Strike on cooldown. Mainly useful when using the associate glyph.', - showWhen: (player: Player) => player.getTalents().ghostlyStrike - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'ruptureForBleed', - label: 'Rupture for Bleed', - labelTooltip: 'Cast Rupture as needed to apply a bleed effect for Hunger for Blood', - showWhen: (player: Player) => player.getTalents().hungerForBlood - }), - ], -}; diff --git a/ui/rogue/presets.ts b/ui/rogue/presets.ts index 004b89b1bd..1fb8fbeb55 100644 --- a/ui/rogue/presets.ts +++ b/ui/rogue/presets.ts @@ -11,13 +11,6 @@ import { SavedTalents } from '../core/proto/ui.js'; import { Rogue_Options as RogueOptions, Rogue_Options_PoisonImbue as Poison, - Rogue_Rotation as RogueRotation, - Rogue_Rotation_AssassinationPriority, - Rogue_Rotation_CombatBuilder, - Rogue_Rotation_CombatPriority, - Rogue_Rotation_Frequency, - Rogue_Rotation_SubtletyBuilder, - Rogue_Rotation_SubtletyPriority, RogueMajorGlyph, } from '../core/proto/rogue.js'; @@ -60,19 +53,6 @@ export const P3_PRESET_HEMO_SUB = PresetUtils.makePresetGear('P3 Hemo Sub', P3He import P3DanceSubGear from './gear_sets/p3_dancesub.gear.json'; export const P3_PRESET_DANCE_SUB = PresetUtils.makePresetGear('P3 Dance Sub', P3DanceSubGear, { talentTree: 2 }); -export const DefaultRotation = RogueRotation.create({ - exposeArmorFrequency: Rogue_Rotation_Frequency.Never, - minimumComboPointsExposeArmor: 2, - tricksOfTheTradeFrequency: Rogue_Rotation_Frequency.Maintain, - assassinationFinisherPriority: Rogue_Rotation_AssassinationPriority.EnvenomRupture, - combatBuilder: Rogue_Rotation_CombatBuilder.SinisterStrike, - combatFinisherPriority: Rogue_Rotation_CombatPriority.RuptureEviscerate, - subtletyBuilder: Rogue_Rotation_SubtletyBuilder.Hemorrhage, - subtletyFinisherPriority: Rogue_Rotation_SubtletyPriority.SubtletyEviscerate, - minimumComboPointsPrimaryFinisher: 4, - minimumComboPointsSecondaryFinisher: 4, -}); - import MutilateApl from './apls/mutilate.apl.json' export const ROTATION_PRESET_MUTILATE = PresetUtils.makePresetAPLRotation('Mutilate', MutilateApl, { talentTree: 0 }); import MutilateExposeApl from './apls/mutilate_expose.apl.json' diff --git a/ui/rogue/sim.ts b/ui/rogue/sim.ts index 50e30cdf2a..c23d324704 100644 --- a/ui/rogue/sim.ts +++ b/ui/rogue/sim.ts @@ -23,12 +23,6 @@ import { IndividualSimUI, registerSpecConfig } from '../core/individual_sim_ui.j import { Rogue_Options_PoisonImbue, - Rogue_Rotation_AssassinationPriority as AssassinationPriority, - Rogue_Rotation_CombatBuilder as CombatBuilder, - Rogue_Rotation_CombatPriority as CombatPriority, - Rogue_Rotation_Frequency as Frequency, - Rogue_Rotation_SubtletyPriority as SubtletyPriority, - RogueMajorGlyph, } from '../core/proto/rogue.js'; import * as IconInputs from '../core/components/icon_inputs.js'; @@ -36,7 +30,6 @@ import * as OtherInputs from '../core/components/other_inputs.js'; import * as RogueInputs from './inputs.js'; import * as Presets from './presets.js'; -import { DefaultOptions } from './presets.js'; const SPEC_CONFIG = registerSpecConfig(Spec.SpecRogue, { cssClass: 'rogue-sim-ui', @@ -81,19 +74,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecRogue, { }, }; }, - (simUI: IndividualSimUI) => { - return { - updateOn: simUI.player.changeEmitter, - getContent: () => { - if (simUI.player.getRotation().combatBuilder == CombatBuilder.Backstab && - simUI.player.getGear().getEquippedItem(ItemSlot.ItemSlotMainHand)?.item.weaponType != WeaponType.WeaponTypeDagger) { - return 'Builder "Backstab" selected, but no dagger equipped.'; - } else { - return ''; - } - }, - }; - }, (simUI: IndividualSimUI) => { return { updateOn: simUI.player.changeEmitter, @@ -149,67 +129,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecRogue, { }, }; }, - (simUI: IndividualSimUI) => { - return { - updateOn: simUI.player.changeEmitter, - getContent: () => { - if (simUI.player.getInFrontOfTarget() && (simUI.player.getRotation().combatBuilder == CombatBuilder.Backstab || - simUI.player.getRotation().openWithGarrote)) { - return 'Option "In Front of Target" selected, but using Backstab or Garrote as builder or opener.'; - } else { - return ''; - } - }, - }; - }, - (simUI: IndividualSimUI) => { - return { - updateOn: simUI.player.changeEmitter, - getContent: () => { - if (simUI.player.getRotation().combatBuilder == CombatBuilder.HemorrhageCombat && !simUI.player.getTalents().hemorrhage) { - return 'Builder "Hemorrhage" selected, but Hemorrhage is not talented.'; - } else { - return ''; - } - }, - }; - }, - (simUI: IndividualSimUI) => { - return { - updateOn: simUI.player.changeEmitter, - getContent: () => { - if (simUI.player.getRotation().useGhostlyStrike && !simUI.player.getMajorGlyphs().includes(RogueMajorGlyph.GlyphOfGhostlyStrike)) { - return '"Use Ghostly Strike" selected, but missing Glyph of Ghostly Strike.'; - } else { - return ''; - } - }, - }; - }, - (simUI: IndividualSimUI) => { - return { - updateOn: simUI.player.changeEmitter, - getContent: () => { - if (simUI.player.getRotation().useFeint && !simUI.player.getMajorGlyphs().includes(RogueMajorGlyph.GlyphOfFeint)) { - return '"Use Feint" selected, but missing Glyph of Feint.'; - } else { - return ''; - } - }, - }; - }, - (simUI: IndividualSimUI) => { - return { - updateOn: simUI.player.changeEmitter, - getContent: () => { - if (simUI.player.getRotation().exposeArmorFrequency == 2 && !simUI.player.getMajorGlyphs().includes(RogueMajorGlyph.GlyphOfExposeArmor) && simUI.player.getTalentTree() == 1) { - return '"Maintain Expose Armor" selected, but missing Glyph of Expose Armor.'; - } else { - return ''; - } - }, - }; - }, (simUI: IndividualSimUI) => { return { updateOn: simUI.player.changeEmitter, @@ -289,8 +208,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecRogue, { }), // Default consumes settings. consumes: Presets.DefaultConsumes, - // Default rotation settings. - rotation: Presets.DefaultRotation, // Default talents. talents: Presets.AssassinationTalents137.data, // Default spec-specific settings. @@ -334,8 +251,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecRogue, { RogueInputs.MainHandImbue, RogueInputs.OffHandImbue, ], - // Inputs to include in the 'Rotation' section on the settings tab. - rotationInputs: RogueInputs.RogueRotationConfig, // Buff and Debuff inputs to include/exclude, overriding the EP-based defaults. includeBuffDebuffInputs: [ IconInputs.SpellCritBuff, @@ -488,37 +403,8 @@ export class RogueSimUI extends IndividualSimUI { constructor(parentElem: HTMLElement, player: Player) { super(parentElem, player, SPEC_CONFIG); this.player.changeEmitter.on((c) => { - const rotation = this.player.getRotation() const options = this.player.getSpecOptions() const encounter = this.sim.encounter - if (this.player.getTalentTree() == 0) { - if (rotation.assassinationFinisherPriority == AssassinationPriority.AssassinationPriorityUnknown) { - rotation.assassinationFinisherPriority = Presets.DefaultRotation.assassinationFinisherPriority; - } - rotation.combatFinisherPriority = CombatPriority.CombatPriorityUnknown; - rotation.combatBuilder = CombatBuilder.SinisterStrike; - rotation.subtletyFinisherPriority = SubtletyPriority.SubtletyPriorityUnknown; - options.honorOfThievesCritRate = -1; - } else if (this.player.getTalentTree() == 1) { - if (rotation.combatFinisherPriority == CombatPriority.CombatPriorityUnknown) { - rotation.combatFinisherPriority = Presets.DefaultRotation.combatFinisherPriority; - rotation.combatBuilder = Presets.DefaultRotation.combatBuilder; - } - rotation.assassinationFinisherPriority = AssassinationPriority.AssassinationPriorityUnknown; - rotation.subtletyFinisherPriority = SubtletyPriority.SubtletyPriorityUnknown; - options.honorOfThievesCritRate = -1; - } else { - if (rotation.subtletyFinisherPriority == SubtletyPriority.SubtletyPriorityUnknown) { - rotation.subtletyFinisherPriority = Presets.DefaultRotation.subtletyFinisherPriority; - } - rotation.assassinationFinisherPriority = AssassinationPriority.AssassinationPriorityUnknown; - rotation.combatFinisherPriority = CombatPriority.CombatPriorityUnknown; - rotation.combatBuilder = CombatBuilder.SinisterStrike; - if (options.honorOfThievesCritRate == -1) { - options.honorOfThievesCritRate = DefaultOptions.honorOfThievesCritRate - } - } - this.player.setRotation(c, rotation) if (!options.applyPoisonsManually) { const mhWeaponSpeed = this.player.getGear().getEquippedItem(ItemSlot.ItemSlotMainHand)?.item.weaponSpeed; const ohWeaponSpeed = this.player.getGear().getEquippedItem(ItemSlot.ItemSlotOffHand)?.item.weaponSpeed; @@ -541,17 +427,8 @@ export class RogueSimUI extends IndividualSimUI { this.player.setSpecOptions(c, options) }); this.sim.encounter.changeEmitter.on((c) => { - const rotation = this.player.getRotation() const options = this.player.getSpecOptions() const encounter = this.sim.encounter - if (this.sim.encounter.targets.length >= 3) { - if (rotation.multiTargetSliceFrequency == Frequency.FrequencyUnknown) { - rotation.multiTargetSliceFrequency = Presets.DefaultRotation.multiTargetSliceFrequency; - } - } else { - rotation.multiTargetSliceFrequency = Frequency.FrequencyUnknown; - } - this.player.setRotation(c, rotation) if (!options.applyPoisonsManually) { const mhWeaponSpeed = this.player.getGear().getEquippedItem(ItemSlot.ItemSlotMainHand)?.item.weaponSpeed; const ohWeaponSpeed = this.player.getGear().getEquippedItem(ItemSlot.ItemSlotOffHand)?.item.weaponSpeed; diff --git a/ui/scss/core/components/individual_sim_ui/_custom_rotation_picker.scss b/ui/scss/core/components/individual_sim_ui/_custom_rotation_picker.scss deleted file mode 100644 index 39966e9f1f..0000000000 --- a/ui/scss/core/components/individual_sim_ui/_custom_rotation_picker.scss +++ /dev/null @@ -1,33 +0,0 @@ -.custom-rotation-picker-root { - .input-root.custom-spells-picker { - flex-wrap: wrap; - align-items: flex-start !important; - - .list-picker-title { - width: unset; - padding: 0; - border: 0; - } - - .list-picker-items { - width: unset; - } - - .list-picker-new-button { - width: 100%; - } - } -} - -.custom-spell-picker-root { - display: flex; - align-items: center; - - &> :not(:last-child) { - margin-right: map.get($spacers, 2); - } - - .number-picker-input { - width: 100% !important; - } -} \ No newline at end of file diff --git a/ui/scss/core/components/individual_sim_ui/_settings_tab.scss b/ui/scss/core/components/individual_sim_ui/_settings_tab.scss index 4bc494696a..daf2b54117 100644 --- a/ui/scss/core/components/individual_sim_ui/_settings_tab.scss +++ b/ui/scss/core/components/individual_sim_ui/_settings_tab.scss @@ -1,6 +1,5 @@ @use "sass:map"; -@import "./custom_rotation_picker"; @import "./consumes_picker"; @import "./cooldowns_picker"; diff --git a/ui/shadow_priest/inputs.ts b/ui/shadow_priest/inputs.ts index 4bae63e95d..fa6f1ceef4 100644 --- a/ui/shadow_priest/inputs.ts +++ b/ui/shadow_priest/inputs.ts @@ -1,8 +1,6 @@ import { Spec } from '../core/proto/common.js'; import { ShadowPriest_Options_Armor as Armor, - ShadowPriest_Rotation_RotationType as RotationType, - ShadowPriest_Rotation_PreCastOption as precastType } from '../core/proto/priest.js'; import { ActionId } from '../core/proto_utils/action_id.js'; @@ -18,44 +16,3 @@ export const ArmorInput = InputHelpers.makeSpecOptionsEnumIconInput({ - fieldName: 'useMindBlast', - id: ActionId.fromSpellId(48127), -}); - -export const ShadowWordDeathInput = InputHelpers.makeSpecOptionsBooleanIconInput({ - fieldName: 'useShadowWordDeath', - id: ActionId.fromSpellId(48158), -}); - -export const ShadowfiendInput = InputHelpers.makeSpecOptionsBooleanIconInput({ - fieldName: 'useShadowfiend', - id: ActionId.fromSpellId(34433), -}); - -export const ShadowPriestRotationConfig = { - inputs: [ - InputHelpers.makeRotationEnumInput({ - fieldName: 'rotationType', - label: 'Rotation Type', - labelTooltip: 'Choose how to clip your mindflay. Basic will never clip. Clipping will clip for other spells and use a 2xMF2 when there is time for 4 ticks. Ideal will evaluate the DPS gain of every action to determine MF actions.', - values: [ - //{ name: 'Basic', value: RotationType.Basic }, - //{ name: 'Clipping', value: RotationType.Clipping }, - { name: 'Ideal', value: RotationType.Ideal }, - { name: 'AoE', value: RotationType.AoE }, - ], - }), - InputHelpers.makeRotationEnumInput({ - fieldName: 'precastType', - label: 'PreCast Spell', - labelTooltip: 'Choose which spell you want to Precast', - values: [ - { name: "None", value: precastType.Nothing }, - { name: 'Vampiric Touch', value: precastType.PrecastVt }, - { name: 'Mind Blast', value: precastType.PrecastMb }, - ], - }), - ], -}; diff --git a/ui/shadow_priest/presets.ts b/ui/shadow_priest/presets.ts index b030140a32..f58b46cb1e 100644 --- a/ui/shadow_priest/presets.ts +++ b/ui/shadow_priest/presets.ts @@ -14,9 +14,7 @@ import { SavedTalents } from '../core/proto/ui.js'; import { ShadowPriest_Options_Armor as Armor, - ShadowPriest_Rotation as Rotation, ShadowPriest_Options as Options, - ShadowPriest_Rotation_RotationType, PriestMajorGlyph as MajorGlyph, PriestMinorGlyph as MinorGlyph, } from '../core/proto/priest.js'; @@ -38,11 +36,6 @@ export const P3_PRESET = PresetUtils.makePresetGear('P3 Preset', P3Gear); import P4Gear from './gear_sets/p4.gear.json'; export const P4_PRESET = PresetUtils.makePresetGear('P4 Preset', P4Gear); -export const DefaultRotation = Rotation.create({ - rotationType: ShadowPriest_Rotation_RotationType.Ideal, -}); - - import DefaultApl from './apls/default.apl.json' export const ROTATION_PRESET_DEFAULT = PresetUtils.makePresetAPLRotation('Default', DefaultApl); import AOE24Apl from './apls/aoe_2_4.apl.json' diff --git a/ui/shadow_priest/sim.ts b/ui/shadow_priest/sim.ts index 45d5c2198e..2c496d09d1 100644 --- a/ui/shadow_priest/sim.ts +++ b/ui/shadow_priest/sim.ts @@ -77,8 +77,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecShadowPriest, { }), // Default consumes settings. consumes: Presets.DefaultConsumes, - // Default rotation settings. - rotation: Presets.DefaultRotation, // Default talents. talents: Presets.StandardTalents.data, // Default spec-specific settings. @@ -99,13 +97,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecShadowPriest, { playerIconInputs: [ ShadowPriestInputs.ArmorInput, ], - rotationIconInputs: [ - ShadowPriestInputs.MindBlastInput, - ShadowPriestInputs.ShadowWordDeathInput, - ShadowPriestInputs.ShadowfiendInput, - ], - // Inputs to include in the 'Rotation' section on the settings tab. - rotationInputs: ShadowPriestInputs.ShadowPriestRotationConfig, // Buff and Debuff inputs to include/exclude, overriding the EP-based defaults. includeBuffDebuffInputs: [ IconInputs.ReplenishmentBuff, diff --git a/ui/smite_priest/inputs.ts b/ui/smite_priest/inputs.ts index 97ea4aa9f6..0a743a8fad 100644 --- a/ui/smite_priest/inputs.ts +++ b/ui/smite_priest/inputs.ts @@ -2,7 +2,7 @@ import { UnitReference, UnitReference_Type as UnitType } from '../core/proto/com import { Spec } from '../core/proto/common.js'; import { ActionId } from '../core/proto_utils/action_id.js'; import { Player } from '../core/player.js'; -import { EventID, TypedEvent } from '../core/typed_event.js'; +import { EventID } from '../core/typed_event.js'; import * as InputHelpers from '../core/components/input_helpers.js'; @@ -35,34 +35,3 @@ export const Shadowfiend = InputHelpers.makeSpecOptionsBooleanIconInput({ - fieldName: 'useDevouringPlague', - label: 'Use Devouring Plague', - labelTooltip: 'Use Devouring Plague whenever its not active.', - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'useShadowWordDeath', - label: 'Use Shadow Word: Death', - labelTooltip: 'Use Shadow Word: Death whenever off CD.', - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'useMindBlast', - label: 'Use Mind Blast', - labelTooltip: 'Use Mind Blast whenever off CD.', - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'memeDream', - label: 'Meme Dream', - labelTooltip: 'Assumes 2nd Smite Priest in raid, so just spams HF + Smite with permanent HF uptime.', - extraCssClasses: ['within-raid-sim-hide'], - }), - InputHelpers.makeRotationNumberInput({ - fieldName: 'allowedHolyFireDelayMs', - label: 'Allowed Delay for HF', - labelTooltip: 'Time, in milliseconds, the player is allowed to wait for Holy Fire if it is about to come off CD.', - }), - ], -}; diff --git a/ui/smite_priest/presets.ts b/ui/smite_priest/presets.ts index 04e0f2b712..bc8aca5e36 100644 --- a/ui/smite_priest/presets.ts +++ b/ui/smite_priest/presets.ts @@ -7,14 +7,12 @@ import { IndividualBuffs, Potions, RaidBuffs, - Spec, TristateEffect, UnitReference, } from '../core/proto/common.js'; import { SavedTalents } from '../core/proto/ui.js'; import { - SmitePriest_Rotation as Rotation, SmitePriest_Options as Options, PriestMajorGlyph as MajorGlyph, PriestMinorGlyph as MinorGlyph, @@ -31,12 +29,6 @@ export const PRERAID_PRESET = PresetUtils.makePresetGear('Preraid Preset', Prera import P1Gear from './gear_sets/p1.gear.json'; export const P1_PRESET = PresetUtils.makePresetGear('P1 Preset', P1Gear); -export const DefaultRotation = Rotation.create({ - useDevouringPlague: true, - useShadowWordDeath: false, - useMindBlast: false, -}); -export const ROTATION_PRESET_LEGACY_DEFAULT = PresetUtils.makePresetLegacyRotation('Legacy Default', Spec.SpecSmitePriest, DefaultRotation); import DefaultApl from './apls/default.apl.json' export const ROTATION_PRESET_APL = PresetUtils.makePresetAPLRotation('Default', DefaultApl); diff --git a/ui/smite_priest/sim.ts b/ui/smite_priest/sim.ts index 4ab3d1a22e..8e13c4ebb8 100644 --- a/ui/smite_priest/sim.ts +++ b/ui/smite_priest/sim.ts @@ -76,8 +76,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecSmitePriest, { }), // Default consumes settings. consumes: Presets.DefaultConsumes, - // Default rotation settings. - rotation: Presets.DefaultRotation, // Default talents. talents: Presets.StandardTalents.data, // Default spec-specific settings. @@ -95,8 +93,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecSmitePriest, { SmitePriestInputs.InnerFire, SmitePriestInputs.Shadowfiend, ], - // Inputs to include in the 'Rotation' section on the settings tab. - rotationInputs: SmitePriestInputs.SmitePriestRotationConfig, // Buff and Debuff inputs to include/exclude, overriding the EP-based defaults. includeBuffDebuffInputs: [ ], @@ -120,7 +116,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecSmitePriest, { ], // Preset rotations that the user can quickly select. rotations: [ - Presets.ROTATION_PRESET_LEGACY_DEFAULT, Presets.ROTATION_PRESET_APL, ], // Preset gear configurations that the user can quickly select. diff --git a/ui/tank_deathknight/inputs.ts b/ui/tank_deathknight/inputs.ts index f254f20def..c806fc3504 100644 --- a/ui/tank_deathknight/inputs.ts +++ b/ui/tank_deathknight/inputs.ts @@ -1,9 +1,6 @@ import { Spec } from '../core/proto/common.js'; import { - DeathknightTalents as DeathknightTalents, - Deathknight_Rotation as DeathknightRotation, - Deathknight_Options as DeathknightOptions, TankDeathknight_Rotation_OptimizationSetting as OptimizationSetting, TankDeathknight_Rotation_Opener as Opener, TankDeathknight_Rotation_BloodSpell as BloodSpell, diff --git a/ui/tank_deathknight/presets.ts b/ui/tank_deathknight/presets.ts index f761c8c9ea..a2d94ff998 100644 --- a/ui/tank_deathknight/presets.ts +++ b/ui/tank_deathknight/presets.ts @@ -4,19 +4,13 @@ import { Food, Glyphs, Potions, - Spec, } from '../core/proto/common.js'; import { SavedTalents } from '../core/proto/ui.js'; import { - TankDeathknight_Rotation as TankDeathKnightRotation, TankDeathknight_Options as TankDeathKnightOptions, DeathknightMajorGlyph, DeathknightMinorGlyph, - TankDeathknight_Rotation_Opener as Opener, - TankDeathknight_Rotation_OptimizationSetting as OptimizationSetting, - TankDeathknight_Rotation_BloodSpell as BloodSpell, - TankDeathknight_Rotation_Presence as Presence, } from '../core/proto/deathknight.js'; import * as PresetUtils from '../core/preset_utils.js'; @@ -34,15 +28,6 @@ export const P1_FROST_PRESET = PresetUtils.makePresetGear('P1 Frost', P1FrostGea import P2FrostGear from './gear_sets/p2_frost.gear.json'; export const P2_FROST_PRESET = PresetUtils.makePresetGear('P2 Frost', P2FrostGear); -export const DefaultRotation = TankDeathKnightRotation.create({ - opener: Opener.Threat, - optimizationSetting: OptimizationSetting.Hps, - bloodSpell: BloodSpell.BloodStrike, - presence: Presence.Frost, -}); - - -export const BLOOD_LEGACY_PRESET_LEGACY_DEFAULT = PresetUtils.makePresetLegacyRotation('Blood Legacy', Spec.SpecTankDeathknight, DefaultRotation); import BloodIcyTouchApl from './apls/blood_icy_touch.apl.json'; export const BLOOD_IT_SPAM_ROTATION_PRESET_DEFAULT = PresetUtils.makePresetAPLRotation('Blood Icy Touch', BloodIcyTouchApl); import BloodAggroApl from './apls/blood_aggro.apl.json'; diff --git a/ui/tank_deathknight/sim.ts b/ui/tank_deathknight/sim.ts index 5857cfe79e..2002043f1c 100644 --- a/ui/tank_deathknight/sim.ts +++ b/ui/tank_deathknight/sim.ts @@ -116,8 +116,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecTankDeathknight, { }), // Default consumes settings. consumes: Presets.DefaultConsumes, - // Default rotation settings. - rotation: Presets.DefaultRotation, // Default talents. talents: Presets.BloodTalents.data, // Default spec-specific settings. @@ -192,7 +190,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecTankDeathknight, { presets: { // Preset rotations that the user can quickly select. rotations: [ - Presets.BLOOD_LEGACY_PRESET_LEGACY_DEFAULT, Presets.BLOOD_IT_SPAM_ROTATION_PRESET_DEFAULT, Presets.BLOOD_AGGRO_ROTATION_PRESET_DEFAULT, ], diff --git a/ui/warlock/inputs.ts b/ui/warlock/inputs.ts index 9368ca7997..f0763c80bc 100644 --- a/ui/warlock/inputs.ts +++ b/ui/warlock/inputs.ts @@ -1,22 +1,13 @@ import { - Warlock_Options as WarlockOptions, - Warlock_Rotation_Type as RotationType, - Warlock_Rotation_Preset as RotationPreset, - Warlock_Rotation_PrimarySpell as PrimarySpell, - Warlock_Rotation_SecondaryDot as SecondaryDot, - Warlock_Rotation_SpecSpell as SpecSpell, - Warlock_Rotation_Curse as Curse, Warlock_Options_WeaponImbue as WeaponImbue, Warlock_Options_Armor as Armor, Warlock_Options_Summon as Summon, } from '../core/proto/warlock.js'; -import { Spec, Glyphs } from '../core/proto/common.js'; +import { Spec } from '../core/proto/common.js'; import { ActionId } from '../core/proto_utils/action_id.js'; import { Player } from '../core/player.js'; -import { EventID, TypedEvent } from '../core/typed_event.js'; -import * as Presets from './presets.js'; import * as InputHelpers from '../core/components/input_helpers.js'; // Configuration for spec-specific UI elements on the settings tab. @@ -54,210 +45,3 @@ export const PetInput = InputHelpers.makeSpecOptionsEnumIconInput) => player.changeEmitter, }); - -export const PrimarySpellInput = InputHelpers.makeRotationEnumIconInput({ - fieldName: 'primarySpell', - values: [ - { actionId: ActionId.fromSpellId(47809), value: PrimarySpell.ShadowBolt }, - { actionId: ActionId.fromSpellId(47838), value: PrimarySpell.Incinerate }, - { actionId: ActionId.fromSpellId(47836), value: PrimarySpell.Seed }, - ], - setValue: (eventID: EventID, player: Player, newValue: number) => { - const newRotation = player.getRotation(); - if (newValue == PrimarySpell.Seed && newRotation.corruption == true) { - newRotation.corruption = false - } - newRotation.primarySpell = newValue - newRotation.preset = RotationPreset.Manual; - player.setRotation(eventID, newRotation); - }, -}); - -export const SecondaryDotInput = InputHelpers.makeRotationEnumIconInput({ - fieldName: 'secondaryDot', - values: [ - { value: SecondaryDot.NoSecondaryDot }, - { actionId: ActionId.fromSpellId(47811), value: SecondaryDot.Immolate }, - { - actionId: ActionId.fromSpellId(47843), value: SecondaryDot.UnstableAffliction, - showWhen: (player: Player) => player.getTalents().unstableAffliction, - }, - ], - changeEmitter: (player: Player) => player.changeEmitter, - setValue: (eventID: EventID, player: Player, newValue: number) => { - const newRotation = player.getRotation(); - newRotation.secondaryDot = newValue; - newRotation.preset = RotationPreset.Manual; - player.setRotation(eventID, newRotation); - }, -}); - -export const SpecSpellInput = InputHelpers.makeRotationEnumIconInput({ - fieldName: 'specSpell', - values: [ - { value: SpecSpell.NoSpecSpell }, - { - actionId: ActionId.fromSpellId(59164), value: SpecSpell.Haunt, - showWhen: (player: Player) => player.getTalents().haunt, - }, - { - actionId: ActionId.fromSpellId(59172), value: SpecSpell.ChaosBolt, - showWhen: (player: Player) => player.getTalents().chaosBolt, - }, - ], - changeEmitter: (player: Player) => player.changeEmitter, - showWhen: (player: Player) => player.getTalents().haunt || player.getTalents().chaosBolt, - setValue: (eventID: EventID, player: Player, newValue: number) => { - const newRotation = player.getRotation(); - newRotation.specSpell = newValue; - newRotation.preset = RotationPreset.Manual; - player.setRotation(eventID, newRotation); - }, -}); - - -export const CorruptionSpell = { - type: 'icon' as const, - id: ActionId.fromSpellId(47813), - states: 2, - extraCssClasses: [ - 'Corruption-picker', - ], - changedEvent: (player: Player) => player.changeEmitter, - getValue: (player: Player) => player.getRotation().corruption, - setValue: (eventID: EventID, player: Player, newValue: boolean) => { - const newRotation = player.getRotation(); - if (newRotation.primarySpell == PrimarySpell.Seed && newValue == true) { - newRotation.primarySpell = PrimarySpell.ShadowBolt - } - newRotation.corruption = newValue; - newRotation.preset = RotationPreset.Manual; - player.setRotation(eventID, newRotation); - }, -}; - -export const WarlockRotationConfig = { - inputs: [ - { - type: 'enum' as const, - - label: 'Sim presets', - labelTooltip: 'Quick switch between sim spec presets. Will UPDATE TALENTS and SPELLS to defaults.', - values: [ - { name: 'Affliction', value: RotationType.Affliction }, - { name: 'Demonology', value: RotationType.Demonology }, - { name: 'Destruction', value: RotationType.Destruction }, - ], - changedEvent: (player: Player) => player.rotationChangeEmitter, - getValue: (player: Player) => player.getRotation().type, - setValue: (eventID: EventID, player: Player, newValue: number) => { - var newRotation = player.getRotation(); - var newOptions: WarlockOptions; - var newGlyphs: Glyphs; - var newTalents: string; - if (newValue == RotationType.Affliction) { - newTalents = Presets.AfflictionTalents.data.talentsString - newGlyphs = Presets.AfflictionTalents.data.glyphs || Glyphs.create(); - newRotation = Presets.AfflictionRotation - newOptions = Presets.AfflictionOptions - } else if (newValue == RotationType.Demonology) { - newTalents = Presets.DemonologyTalents.data.talentsString - newGlyphs = Presets.DemonologyTalents.data.glyphs || Glyphs.create(); - newRotation = Presets.DemonologyRotation - newOptions = Presets.DemonologyOptions - } else if (newValue == RotationType.Destruction) { - newTalents = Presets.DestructionTalents.data.talentsString - newGlyphs = Presets.DestructionTalents.data.glyphs || Glyphs.create(); - newRotation = Presets.DestructionRotation - newOptions = Presets.DestructionOptions - } - newRotation.type = newValue; - newRotation.preset = RotationPreset.Automatic; - TypedEvent.freezeAllAndDo(() => { - player.setTalentsString(eventID, newTalents); - player.setSpecOptions(eventID, newOptions); - player.setGlyphs(eventID, newGlyphs); - player.setRotation(eventID, newRotation); - }); - }, - }, - - { - type: 'enum' as const, - label: 'Spell & Talent', - labelTooltip: 'Putting it on Automatic will UPDATE talents and spells to defaults.', - values: [ - { name: "Manual", value: RotationPreset.Manual }, - { name: "Automatic", value: RotationPreset.Automatic }, - ], - changedEvent: (player: Player) => player.rotationChangeEmitter, - getValue: (player: Player) => player.getRotation().preset, - setValue: (eventID: EventID, player: Player, newValue: number) => { - var newRotation = player.getRotation(); - if (newValue == RotationPreset.Automatic) { - var newOptions: WarlockOptions; - var newGlyphs: Glyphs; - var newTalents: string; - if (newRotation.type == RotationType.Affliction) { - newTalents = Presets.AfflictionTalents.data.talentsString - newGlyphs = Presets.AfflictionTalents.data.glyphs || Glyphs.create() - newRotation = Presets.AfflictionRotation - newOptions = Presets.AfflictionOptions - } else if (newRotation.type == RotationType.Demonology) { - newTalents = Presets.DemonologyTalents.data.talentsString - newGlyphs = Presets.DemonologyTalents.data.glyphs || Glyphs.create() - newRotation = Presets.DemonologyRotation - newOptions = Presets.DemonologyOptions - } else if (newRotation.type == RotationType.Destruction) { - newTalents = Presets.DestructionTalents.data.talentsString - newGlyphs = Presets.DestructionTalents.data.glyphs || Glyphs.create() - newRotation = Presets.DestructionRotation - newOptions = Presets.DestructionOptions - } - } - newRotation.preset = newValue; - TypedEvent.freezeAllAndDo(() => { - if (newValue == RotationPreset.Automatic) { - player.setTalentsString(eventID, newTalents); - player.setSpecOptions(eventID, newOptions); - player.setGlyphs(eventID, newGlyphs); - } - player.setRotation(eventID, newRotation); - }); - }, - }, - { - type: 'enum' as const, - label: 'Curse', - labelTooltip: 'Manual curse selection.', - values: [ - { name: "None", value: Curse.NoCurse }, - { name: "Elements", value: Curse.Elements }, - { name: "Weakness", value: Curse.Weakness }, - { name: "Doom", value: Curse.Doom }, - { name: "Agony", value: Curse.Agony }, - { name: "Tongues", value: Curse.Tongues } - ], - changedEvent: (player: Player) => player.rotationChangeEmitter, - getValue: (player: Player) => player.getRotation().curse, - setValue: (eventID: EventID, player: Player, newValue: number) => { - const newRotation = player.getRotation(); - newRotation.curse = newValue; - newRotation.preset = RotationPreset.Manual; - player.setRotation(eventID, newRotation); - }, - }, - - InputHelpers.makeRotationBooleanInput({ - fieldName: 'useInfernal', - label: 'Summon Infernal', - labelTooltip: 'Casts Inferno 60s before the fight is over', - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'detonateSeed', - label: 'Detonate Seed on Cast', - labelTooltip: 'Simulates raid doing damage to targets such that seed detonates immediately on cast.', - showWhen: (player: Player) => player.getRotation().primarySpell == PrimarySpell.Seed, - }), - ], -}; diff --git a/ui/warlock/presets.ts b/ui/warlock/presets.ts index 7401555967..fef9006aa3 100644 --- a/ui/warlock/presets.ts +++ b/ui/warlock/presets.ts @@ -10,17 +10,12 @@ import { Debuffs, TristateEffect, Faction, - Spec, Profession, + Profession, } from '../core/proto/common.js'; import { SavedTalents } from '../core/proto/ui.js'; import { - Warlock_Rotation as WarlockRotation, Warlock_Options as WarlockOptions, - Warlock_Rotation_PrimarySpell as PrimarySpell, - Warlock_Rotation_SecondaryDot as SecondaryDot, - Warlock_Rotation_SpecSpell as SpecSpell, - Warlock_Rotation_Curse as Curse, Warlock_Options_WeaponImbue as WeaponImbue, Warlock_Options_Armor as Armor, Warlock_Options_Summon as Summon, @@ -65,43 +60,10 @@ export const P3_DESTRO_HORDE_PRESET = PresetUtils.makePresetGear('P3 Destro [H]' import P4DestroGear from './gear_sets/p4_destro.gear.json'; export const P4_DESTRO_PRESET = PresetUtils.makePresetGear('P4 Destro', P4DestroGear, { tooltip: BIS_TOOLTIP, talentTree: 2 }); -export const AfflictionRotation = WarlockRotation.create({ - primarySpell: PrimarySpell.ShadowBolt, - secondaryDot: SecondaryDot.UnstableAffliction, - specSpell: SpecSpell.Haunt, - curse: Curse.Agony, - corruption: true, - useInfernal: false, - detonateSeed: true, -}); - -export const DemonologyRotation = WarlockRotation.create({ - primarySpell: PrimarySpell.ShadowBolt, - secondaryDot: SecondaryDot.Immolate, - specSpell: SpecSpell.NoSpecSpell, - curse: Curse.Doom, - corruption: true, - useInfernal: false, - detonateSeed: true, -}); - -export const DestructionRotation = WarlockRotation.create({ - primarySpell: PrimarySpell.Incinerate, - secondaryDot: SecondaryDot.Immolate, - specSpell: SpecSpell.ChaosBolt, - curse: Curse.Doom, - corruption: false, - useInfernal: false, - detonateSeed: true, -}); - -export const APL_Affliction_Legacy = PresetUtils.makePresetLegacyRotation('Affliction Legacy', Spec.SpecWarlock, AfflictionRotation, { talentTree: 0 }); import AfflictionApl from './apls/affliction.apl.json'; export const APL_Affliction_Default = PresetUtils.makePresetAPLRotation('Affliction', AfflictionApl, { talentTree: 0 }); -export const APL_Demo_Legacy = PresetUtils.makePresetLegacyRotation('Demo Legacy', Spec.SpecWarlock, DemonologyRotation, { talentTree: 1 }); import DemoApl from './apls/demo.apl.json'; export const APL_Demo_Default = PresetUtils.makePresetAPLRotation('Demo', DemoApl, { talentTree: 1 }); -export const APL_Destro_Legacy = PresetUtils.makePresetLegacyRotation('Destro Legacy', Spec.SpecWarlock, DestructionRotation, { talentTree: 2 }); import DestroApl from './apls/destro.apl.json'; export const APL_Destro_Default = PresetUtils.makePresetAPLRotation('Destro', DestroApl, { talentTree: 2 }); diff --git a/ui/warlock/sim.ts b/ui/warlock/sim.ts index efb04a3d60..35d02c3813 100644 --- a/ui/warlock/sim.ts +++ b/ui/warlock/sim.ts @@ -70,8 +70,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecWarlock, { // Default consumes settings. consumes: Presets.DefaultConsumes, - // Default rotation settings. - rotation: Presets.AfflictionRotation, // Default talents. talents: Presets.AfflictionTalents.data, // Default spec-specific settings. @@ -102,7 +100,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecWarlock, { WarlockInputs.SecondaryDotInput, WarlockInputs.SpecSpellInput, ], - rotationInputs: WarlockInputs.WarlockRotationConfig, // Buff and Debuff inputs to include/exclude, overriding the EP-based defaults. includeBuffDebuffInputs: [ @@ -147,11 +144,8 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecWarlock, { ], // Preset rotations that the user can quickly select. rotations: [ - Presets.APL_Affliction_Legacy, Presets.APL_Affliction_Default, - Presets.APL_Demo_Legacy, Presets.APL_Demo_Default, - Presets.APL_Destro_Legacy, Presets.APL_Destro_Default, ], diff --git a/ui/warrior/inputs.ts b/ui/warrior/inputs.ts index a68d1b04bc..afb05c2303 100644 --- a/ui/warrior/inputs.ts +++ b/ui/warrior/inputs.ts @@ -1,18 +1,8 @@ import { Spec } from '../core/proto/common.js'; import { ActionId } from '../core/proto_utils/action_id.js'; -import { Player } from '../core/player.js'; -import { EventID, TypedEvent } from '../core/typed_event.js'; import { WarriorShout, - WarriorTalents as WarriorTalents, - Warrior, - Warrior_Rotation as WarriorRotation, - Warrior_Rotation_SunderArmor as SunderArmor, - Warrior_Options as WarriorOptions, - Warrior_Rotation_StanceOption as StanceOption, - Warrior_Rotation_SpellOption as SpellOption, - Warrior_Rotation_MainGcd as MainGcd, } from '../core/proto/warrior.js'; import * as InputHelpers from '../core/components/input_helpers.js'; @@ -59,190 +49,3 @@ export const ShoutPicker = InputHelpers.makeSpecOptionsEnumIconInput({ - fieldName: 'useMs', - label: 'Use Mortal Strike', - labelTooltip: 'Use Mortal Strike when rage threshold is met.', - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), - showWhen: (player: Player) => player.getTalentTree() == 0 && !player.getRotation().customRotationOption, - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'useCleave', - label: 'Use Cleave', - labelTooltip: 'Use Cleave instead of Heroic Strike.', - showWhen: (player: Player) => !player.getRotation().customRotationOption, - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'useRend', - label: 'Use Rend', - labelTooltip: 'Use Rend when rage threshold is met and the debuff duration is less than refresh time.', - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), - showWhen: (player: Player) => !player.getRotation().customRotationOption, - }), - - InputHelpers.makeRotationBooleanInput({ - fieldName: 'useOverpower', - label: 'Use Overpower', - labelTooltip: 'Use Overpower whenever it is available on an open GCD.', - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), - showWhen: (player: Player) => player.getTalentTree() == 1 && !player.getRotation().customRotationOption, - }), - - InputHelpers.makeRotationEnumInput({ - fieldName: 'mainGcd', - label: 'Main GCD', - labelTooltip: 'Main GCD ability that will be prioritized above other abilities.', - values: [ - { name: 'Slam', value: MainGcd.Slam }, - { name: 'Bloodthirst', value: MainGcd.Bloodthirst }, - { name: 'Whirlwind', value: MainGcd.Whirlwind }, - ], - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), - showWhen: (player: Player) => player.getTalentTree() == 1 && !player.getRotation().customRotationOption, - }), - InputHelpers.makeRotationNumberInput({ - fieldName: 'msRageThreshold', - label: 'Mortal Strike rage threshold', - labelTooltip: 'Mortal Strike when rage is above:', - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), - showWhen: (player: Player) => (player.getRotation().useMs || player.getRotation().customRotationOption) && player.getTalentTree() == 0, - }), - InputHelpers.makeRotationNumberInput({ - fieldName: 'slamRageThreshold', - label: 'Slam rage threshold', - labelTooltip: 'Slam when rage is above:', - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), - showWhen: (player: Player) => (player.getRotation().useMs || player.getRotation().customRotationOption) && player.getTalentTree() == 0, - }), - InputHelpers.makeRotationNumberInput({ - fieldName: 'bloodsurgeDurationThreshold', - label: 'Exp Slam: Bloodsurge duration threshold (s)', - labelTooltip: 'Cast Exp Slam when Bloodsurge duration is below (seconds):', - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), - showWhen: (player: Player) => player.getRotation().customRotationOption && player.getTalentTree() == 1, - }), - InputHelpers.makeRotationNumberInput({ - fieldName: 'hsRageThreshold', - label: 'HS rage threshold', - labelTooltip: 'Heroic Strike when rage is above:', - }), - InputHelpers.makeRotationNumberInput({ - fieldName: 'rendHealthThresholdAbove', - label: 'Rend health threshold (%)', - labelTooltip: 'Rend will only be used when boss health is above this value in %.', - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), - showWhen: (player: Player) => (player.getRotation().useRend == true || player.getRotation().customRotationOption), - }), - InputHelpers.makeRotationNumberInput({ - fieldName: 'rendRageThresholdBelow', - label: 'Rend rage threshold below', - labelTooltip: 'Rend will only be used when rage is smaller than this value.', - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), - showWhen: (player: Player) => (player.getRotation().useRend == true || player.getRotation().customRotationOption) && player.getTalentTree() == 1, - }), - InputHelpers.makeRotationNumberInput({ - fieldName: 'rendCdThreshold', - label: 'Rend Refresh Time (s)', - labelTooltip: 'Refresh Rend when the remaining duration is less than this amount of time (seconds).', - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), - showWhen: (player: Player) => player.getRotation().useRend == true || player.getRotation().customRotationOption, - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'useHsDuringExecute', - label: 'HS during Execute Phase', - labelTooltip: 'Use Heroic Strike during Execute Phase.', - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'useBtDuringExecute', - label: 'BT during Execute Phase', - labelTooltip: 'Use Bloodthirst during Execute Phase.', - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), - showWhen: (player: Player) => player.getTalentTree() == 1, - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'useWwDuringExecute', - label: 'WW during Execute Phase', - labelTooltip: 'Use Whirlwind during Execute Phase.', - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), - showWhen: (player: Player) => player.getTalentTree() == 1, - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'useSlamOverExecute', - label: 'Slam during Execute Phase', - labelTooltip: 'Use Slam Over Execute when Bloodsurge Procs in Execute Phase.', - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), - showWhen: (player: Player) => player.getTalentTree() == 1, - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'executePhaseOverpower', - label: 'Overpower in Execute Phase', - labelTooltip: 'Use Overpower instead of Execute whenever it is available.', - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), - showWhen: (player: Player) => (player.getRotation().useOverpower == true || player.getRotation().customRotationOption) && player.getTalentTree() == 1, - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'spamExecute', - label: 'Spam Execute', - labelTooltip: 'Use Execute whenever possible during Execute Phase.', - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), - showWhen: (player: Player) => player.getTalentTree() == 0, - }), - InputHelpers.makeRotationEnumInput({ - fieldName: 'sunderArmor', - label: 'Sunder Armor', - values: [ - { name: 'Never', value: SunderArmor.SunderArmorNone }, - { name: 'Help Stack', value: SunderArmor.SunderArmorHelpStack }, - { name: 'Maintain Debuff', value: SunderArmor.SunderArmorMaintain }, - ], - }), - InputHelpers.makeRotationEnumInput({ - fieldName: 'stanceOption', - label: 'Stance Option', - labelTooltip: 'Stance to stay on. The default for Fury (Bloodthirst) is Berserker Stance and Battle Stance for everything else.', - values: [ - { name: 'Default', value: StanceOption.DefaultStance }, - { name: 'Battle Stance', value: StanceOption.BattleStance }, - { name: 'Berserker Stance', value: StanceOption.BerserkerStance }, - ], - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'maintainDemoShout', - label: 'Maintain Demo Shout', - labelTooltip: 'Keep Demo Shout active on the primary target.', - }), - InputHelpers.makeRotationBooleanInput({ - fieldName: 'maintainThunderClap', - label: 'Maintain Thunder Clap', - labelTooltip: 'Keep Thunder Clap active on the primary target.', - }), - - InputHelpers.makeRotationBooleanInput({ - fieldName: 'customRotationOption', - label: 'Custom Rotation (Advanced)', - labelTooltip: 'Create your own rotation action priority list.', - showWhen: (player: Player) => player.sim.getShowExperimental(), - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), - }), - - InputHelpers.makeCustomRotationInput({ - fieldName: 'customRotation', - numColumns: 3, - showWhen: (player: Player) => player.getRotation().customRotationOption && player.sim.getShowExperimental(), - values: [ - { actionId: ActionId.fromSpellId(23881), value: SpellOption.BloodthirstCustom }, - { actionId: ActionId.fromSpellId(1680), value: SpellOption.WhirlwindCustom }, - { actionId: ActionId.fromSpellId(47475), value: SpellOption.SlamCustom }, - { actionId: ActionId.fromSpellId(47475), value: SpellOption.SlamExpiring, text: "Exp", showWhen: (player: Player) => player.getTalentTree() == 1, }, - { actionId: ActionId.fromSpellId(47486), value: SpellOption.MortalStrike }, - { actionId: ActionId.fromSpellId(47465), value: SpellOption.Rend }, - { actionId: ActionId.fromSpellId(7384), value: SpellOption.Overpower }, - { actionId: ActionId.fromSpellId(47471), value: SpellOption.Execute }, - { actionId: ActionId.fromSpellId(47502), value: SpellOption.ThunderClap }, - ], - }), - ], -}; diff --git a/ui/warrior/presets.ts b/ui/warrior/presets.ts index da5f32fdbe..51ca2e0e2a 100644 --- a/ui/warrior/presets.ts +++ b/ui/warrior/presets.ts @@ -10,13 +10,9 @@ import { SavedTalents } from '../core/proto/ui.js'; import { WarriorShout, - Warrior_Rotation as WarriorRotation, - Warrior_Rotation_SunderArmor as SunderArmor, Warrior_Options as WarriorOptions, WarriorMajorGlyph, WarriorMinorGlyph, - Warrior_Rotation_StanceOption as StanceOption, - Warrior_Rotation_MainGcd as MainGcd, } from '../core/proto/warrior.js'; import * as PresetUtils from '../core/preset_utils.js'; @@ -58,43 +54,6 @@ export const P4_FURY_PRESET_ALLIANCE = PresetUtils.makePresetGear('P4 Fury [A]', import P4FuryHordeGear from './gear_sets/p4_fury_horde.gear.json'; export const P4_FURY_PRESET_HORDE = PresetUtils.makePresetGear('P4 Fury [H]', P4FuryHordeGear, { talentTrees: [1,2], faction: Faction.Horde }); -export const DefaultRotation = WarriorRotation.create({ - useRend: true, - useCleave: false, - useOverpower: false, - executePhaseOverpower: false, - - mainGcd: MainGcd.Bloodthirst, - - sunderArmor: SunderArmor.SunderArmorMaintain, - - hsRageThreshold: 12, - rendHealthThresholdAbove: 20, - rendRageThresholdBelow: 100, - slamRageThreshold: 25, - rendCdThreshold: 0, - useHsDuringExecute: true, - useBtDuringExecute: true, - useWwDuringExecute: true, - useSlamOverExecute: true, - stanceOption: StanceOption.DefaultStance, -}); - -export const ArmsRotation = WarriorRotation.create({ - useRend: true, - useMs: true, - useCleave: false, - sunderArmor: SunderArmor.SunderArmorMaintain, - msRageThreshold: 30, - slamRageThreshold: 25, - hsRageThreshold: 50, - rendCdThreshold: 0, - rendHealthThresholdAbove: 100, - useHsDuringExecute: true, - spamExecute: true, - stanceOption: StanceOption.DefaultStance, -}); - import FuryApl from './apls/fury.apl.json'; export const ROTATION_FURY = PresetUtils.makePresetAPLRotation('Fury', FuryApl, { talentTree: 1 }); import FurySunderApl from './apls/fury_sunder.apl.json'; diff --git a/ui/warrior/sim.ts b/ui/warrior/sim.ts index bf98f00ba9..d81b417f74 100644 --- a/ui/warrior/sim.ts +++ b/ui/warrior/sim.ts @@ -102,8 +102,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecWarrior, { }), // Default consumes settings. consumes: Presets.DefaultConsumes, - // Default rotation settings. - rotation: Presets.DefaultRotation, // Default talents. talents: Presets.FuryTalents.data, // Default spec-specific settings. @@ -145,8 +143,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecWarrior, { WarriorInputs.Recklessness, WarriorInputs.ShatteringThrow, ], - // Inputs to include in the 'Rotation' section on the settings tab. - rotationInputs: WarriorInputs.WarriorRotationConfig, // Buff and Debuff inputs to include/exclude, overriding the EP-based defaults. includeBuffDebuffInputs: [ // just for Bryntroll From 264b43641001db92758340cd662f7c2920d168d3 Mon Sep 17 00:00:00 2001 From: James Tanner Date: Fri, 29 Dec 2023 13:35:22 +0900 Subject: [PATCH 02/28] Rename getRotation() --> getSimpleRotation() for clarity --- .../individual_sim_ui/cooldowns_picker.ts | 26 ++--- .../individual_sim_ui/rotation_tab.ts | 2 +- ui/core/components/input_helpers.ts | 24 ++--- ui/core/components/other_inputs.ts | 8 +- ui/core/player.ts | 95 +++++++++---------- ui/feral_druid/inputs.ts | 14 +-- ui/hunter/inputs.ts | 4 +- ui/warlock/sim.ts | 7 -- 8 files changed, 83 insertions(+), 97 deletions(-) diff --git a/ui/core/components/individual_sim_ui/cooldowns_picker.ts b/ui/core/components/individual_sim_ui/cooldowns_picker.ts index c682bcc575..7c02bf5dba 100644 --- a/ui/core/components/individual_sim_ui/cooldowns_picker.ts +++ b/ui/core/components/individual_sim_ui/cooldowns_picker.ts @@ -18,7 +18,7 @@ export class CooldownsPicker extends Component { this.player = player; this.cooldownPickers = []; - TypedEvent.onAny([this.player.cooldownsChangeEmitter, this.player.sim.unitMetadataEmitter]).on(eventID => { + TypedEvent.onAny([this.player.rotationChangeEmitter, this.player.sim.unitMetadataEmitter]).on(eventID => { this.update(); }); this.update(); @@ -26,7 +26,7 @@ export class CooldownsPicker extends Component { private update() { this.rootElem.innerHTML = ''; - const cooldowns = this.player.getCooldowns().cooldowns; + const cooldowns = this.player.getSimpleCooldowns().cooldowns; this.cooldownPickers = []; for (let i = 0; i < cooldowns.length + 1; i++) { @@ -63,9 +63,9 @@ export class CooldownsPicker extends Component { const deleteButton = deleteButtonFragment.children[0] as HTMLElement; const deleteButtonTooltip = Tooltip.getOrCreateInstance(deleteButton, {title: 'Delete Cooldown'}); deleteButton.addEventListener('click', event => { - const newCooldowns = this.player.getCooldowns(); + const newCooldowns = this.player.getSimpleCooldowns(); newCooldowns.cooldowns.splice(i, 1); - this.player.setCooldowns(TypedEvent.nextEventID(), newCooldowns); + this.player.setSimpleCooldowns(TypedEvent.nextEventID(), newCooldowns); deleteButtonTooltip.hide(); }); row.appendChild(deleteButton); @@ -90,10 +90,10 @@ export class CooldownsPicker extends Component { equals: (a: ActionIdProto, b: ActionIdProto) => ActionIdProto.equals(a, b), zeroValue: ActionIdProto.create(), backupIconUrl: (value: ActionIdProto) => ActionId.fromProto(value), - changedEvent: (player: Player) => player.cooldownsChangeEmitter, - getValue: (player: Player) => player.getCooldowns().cooldowns[cooldownIndex]?.id || ActionIdProto.create(), + changedEvent: (player: Player) => player.rotationChangeEmitter, + getValue: (player: Player) => player.getSimpleCooldowns().cooldowns[cooldownIndex]?.id || ActionIdProto.create(), setValue: (eventID: EventID, player: Player, newValue: ActionIdProto) => { - const newCooldowns = player.getCooldowns(); + const newCooldowns = player.getSimpleCooldowns(); while (newCooldowns.cooldowns.length < cooldownIndex) { newCooldowns.cooldowns.push(Cooldown.create()); @@ -103,7 +103,7 @@ export class CooldownsPicker extends Component { timings: [], }); - player.setCooldowns(eventID, newCooldowns); + player.setSimpleCooldowns(eventID, newCooldowns); }, }); return actionPicker; @@ -115,17 +115,17 @@ export class CooldownsPicker extends Component { 'cooldown-timings-picker', ], placeholder: '20, 40, ...', - changedEvent: (player: Player) => player.cooldownsChangeEmitter, + changedEvent: (player: Player) => player.rotationChangeEmitter, getValue: (player: Player) => { - return player.getCooldowns().cooldowns[cooldownIndex]?.timings || []; + return player.getSimpleCooldowns().cooldowns[cooldownIndex]?.timings || []; }, setValue: (eventID: EventID, player: Player, newValue: Array) => { - const newCooldowns = player.getCooldowns(); + const newCooldowns = player.getSimpleCooldowns(); newCooldowns.cooldowns[cooldownIndex].timings = newValue; - player.setCooldowns(eventID, newCooldowns); + player.setSimpleCooldowns(eventID, newCooldowns); }, enableWhen: (player: Player) => { - const curCooldown = player.getCooldowns().cooldowns[cooldownIndex]; + const curCooldown = player.getSimpleCooldowns().cooldowns[cooldownIndex]; return curCooldown && !ActionIdProto.equals(curCooldown.id, ActionIdProto.create()); }, }); diff --git a/ui/core/components/individual_sim_ui/rotation_tab.ts b/ui/core/components/individual_sim_ui/rotation_tab.ts index e962848ee1..81742a4f7b 100644 --- a/ui/core/components/individual_sim_ui/rotation_tab.ts +++ b/ui/core/components/individual_sim_ui/rotation_tab.ts @@ -197,7 +197,7 @@ export class RotationTab extends SimTab { player.setAplRotation(eventID, newRotation.rotation || APLRotation.create()); }); }, - changeEmitters: [this.simUI.player.rotationChangeEmitter, this.simUI.player.cooldownsChangeEmitter, this.simUI.player.talentsChangeEmitter], + changeEmitters: [this.simUI.player.rotationChangeEmitter, this.simUI.player.talentsChangeEmitter], equals: (a: SavedRotation, b: SavedRotation) => { // Uncomment this to debug equivalence checks with preset rotations (e.g. the chip doesn't highlight) //console.log(`Rot A: ${SavedRotation.toJsonString(a, {prettySpaces: 2})}\n\nRot B: ${SavedRotation.toJsonString(b, {prettySpaces: 2})}`); diff --git a/ui/core/components/input_helpers.ts b/ui/core/components/input_helpers.ts index 4058200c79..4ad78bfd18 100644 --- a/ui/core/components/input_helpers.ts +++ b/ui/core/components/input_helpers.ts @@ -80,11 +80,11 @@ export function makeRotationBooleanInput(config: PlayerBo label: config.label, labelTooltip: config.labelTooltip, getModObject: (player: Player) => player, - getValue: config.getValue || ((player: Player) => player.getRotation()[config.fieldName] as unknown as boolean), + getValue: config.getValue || ((player: Player) => player.getSimpleRotation()[config.fieldName] as unknown as boolean), setValue: config.setValue || ((eventID: EventID, player: Player, newVal: boolean) => { - const newMessage = player.getRotation(); + const newMessage = player.getSimpleRotation(); (newMessage[config.fieldName] as unknown as boolean) = newVal; - player.setRotation(eventID, newMessage); + player.setSimpleRotation(eventID, newMessage); }), changedEvent: config.changeEmitter || ((player: Player) => player.rotationChangeEmitter), enableWhen: config.enableWhen, @@ -163,11 +163,11 @@ export function makeRotationNumberInput(config: PlayerNum float: config.float, positive: config.positive, getModObject: (player: Player) => player, - getValue: config.getValue || ((player: Player) => player.getRotation()[config.fieldName] as unknown as number), + getValue: config.getValue || ((player: Player) => player.getSimpleRotation()[config.fieldName] as unknown as number), setValue: config.setValue || ((eventID: EventID, player: Player, newVal: number) => { - const newMessage = player.getRotation(); + const newMessage = player.getSimpleRotation(); (newMessage[config.fieldName] as unknown as number) = newVal; - player.setRotation(eventID, newMessage); + player.setSimpleRotation(eventID, newMessage); }), changedEvent: config.changeEmitter || ((player: Player) => player.rotationChangeEmitter), enableWhen: config.enableWhen, @@ -245,11 +245,11 @@ export function makeRotationEnumInput(config: PlayerEn labelTooltip: config.labelTooltip, values: config.values, getModObject: (player: Player) => player, - getValue: config.getValue || ((player: Player) => player.getRotation()[config.fieldName] as unknown as number), + getValue: config.getValue || ((player: Player) => player.getSimpleRotation()[config.fieldName] as unknown as number), setValue: config.setValue || ((eventID: EventID, player: Player, newVal: number) => { - const newMessage = player.getRotation(); + const newMessage = player.getSimpleRotation(); (newMessage[config.fieldName] as unknown as number) = newVal; - player.setRotation(eventID, newMessage); + player.setSimpleRotation(eventID, newMessage); }), changedEvent: config.changeEmitter || ((player: Player) => player.rotationChangeEmitter), enableWhen: config.enableWhen, @@ -434,11 +434,11 @@ export function makeRotationEnumIconInput(config: Play showWhen: config.showWhen, zeroValue: 0 as unknown as T, getModObject: (player: Player) => player, - getValue: config.getValue || ((player: Player) => player.getRotation()[config.fieldName] as unknown as T), + getValue: config.getValue || ((player: Player) => player.getSimpleRotation()[config.fieldName] as unknown as T), setValue: config.setValue || ((eventID: EventID, player: Player, newVal: T) => { - const newMessage = player.getRotation(); + const newMessage = player.getSimpleRotation(); (newMessage[config.fieldName] as unknown as T) = newVal; - player.setRotation(eventID, newMessage); + player.setSimpleRotation(eventID, newMessage); }), changedEvent: config.changeEmitter || ((player: Player) => player.rotationChangeEmitter), extraCssClasses: config.extraCssClasses, diff --git a/ui/core/components/other_inputs.ts b/ui/core/components/other_inputs.ts index fcac703cd2..2b37af2c48 100644 --- a/ui/core/components/other_inputs.ts +++ b/ui/core/components/other_inputs.ts @@ -250,12 +250,12 @@ export const HpPercentForDefensives = {

% of Maximum Health, below which defensive cooldowns are allowed to be used.

If set to 0, this restriction is disabled.

`, - changedEvent: (player: Player) => player.cooldownsChangeEmitter, - getValue: (player: Player) => player.getCooldowns().hpPercentForDefensives * 100, + changedEvent: (player: Player) => player.rotationChangeEmitter, + getValue: (player: Player) => player.getSimpleCooldowns().hpPercentForDefensives * 100, setValue: (eventID: EventID, player: Player, newValue: number) => { - const cooldowns = player.getCooldowns(); + const cooldowns = player.getSimpleCooldowns(); cooldowns.hpPercentForDefensives = newValue / 100; - player.setCooldowns(eventID, cooldowns); + player.setSimpleCooldowns(eventID, cooldowns); }, }; diff --git a/ui/core/player.ts b/ui/core/player.ts index 3a5e80b252..7690346209 100644 --- a/ui/core/player.ts +++ b/ui/core/player.ts @@ -246,12 +246,10 @@ export class Player { private race: Race; private profession1: Profession = 0; private profession2: Profession = 0; - private rotation: SpecRotation; aplRotation: APLRotation = APLRotation.create(); private talentsString: string = ''; private glyphs: Glyphs = Glyphs.create(); private specOptions: SpecOptions; - private cooldowns: Cooldowns = Cooldowns.create(); private reactionTime: number = 0; private channelClipDelay: number = 0; private inFrontOfTarget: boolean = false; @@ -290,7 +288,6 @@ export class Player { readonly talentsChangeEmitter = new TypedEvent('PlayerTalents'); readonly glyphsChangeEmitter = new TypedEvent('PlayerGlyphs'); readonly specOptionsChangeEmitter = new TypedEvent('PlayerSpecOptions'); - readonly cooldownsChangeEmitter = new TypedEvent('PlayerCooldowns'); readonly inFrontOfTargetChangeEmitter = new TypedEvent('PlayerInFrontOfTarget'); readonly distanceFromTargetChangeEmitter = new TypedEvent('PlayerDistanceFromTarget'); readonly healingModelChangeEmitter = new TypedEvent('PlayerHealingModel'); @@ -312,7 +309,6 @@ export class Player { this.spec = spec; this.race = specToEligibleRaces[this.spec][0]; this.specTypeFunctions = specTypeFunctions[this.spec] as SpecTypeFunctions; - this.rotation = this.specTypeFunctions.rotationCreate(); this.specOptions = this.specTypeFunctions.optionsCreate(); const specConfig = SPEC_CONFIGS[this.spec] as PlayerConfig; @@ -343,7 +339,6 @@ export class Player { this.talentsChangeEmitter, this.glyphsChangeEmitter, this.specOptionsChangeEmitter, - this.cooldownsChangeEmitter, this.miscOptionsChangeEmitter, this.inFrontOfTargetChangeEmitter, this.distanceFromTargetChangeEmitter, @@ -597,24 +592,6 @@ export class Player { this.consumesChangeEmitter.emit(eventID); } - getCooldowns(): Cooldowns { - // Make a defensive copy - return Cooldowns.clone(this.aplRotation.simple?.cooldowns || Cooldowns.create()); - } - - setCooldowns(eventID: EventID, newCooldowns: Cooldowns) { - if (Cooldowns.equals(this.getCooldowns(), newCooldowns)) - return; - - if (!this.aplRotation.simple) { - this.aplRotation.simple = SimpleRotation.create(); - } - this.aplRotation.simple.cooldowns = newCooldowns; - this.rotationChangeEmitter.emit(eventID); - - this.cooldownsChangeEmitter.emit(eventID); - } - canDualWield2H(): boolean { return this.getClass() == Class.ClassWarrior && (this.getTalents() as SpecTalents).titansGrip; } @@ -751,7 +728,15 @@ export class Player { return this.getMeleeCritCapInfo().playerCritCapDelta } - getRotation(): SpecRotation { + setAplRotation(eventID: EventID, newRotation: APLRotation) { + if (APLRotation.equals(newRotation, this.aplRotation)) + return; + + this.aplRotation = APLRotation.clone(newRotation); + this.rotationChangeEmitter.emit(eventID); + } + + getSimpleRotation(): SpecRotation { const jsonStr = this.aplRotation.simple?.specRotationJson || ''; if (!jsonStr) { return this.specTypeFunctions.rotationCreate(); @@ -766,8 +751,8 @@ export class Player { } } - setRotation(eventID: EventID, newRotation: SpecRotation) { - if (this.specTypeFunctions.rotationEquals(newRotation, this.getRotation())) + setSimpleRotation(eventID: EventID, newRotation: SpecRotation) { + if (this.specTypeFunctions.rotationEquals(newRotation, this.getSimpleRotation())) return; if (!this.aplRotation.simple) { @@ -778,11 +763,19 @@ export class Player { this.rotationChangeEmitter.emit(eventID); } - setAplRotation(eventID: EventID, newRotation: APLRotation) { - if (APLRotation.equals(newRotation, this.aplRotation)) + getSimpleCooldowns(): Cooldowns { + // Make a defensive copy + return Cooldowns.clone(this.aplRotation.simple?.cooldowns || Cooldowns.create()); + } + + setSimpleCooldowns(eventID: EventID, newCooldowns: Cooldowns) { + if (Cooldowns.equals(this.getSimpleCooldowns(), newCooldowns)) return; - this.aplRotation = APLRotation.clone(newRotation); + if (!this.aplRotation.simple) { + this.aplRotation.simple = SimpleRotation.create(); + } + this.aplRotation.simple.cooldowns = newCooldowns; this.rotationChangeEmitter.emit(eventID); } @@ -809,8 +802,8 @@ export class Player { return rot; } else if (type == APLRotationType.TypeSimple && this.simpleRotationGenerator) { // Clone to avoid modifying preset rotations, which are often returned directly. - const simpleRot = this.getRotation(); - const rot = APLRotation.clone(this.simpleRotationGenerator(this, simpleRot, this.getCooldowns())); + const simpleRot = this.getSimpleRotation(); + const rot = APLRotation.clone(this.simpleRotationGenerator(this, simpleRot, this.getSimpleCooldowns())); rot.simple = this.aplRotation.simple; rot.type = APLRotationType.TypeSimple; return rot; @@ -1342,7 +1335,7 @@ export class Player { } if (exportCategory(SimSettingCategories.Rotation)) { PlayerProto.mergePartial(player, { - cooldowns: Cooldowns.create({ hpPercentForDefensives: this.getCooldowns().hpPercentForDefensives }), + cooldowns: Cooldowns.create({ hpPercentForDefensives: this.getSimpleCooldowns().hpPercentForDefensives }), rotation: aplRotation, }); } @@ -1474,32 +1467,32 @@ export class Player { } if (this.spec == Spec.SpecBalanceDruid) { - const rot = this.getRotation() as SpecRotation; + const rot = this.getSimpleRotation() as SpecRotation; if (rot.okfPpm) { rot.okfPpm = 0; - this.setRotation(eventID, rot as SpecRotation); + this.setSimpleRotation(eventID, rot as SpecRotation); } } if (this.spec == Spec.SpecHunter) { - const rot = this.getRotation() as SpecRotation; + const rot = this.getSimpleRotation() as SpecRotation; if (rot.timeToTrapWeaveMs) { const options = this.getSpecOptions() as SpecOptions; options.timeToTrapWeaveMs = rot.timeToTrapWeaveMs; this.setSpecOptions(eventID, options as SpecOptions); rot.timeToTrapWeaveMs = 0; - this.setRotation(eventID, rot as SpecRotation); + this.setSimpleRotation(eventID, rot as SpecRotation); } } if (this.spec == Spec.SpecMage) { - const rot = this.getRotation() as SpecRotation; + const rot = this.getSimpleRotation() as SpecRotation; if (rot.waterElementalDisobeyChance) { const options = this.getSpecOptions() as SpecOptions; options.waterElementalDisobeyChance = rot.waterElementalDisobeyChance; rot.waterElementalDisobeyChance = 0; this.setSpecOptions(eventID, options as SpecOptions); - this.setRotation(eventID, rot as SpecRotation); + this.setSimpleRotation(eventID, rot as SpecRotation); } } @@ -1513,13 +1506,13 @@ export class Player { } if ([Spec.SpecEnhancementShaman, Spec.SpecRestorationShaman, Spec.SpecElementalShaman].includes(this.spec)) { - const rot = this.getRotation() as SpecRotation; + const rot = this.getSimpleRotation() as SpecRotation; if (rot.totems) { const options = this.getSpecOptions() as SpecOptions; options.totems = rot.totems; this.setSpecOptions(eventID, options as SpecOptions); rot.totems = undefined; - this.setRotation(eventID, rot as SpecRotation); + this.setSimpleRotation(eventID, rot as SpecRotation); } const opt = this.getSpecOptions() as SpecOptions; @@ -1527,7 +1520,7 @@ export class Player { if (opt.bloodlust) { opt.bloodlust = false; - var tRot = this.getRotation(); + var tRot = this.getSimpleRotation(); if (this.spec == Spec.SpecElementalShaman) { (tRot as ElementalShaman_Rotation).bloodlust = ElementalShaman_Rotation_BloodlustUse.UseBloodlust; } else if (this.spec == Spec.SpecEnhancementShaman) { @@ -1536,47 +1529,47 @@ export class Player { (tRot as RestorationShaman_Rotation).bloodlust = RestorationShaman_Rotation_BloodlustUse.UseBloodlust; } - this.setRotation(eventID, tRot as SpecRotation); + this.setSimpleRotation(eventID, tRot as SpecRotation); this.setSpecOptions(eventID, opt as SpecOptions); } // Update Ele TS range option. if (this.spec == Spec.SpecElementalShaman) { var eleOpt = this.getSpecOptions() as ElementalShaman_Options; - var eleRot = this.getRotation() as ElementalShaman_Rotation; + var eleRot = this.getSimpleRotation() as ElementalShaman_Rotation; if (eleRot.inThunderstormRange) { eleOpt.thunderstormRange = ElementalShaman_Options_ThunderstormRange.TSInRange; eleRot.inThunderstormRange = false; - this.setRotation(eventID, eleRot as SpecRotation); + this.setSimpleRotation(eventID, eleRot as SpecRotation); this.setSpecOptions(eventID, eleOpt as SpecOptions); } } } if (this.spec == Spec.SpecWarlock || this.spec == Spec.SpecDeathknight) { - const rot = this.getRotation() as SpecRotation; + const rot = this.getSimpleRotation() as SpecRotation; if (rot.enableWeaponSwap) { this.setEnableItemSwap(eventID, rot.enableWeaponSwap); rot.enableWeaponSwap = false; - this.setRotation(eventID, rot as SpecRotation) + this.setSimpleRotation(eventID, rot as SpecRotation) } if (rot.weaponSwap) { this.setItemSwapGear(eventID, this.sim.db.lookupItemSwap(rot.weaponSwap)); rot.weaponSwap = undefined; - this.setRotation(eventID, rot as SpecRotation) + this.setSimpleRotation(eventID, rot as SpecRotation) } } if (this.spec == Spec.SpecEnhancementShaman) { - const rot = this.getRotation() as SpecRotation; + const rot = this.getSimpleRotation() as SpecRotation; if (rot.enableItemSwap) { this.setEnableItemSwap(eventID, rot.enableItemSwap); rot.enableItemSwap = false; - this.setRotation(eventID, rot as SpecRotation) + this.setSimpleRotation(eventID, rot as SpecRotation) } if (rot.itemSwap) { this.setItemSwapGear(eventID, this.sim.db.lookupItemSwap(rot.itemSwap)); rot.itemSwap = undefined; - this.setRotation(eventID, rot as SpecRotation) + this.setSimpleRotation(eventID, rot as SpecRotation) } } }); @@ -1597,7 +1590,7 @@ export class Player { this.setHealingModel(eventID, HealingModel.create({ burstWindow: isTankSpec(this.spec) ? 6 : 0, })); - this.setCooldowns(eventID, Cooldowns.create({ + this.setSimpleCooldowns(eventID, Cooldowns.create({ hpPercentForDefensives: isTankSpec(this.spec) ? 0.35 : 0, })); this.setBonusStats(eventID, new Stats()); diff --git a/ui/feral_druid/inputs.ts b/ui/feral_druid/inputs.ts index 03e89d8fa6..88b482a56a 100644 --- a/ui/feral_druid/inputs.ts +++ b/ui/feral_druid/inputs.ts @@ -45,12 +45,12 @@ export const AssumeBleedActive = InputHelpers.makeSpecOptionsBooleanInput): boolean { - let rot = player.getRotation(); + let rot = player.getSimpleRotation(); return rot.manualParams && rot.rotationType == AplType.SingleTarget; } function ShouldShowAdvParamAoe(player: Player): boolean { - let rot = player.getRotation(); + let rot = player.getSimpleRotation(); return rot.manualParams && rot.rotationType == AplType.Aoe; } @@ -89,7 +89,7 @@ export const FeralDruidRotationConfig = { labelTooltip: 'Max allowed delay to wait for ff to come off CD in seconds', float: true, positive: true, - showWhen: (player: Player) => player.getRotation().manualParams, + showWhen: (player: Player) => player.getSimpleRotation().manualParams, }), InputHelpers.makeRotationNumberInput({ fieldName: 'minRoarOffset', @@ -120,7 +120,7 @@ export const FeralDruidRotationConfig = { label: 'Bite Time', labelTooltip: 'Min seconds on Rip/Roar to bite', showWhen: (player: Player) => - ShouldShowAdvParamST(player) && player.getRotation().useBite == true && player.getRotation().biteModeType == BiteModeType.Emperical, + ShouldShowAdvParamST(player) && player.getSimpleRotation().useBite == true && player.getSimpleRotation().biteModeType == BiteModeType.Emperical, }), InputHelpers.makeRotationBooleanInput({ fieldName: 'flowerWeave', @@ -133,7 +133,7 @@ export const FeralDruidRotationConfig = { fieldName: 'raidTargets', label: 'GotW Raid Targets', labelTooltip: 'Raid size to assume for clearcast proc chance (can include pets as well, so 25 man raid potentically can be ~30)', - showWhen: (player: Player) => player.aplRotation.enabled || (ShouldShowAdvParamAoe(player) && player.getRotation().flowerWeave == true), + showWhen: (player: Player) => player.aplRotation.enabled || (ShouldShowAdvParamAoe(player) && player.getSimpleRotation().flowerWeave == true), }), // Can be uncommented if/when analytical bite mode is added //InputHelpers.makeRotationEnumInput({ @@ -143,14 +143,14 @@ export const FeralDruidRotationConfig = { // values: [ // { name: 'Emperical', value: BiteModeType.Emperical }, // ], - // showWhen: (player: Player) => player.getRotation().useBite == true + // showWhen: (player: Player) => player.getSimpleRotation().useBite == true //}), InputHelpers.makeRotationNumberInput({ fieldName: 'hotUptime', label: 'Revitalize Hot Uptime', labelTooltip: 'Hot uptime percentage to assume when theorizing energy gains', percent: true, - showWhen: (player: Player) => player.getRotation().useBite == true && player.getRotation().biteModeType == BiteModeType.Analytical, + showWhen: (player: Player) => player.getSimpleRotation().useBite == true && player.getSimpleRotation().biteModeType == BiteModeType.Analytical, }), ], }; diff --git a/ui/hunter/inputs.ts b/ui/hunter/inputs.ts index e28f2091da..ba34a5ee91 100644 --- a/ui/hunter/inputs.ts +++ b/ui/hunter/inputs.ts @@ -78,7 +78,7 @@ export const HunterRotationConfig = { { name: 'Scorpid Sting', value: StingType.ScorpidSting }, { name: 'Serpent Sting', value: StingType.SerpentSting }, ], - showWhen: (player: Player) => player.getRotation().type == RotationType.SingleTarget, + showWhen: (player: Player) => player.getSimpleRotation().type == RotationType.SingleTarget, }), InputHelpers.makeRotationBooleanInput({ fieldName: 'trapWeave', @@ -89,7 +89,7 @@ export const HunterRotationConfig = { fieldName: 'allowExplosiveShotDownrank', label: 'Allow ES Downrank', labelTooltip: 'Weaves Explosive Shot Rank 3 during LNL procs. This works because the rank 3 and rank 4 dots can stack.', - showWhen: (player: Player) => player.getRotation().type != RotationType.Custom && player.getTalents().explosiveShot && player.getTalents().lockAndLoad > 0, + showWhen: (player: Player) => player.getSimpleRotation().type != RotationType.Custom && player.getTalents().explosiveShot && player.getTalents().lockAndLoad > 0, changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), }), InputHelpers.makeRotationBooleanInput({ diff --git a/ui/warlock/sim.ts b/ui/warlock/sim.ts index 35d02c3813..c35da9c98c 100644 --- a/ui/warlock/sim.ts +++ b/ui/warlock/sim.ts @@ -93,13 +93,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecWarlock, { WarlockInputs.ArmorInput, WarlockInputs.WeaponImbueInput, ], - // Inputs to include in the 'Rotation' section on the settings tab. - rotationIconInputs: [ - WarlockInputs.PrimarySpellInput, - WarlockInputs.CorruptionSpell, - WarlockInputs.SecondaryDotInput, - WarlockInputs.SpecSpellInput, - ], // Buff and Debuff inputs to include/exclude, overriding the EP-based defaults. includeBuffDebuffInputs: [ From e017516454a06239a95abd8618ab8d46f01de91f Mon Sep 17 00:00:00 2001 From: James Tanner Date: Mon, 1 Jan 2024 20:36:44 -0800 Subject: [PATCH 03/28] Clean up hunter pet rotation code --- sim/hunter/pet.go | 44 +++++++++++++------------------------------- 1 file changed, 13 insertions(+), 31 deletions(-) diff --git a/sim/hunter/pet.go b/sim/hunter/pet.go index d471071865..c32203ecc1 100644 --- a/sim/hunter/pet.go +++ b/sim/hunter/pet.go @@ -106,42 +106,24 @@ func (hp *HunterPet) ExecuteCustomRotation(sim *core.Simulation) { } target := hp.CurrentTarget - if hp.config.RandomSelection { - if sim.RandomFloat("Hunter Pet Ability") < 0.5 { - if !hp.specialAbility.CanCast(sim, target) || !hp.specialAbility.Cast(sim, target) { - if !hp.focusDump.Cast(sim, target) { - // Do nothing - } - } - } else { - if !hp.focusDump.Cast(sim, target) { - if !hp.specialAbility.CanCast(sim, target) || !hp.specialAbility.Cast(sim, target) { - // Do nothing - } - } - } + + if hp.focusDump == nil { + hp.specialAbility.Cast(sim, target) + return + } + if hp.specialAbility == nil { + hp.focusDump.Cast(sim, target) return } - if !hp.specialAbility.CanCast(sim, target) || hp.specialAbility.Cast(sim, target) { - // For abilities that don't use the GCD. - if hp.GCD.IsReady(sim) { - if hp.focusDump != nil { - if !hp.focusDump.Cast(sim, target) { - // Do nothing - } - } else { - // Do nothing - } - } - } else { - if hp.focusDump != nil { - if !hp.focusDump.Cast(sim, target) { - // Do nothing - } + if hp.config.RandomSelection { + if sim.RandomFloat("Hunter Pet Ability") < 0.5 { + _ = hp.specialAbility.Cast(sim, target) || hp.focusDump.Cast(sim, target) } else { - // Do nothing + _ = hp.focusDump.Cast(sim, target) || hp.specialAbility.Cast(sim, target) } + } else { + _ = hp.specialAbility.Cast(sim, target) || hp.focusDump.Cast(sim, target) } } From 2e6a97a7bfc4563ea4cabac73025e1850a3f2b15 Mon Sep 17 00:00:00 2001 From: James Tanner Date: Tue, 2 Jan 2024 19:58:05 -0800 Subject: [PATCH 04/28] Start cleaning up backend legacy rotation code --- proto/apl.proto | 4 - sim/core/agent.go | 9 - sim/core/apl.go | 4 +- sim/core/apl_value.go | 2 - sim/core/apl_values_spell.go | 24 -- sim/core/attack.go | 16 +- sim/core/cast.go | 14 +- sim/core/character.go | 16 - sim/core/consumes.go | 5 - sim/core/dot.go | 8 +- sim/core/energy.go | 39 +- sim/core/major_cooldown.go | 74 ---- sim/core/mana.go | 39 +- sim/core/pet.go | 2 - sim/core/rage.go | 19 +- sim/core/spell.go | 6 +- sim/core/target.go | 1 - sim/core/target_ai.go | 6 - sim/core/target_dummy.go | 4 - sim/core/unit.go | 14 +- sim/druid/tank/tank.go | 12 +- sim/hunter/aspects.go | 4 - sim/hunter/hunter.go | 23 -- sim/hunter/pet_abilities.go | 3 +- sim/hunter/rotation.go | 385 ------------------- sim/hunter/volley.go | 3 +- sim/warrior/dps/dps_warrior.go | 20 +- sim/warrior/protection/protection_warrior.go | 9 +- 28 files changed, 42 insertions(+), 723 deletions(-) delete mode 100644 sim/hunter/rotation.go diff --git a/proto/apl.proto b/proto/apl.proto index 6608420050..2f683604b1 100644 --- a/proto/apl.proto +++ b/proto/apl.proto @@ -142,7 +142,6 @@ message APLValue { APLValueSpellIsReady spell_is_ready = 20; APLValueSpellTimeToReady spell_time_to_ready = 21; APLValueSpellCastTime spell_cast_time = 35; - APLValueSpellChannelTime spell_channel_time = 36; APLValueSpellTravelTime spell_travel_time = 37; APLValueSpellCPM spell_cpm = 42; APLValueSpellIsChanneling spell_is_channeling = 56; @@ -448,9 +447,6 @@ message APLValueSpellTimeToReady { message APLValueSpellCastTime { ActionID spell_id = 1; } -message APLValueSpellChannelTime { - ActionID spell_id = 1; -} message APLValueChannelClipDelay { } message APLValueFrontOfTarget { diff --git a/sim/core/agent.go b/sim/core/agent.go index d4b6d981dc..13b9037561 100644 --- a/sim/core/agent.go +++ b/sim/core/agent.go @@ -32,15 +32,6 @@ type Agent interface { // and once after the final iteration. Reset(sim *Simulation) - // Called whenever the GCD becomes ready for this Agent. - OnGCDReady(sim *Simulation) - - // Called after each auto attack performed by this Agent. - // This is different from Aura.OnSpellHit in that it is invoked fully after - // everything related to the attack is complete, and it is only invoked for - // auto attacks (white hits or white-hit-replacers). - OnAutoAttack(sim *Simulation, spell *Spell) - // Custom factories for APL values and actions, for cases where the value/action // involves class or spec-specific behavior. // diff --git a/sim/core/apl.go b/sim/core/apl.go index 8ee0253195..1fffcf8889 100644 --- a/sim/core/apl.go +++ b/sim/core/apl.go @@ -67,7 +67,7 @@ func (unit *Unit) newCustomRotation() *APLRotation { } func (unit *Unit) newAPLRotation(config *proto.APLRotation) *APLRotation { - if config == nil || !unit.IsUsingAPL { + if config == nil { return nil } @@ -227,8 +227,6 @@ func (apl *APLRotation) DoNextAction(sim *Simulation) { gcdReady := apl.unit.GCD.IsReady(sim) if gcdReady { apl.unit.WaitUntil(sim, sim.CurrentTime+time.Millisecond*50) - } else { - apl.unit.DoNothing() } apl.unit.DoneAPLLoop(sim, !gcdReady) diff --git a/sim/core/apl_value.go b/sim/core/apl_value.go index b6f4fe4d0f..7d47505c69 100644 --- a/sim/core/apl_value.go +++ b/sim/core/apl_value.go @@ -157,8 +157,6 @@ func (rot *APLRotation) newAPLValue(config *proto.APLValue) APLValue { return rot.newValueSpellTimeToReady(config.GetSpellTimeToReady()) case *proto.APLValue_SpellCastTime: return rot.newValueSpellCastTime(config.GetSpellCastTime()) - case *proto.APLValue_SpellChannelTime: - return rot.newValueSpellChannelTime(config.GetSpellChannelTime()) case *proto.APLValue_SpellTravelTime: return rot.newValueSpellTravelTime(config.GetSpellTravelTime()) case *proto.APLValue_SpellCpm: diff --git a/sim/core/apl_values_spell.go b/sim/core/apl_values_spell.go index af2e37cddb..db6d8eff40 100644 --- a/sim/core/apl_values_spell.go +++ b/sim/core/apl_values_spell.go @@ -103,30 +103,6 @@ func (value *APLValueSpellCastTime) String() string { return fmt.Sprintf("Cast Time(%s)", value.spell.ActionID) } -type APLValueSpellChannelTime struct { - DefaultAPLValueImpl - spell *Spell -} - -func (rot *APLRotation) newValueSpellChannelTime(config *proto.APLValueSpellChannelTime) APLValue { - spell := rot.GetAPLSpell(config.SpellId) - if spell == nil { - return nil - } - return &APLValueSpellChannelTime{ - spell: spell, - } -} -func (value *APLValueSpellChannelTime) Type() proto.APLValueType { - return proto.APLValueType_ValueTypeDuration -} -func (value *APLValueSpellChannelTime) GetDuration(_ *Simulation) time.Duration { - return value.spell.Unit.ApplyCastSpeedForSpell(value.spell.DefaultCast.ChannelTime, value.spell) -} -func (value *APLValueSpellChannelTime) String() string { - return fmt.Sprintf("Channel Time(%s)", value.spell.ActionID) -} - type APLValueSpellTravelTime struct { DefaultAPLValueImpl spell *Spell diff --git a/sim/core/attack.go b/sim/core/attack.go index f0eb1e2e6e..aa601b5b16 100644 --- a/sim/core/attack.go +++ b/sim/core/attack.go @@ -263,10 +263,9 @@ func (wa *WeaponAttack) swing(sim *Simulation) time.Duration { attackSpell := wa.spell if wa.replaceSwing != nil { - if wa.unit.IsUsingAPL { - // Need to check APL here to allow last-moment HS queue casts. - wa.unit.Rotation.DoNextAction(sim) - } + // Need to check APL here to allow last-moment HS queue casts. + wa.unit.Rotation.DoNextAction(sim) + // Allow MH swing to be overridden for abilities like Heroic Strike. attackSpell = wa.replaceSwing(sim, attackSpell) } @@ -277,11 +276,7 @@ func (wa *WeaponAttack) swing(sim *Simulation) time.Duration { attackSpell.Cast(sim, wa.unit.CurrentTarget) if !sim.Options.Interactive { - if wa.unit.IsUsingAPL { - wa.unit.Rotation.DoNextAction(sim) - } else { - wa.agent.OnAutoAttack(sim, attackSpell) - } + wa.unit.Rotation.DoNextAction(sim) } return wa.swingAt @@ -422,9 +417,6 @@ func (unit *Unit) EnableAutoAttacks(agent Agent, options AutoAttackOptions) { } } -// Empty handler so Agents don't have to provide one if they have no logic to add. -func (unit *Unit) OnAutoAttack(_ *Simulation, _ *Spell) {} - func (aa *AutoAttacks) finalize() { if aa.AutoSwingMelee { aa.mh.spell = aa.mh.unit.GetOrRegisterSpell(aa.mh.config) diff --git a/sim/core/cast.go b/sim/core/cast.go index ca86cdbacf..8a2c34a3c9 100644 --- a/sim/core/cast.go +++ b/sim/core/cast.go @@ -47,9 +47,6 @@ type Cast struct { // The amount of time between the call to spell.Cast() and when the spell // effects are invoked. CastTime time.Duration - - // Additional GCD delay after the cast completes. - ChannelTime time.Duration } func (cast *Cast) EffectiveTime() time.Duration { @@ -58,15 +55,14 @@ func (cast *Cast) EffectiveTime() time.Duration { // TODO: isn't this wrong for spells like shadowfury, that have a reduced GCD? gcd = max(GCDMin, gcd) } - fullCastTime := cast.CastTime + cast.ChannelTime - return max(gcd, fullCastTime) + return max(gcd, cast.CastTime) } type CastFunc func(*Simulation, *Unit) type CastSuccessFunc func(*Simulation, *Unit) bool func (spell *Spell) castFailureHelper(sim *Simulation, message string, vals ...any) bool { - if sim.CurrentTime < 0 && spell.Unit.IsUsingAPL { + if sim.CurrentTime < 0 && spell.Unit.Rotation != nil { spell.Unit.Rotation.ValidationWarning(fmt.Sprintf(spell.ActionID.String()+" failed to cast: "+message, vals...)) } else { if sim.Log != nil && !spell.Flags.Matches(SpellFlagNoLogs) { @@ -105,7 +101,6 @@ func (spell *Spell) makeCastFunc(config CastConfig) CastSuccessFunc { if !config.IgnoreHaste { spell.CurCast.GCD = spell.Unit.ApplyCastSpeed(spell.CurCast.GCD) spell.CurCast.CastTime = spell.Unit.ApplyCastSpeedForSpell(spell.CurCast.CastTime, spell) - spell.CurCast.ChannelTime = spell.Unit.ApplyCastSpeedForSpell(spell.CurCast.ChannelTime, spell) } if config.CD.Timer != nil { @@ -173,11 +168,6 @@ func (spell *Spell) makeCastFunc(config CastConfig) CastSuccessFunc { return true } - // Instants/Channels - if spell.CurCast.ChannelTime > 0 { - spell.Unit.Hardcast = Hardcast{Expires: sim.CurrentTime + spell.CurCast.ChannelTime, ActionID: spell.ActionID} - } - if sim.Log != nil && !spell.Flags.Matches(SpellFlagNoLogs) { spell.Unit.Log(sim, "Casting %s (Cost = %0.03f, Cast Time = %s, Effective Time = %s)", spell.ActionID, max(0, spell.CurCast.Cost), spell.CurCast.CastTime, spell.CurCast.EffectiveTime()) diff --git a/sim/core/character.go b/sim/core/character.go index 892d2ccb59..2f21f7b69f 100644 --- a/sim/core/character.go +++ b/sim/core/character.go @@ -106,10 +106,6 @@ func NewCharacter(party *Party, partyIndex int, player *proto.Player) Character ChannelClipDelay: max(0, time.Duration(player.ChannelClipDelayMs)*time.Millisecond), DistanceFromTarget: player.DistanceFromTarget, NibelungAverageCasts: player.NibelungAverageCasts, - IsUsingAPL: player.Rotation != nil && - (player.Rotation.Type == proto.APLRotation_TypeAPL || - player.Rotation.Type == proto.APLRotation_TypeAuto || - player.Rotation.Type == proto.APLRotation_TypeSimple), }, Name: player.Name, @@ -439,7 +435,6 @@ func (character *Character) initialize(agent Agent) { if sim.Options.Interactive { if character.GCD.IsReady(sim) { sim.NeedsInput = true - character.doNothing = false } return } @@ -448,17 +443,6 @@ func (character *Character) initialize(agent Agent) { character.Rotation.DoNextAction(sim) return } - - character.TryUseCooldowns(sim) - if character.GCD.IsReady(sim) { - agent.OnGCDReady(sim) - - if !character.doNothing && character.GCD.IsReady(sim) && (!character.IsWaiting() && !character.IsWaitingForMana()) { - msg := fmt.Sprintf("Character `%s` did not perform any actions. Either this is a bug or agent should use 'WaitUntil' or 'WaitForMana' to explicitly wait.\n\tIf character has no action to perform use 'DoNothing'.", character.Label) - panic(msg) - } - character.doNothing = false - } }, } } diff --git a/sim/core/consumes.go b/sim/core/consumes.go index 4b00025978..da709a3ae1 100644 --- a/sim/core/consumes.go +++ b/sim/core/consumes.go @@ -466,11 +466,6 @@ func registerPotionCD(agent Agent, consumes *proto.Consumes) { startingMCD := makePotionActivation(startingPotion, character, potionCD) if startingMCD.Spell != nil { startingMCD.Spell.Flags |= SpellFlagPrepullPotion - if !character.IsUsingAPL { - character.RegisterPrepullAction(-1*time.Second, func(sim *Simulation) { - startingMCD.Spell.Cast(sim, nil) - }) - } } var defaultMCD MajorCooldown diff --git a/sim/core/dot.go b/sim/core/dot.go index f66c3c7897..4ad4bf6e4a 100644 --- a/sim/core/dot.go +++ b/sim/core/dot.go @@ -204,7 +204,7 @@ func (dot *Dot) TickOnce(sim *Simulation) { dot.lastTickTime = sim.CurrentTime dot.OnTick(sim, dot.Unit, dot) - if dot.isChanneled && dot.Spell.Unit.IsUsingAPL { + if dot.isChanneled { // Note: even if the clip delay is 0ms, need a WaitUntil so that APL is called after the channel aura fully fades. if dot.MaxTicksRemaining() == 0 { if dot.Spell.Unit.GCD.IsReady(sim) { @@ -278,10 +278,8 @@ func newDot(config Dot) *Dot { } if dot.isChanneled { dot.Spell.Unit.ChanneledDot = nil - if dot.Spell.Unit.IsUsingAPL { - dot.Spell.Unit.Rotation.interruptChannelIf = nil - dot.Spell.Unit.Rotation.allowChannelRecastOnInterrupt = false - } + dot.Spell.Unit.Rotation.interruptChannelIf = nil + dot.Spell.Unit.Rotation.allowChannelRecastOnInterrupt = false } }) diff --git a/sim/core/energy.go b/sim/core/energy.go index 69695547dd..34f44e8f32 100644 --- a/sim/core/energy.go +++ b/sim/core/energy.go @@ -13,9 +13,6 @@ import ( const EnergyTickDuration = time.Millisecond * 100 const EnergyPerTick = 1.0 -// OnEnergyGain is called any time energy is increased. -type OnEnergyGain func(sim *Simulation) - type energyBar struct { unit *Unit @@ -33,8 +30,6 @@ type energyBar struct { // Increments by 1 at each value of energyDecisionThresholds. cumulativeEnergyDecisionThresholds []int - onEnergyGain func(*Simulation, bool) - nextEnergyTick time.Duration // Multiplies energy regen from ticks. @@ -44,27 +39,12 @@ type energyBar struct { EnergyRefundMetrics *ResourceMetrics } -func (unit *Unit) EnableEnergyBar(maxEnergy float64, onEnergyGain OnEnergyGain) { +func (unit *Unit) EnableEnergyBar(maxEnergy float64) { unit.SetCurrentPowerBar(EnergyBar) unit.energyBar = energyBar{ - unit: unit, - maxEnergy: max(100, maxEnergy), - onEnergyGain: func(sim *Simulation, crossedThreshold bool) { - if sim.CurrentTime < 0 { - return - } - - if !sim.Options.Interactive && (!unit.IsWaitingForEnergy() || unit.DoneWaitingForEnergy(sim)) { - if unit.IsUsingAPL { - if crossedThreshold { - unit.Rotation.DoNextAction(sim) - } - } else { - onEnergyGain(sim) - } - } - }, + unit: unit, + maxEnergy: max(100, maxEnergy), EnergyTickMultiplier: 1, regenMetrics: unit.NewEnergyMetrics(ActionID{OtherID: proto.OtherAction_OtherActionEnergyRegen}), EnergyRefundMetrics: unit.NewEnergyMetrics(ActionID{OtherID: proto.OtherAction_OtherActionRefund}), @@ -76,9 +56,6 @@ func (eb *energyBar) setupEnergyThresholds() { if eb.unit == nil { return } - if !eb.unit.IsUsingAPL { - return - } var energyThresholds []int // Energy thresholds from spell costs. @@ -153,6 +130,16 @@ func (eb *energyBar) NextEnergyTickAt() time.Duration { return eb.nextEnergyTick } +func (eb *energyBar) onEnergyGain(sim *Simulation, crossedThreshold bool) { + if sim.CurrentTime < 0 { + return + } + + if !sim.Options.Interactive && crossedThreshold && (!eb.unit.IsWaitingForEnergy() || eb.unit.DoneWaitingForEnergy(sim)) { + eb.unit.Rotation.DoNextAction(sim) + } +} + func (eb *energyBar) addEnergyInternal(sim *Simulation, amount float64, metrics *ResourceMetrics) bool { if amount < 0 { panic("Trying to add negative energy!") diff --git a/sim/core/major_cooldown.go b/sim/core/major_cooldown.go index adc5d218bd..17e1805910 100644 --- a/sim/core/major_cooldown.go +++ b/sim/core/major_cooldown.go @@ -227,50 +227,6 @@ func (mcdm *majorCooldownManager) finalize() { mcdm.majorCooldowns = make([]*MajorCooldown, len(mcdm.initialMajorCooldowns)) } -// Adds a delay to the first usage of all CDs so that debuffs have time -// to be applied. MCDs that have a user-specified timing are not delayed. -// -// This function should be called from Agent.Init(). -func (mcdm *majorCooldownManager) DelayDPSCooldownsForArmorDebuffs(delay time.Duration) { - if mcdm.character.IsUsingAPL { - return - } - mcdm.character.Env.RegisterPostFinalizeEffect(func() { - for i := range mcdm.initialMajorCooldowns { - mcd := &mcdm.initialMajorCooldowns[i] - if len(mcd.timings) == 0 && mcd.Type.Matches(CooldownTypeDPS) && !mcd.Type.Matches(CooldownTypeExplosive) { - oldShouldActivate := mcd.ShouldActivate - mcd.ShouldActivate = func(sim *Simulation, character *Character) bool { - if oldShouldActivate != nil && !oldShouldActivate(sim, character) { - return false - } - return sim.CurrentTime >= delay - } - } - } - }) -} - -// Adds a delay to the first usage of all CDs overriding shouldActivate for cooldownTypeDPS, -// MCDs that have a user-specified timing are not delayed. -// This function should be called from Agent.Init(). -func (mcdm *majorCooldownManager) DelayDPSCooldowns(delay time.Duration) { - mcdm.character.Env.RegisterPostFinalizeEffect(func() { - for i := range mcdm.initialMajorCooldowns { - mcd := &mcdm.initialMajorCooldowns[i] - if len(mcd.timings) == 0 && mcd.Type.Matches(CooldownTypeDPS) { - oldShouldActivate := mcd.ShouldActivate - mcd.ShouldActivate = func(sim *Simulation, character *Character) bool { - if oldShouldActivate != nil && !oldShouldActivate(sim, character) { - return false - } - return sim.CurrentTime >= delay - } - } - } - }) -} - func (mcdm *majorCooldownManager) reset(_ *Simulation) { for i := range mcdm.majorCooldowns { newMCD := &MajorCooldown{} @@ -368,36 +324,6 @@ func (mcdm *majorCooldownManager) getFirstReadyMCD(sim *Simulation) *MajorCooldo return nil } -func (mcdm *majorCooldownManager) TryUseCooldowns(sim *Simulation) { - if sim.CurrentTime < mcdm.minReady { - return - } - -restart: - for _, mcd := range mcdm.majorCooldowns { - if !mcd.IsReady(sim) { - break - } - - if mcd.tryActivateInternal(sim, mcdm.character) { - if mcd.IsReady(sim) { - continue // activation failed - } - mcdm.sort() - - if mcd.Spell.DefaultCast.GCD > 0 { - // If the GCD was used, don't use any more MCDs until the next cycle so - // their durations aren't partially wasted. - break - } - - // many MCDs are off the GCD, so it makes sense to continue - goto restart - } - } - mcdm.minReady = mcdm.majorCooldowns[0].ReadyAt() -} - // This function should be called if the CD for a major cooldown changes outside // of the TryActivate() call. func (mcdm *majorCooldownManager) UpdateMajorCooldowns() { diff --git a/sim/core/mana.go b/sim/core/mana.go index 29cab3520e..903b802494 100644 --- a/sim/core/mana.go +++ b/sim/core/mana.go @@ -11,12 +11,8 @@ import ( const ThreatPerManaGained = 0.5 -type OnManaTick func(sim *Simulation) - type manaBar struct { - unit *Unit - OnManaTick OnManaTick - + unit *Unit BaseMana float64 currentMana float64 @@ -60,20 +56,6 @@ func (character *Character) EnableManaBarWithModifier(modifier float64) { character.Unit.manaBar.unit = &character.Unit } -// EnableResumeAfterManaWait will setup the OnManaTick callback to resume the given callback -// -// once enough mana has been gained after calling unit.WaitForMana() -func (character *Character) EnableResumeAfterManaWait(callback func(sim *Simulation)) { - if callback == nil { - panic("attempted to setup a mana tick callback that was nil") - } - character.OnManaTick = func(sim *Simulation) { - if character.FinishedWaitingForManaAndGCDReady(sim) { - callback(sim) - } - } -} - func (unit *Unit) HasManaBar() bool { return unit.manaBar.unit != nil } @@ -263,26 +245,19 @@ func (sim *Simulation) initManaTickAction() { char := player.GetCharacter() char.ManaTick(sim) - if char.OnManaTick != nil { - // Only execute APL actions after mana ticks once pre-pull has completed. - if char.IsUsingAPL && sim.CurrentTime > 0 { - if char.IsWaitingForMana() && !char.DoneWaitingForMana(sim) { - continue - } - - char.Rotation.DoNextAction(sim) - } else { - char.OnManaTick(sim) + // Only execute APL actions after mana ticks once pre-pull has completed. + if sim.CurrentTime > 0 { + if char.IsWaitingForMana() && !char.DoneWaitingForMana(sim) { + continue } + + char.Rotation.DoNextAction(sim) } } for _, petAgent := range petsWithManaBars { pet := petAgent.GetPet() if pet.IsEnabled() { pet.ManaTick(sim) - if pet.OnManaTick != nil { - pet.OnManaTick(sim) - } } } diff --git a/sim/core/pet.go b/sim/core/pet.go index edbc22f595..a06684fbec 100644 --- a/sim/core/pet.go +++ b/sim/core/pet.go @@ -62,7 +62,6 @@ func NewPet(name string, owner *Character, baseStats stats.Stats, statInheritanc PseudoStats: stats.NewPseudoStats(), auraTracker: newAuraTracker(), Metrics: NewUnitMetrics(), - IsUsingAPL: true, StatDependencyManager: stats.NewStatDependencyManager(), }, @@ -238,7 +237,6 @@ func (pet *Pet) Disable(sim *Simulation) { pet.focusBar.disable(sim) pet.AutoAttacks.CancelAutoSwing(sim) pet.enabled = false - pet.DoNothing() // mark it is as doing nothing now. // If a pet is immediately re-summoned it might try to use GCD, so we need to clear it. pet.Hardcast = Hardcast{} diff --git a/sim/core/rage.go b/sim/core/rage.go index 6125a18934..8bcb23f11e 100644 --- a/sim/core/rage.go +++ b/sim/core/rage.go @@ -10,17 +10,12 @@ const MaxRage = 100.0 const RageFactor = 453.3 const ThreatPerRageGained = 5 -// OnRageGain is called any time rage is increased. -type OnRageGain func(sim *Simulation) - type rageBar struct { unit *Unit startingRage float64 currentRage float64 - onRageGain OnRageGain - RageRefundMetrics *ResourceMetrics } @@ -31,7 +26,7 @@ type RageBarOptions struct { OHSwingSpeed float64 } -func (unit *Unit) EnableRageBar(options RageBarOptions, onRageGain OnRageGain) { +func (unit *Unit) EnableRageBar(options RageBarOptions) { rageFromDamageTakenMetrics := unit.NewRageMetrics(ActionID{OtherID: proto.OtherAction_OtherActionDamageTaken}) unit.SetCurrentPowerBar(RageBar) @@ -102,10 +97,8 @@ func (unit *Unit) EnableRageBar(options RageBarOptions, onRageGain OnRageGain) { }) unit.rageBar = rageBar{ - unit: unit, - startingRage: max(0, min(options.StartingRage, MaxRage)), - onRageGain: onRageGain, - + unit: unit, + startingRage: max(0, min(options.StartingRage, MaxRage)), RageRefundMetrics: unit.NewRageMetrics(ActionID{OtherID: proto.OtherAction_OtherActionRefund}), } } @@ -132,11 +125,7 @@ func (rb *rageBar) AddRage(sim *Simulation, amount float64, metrics *ResourceMet rb.currentRage = newRage if !sim.Options.Interactive { - if rb.unit.IsUsingAPL { - rb.unit.Rotation.DoNextAction(sim) - } else { - rb.onRageGain(sim) - } + rb.unit.Rotation.DoNextAction(sim) } } diff --git a/sim/core/spell.go b/sim/core/spell.go index ae62dbff57..d8848b13a9 100644 --- a/sim/core/spell.go +++ b/sim/core/spell.go @@ -165,10 +165,6 @@ func (unit *Unit) RegisterSpell(config SpellConfig) *Spell { config.DamageMultiplier = 1 } - if unit.IsUsingAPL { - config.Cast.DefaultCast.ChannelTime = 0 - } - if (config.DamageMultiplier != 0 || config.ThreatMultiplier != 0) && config.ProcMask == ProcMaskUnknown { panic("ProcMask for spell " + config.ActionID.String() + " not set") } @@ -270,7 +266,7 @@ func (unit *Unit) RegisterSpell(config SpellConfig) *Spell { panic("Empty DefaultCast with a cost for spell " + config.ActionID.String()) } - if spell.DefaultCast.GCD == 0 && spell.DefaultCast.CastTime == 0 && spell.DefaultCast.ChannelTime == 0 { + if spell.DefaultCast.GCD == 0 && spell.DefaultCast.CastTime == 0 { config.Cast.IgnoreHaste = true } diff --git a/sim/core/target.go b/sim/core/target.go index 2deb2bdbf4..a5a28b78e8 100644 --- a/sim/core/target.go +++ b/sim/core/target.go @@ -155,7 +155,6 @@ func NewTarget(options *proto.Target, targetIndex int32) *Target { preset := GetPresetTargetWithID(options.Id) if preset != nil && preset.AI != nil { target.AI = preset.AI() - target.IsUsingAPL = true } return target diff --git a/sim/core/target_ai.go b/sim/core/target_ai.go index ebfad485d3..6bb2085cbd 100644 --- a/sim/core/target_ai.go +++ b/sim/core/target_ai.go @@ -57,12 +57,6 @@ func (target *Target) ApplyTalents() {} func (target *Target) GetCharacter() *Character { return nil } func (target *Target) Initialize() {} -func (target *Target) DoNothing() { - target.doNothing = true -} - -func (target *Target) OnAutoAttack(sim *Simulation, _ *Spell) {} -func (target *Target) OnGCDReady(sim *Simulation) {} func (target *Target) ExecuteCustomRotation(sim *Simulation) { if target.AI != nil { target.AI.ExecuteCustomRotation(sim) diff --git a/sim/core/target_dummy.go b/sim/core/target_dummy.go index 81c2251326..b232f9914a 100644 --- a/sim/core/target_dummy.go +++ b/sim/core/target_dummy.go @@ -48,8 +48,4 @@ func (td *TargetDummy) AddPartyBuffs(partyBuffs *proto.PartyBuffs) {} func (td *TargetDummy) ApplyTalents() {} func (td *TargetDummy) Initialize() {} func (td *TargetDummy) Reset(sim *Simulation) {} -func (td *TargetDummy) OnGCDReady(sim *Simulation) { - td.DoNothing() -} -func (td *TargetDummy) OnAutoAttack(sim *Simulation, spell *Spell) {} func (td *TargetDummy) ExecuteCustomRotation(sim *Simulation) {} diff --git a/sim/core/unit.go b/sim/core/unit.go index 7541db3a40..250a666f29 100644 --- a/sim/core/unit.go +++ b/sim/core/unit.go @@ -123,8 +123,7 @@ type Unit struct { // Must be enabled to use, with "EnableAutoAttacks()". AutoAttacks AutoAttacks - IsUsingAPL bool // Used for checks before the finalize() stage, when apl rotations are created. - Rotation *APLRotation + Rotation *APLRotation // Statistics describing the results of the sim. Metrics UnitMetrics @@ -134,8 +133,7 @@ type Unit struct { AttackTables []*AttackTable DynamicDamageTakenModifiers []DynamicDamageTakenModifier - GCD *Timer - doNothing bool // flags that this character chose to do nothing. + GCD *Timer // Used for applying the effect of a hardcast spell when casting finishes. // For channeled spells, only Expires is set. @@ -174,14 +172,6 @@ func (unit *Unit) IsEnabled() bool { return unit.enabled } -// DoNothing will explicitly declare that the character is intentionally doing nothing. -// -// If the GCD is not used during OnGCDReady and this flag is set, OnGCDReady will not be called again -// until it is used in some other way (like from an auto attack or resource regeneration). -func (unit *Unit) DoNothing() { - unit.doNothing = true -} - func (unit *Unit) IsActive() bool { return unit.IsEnabled() && unit.CurrentHealthPercent() > 0 } diff --git a/sim/druid/tank/tank.go b/sim/druid/tank/tank.go index 0c3f2c5bf2..cd8e1f895a 100644 --- a/sim/druid/tank/tank.go +++ b/sim/druid/tank/tank.go @@ -38,21 +38,11 @@ func NewFeralTankDruid(character *core.Character, options *proto.Player) *FeralT bear.SelfBuffs.InnervateTarget = tankOptions.Options.InnervateTarget } - rbo := core.RageBarOptions{ + bear.EnableRageBar(core.RageBarOptions{ StartingRage: bear.Options.StartingRage, RageMultiplier: 1, MHSwingSpeed: 2.5, - } - - bear.EnableRageBar(rbo, func(sim *core.Simulation) { - if bear.GCD.IsReady(sim) { - bear.TryUseCooldowns(sim) - if bear.GCD.IsReady(sim) { - bear.doRotation(sim) - } - } }) - bear.EnableAutoAttacks(bear, core.AutoAttackOptions{ // Base paw weapon. MainHand: bear.GetBearWeapon(), diff --git a/sim/hunter/aspects.go b/sim/hunter/aspects.go index 05a49840c7..9788a2058c 100644 --- a/sim/hunter/aspects.go +++ b/sim/hunter/aspects.go @@ -142,8 +142,4 @@ func (hunter *Hunter) applySharedAspectConfig(isHawk bool, aura *core.Aura) { aura.Duration = core.NeverExpires aura.NewExclusiveEffect("Aspect", true, core.ExclusiveEffect{}) - - aura.ApplyOnGain(func(aura *core.Aura, sim *core.Simulation) { - hunter.currentAspect = aura - }) } diff --git a/sim/hunter/hunter.go b/sim/hunter/hunter.go index 450104892d..617fec6ac6 100644 --- a/sim/hunter/hunter.go +++ b/sim/hunter/hunter.go @@ -3,7 +3,6 @@ package hunter import ( "time" - "github.com/wowsims/wotlk/sim/common" "github.com/wowsims/wotlk/sim/core" "github.com/wowsims/wotlk/sim/core/proto" "github.com/wowsims/wotlk/sim/core/stats" @@ -43,12 +42,6 @@ type Hunter struct { AmmoDamageBonus float64 NormalizedAmmoDamageBonus float64 - currentAspect *core.Aura - - // Used for deciding when we can use hawk for the rest of the fight. - manaSpentPerSecondAtFirstAspectSwap float64 - permaHawk bool - // The most recent time at which moving could have started, for trap weaving. mayMoveAt time.Duration @@ -83,10 +76,6 @@ type Hunter struct { RapidFireAura *core.Aura ScorpidStingAuras core.AuraArray TalonOfAlarAura *core.Aura - - CustomRotation *common.CustomRotation - rotationConditions map[*core.Spell]RotationCondition - rotationPriority []*core.Spell } func (hunter *Hunter) GetCharacter() *core.Character { @@ -146,16 +135,6 @@ func (hunter *Hunter) Initialize() { hunter.registerKillCommandCD() hunter.registerRapidFireCD() - if !hunter.IsUsingAPL { - hunter.DelayDPSCooldownsForArmorDebuffs(time.Second * 10) - } - - hunter.initRotation() - hunter.CustomRotation = hunter.makeCustomRotation() - if hunter.CustomRotation == nil { - hunter.Rotation.Type = proto.Hunter_Rotation_SingleTarget - } - if hunter.Options.UseHuntersMark { hunter.RegisterPrepullAction(0, func(sim *core.Simulation) { huntersMarkAura := core.HuntersMarkAura(hunter.CurrentTarget, hunter.Talents.ImprovedHuntersMark, hunter.HasMajorGlyph(proto.HunterMajorGlyph_GlyphOfHuntersMark)) @@ -166,8 +145,6 @@ func (hunter *Hunter) Initialize() { func (hunter *Hunter) Reset(_ *core.Simulation) { hunter.mayMoveAt = 0 - hunter.manaSpentPerSecondAtFirstAspectSwap = 0 - hunter.permaHawk = false } func NewHunter(character *core.Character, options *proto.Player) *Hunter { diff --git a/sim/hunter/pet_abilities.go b/sim/hunter/pet_abilities.go index 5e999e4bf2..2de616ea40 100644 --- a/sim/hunter/pet_abilities.go +++ b/sim/hunter/pet_abilities.go @@ -462,8 +462,7 @@ func (hp *HunterPet) newPin() *core.Spell { Cast: core.CastConfig{ DefaultCast: core.Cast{ - GCD: PetGCD, - ChannelTime: time.Second * 4, + GCD: PetGCD, }, IgnoreHaste: true, CD: core.Cooldown{ diff --git a/sim/hunter/rotation.go b/sim/hunter/rotation.go deleted file mode 100644 index 62b6fd1ac0..0000000000 --- a/sim/hunter/rotation.go +++ /dev/null @@ -1,385 +0,0 @@ -package hunter - -import ( - "time" - - "github.com/wowsims/wotlk/sim/common" - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/core/proto" -) - -func (hunter *Hunter) OnAutoAttack(sim *core.Simulation, spell *core.Spell) { - hunter.mayMoveAt = sim.CurrentTime - if !hunter.IsUsingAPL { - hunter.TryUseCooldowns(sim) - } - if hunter.GCD.IsReady(sim) { - hunter.rotation(sim) - } -} - -func (hunter *Hunter) OnGCDReady(sim *core.Simulation) { - hunter.rotation(sim) -} - -func (hunter *Hunter) rotation(sim *core.Simulation) { - if hunter.IsUsingAPL { - return - } - hunter.trySwapAspect(sim) - - if hunter.SilencingShot.IsReady(sim) { - hunter.SilencingShot.Cast(sim, hunter.CurrentTarget) - } - - if hunter.Rotation.Type == proto.Hunter_Rotation_Custom { - hunter.CustomRotation.Cast(sim) - } else if hunter.Rotation.Type == proto.Hunter_Rotation_Aoe { - spell := hunter.aoeChooseSpell(sim) - - success := spell.Cast(sim, hunter.CurrentTarget) - if !success { - hunter.WaitForMana(sim, spell.CurCast.Cost) - } - } else { - spell, target := hunter.singleTargetChooseSpell(sim) - if spell == nil { - if hunter.GCD.IsReady(sim) { - hunter.WaitUntil(sim, sim.CurrentTime+100*time.Millisecond) - } - } else { - success := spell.Cast(sim, target) - if !success { - hunter.WaitForMana(sim, spell.CurCast.Cost) - } - } - } -} - -func (hunter *Hunter) aoeChooseSpell(sim *core.Simulation) *core.Spell { - if hunter.Rotation.TrapWeave && hunter.ExplosiveTrap.IsReady(sim) && !hunter.ExplosiveTrap.AOEDot().IsActive() { - return hunter.TrapWeaveSpell - } else { - return hunter.Volley - } -} - -func (hunter *Hunter) singleTargetChooseSpell(sim *core.Simulation) (*core.Spell, *core.Unit) { - for _, spell := range hunter.rotationPriority { - if spell == nil { - continue - } - - for i := int32(0); i < hunter.Env.GetNumTargets(); i++ { - if hunter.rotationConditions[spell].CanUse(sim, hunter.Env.GetTargetUnit(i)) { - return spell, hunter.Env.GetTargetUnit(i) - } - } - } - return nil, nil -} - -// Returns whether an aspect was swapped. -func (hunter *Hunter) trySwapAspect(sim *core.Simulation) bool { - currentMana := hunter.CurrentManaPercent() - if hunter.currentAspect == hunter.AspectOfTheViperAura && hunter.Rotation.ViperStartManaPercent < 1 { - if !hunter.permaHawk && - hunter.CurrentMana() > hunter.manaSpentPerSecondAtFirstAspectSwap*sim.GetRemainingDuration().Seconds() { - hunter.permaHawk = true - } - if hunter.permaHawk || currentMana > hunter.Rotation.ViperStopManaPercent { - hunter.AspectOfTheDragonhawk.Cast(sim, nil) - return true - } - } else if hunter.currentAspect != hunter.AspectOfTheViperAura && !hunter.permaHawk && currentMana < hunter.Rotation.ViperStartManaPercent { - if hunter.manaSpentPerSecondAtFirstAspectSwap == 0 { - hunter.manaSpentPerSecondAtFirstAspectSwap = (hunter.Metrics.ManaSpent - hunter.Metrics.ManaGained) / sim.CurrentTime.Seconds() - } - if !hunter.permaHawk && - hunter.CurrentMana() > hunter.manaSpentPerSecondAtFirstAspectSwap*sim.GetRemainingDuration().Seconds() { - hunter.permaHawk = true - } - hunter.AspectOfTheViper.Cast(sim, nil) - return true - } - return false -} - -func (hunter *Hunter) shouldCastSteadyShot(sim *core.Simulation) bool { - for _, spell := range hunter.rotationPriority { - if spell == nil { - continue - } - ttr := spell.TimeToReady(sim) - if ttr > 0 && ttr < time.Duration(hunter.Rotation.SteadyShotMaxDelay)*time.Millisecond { - return false - } - } - return true -} - -func (hunter *Hunter) makeCustomRotation() *common.CustomRotation { - return common.NewCustomRotation(hunter.Rotation.CustomRotation, hunter.GetCharacter(), map[int32]common.CustomSpell{ - int32(proto.Hunter_Rotation_ArcaneShot): { - Action: func(sim *core.Simulation, target *core.Unit) (bool, float64) { - cost := hunter.ArcaneShot.CurCast.Cost - return hunter.ArcaneShot.Cast(sim, target), cost - }, - Condition: func(sim *core.Simulation) bool { - return hunter.ArcaneShot.IsReady(sim) && (hunter.ExplosiveShotR4 == nil || (!hunter.ExplosiveShotR4.CurDot().IsActive() && !hunter.ExplosiveShotR3.CurDot().IsActive())) - }, - }, - int32(proto.Hunter_Rotation_AimedShot): { - Action: func(sim *core.Simulation, target *core.Unit) (bool, float64) { - cost := hunter.AimedShot.CurCast.Cost - return hunter.AimedShot.Cast(sim, target), cost - }, - Condition: func(sim *core.Simulation) bool { - return hunter.AimedShot.IsReady(sim) - }, - }, - int32(proto.Hunter_Rotation_BlackArrow): { - Action: func(sim *core.Simulation, target *core.Unit) (bool, float64) { - cost := hunter.BlackArrow.CurCast.Cost - return hunter.BlackArrow.Cast(sim, target), cost - }, - Condition: func(sim *core.Simulation) bool { - return hunter.BlackArrow.IsReady(sim) - }, - }, - int32(proto.Hunter_Rotation_ChimeraShot): { - Action: func(sim *core.Simulation, target *core.Unit) (bool, float64) { - cost := hunter.ChimeraShot.CurCast.Cost - return hunter.ChimeraShot.Cast(sim, target), cost - }, - Condition: func(sim *core.Simulation) bool { - return hunter.ChimeraShot.IsReady(sim) - }, - }, - int32(proto.Hunter_Rotation_ExplosiveShot): { - Action: func(sim *core.Simulation, target *core.Unit) (bool, float64) { - cost := hunter.ExplosiveShotR4.CurCast.Cost - return hunter.ExplosiveShotR4.Cast(sim, target), cost - }, - Condition: func(sim *core.Simulation) bool { - return hunter.ExplosiveShotR4.IsReady(sim) && !hunter.ExplosiveShotR4.CurDot().IsActive() - }, - }, - int32(proto.Hunter_Rotation_ExplosiveShotDownrank): { - Action: func(sim *core.Simulation, target *core.Unit) (bool, float64) { - cost := hunter.ExplosiveShotR3.CurCast.Cost - return hunter.ExplosiveShotR3.Cast(sim, target), cost - }, - Condition: func(sim *core.Simulation) bool { - return hunter.ExplosiveShotR3.IsReady(sim) && !hunter.ExplosiveShotR3.CurDot().IsActive() - }, - }, - int32(proto.Hunter_Rotation_ExplosiveTrap): { - Action: func(sim *core.Simulation, target *core.Unit) (bool, float64) { - cost := hunter.TrapWeaveSpell.CurCast.Cost - return hunter.TrapWeaveSpell.Cast(sim, target), cost - }, - Condition: func(sim *core.Simulation) bool { - return hunter.ExplosiveTrap.IsReady(sim) && !hunter.ExplosiveTrap.AOEDot().IsActive() - }, - }, - int32(proto.Hunter_Rotation_KillShot): { - Action: func(sim *core.Simulation, target *core.Unit) (bool, float64) { - cost := hunter.KillShot.CurCast.Cost - return hunter.KillShot.Cast(sim, target), cost - }, - Condition: func(sim *core.Simulation) bool { - return sim.IsExecutePhase20() && hunter.KillShot.IsReady(sim) - }, - }, - int32(proto.Hunter_Rotation_MultiShot): { - Action: func(sim *core.Simulation, target *core.Unit) (bool, float64) { - cost := hunter.MultiShot.CurCast.Cost - return hunter.MultiShot.Cast(sim, target), cost - }, - Condition: func(sim *core.Simulation) bool { - return hunter.MultiShot.IsReady(sim) - }, - }, - int32(proto.Hunter_Rotation_ScorpidStingSpell): { - Action: func(sim *core.Simulation, target *core.Unit) (bool, float64) { - cost := hunter.ScorpidSting.CurCast.Cost - return hunter.ScorpidSting.Cast(sim, target), cost - }, - Condition: func(sim *core.Simulation) bool { - return hunter.Rotation.Sting == proto.Hunter_Rotation_ScorpidSting && !hunter.ScorpidStingAuras.Get(hunter.CurrentTarget).IsActive() - }, - }, - int32(proto.Hunter_Rotation_SerpentStingSpell): { - Action: func(sim *core.Simulation, target *core.Unit) (bool, float64) { - cost := hunter.SerpentSting.CurCast.Cost - for i := int32(0); i < hunter.Env.GetNumTargets(); i++ { - target := hunter.Env.GetTargetUnit(i) - if !hunter.SerpentSting.Dot(target).IsActive() { - return hunter.SerpentSting.Cast(sim, target), cost - } - } - panic("No valid serpent-sting target found") - }, - Condition: func(sim *core.Simulation) bool { - if hunter.Rotation.Sting != proto.Hunter_Rotation_SerpentSting { - return false - } - if hunter.Rotation.MultiDotSerpentSting { - for i := int32(0); i < hunter.Env.GetNumTargets(); i++ { - if !hunter.SerpentSting.Dot(hunter.Env.GetTargetUnit(i)).IsActive() { - return true - } - } - } - return !hunter.SerpentSting.CurDot().IsActive() - }, - }, - int32(proto.Hunter_Rotation_SteadyShot): { - Action: func(sim *core.Simulation, target *core.Unit) (bool, float64) { - cost := hunter.SteadyShot.CurCast.Cost - return hunter.SteadyShot.Cast(sim, target), cost - }, - Condition: func(sim *core.Simulation) bool { - return hunter.shouldCastSteadyShot(sim) - }, - }, - int32(proto.Hunter_Rotation_Volley): { - Action: func(sim *core.Simulation, target *core.Unit) (bool, float64) { - cost := hunter.Volley.CurCast.Cost - return hunter.Volley.Cast(sim, target), cost - }, - Condition: func(sim *core.Simulation) bool { - return true - }, - }, - }) -} - -type RotationCondition struct { - CanUse func(sim *core.Simulation, target *core.Unit) bool -} - -func (hunter *Hunter) initRotation() { - hunter.rotationConditions = map[*core.Spell]RotationCondition{ - hunter.KillShot: RotationCondition{ - func(sim *core.Simulation, target *core.Unit) bool { - return sim.IsExecutePhase20() && hunter.KillShot.IsReady(sim) - }, - }, - hunter.ExplosiveShotR4: RotationCondition{ - func(sim *core.Simulation, target *core.Unit) bool { - if target != hunter.CurrentTarget { - return false - } - return hunter.ExplosiveShotR4.IsReady(sim) && !hunter.ExplosiveShotR4.CurDot().IsActive() - }, - }, - hunter.ExplosiveShotR3: RotationCondition{ - func(sim *core.Simulation, target *core.Unit) bool { - if target != hunter.CurrentTarget { - return false - } - return hunter.Rotation.AllowExplosiveShotDownrank && hunter.ExplosiveShotR3.IsReady(sim) && !hunter.ExplosiveShotR3.CurDot().IsActive() - }, - }, - hunter.ScorpidSting: RotationCondition{ - func(sim *core.Simulation, target *core.Unit) bool { - if target != hunter.CurrentTarget { - return false - } - return hunter.Rotation.Sting == proto.Hunter_Rotation_ScorpidSting && !hunter.ScorpidStingAuras.Get(hunter.CurrentTarget).IsActive() - }, - }, - hunter.SerpentSting: RotationCondition{ - func(sim *core.Simulation, target *core.Unit) bool { - if target != hunter.CurrentTarget && !hunter.Rotation.MultiDotSerpentSting { - return false - } - return hunter.Rotation.Sting == proto.Hunter_Rotation_SerpentSting && !hunter.SerpentSting.Dot(target).IsActive() - }, - }, - hunter.ChimeraShot: RotationCondition{ - func(sim *core.Simulation, target *core.Unit) bool { - return hunter.ChimeraShot.IsReady(sim) - }, - }, - hunter.BlackArrow: RotationCondition{ - func(sim *core.Simulation, target *core.Unit) bool { - return !hunter.Rotation.TrapWeave && hunter.BlackArrow.IsReady(sim) - }, - }, - hunter.TrapWeaveSpell: RotationCondition{ - func(sim *core.Simulation, target *core.Unit) bool { - return hunter.Rotation.TrapWeave && hunter.ExplosiveTrap.IsReady(sim) && !hunter.ExplosiveTrap.AOEDot().IsActive() - }, - }, - hunter.AimedShot: RotationCondition{ - func(sim *core.Simulation, target *core.Unit) bool { - return hunter.AimedShot.IsReady(sim) - }, - }, - hunter.MultiShot: RotationCondition{ - func(sim *core.Simulation, target *core.Unit) bool { - return hunter.MultiShot.IsReady(sim) - }, - }, - hunter.ArcaneShot: RotationCondition{ - func(sim *core.Simulation, target *core.Unit) bool { - return hunter.ArcaneShot.IsReady(sim) && (!hunter.ExplosiveShotR4.CurDot().IsActive() && !hunter.ExplosiveShotR3.CurDot().IsActive()) - }, - }, - hunter.SteadyShot: RotationCondition{ - func(sim *core.Simulation, target *core.Unit) bool { - return hunter.SteadyShot.IsReady(sim) && hunter.shouldCastSteadyShot(sim) - }, - }, - } - - if hunter.PrimaryTalentTree == 0 { - // BM - hunter.rotationPriority = []*core.Spell{ - hunter.KillShot, - hunter.TrapWeaveSpell, - hunter.SerpentSting, - hunter.ScorpidSting, - hunter.AimedShot, - hunter.MultiShot, - hunter.SteadyShot, - } - } else if hunter.PrimaryTalentTree == 1 { - // MM - hunter.rotationPriority = []*core.Spell{ - hunter.KillShot, - hunter.SerpentSting, - hunter.ScorpidSting, - hunter.TrapWeaveSpell, - hunter.ChimeraShot, - hunter.AimedShot, - hunter.MultiShot, - hunter.SteadyShot, - } - } else { - // SV - hunter.rotationPriority = []*core.Spell{ - hunter.KillShot, - hunter.ExplosiveShotR4, - hunter.ExplosiveShotR3, - hunter.TrapWeaveSpell, - hunter.SerpentSting, - hunter.ScorpidSting, - hunter.BlackArrow, - hunter.AimedShot, - hunter.MultiShot, - hunter.SteadyShot, - } - } - - if hunter.Env.GetNumTargets() > 1 { - for i, spell := range hunter.rotationPriority { - if spell == hunter.AimedShot { - hunter.rotationPriority[i] = nil - } - } - } -} diff --git a/sim/hunter/volley.go b/sim/hunter/volley.go index 205c4c871d..c865cd8440 100644 --- a/sim/hunter/volley.go +++ b/sim/hunter/volley.go @@ -20,8 +20,7 @@ func (hunter *Hunter) registerVolleySpell() { }, Cast: core.CastConfig{ DefaultCast: core.Cast{ - GCD: core.GCDDefault, - ChannelTime: time.Second * 6, + GCD: core.GCDDefault, }, }, diff --git a/sim/warrior/dps/dps_warrior.go b/sim/warrior/dps/dps_warrior.go index cfbbc96319..fcc5c19535 100644 --- a/sim/warrior/dps/dps_warrior.go +++ b/sim/warrior/dps/dps_warrior.go @@ -69,23 +69,7 @@ func NewDpsWarrior(character *core.Character, options *proto.Player) *DpsWarrior rbo.OHSwingSpeed = oh.SwingSpeed } - war.EnableRageBar(rbo, func(sim *core.Simulation) { - if war.GCD.IsReady(sim) { - war.TryUseCooldowns(sim) - if war.GCD.IsReady(sim) { - // Pause rotation until after AM ticks to detect procs that happened right after the ticks - if war.LastAMTick == sim.CurrentTime { - war.WaitUntil(sim, sim.CurrentTime+time.Microsecond*1) - core.StartDelayedAction(sim, core.DelayedActionOptions{ - DoAt: sim.CurrentTime + time.Microsecond*1, - OnAction: war.doRotation, - }) - } else { - war.doRotation(sim) - } - } - } - }) + war.EnableRageBar(rbo) war.EnableAutoAttacks(war, core.AutoAttackOptions{ MainHand: war.WeaponFromMainHand(war.DefaultMeleeCritMultiplier()), OffHand: war.WeaponFromOffHand(war.DefaultMeleeCritMultiplier()), @@ -137,8 +121,6 @@ func (war *DpsWarrior) Initialize() { } else if war.Rotation.StanceOption == proto.Warrior_Rotation_BattleStance { war.BattleStanceAura.BuildPhase = core.CharacterBuildPhaseTalents } - - war.DelayDPSCooldownsForArmorDebuffs(time.Second * 10) } func (war *DpsWarrior) Reset(sim *core.Simulation) { diff --git a/sim/warrior/protection/protection_warrior.go b/sim/warrior/protection/protection_warrior.go index 9a7849ea1c..d8c4ce30fb 100644 --- a/sim/warrior/protection/protection_warrior.go +++ b/sim/warrior/protection/protection_warrior.go @@ -55,14 +55,7 @@ func NewProtectionWarrior(character *core.Character, options *proto.Player) *Pro rbo.OHSwingSpeed = oh.SwingSpeed } - war.EnableRageBar(rbo, func(sim *core.Simulation) { - if war.GCD.IsReady(sim) { - war.TryUseCooldowns(sim) - if war.GCD.IsReady(sim) { - war.doRotation(sim) - } - } - }) + war.EnableRageBar(rbo) war.EnableAutoAttacks(war, core.AutoAttackOptions{ MainHand: war.WeaponFromMainHand(war.DefaultMeleeCritMultiplier()), OffHand: war.WeaponFromOffHand(war.DefaultMeleeCritMultiplier()), From 681d4cd9ae7f0f47ee21384f74449edce495af29 Mon Sep 17 00:00:00 2001 From: James Tanner Date: Wed, 3 Jan 2024 18:18:15 -0800 Subject: [PATCH 05/28] Commiting to update from master --- sim/core/mana.go | 29 +- sim/deathknight/army_of_the_dead.go | 3 +- sim/deathknight/blood_boil.go | 7 - sim/deathknight/blood_strike.go | 1 - sim/deathknight/death_strike.go | 1 - sim/deathknight/deathknight.go | 194 ----- sim/deathknight/dps/dps_deathknight.go | 469 ------------ sim/deathknight/dps/rotation_blood.go | 357 --------- sim/deathknight/dps/rotation_blood_helper.go | 213 ------ sim/deathknight/dps/rotation_frost.go | 203 ------ sim/deathknight/dps/rotation_frost_aoe.go | 185 ----- sim/deathknight/dps/rotation_frost_helper.go | 259 ------- .../dps/rotation_frost_sub_blood.go | 417 ----------- .../dps/rotation_frost_sub_blood_desync.go | 243 ------- .../dps/rotation_frost_sub_unholy.go | 267 ------- sim/deathknight/dps/rotation_shared_helper.go | 111 --- sim/deathknight/dps/rotation_unholy.go | 676 ------------------ sim/deathknight/dps/rotation_unholy_helper.go | 457 ------------ sim/deathknight/frost_strike.go | 1 - sim/deathknight/ghoul_frenzy.go | 12 - sim/deathknight/heart_strike.go | 1 - sim/deathknight/horn_of_winter.go | 8 - sim/deathknight/howling_blast.go | 7 - sim/deathknight/icy_touch.go | 1 - sim/deathknight/items.go | 12 +- sim/deathknight/obliterate.go | 1 - sim/deathknight/pestilence.go | 1 - sim/deathknight/plague_strike.go | 1 - sim/deathknight/rotation.go | 296 -------- sim/deathknight/rotation_helper.go | 53 -- sim/deathknight/scourge_strike.go | 1 - sim/deathknight/tank/openers.go | 130 ---- sim/deathknight/tank/rotation_hps.go | 46 -- sim/deathknight/tank/rotation_shared.go | 63 -- sim/deathknight/tank/rotation_tps.go | 73 -- sim/deathknight/tank/tank_deathknight.go | 53 +- sim/deathknight/unholy_frenzy.go | 2 +- sim/hunter/hunter.go | 9 +- 38 files changed, 22 insertions(+), 4841 deletions(-) delete mode 100644 sim/deathknight/dps/rotation_blood.go delete mode 100644 sim/deathknight/dps/rotation_blood_helper.go delete mode 100644 sim/deathknight/dps/rotation_frost.go delete mode 100644 sim/deathknight/dps/rotation_frost_aoe.go delete mode 100644 sim/deathknight/dps/rotation_frost_helper.go delete mode 100644 sim/deathknight/dps/rotation_frost_sub_blood.go delete mode 100644 sim/deathknight/dps/rotation_frost_sub_blood_desync.go delete mode 100644 sim/deathknight/dps/rotation_frost_sub_unholy.go delete mode 100644 sim/deathknight/dps/rotation_shared_helper.go delete mode 100644 sim/deathknight/dps/rotation_unholy.go delete mode 100644 sim/deathknight/dps/rotation_unholy_helper.go delete mode 100644 sim/deathknight/rotation.go delete mode 100644 sim/deathknight/rotation_helper.go delete mode 100644 sim/deathknight/tank/openers.go delete mode 100644 sim/deathknight/tank/rotation_hps.go delete mode 100644 sim/deathknight/tank/rotation_shared.go delete mode 100644 sim/deathknight/tank/rotation_tps.go diff --git a/sim/core/mana.go b/sim/core/mana.go index 903b802494..59f245afb5 100644 --- a/sim/core/mana.go +++ b/sim/core/mana.go @@ -213,25 +213,24 @@ func (unit *Unit) TimeUntilManaRegen(desiredMana float64) time.Duration { } func (sim *Simulation) initManaTickAction() { - var playersWithManaBars []Agent - var petsWithManaBars []PetAgent + var unitsWithManaBars []*Unit for _, party := range sim.Raid.Parties { for _, player := range party.Players { character := player.GetCharacter() if character.HasManaBar() { - playersWithManaBars = append(playersWithManaBars, player) + unitsWithManaBars = append(unitsWithManaBars, &player.GetCharacter().Unit) } for _, petAgent := range character.PetAgents { if petAgent.GetPet().HasManaBar() { - petsWithManaBars = append(petsWithManaBars, petAgent) + unitsWithManaBars = append(unitsWithManaBars, &petAgent.GetCharacter().Unit) } } } } - if len(playersWithManaBars) == 0 && len(petsWithManaBars) == 0 { + if len(unitsWithManaBars) == 0 { return } @@ -241,23 +240,9 @@ func (sim *Simulation) initManaTickAction() { Priority: ActionPriorityRegen, } pa.OnAction = func(sim *Simulation) { - for _, player := range playersWithManaBars { - char := player.GetCharacter() - char.ManaTick(sim) - - // Only execute APL actions after mana ticks once pre-pull has completed. - if sim.CurrentTime > 0 { - if char.IsWaitingForMana() && !char.DoneWaitingForMana(sim) { - continue - } - - char.Rotation.DoNextAction(sim) - } - } - for _, petAgent := range petsWithManaBars { - pet := petAgent.GetPet() - if pet.IsEnabled() { - pet.ManaTick(sim) + for _, unit := range unitsWithManaBars { + if unit.IsEnabled() { + unit.ManaTick(sim) } } diff --git a/sim/deathknight/army_of_the_dead.go b/sim/deathknight/army_of_the_dead.go index 73a284e330..a2bde0ae51 100644 --- a/sim/deathknight/army_of_the_dead.go +++ b/sim/deathknight/army_of_the_dead.go @@ -51,8 +51,7 @@ func (dk *Deathknight) registerArmyOfTheDeadCD() { }, Cast: core.CastConfig{ DefaultCast: core.Cast{ - ChannelTime: time.Second * 4, - GCD: core.GCDDefault, + GCD: core.GCDDefault, }, CD: core.Cooldown{ Timer: dk.NewTimer(), diff --git a/sim/deathknight/blood_boil.go b/sim/deathknight/blood_boil.go index b0847d391c..943aa60057 100644 --- a/sim/deathknight/blood_boil.go +++ b/sim/deathknight/blood_boil.go @@ -31,21 +31,14 @@ func (dk *Deathknight) registerBloodBoilSpell() { ThreatMultiplier: 1.0, ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - dk.AoESpellNumTargetsHit = 0 - for _, aoeTarget := range sim.Encounter.TargetUnits { baseDamage := (sim.Roll(180, 220) + 0.06*dk.getImpurityBonus(spell)) * dk.RoRTSBonus(aoeTarget) * core.TernaryFloat64(dk.DiseasesAreActive(aoeTarget), 1.5, 1.0) baseDamage *= sim.Encounter.AOECapMultiplier() result := spell.CalcAndDealDamage(sim, aoeTarget, baseDamage, spell.OutcomeMagicHitAndCrit) - if result.Landed() { - dk.AoESpellNumTargetsHit++ - } - if aoeTarget == target { spell.SpendRefundableCost(sim, result) - dk.LastOutcome = result.Outcome } } }, diff --git a/sim/deathknight/blood_strike.go b/sim/deathknight/blood_strike.go index 399725e619..96d53a6f16 100644 --- a/sim/deathknight/blood_strike.go +++ b/sim/deathknight/blood_strike.go @@ -60,7 +60,6 @@ func (dk *Deathknight) newBloodStrikeSpell(isMH bool) *core.Spell { if isMH { spell.SpendRefundableCostAndConvertBloodRune(sim, result, deathConvertChance) dk.threatOfThassarianProc(sim, result, dk.BloodStrikeOhHit) - dk.LastOutcome = result.Outcome if result.Landed() { if dk.DesolationAura != nil { diff --git a/sim/deathknight/death_strike.go b/sim/deathknight/death_strike.go index f45bb4d5a1..de85bd7a11 100644 --- a/sim/deathknight/death_strike.go +++ b/sim/deathknight/death_strike.go @@ -66,7 +66,6 @@ func (dk *Deathknight) newDeathStrikeSpell(isMH bool) *core.Spell { if isMH { spell.SpendRefundableCostAndConvertFrostOrUnholyRune(sim, result, deathConvertChance) - dk.LastOutcome = result.Outcome if result.Landed() { healingAmount := 0.05 * dk.dkCountActiveDiseases(target) * dk.MaxHealth() * (1.0 + 0.5*float64(dk.Talents.ImprovedDeathStrike)) diff --git a/sim/deathknight/deathknight.go b/sim/deathknight/deathknight.go index 469285f364..9c05192037 100644 --- a/sim/deathknight/deathknight.go +++ b/sim/deathknight/deathknight.go @@ -75,8 +75,6 @@ type Deathknight struct { Inputs DeathknightInputs - RotationHelper - Ghoul *GhoulPet RaiseDead *core.Spell @@ -314,33 +312,6 @@ func (dk *Deathknight) Initialize() { dk.registerDeathPactSpell() dk.registerUnholyFrenzyCD() - dk.RegisterAura(core.Aura{ - Label: "Last Cast Assigner", - Duration: core.NeverExpires, - OnReset: func(aura *core.Aura, sim *core.Simulation) { - aura.Activate(sim) - }, - OnCastComplete: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell) { - if spell.DefaultCast.GCD > 0 { - dk.LastCast = spell - } - }, - }) - - if !dk.IsUsingAPL { - if dk.Inputs.PrecastHornOfWinter { - dk.RegisterPrepullAction(-1500*time.Millisecond, func(sim *core.Simulation) { - dk.HornOfWinter.Cast(sim, nil) - }) - } - - if dk.Inputs.ArmyOfTheDeadType == proto.Deathknight_Rotation_PreCast { - dk.RegisterPrepullAction(-10*time.Second, func(sim *core.Simulation) { - dk.ArmyOfTheDead.Cast(sim, nil) - }) - } - } - // allows us to use these auras in the APL pre-pull actions wotlk.CreateBlackMagicProcAura(&dk.Character) CreateVirulenceProcAura(&dk.Character) @@ -393,8 +364,6 @@ func (dk *Deathknight) ResetBonusCoeffs() { func (dk *Deathknight) Reset(sim *core.Simulation) { dk.LastTickTime = -1 - dk.LastCast = nil - dk.NextCast = nil dk.DeathStrikeHeals = dk.DeathStrikeHeals[:0] dk.MakeTSRoRAssumptions = sim.Raid.Size() <= 1 } @@ -475,7 +444,6 @@ func NewDeathknight(character *core.Character, inputs DeathknightInputs, talents dk.RuneWeapon = dk.NewRuneWeapon() } - dk.RotationSequence = &Sequence{} // done here so enchants that modify stats are applied before stats are calculated dk.registerItems() @@ -498,26 +466,6 @@ func (dk *Deathknight) bonusCritMultiplier(bonusTalentPoints int32) float64 { return dk.MeleeCritMultiplier(1, 0.15*float64(bonusTalentPoints)) } -func (dk *Deathknight) AverageDSHeal() float64 { - count := len(dk.DeathStrikeHeals) - if count >= 5 { - sum := dk.DeathStrikeHeals[count-1] - sum += dk.DeathStrikeHeals[count-2] - sum += dk.DeathStrikeHeals[count-3] - sum += dk.DeathStrikeHeals[count-4] - sum += dk.DeathStrikeHeals[count-5] - return sum / 5.0 - } else if count > 0 { - sum := dk.DeathStrikeHeals[count-1] - for i := 1; i < count; i++ { - sum += dk.DeathStrikeHeals[count-i-1] - } - return sum / float64(count) - } else { - return 0 - } -} - // Agent is a generic way to access underlying warrior on any of the agents. func (dk *Deathknight) GetDeathKnight() *Deathknight { @@ -527,145 +475,3 @@ func (dk *Deathknight) GetDeathKnight() *Deathknight { type DeathKnightAgent interface { GetDeathKnight() *Deathknight } - -func PointsInTalents(talents *proto.DeathknightTalents) (int, int, int) { - blood := 0 - blood += int(talents.Butchery) - blood += int(talents.Subversion) - blood += int(talents.BladeBarrier) - blood += int(talents.BladedArmor) - blood += int(talents.ScentOfBlood) - blood += int(talents.TwoHandedWeaponSpecialization) - blood += int(talents.DarkConviction) - blood += int(talents.DeathRuneMastery) - blood += int(talents.ImprovedRuneTap) - blood += int(talents.SpellDeflection) - blood += int(talents.Vendetta) - blood += int(talents.BloodyStrikes) - blood += int(talents.VeteranOfTheThirdWar) - blood += int(talents.BloodyVengeance) - blood += int(talents.AbominationsMight) - blood += int(talents.Bloodworms) - blood += int(talents.ImprovedBloodPresence) - blood += int(talents.ImprovedDeathStrike) - blood += int(talents.SuddenDoom) - blood += int(talents.WillOfTheNecropolis) - blood += int(talents.MightOfMograine) - blood += int(talents.BloodGorged) - if talents.RuneTap { - blood++ - } - if talents.Hysteria { - blood++ - } - if talents.MarkOfBlood { - blood++ - } - if talents.VampiricBlood { - blood++ - } - if talents.HeartStrike { - blood++ - } - if talents.DancingRuneWeapon { - blood++ - } - - frost := 0 - - frost += int(talents.ImprovedIcyTouch) - frost += int(talents.RunicPowerMastery) - frost += int(talents.Toughness) - frost += int(talents.IcyReach) - frost += int(talents.BlackIce) - frost += int(talents.NervesOfColdSteel) - frost += int(talents.IcyTalons) - frost += int(talents.Annihilation) - frost += int(talents.KillingMachine) - frost += int(talents.ChillOfTheGrave) - frost += int(talents.EndlessWinter) - frost += int(talents.FrigidDreadplate) - frost += int(talents.GlacierRot) - frost += int(talents.MercilessCombat) - frost += int(talents.Rime) - frost += int(talents.Chilblains) - frost += int(talents.ImprovedFrostPresence) - frost += int(talents.ThreatOfThassarian) - frost += int(talents.BloodOfTheNorth) - frost += int(talents.Acclimation) - frost += int(talents.GuileOfGorefiend) - frost += int(talents.TundraStalker) - if talents.HowlingBlast { - frost++ - } - if talents.Lichborne { - frost++ - } - if talents.Deathchill { - frost++ - } - if talents.ImprovedIcyTalons { - frost++ - } - if talents.HungeringCold { - frost++ - } - if talents.UnbreakableArmor { - frost++ - } - if talents.FrostStrike { - frost++ - } - - unholy := 0 - - unholy += int(talents.ViciousStrikes) - unholy += int(talents.Virulence) - unholy += int(talents.Anticipation) - unholy += int(talents.Epidemic) - unholy += int(talents.Morbidity) - unholy += int(talents.UnholyCommand) - unholy += int(talents.RavenousDead) - unholy += int(talents.Outbreak) - unholy += int(talents.Necrosis) - unholy += int(talents.OnAPaleHorse) - unholy += int(talents.BloodCakedBlade) - unholy += int(talents.NightOfTheDead) - unholy += int(talents.Impurity) - unholy += int(talents.Dirge) - unholy += int(talents.Desecration) - unholy += int(talents.MagicSuppression) - unholy += int(talents.Reaping) - unholy += int(talents.Desolation) - unholy += int(talents.ImprovedUnholyPresence) - unholy += int(talents.CryptFever) - unholy += int(talents.WanderingPlague) - unholy += int(talents.EbonPlaguebringer) - unholy += int(talents.RageOfRivendare) - if talents.CorpseExplosion { - unholy++ - } - if talents.UnholyBlight { - unholy++ - } - if talents.MasterOfGhouls { - unholy++ - } - if talents.AntiMagicZone { - unholy++ - } - if talents.GhoulFrenzy { - unholy++ - } - if talents.BoneShield { - unholy++ - } - if talents.ScourgeStrike { - unholy++ - } - if talents.SummonGargoyle { - unholy++ - } - - return blood, frost, unholy -} diff --git a/sim/deathknight/dps/dps_deathknight.go b/sim/deathknight/dps/dps_deathknight.go index e342615622..458fb5876f 100644 --- a/sim/deathknight/dps/dps_deathknight.go +++ b/sim/deathknight/dps/dps_deathknight.go @@ -1,9 +1,6 @@ package dps import ( - "time" - - "github.com/wowsims/wotlk/sim/common" "github.com/wowsims/wotlk/sim/core" "github.com/wowsims/wotlk/sim/core/proto" "github.com/wowsims/wotlk/sim/deathknight" @@ -28,17 +25,6 @@ func RegisterDpsDeathknight() { type DpsDeathknight struct { *deathknight.Deathknight - - sr SharedRotation - br BloodRotation - fr FrostRotation - ur UnholyRotation - - CustomRotation *common.CustomRotation - - Rotation *proto.Deathknight_Rotation - - rotationSetup func() } func NewDpsDeathknight(character *core.Character, player *proto.Player) *DpsDeathknight { @@ -64,7 +50,6 @@ func NewDpsDeathknight(character *core.Character, player *proto.Player) *DpsDeat AvgAMSSuccessRate: dk.Rotation.AvgAmsSuccessRate, AvgAMSHit: dk.Rotation.AvgAmsHit, }, player.TalentsString, dk.Rotation.PreNerfedGargoyle), - Rotation: dk.Rotation, } dpsDk.Inputs.UnholyFrenzyTarget = dk.Options.UnholyFrenzyTarget @@ -75,10 +60,6 @@ func NewDpsDeathknight(character *core.Character, player *proto.Player) *DpsDeat AutoSwingMelee: true, }) - dpsDk.br.dk = dpsDk - dpsDk.sr.dk = dpsDk - dpsDk.ur.dk = dpsDk - return dpsDk } @@ -90,465 +71,15 @@ func (dk *DpsDeathknight) FrostPointsInUnholy() int32 { return dk.Talents.ViciousStrikes + dk.Talents.Virulence + dk.Talents.Epidemic + dk.Talents.RavenousDead + dk.Talents.Necrosis + dk.Talents.BloodCakedBlade } -func (dk *DpsDeathknight) SetupRotations() { - bl, fr, uh := deathknight.PointsInTalents(dk.Talents) - - if dk.Rotation.AutoRotation { - if uh > fr && uh > bl { - // Unholy - dk.Rotation.BtGhoulFrenzy = false - dk.Rotation.UseEmpowerRuneWeapon = true - dk.Rotation.HoldErwArmy = true - dk.Rotation.UseGargoyle = true - dk.Inputs.ArmyOfTheDeadType = proto.Deathknight_Rotation_AsMajorCd - dk.Rotation.BloodTap = proto.Deathknight_Rotation_GhoulFrenzy - dk.Rotation.FirstDisease = proto.Deathknight_Rotation_FrostFever - dk.Rotation.StartingPresence = proto.Deathknight_Rotation_Unholy - dk.Rotation.BlPresence = proto.Deathknight_Rotation_Blood - dk.Rotation.Presence = proto.Deathknight_Rotation_Blood - dk.Rotation.GargoylePresence = proto.Deathknight_Rotation_Unholy - - mh := dk.GetMHWeapon() - oh := dk.GetOHWeapon() - - if mh != nil && oh != nil { - // DW - dk.Rotation.BloodRuneFiller = proto.Deathknight_Rotation_BloodBoil - dk.Rotation.UseDeathAndDecay = true - } else { - // 2h - if dk.Env.GetNumTargets() > 1 { - dk.Rotation.BloodRuneFiller = proto.Deathknight_Rotation_BloodBoil - dk.Rotation.UseDeathAndDecay = true - } else { - dk.Rotation.BloodRuneFiller = proto.Deathknight_Rotation_BloodStrike - dk.Rotation.UseDeathAndDecay = false - } - } - // Always use DnD if you have the glyph. - if dk.HasMajorGlyph(proto.DeathknightMajorGlyph_GlyphOfDeathAndDecay) { - dk.Rotation.UseDeathAndDecay = true - } - } else if fr > uh && fr > bl { - // Frost rotations here. - } else if bl > fr && bl > uh { - // Blood rotations here. - - // AotD not good as Major CD in blood due to DRW confclits - if dk.Inputs.ArmyOfTheDeadType == proto.Deathknight_Rotation_AsMajorCd { - dk.Inputs.ArmyOfTheDeadType = proto.Deathknight_Rotation_PreCast - dk.Rotation.HoldErwArmy = false - } - } else { - // some weird spec where two trees are equal... - } - } - - dk.RotationSequence.Clear() - - dk.Inputs.FuStrike = deathknight.FuStrike_Obliterate - dk.rotationSetup = dk.setupBloodRotations - dk.CustomRotation = dk.makeCustomRotation() - if dk.CustomRotation == nil || dk.Rotation.FrostRotationType == proto.Deathknight_Rotation_SingleTarget { - dk.Rotation.FrostRotationType = proto.Deathknight_Rotation_SingleTarget - if fr > uh && fr > bl { - // AotD as major CD doesn't work well with frost - if dk.Inputs.ArmyOfTheDeadType == proto.Deathknight_Rotation_AsMajorCd { - dk.Inputs.ArmyOfTheDeadType = proto.Deathknight_Rotation_PreCast - dk.Rotation.HoldErwArmy = false - } - if bl > uh { - if dk.Rotation.DesyncRotation { - dk.rotationSetup = dk.setupFrostSubBloodDesyncOpener - } else if dk.Rotation.UseEmpowerRuneWeapon { - dk.rotationSetup = dk.setupFrostSubBloodERWOpener - } else { - dk.rotationSetup = dk.setupFrostSubBloodNoERWOpener - } - } else { - dk.Rotation.FrostRotationType = proto.Deathknight_Rotation_SingleTarget - if dk.Rotation.UseEmpowerRuneWeapon { - dk.rotationSetup = dk.setupFrostSubUnholyERWOpener - } else { - // TODO you can't unh sub without ERW in the opener...yet - dk.Rotation.UseEmpowerRuneWeapon = true - dk.rotationSetup = dk.setupFrostSubUnholyERWOpener - } - } - } else if uh > fr && uh > bl { - dk.rotationSetup = dk.setupUnholyRotations - } else if bl > fr && bl > uh { - if dk.Inputs.ArmyOfTheDeadType == proto.Deathknight_Rotation_AsMajorCd { - dk.Inputs.ArmyOfTheDeadType = proto.Deathknight_Rotation_PreCast - dk.Rotation.HoldErwArmy = false - } - dk.rotationSetup = dk.setupBloodRotations - } - } else { - dk.rotationSetup = dk.setupCustomRotations - } - - dk.rotationSetup() -} - func (dk *DpsDeathknight) GetDeathknight() *deathknight.Deathknight { return dk.Deathknight } func (dk *DpsDeathknight) Initialize() { dk.Deathknight.Initialize() - - dk.sr.Initialize(dk) - dk.br.Initialize(dk) - dk.fr.Initialize(dk) - dk.ur.Initialize(dk) - - dk.SetupRotations() -} - -func (dk *DpsDeathknight) setupGargProcTrackers() { - snapshotManager := dk.ur.gargoyleSnapshot - - // Don't need to wait for haste snapshots anymore - if dk.Rotation.PreNerfedGargoyle { - snapshotManager.AddProc(40211, "Potion of Speed", true) - snapshotManager.AddProc(54999, "Hyperspeed Acceleration", true) - snapshotManager.AddProc(26297, "Berserking (Troll)", true) - snapshotManager.AddProc(33697, "Blood Fury", true) - - snapshotManager.AddProc(55379, "Thundering Skyflare Diamond Proc", false) - snapshotManager.AddProc(59626, "Black Magic Proc", false) - snapshotManager.AddProc(53344, "Rune Of The Fallen Crusader Proc", false) - - snapshotManager.AddProc(37390, "Meteorite Whetstone Proc", false) - snapshotManager.AddProc(39229, "Embrace of the Spider Proc", false) - snapshotManager.AddProc(44308, "Signet of Edward the Odd Proc", false) - snapshotManager.AddProc(43573, "Tears of Bitter Anguish Proc", false) - snapshotManager.AddProc(45609, "Comet's Trail Proc", false) - snapshotManager.AddProc(45866, "Elemental Focus Stone Proc", false) - - snapshotManager.AddProc(53344, "Rune Of The Fallen Crusader Proc", false) - } else { - fcEnchantId := int32(3368) - // Only worth snapshotting if both are on (might want to re-visit this after P2) - if mh, oh := dk.Character.MainHand(), dk.Character.OffHand(); mh.Enchant.EffectID == fcEnchantId && oh.Enchant.EffectID == fcEnchantId { - snapshotManager.AddProc(53344, "Rune Of The Fallen Crusader Proc", false) - } - } - - snapshotManager.AddProc(42987, "DMC Greatness Strength Proc", false) - - snapshotManager.AddProc(47115, "Deaths Verdict Strength Proc", false) - snapshotManager.AddProc(47131, "Deaths Verdict H Strength Proc", false) - snapshotManager.AddProc(47303, "Deaths Choice Strength Proc", false) - snapshotManager.AddProc(47464, "Deaths Choice H Strength Proc", false) - - snapshotManager.AddProc(71484, "Deathbringer's Will Strength Proc", false) - snapshotManager.AddProc(71492, "Deathbringer's Will Haste Proc", false) - snapshotManager.AddProc(71561, "Deathbringer's Will H Strength Proc", false) - snapshotManager.AddProc(71560, "Deathbringer's Will H Haste Proc", false) - - snapshotManager.AddProc(40684, "Mirror of Truth Proc", false) - snapshotManager.AddProc(40767, "Sonic Booster Proc", false) - snapshotManager.AddProc(44914, "Anvil of Titans Proc", false) - snapshotManager.AddProc(45286, "Pyrite Infuser Proc", false) - snapshotManager.AddProc(45522, "Blood of the Old God Proc", false) - snapshotManager.AddProc(47214, "Banner of Victory Proc", false) - snapshotManager.AddProc(49074, "Coren's Chromium Coaster Proc", false) - snapshotManager.AddProc(50342, "Whispering Fanged Skull Proc", false) - snapshotManager.AddProc(50343, "Whispering Fanged Skull H Proc", false) - snapshotManager.AddProc(50401, "Ashen Band of Unmatched Vengeance Proc", false) - snapshotManager.AddProc(50402, "Ashen Band of Endless Vengeance Proc", false) - snapshotManager.AddProc(52571, "Ashen Band of Unmatched Might Proc", false) - snapshotManager.AddProc(52572, "Ashen Band of Endless Might Proc", false) - snapshotManager.AddProc(54569, "Sharpened Twilight Scale Proc", false) - snapshotManager.AddProc(54590, "Sharpened Twilight Scale H Proc", false) -} - -func (dk *DpsDeathknight) setupGargoyleCooldowns() { - dk.ur.gargoyleSnapshot.ClearMajorCooldowns() - - // hyperspeed accelerators - dk.gargoyleHasteCooldownSync(core.ActionID{SpellID: 54758}, false) - - // berserking (troll) - dk.gargoyleHasteCooldownSync(core.ActionID{SpellID: 26297}, false) - - // blood fury (orc) - dk.gargoyleAPCooldownSync(core.ActionID{SpellID: 33697}, false) - - // potion of speed - dk.gargoyleHasteCooldownSync(core.ActionID{ItemID: 40211}, true) - - // active ap trinkets - dk.gargoyleAPCooldownSync(core.ActionID{ItemID: 35937}, false) - dk.gargoyleAPCooldownSync(core.ActionID{ItemID: 36871}, false) - dk.gargoyleAPCooldownSync(core.ActionID{ItemID: 37166}, false) - dk.gargoyleAPCooldownSync(core.ActionID{ItemID: 37556}, false) - dk.gargoyleAPCooldownSync(core.ActionID{ItemID: 37557}, false) - dk.gargoyleAPCooldownSync(core.ActionID{ItemID: 38080}, false) - dk.gargoyleAPCooldownSync(core.ActionID{ItemID: 38081}, false) - dk.gargoyleAPCooldownSync(core.ActionID{ItemID: 38761}, false) - dk.gargoyleAPCooldownSync(core.ActionID{ItemID: 39257}, false) - dk.gargoyleAPCooldownSync(core.ActionID{ItemID: 45263}, false) - dk.gargoyleAPCooldownSync(core.ActionID{ItemID: 46086}, false) - dk.gargoyleAPCooldownSync(core.ActionID{ItemID: 47734}, false) - - // active haste trinkets - dk.gargoyleHasteCooldownSync(core.ActionID{ItemID: 36972}, false) - dk.gargoyleHasteCooldownSync(core.ActionID{ItemID: 37558}, false) - dk.gargoyleHasteCooldownSync(core.ActionID{ItemID: 37560}, false) - dk.gargoyleHasteCooldownSync(core.ActionID{ItemID: 37562}, false) - dk.gargoyleHasteCooldownSync(core.ActionID{ItemID: 38070}, false) - dk.gargoyleHasteCooldownSync(core.ActionID{ItemID: 38258}, false) - dk.gargoyleHasteCooldownSync(core.ActionID{ItemID: 38259}, false) - dk.gargoyleHasteCooldownSync(core.ActionID{ItemID: 38764}, false) - dk.gargoyleHasteCooldownSync(core.ActionID{ItemID: 40531}, false) - dk.gargoyleHasteCooldownSync(core.ActionID{ItemID: 43836}, false) - dk.gargoyleHasteCooldownSync(core.ActionID{ItemID: 45466}, false) - dk.gargoyleHasteCooldownSync(core.ActionID{ItemID: 46088}, false) - dk.gargoyleHasteCooldownSync(core.ActionID{ItemID: 48722}, false) - dk.gargoyleHasteCooldownSync(core.ActionID{ItemID: 50260}, false) -} - -func (dk *DpsDeathknight) gargoyleAPCooldownSync(actionID core.ActionID, isPotion bool) { - if majorCd := dk.Character.GetMajorCooldown(actionID); majorCd != nil { - - majorCd.ShouldActivate = func(sim *core.Simulation, character *core.Character) bool { - if dk.ur.activatingGargoyle { - return true - } - if dk.SummonGargoyle.CD.TimeToReady(sim) > majorCd.Spell.CD.Duration && !isPotion { - return true - } - if dk.SummonGargoyle.CD.ReadyAt() > sim.Duration { - return true - } - - return false - } - - dk.ur.gargoyleSnapshot.AddMajorCooldown(majorCd) - } -} - -func (dk *DpsDeathknight) gargoyleHasteCooldownSync(actionID core.ActionID, isPotion bool) { - if majorCd := dk.Character.GetMajorCooldown(actionID); majorCd != nil { - - majorCd.ShouldActivate = func(sim *core.Simulation, character *core.Character) bool { - if !dk.Rotation.PreNerfedGargoyle { - aura := dk.SummonGargoyleAura - - if aura != nil && aura.IsActive() { - return true - } - if dk.SummonGargoyle.CD.TimeToReady(sim) > majorCd.Spell.CD.Duration-10*time.Second && !isPotion { - return true - } - if dk.SummonGargoyle.CD.ReadyAt() > sim.Duration { - return true - } - - return false - } else { - if dk.ur.activatingGargoyle { - return true - } - if dk.SummonGargoyle.CD.TimeToReady(sim) > majorCd.Spell.CD.Duration-10*time.Second && !isPotion { - return true - } - if dk.SummonGargoyle.CD.ReadyAt() > sim.Duration { - return true - } - } - - return false - } - - dk.ur.gargoyleSnapshot.AddMajorCooldown(majorCd) - } -} - -func (dk *DpsDeathknight) setupDrwProcTrackers() { - snapshotManager := dk.br.drwSnapshot - - snapshotManager.AddProc(40211, "Potion of Speed", true) - snapshotManager.AddProc(54999, "Hyperspeed Acceleration", true) - snapshotManager.AddProc(26297, "Berserking (Troll)", true) - snapshotManager.AddProc(33697, "Blood Fury", true) - - snapshotManager.AddProc(55379, "Thundering Skyflare Diamond Proc", false) - snapshotManager.AddProc(59626, "Black Magic Proc", false) - snapshotManager.AddProc(53344, "Rune Of The Fallen Crusader Proc", false) - - snapshotManager.AddProc(37390, "Meteorite Whetstone Proc", false) - snapshotManager.AddProc(39229, "Embrace of the Spider Proc", false) - snapshotManager.AddProc(44308, "Signet of Edward the Odd Proc", false) - snapshotManager.AddProc(43573, "Tears of Bitter Anguish Proc", false) - snapshotManager.AddProc(45609, "Comet's Trail Proc", false) - snapshotManager.AddProc(45866, "Elemental Focus Stone Proc", false) - - snapshotManager.AddProc(53344, "Rune Of The Fallen Crusader Proc", false) - - snapshotManager.AddProc(42987, "DMC Greatness Strength Proc", false) - - snapshotManager.AddProc(47115, "Deaths Verdict Strength Proc", false) - snapshotManager.AddProc(47131, "Deaths Verdict H Strength Proc", false) - snapshotManager.AddProc(47303, "Deaths Choice Strength Proc", false) - snapshotManager.AddProc(47464, "Deaths Choice H Strength Proc", false) - - snapshotManager.AddProc(71484, "Deathbringer's Will Strength Proc", false) - snapshotManager.AddProc(71492, "Deathbringer's Will Haste Proc", false) - snapshotManager.AddProc(71491, "Deathbringer's Will Crit Proc", false) - snapshotManager.AddProc(71561, "Deathbringer's Will H Strength Proc", false) - snapshotManager.AddProc(71560, "Deathbringer's Will H Haste Proc", false) - snapshotManager.AddProc(71559, "Deathbringer's Will H Crit Proc", false) - - snapshotManager.AddProc(40684, "Mirror of Truth Proc", false) - snapshotManager.AddProc(40767, "Sonic Booster Proc", false) - snapshotManager.AddProc(44914, "Anvil of Titans Proc", false) - snapshotManager.AddProc(45286, "Pyrite Infuser Proc", false) - snapshotManager.AddProc(45522, "Blood of the Old God Proc", false) - snapshotManager.AddProc(47214, "Banner of Victory Proc", false) - snapshotManager.AddProc(49074, "Coren's Chromium Coaster Proc", false) - snapshotManager.AddProc(50342, "Whispering Fanged Skull Proc", false) - snapshotManager.AddProc(50343, "Whispering Fanged Skull H Proc", false) - snapshotManager.AddProc(50401, "Ashen Band of Unmatched Vengeance Proc", false) - snapshotManager.AddProc(50402, "Ashen Band of Endless Vengeance Proc", false) - snapshotManager.AddProc(52571, "Ashen Band of Unmatched Might Proc", false) - snapshotManager.AddProc(52572, "Ashen Band of Endless Might Proc", false) - snapshotManager.AddProc(54569, "Sharpened Twilight Scale Proc", false) - snapshotManager.AddProc(54590, "Sharpened Twilight Scale H Proc", false) - - //snapshotManager.AddProc(40256, "Grim Toll Proc", false) - //snapshotManager.AddProc(45931, "Mjolnir Runestone Proc", false) - snapshotManager.AddProc(46038, "Dark Matter Proc", false) - snapshotManager.AddProc(50198, "Needle-Encrusted Scorpion Proc", false) -} - -func (dk *DpsDeathknight) setupDrwCooldowns() { - dk.br.drwSnapshot.ClearMajorCooldowns() - - // Unholy Frenzy - dk.drwCooldownSync(core.ActionID{SpellID: 49016, Tag: dk.Index}, false) - - // hyperspeed accelerators - dk.drwCooldownSync(core.ActionID{SpellID: 54758}, false) - - // berserking (troll) - dk.drwCooldownSync(core.ActionID{SpellID: 26297}, false) - - // blood fury (orc) - dk.drwCooldownSync(core.ActionID{SpellID: 33697}, false) - - // potion of speed - dk.drwCooldownSync(core.ActionID{ItemID: 40211}, true) - - // active ap trinkets - dk.drwCooldownSync(core.ActionID{ItemID: 35937}, false) - dk.drwCooldownSync(core.ActionID{ItemID: 36871}, false) - dk.drwCooldownSync(core.ActionID{ItemID: 37166}, false) - dk.drwCooldownSync(core.ActionID{ItemID: 37556}, false) - dk.drwCooldownSync(core.ActionID{ItemID: 37557}, false) - dk.drwCooldownSync(core.ActionID{ItemID: 38080}, false) - dk.drwCooldownSync(core.ActionID{ItemID: 38081}, false) - dk.drwCooldownSync(core.ActionID{ItemID: 38761}, false) - dk.drwCooldownSync(core.ActionID{ItemID: 39257}, false) - dk.drwCooldownSync(core.ActionID{ItemID: 45263}, false) - dk.drwCooldownSync(core.ActionID{ItemID: 46086}, false) - dk.drwCooldownSync(core.ActionID{ItemID: 47734}, false) - - // active haste trinkets - dk.drwCooldownSync(core.ActionID{ItemID: 36972}, false) - dk.drwCooldownSync(core.ActionID{ItemID: 37558}, false) - dk.drwCooldownSync(core.ActionID{ItemID: 37560}, false) - dk.drwCooldownSync(core.ActionID{ItemID: 37562}, false) - dk.drwCooldownSync(core.ActionID{ItemID: 38070}, false) - dk.drwCooldownSync(core.ActionID{ItemID: 38258}, false) - dk.drwCooldownSync(core.ActionID{ItemID: 38259}, false) - dk.drwCooldownSync(core.ActionID{ItemID: 38764}, false) - dk.drwCooldownSync(core.ActionID{ItemID: 40531}, false) - dk.drwCooldownSync(core.ActionID{ItemID: 43836}, false) - dk.drwCooldownSync(core.ActionID{ItemID: 45466}, false) - dk.drwCooldownSync(core.ActionID{ItemID: 46088}, false) - dk.drwCooldownSync(core.ActionID{ItemID: 48722}, false) - dk.drwCooldownSync(core.ActionID{ItemID: 50260}, false) -} - -func (dk *DpsDeathknight) drwCooldownSync(actionID core.ActionID, isPotion bool) { - if majorCd := dk.Character.GetMajorCooldown(actionID); majorCd != nil { - - majorCd.ShouldActivate = func(sim *core.Simulation, character *core.Character) bool { - if character != &dk.Character { - return true - } - // Opener use everything - if sim.CurrentTime < 2*time.Second { - return true - } - // If the fight is long enough for Unholy Frenzy we use potion with it - if isPotion && dk.br.activatingDrw && sim.Duration > 200*time.Second { - if dk.UnholyFrenzy.IsReady(sim) || dk.UnholyFrenzyAura.IsActive() { - return true - } - return false - } - if dk.br.activatingDrw { - return true - } - - if dk.DancingRuneWeapon.CD.TimeToReady(sim) > majorCd.Spell.CD.Duration && !isPotion { - return true - } - if !dk.DancingRuneWeapon.IsReady(sim) && dk.DancingRuneWeapon.CD.ReadyAt() > sim.Duration { - return true - } - - return false - } - - dk.br.drwSnapshot.AddMajorCooldown(majorCd) - } } func (dk *DpsDeathknight) Reset(sim *core.Simulation) { dk.Deathknight.Reset(sim) - - dk.sr.Reset(sim) - dk.br.Reset(sim) - dk.fr.Reset(sim) - dk.ur.Reset(sim) - - dk.RotationSequence.Clear() - dk.rotationSetup() - dk.Presence = deathknight.UnsetPresence - - b, f, u := deathknight.PointsInTalents(dk.Talents) - - if dk.IsUsingAPL { - return - } - - if f > u && f > b { - if dk.Rotation.Presence == proto.Deathknight_Rotation_Blood { - dk.ChangePresence(sim, deathknight.BloodPresence) - } else if dk.Rotation.Presence == proto.Deathknight_Rotation_Frost { - dk.ChangePresence(sim, deathknight.FrostPresence) - } else if dk.Rotation.Presence == proto.Deathknight_Rotation_Unholy { - dk.ChangePresence(sim, deathknight.UnholyPresence) - } - } - - if u > f && u > b { - if dk.Rotation.StartingPresence == proto.Deathknight_Rotation_Unholy { - dk.ChangePresence(sim, deathknight.UnholyPresence) - } else if dk.Talents.SummonGargoyle { - dk.ChangePresence(sim, deathknight.BloodPresence) - } - } - - if b > f && b > u { - dk.ChangePresence(sim, deathknight.BloodPresence) - } } diff --git a/sim/deathknight/dps/rotation_blood.go b/sim/deathknight/dps/rotation_blood.go deleted file mode 100644 index 4b675587b5..0000000000 --- a/sim/deathknight/dps/rotation_blood.go +++ /dev/null @@ -1,357 +0,0 @@ -package dps - -import ( - "time" - - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/core/proto" - "github.com/wowsims/wotlk/sim/deathknight" -) - -func (dk *DpsDeathknight) setupBloodRotations() { - dk.Inputs.FuStrike = deathknight.FuStrike_DeathStrike - if dk.Talents.Annihilation > 0 { - dk.Inputs.FuStrike = deathknight.FuStrike_Obliterate - } - - switch dk.Rotation.BloodSpender { - case proto.Deathknight_Rotation_HS: - dk.br.bloodSpell = dk.HeartStrike - if !dk.Talents.HeartStrike { - dk.br.bloodSpell = dk.BloodStrike - } - case proto.Deathknight_Rotation_BB: - dk.br.bloodSpell = dk.BloodBoil - case proto.Deathknight_Rotation_BS: - dk.br.bloodSpell = dk.BloodStrike - } - - if dk.Rotation.UseDancingRuneWeapon && dk.Talents.DancingRuneWeapon { - dk.setupDrwCooldowns() - } - - dk.RotationSequence.Clear(). - NewAction(dk.RotationActionCallback_IT). - NewAction(dk.RotationActionCallback_PS). - NewAction(dk.RotationActionBL_FU). - NewAction(dk.blBloodRuneAction()). - NewAction(dk.RotationActionBL_BS). - NewAction(dk.RotationActionCallback_ERW). - NewAction(dk.RotationActionCallback_RD). - NewAction(dk.RotationActionBL_DRW_Custom) - - if dk.Rotation.UseDancingRuneWeapon && dk.sr.hasGod && dk.Rotation.DrwDiseases == proto.Deathknight_Rotation_Pestilence { - dk.RotationSequence. - NewAction(dk.RotationActionBL_FU). - NewAction(dk.RotationActionCallback_Pesti). - NewAction(dk.RotationActionCallback_BT). - NewAction(dk.blBloodRuneAction()). - NewAction(dk.RotationActionBL_BS). - NewAction(dk.RotationActionBL_BS). - NewAction(dk.RotationActionBL_BS) - } else if dk.Rotation.UseDancingRuneWeapon && dk.Rotation.DrwDiseases == proto.Deathknight_Rotation_Normal { - dk.RotationSequence. - NewAction(dk.RotationActionCallback_IT). - NewAction(dk.RotationActionCallback_PS). - NewAction(dk.blBloodRuneAction()). - NewAction(dk.RotationActionCallback_BT). - NewAction(dk.RotationActionBL_BS). - NewAction(dk.RotationActionBL_BS). - NewAction(dk.RotationActionBL_BS). - NewAction(dk.RotationActionBL_BS) - } else { - dk.RotationSequence. - NewAction(dk.RotationActionBL_FU). - NewAction(dk.RotationActionBL_BS). - NewAction(dk.RotationActionCallback_BT). - NewAction(dk.RotationActionBL_BS). - NewAction(dk.RotationActionBL_BS). - NewAction(dk.RotationActionBL_BS). - NewAction(dk.RotationActionBL_BS) - } - - dk.RotationSequence.NewAction(dk.RotationActionBL_BloodRotation) -} - -func (dk *DpsDeathknight) RotationActionBL_BloodRotation(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - casted := false - - if !dk.blDiseaseCheck(sim, target, dk.RaiseDead, true, 1) { - dk.blRecastDiseasesSequence(sim) - return sim.CurrentTime - } else if dk.blDrwCheck(sim, target, 100*time.Millisecond) { - dk.blAfterDrwSequence(sim) - return sim.CurrentTime - } - - if dk.blBloodTapCheck(sim, target) { - return sim.CurrentTime - } - - if dk.RaiseDead.CanCast(sim, nil) && sim.GetRemainingDuration() >= time.Second*30 { - if dk.Talents.DancingRuneWeapon && dk.Rotation.UseDancingRuneWeapon && (dk.DancingRuneWeapon.IsReady(sim) || dk.DancingRuneWeapon.TimeToReady(sim) < 5*time.Second) { - // Use CDs - dk.br.activatingDrw = true - dk.br.drwSnapshot.ActivateMajorCooldowns(sim) - dk.UpdateMajorCooldowns() - dk.br.activatingDrw = false - } - dk.RaiseDead.Cast(sim, target) - return sim.CurrentTime - } - - fuStrike := dk.DeathStrike - if dk.Inputs.FuStrike == deathknight.FuStrike_Obliterate { - fuStrike = dk.Obliterate - } - - if !casted { - if dk.blDiseaseCheck(sim, target, dk.br.bloodSpell, true, 1) { - if dk.shShouldSpreadDisease(sim) { - return dk.blSpreadDiseases(sim, target, s) - } else { - casted = dk.br.bloodSpell.Cast(sim, target) - } - } else { - dk.blRecastDiseasesSequence(sim) - return sim.CurrentTime - } - if !casted { - if dk.blDiseaseCheck(sim, target, fuStrike, true, 1) { - casted = fuStrike.Cast(sim, target) - } else { - dk.blRecastDiseasesSequence(sim) - return sim.CurrentTime - } - if !casted { - if dk.blDeathCoilCheck(sim) { - casted = dk.DeathCoil.Cast(sim, target) - } - if !casted && dk.HornOfWinter.CanCast(sim, nil) { - dk.HornOfWinter.Cast(sim, target) - } - } - } - } - - return -1 -} - -func (dk *DpsDeathknight) blAfterDrwSequence(sim *core.Simulation) { - dk.RotationSequence.Clear() - - if dk.sr.hasGod && dk.Rotation.DrwDiseases == proto.Deathknight_Rotation_Pestilence { - dk.RotationSequence.NewAction(dk.RotationActionBL_Pesti_DRW) - } else if dk.Rotation.DrwDiseases == proto.Deathknight_Rotation_Normal { - dk.RotationSequence. - NewAction(dk.RotationActionBL_IT_DRW). - NewAction(dk.RotationActionBL_PS_DRW) - } - - dk.RotationSequence. - NewAction(dk.RotationActionBL_ResetToBloodMain) -} - -func (dk *DpsDeathknight) blRecastDiseasesSequence(sim *core.Simulation) { - dk.RotationSequence.Clear() - - // If we have glyph of Disease and both dots active try to refresh with pesti - didPesti := false - if dk.sr.hasGod { - if dk.FrostFeverSpell.Dot(dk.CurrentTarget).IsActive() && dk.BloodPlagueSpell.Dot(dk.CurrentTarget).IsActive() { - didPesti = true - dk.RotationSequence.NewAction(dk.RotationActionCallback_Pesti_Custom) - } - } - - // If we did not pesti queue normal dot refresh - if !didPesti { - dk.RotationSequence. - NewAction(dk.RotationActionBL_FF_ClipCheck). - NewAction(dk.RotationActionBL_IT_Custom). - NewAction(dk.RotationActionBL_BP_ClipCheck). - NewAction(dk.RotationActionBL_PS_Custom) - } - - dk.RotationSequence. - NewAction(dk.RotationActionBL_ResetToBloodMain) -} - -func (dk *DpsDeathknight) RotationActionBL_ResetToBloodMain(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - dk.RotationSequence.Clear(). - NewAction(dk.RotationActionBL_BloodRotation) - - return sim.CurrentTime -} - -func (dk *DpsDeathknight) RotationActionBL_DRW_Snapshot(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - dk.br.activatingDrw = true - dk.br.drwSnapshot.ActivateMajorCooldowns(sim) - dk.UpdateMajorCooldowns() - dk.br.activatingDrw = false - s.Advance() - return sim.CurrentTime -} - -func (dk *DpsDeathknight) RotationActionBL_DRW_Custom(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - if dk.Rotation.UseDancingRuneWeapon && dk.Talents.DancingRuneWeapon { - casted := dk.DancingRuneWeapon.Cast(sim, target) - if casted { - dk.br.drwSnapshot.ResetProcTrackers() - dk.br.drwMaxDelay = -1 - } - s.ConditionalAdvance(casted) - } else { - s.Advance() - } - return -1 -} - -func (dk *DpsDeathknight) RotationActionBL_BS(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - ffRemaining := dk.FrostFeverSpell.Dot(target).RemainingDuration(sim) - bpRemaining := dk.BloodPlagueSpell.Dot(target).RemainingDuration(sim) - casted := false - - // FF is not active or will drop before Gcd is ready after this cast - if dk.sr.hasGod && (!dk.FrostFeverSpell.Dot(target).IsActive() || ffRemaining <= core.GCDDefault || !dk.BloodPlagueSpell.Dot(target).IsActive() || bpRemaining <= core.GCDDefault) { - casted = dk.Pestilence.Cast(sim, target) - } else { - casted = dk.br.bloodSpell.Cast(sim, target) - } - - advance := dk.LastOutcome.Matches(core.OutcomeLanded) - s.ConditionalAdvance(casted && advance) - return -1 -} - -func (dk *DpsDeathknight) RotationActionBL_BS_ERW(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - casted := dk.br.bloodSpell.Cast(sim, target) - advance := casted && dk.LastOutcome.Matches(core.OutcomeLanded) - - if advance { - casted = dk.EmpowerRuneWeapon.Cast(sim, target) - advance = casted && advance - s.ConditionalAdvance(advance) - } - return -1 -} - -func (dk *DpsDeathknight) RotationActionBL_FU(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - casted := false - if dk.Inputs.FuStrike == deathknight.FuStrike_DeathStrike { - casted = dk.DeathStrike.Cast(sim, target) - } else if dk.Inputs.FuStrike == deathknight.FuStrike_Obliterate { - casted = dk.Obliterate.Cast(sim, target) - } - advance := dk.LastOutcome.Matches(core.OutcomeLanded) - - s.ConditionalAdvance(casted && advance) - return -1 -} - -func (dk *DpsDeathknight) RotationActionBL_Pesti_DRW(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - casted := dk.Pestilence.Cast(sim, target) - advance := dk.LastOutcome.Matches(core.OutcomeLanded) - - if !casted { - if dk.Inputs.FuStrike == deathknight.FuStrike_DeathStrike { - dk.DeathStrike.Cast(sim, target) - } else if dk.Inputs.FuStrike == deathknight.FuStrike_Obliterate { - dk.Obliterate.Cast(sim, target) - } - } - - s.ConditionalAdvance(casted && advance) - return -1 -} - -// Custom PS callback for tracking recasts for pestilence disease sync -func (dk *DpsDeathknight) RotationActionBL_PS_DRW(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - casted := dk.PlagueStrike.Cast(sim, target) - advance := dk.LastOutcome.Matches(core.OutcomeLanded) - - if !casted { - if dk.Talents.HeartStrike { - dk.HeartStrike.Cast(sim, target) - } else { - dk.BloodStrike.Cast(sim, target) - } - } - - dk.sr.recastedBP = casted && advance - s.ConditionalAdvance(casted && advance) - return -1 -} - -// Custom IT callback for tracking recasts for pestilence disease sync -func (dk *DpsDeathknight) RotationActionBL_IT_DRW(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - casted := dk.IcyTouch.Cast(sim, target) - advance := dk.LastOutcome.Matches(core.OutcomeLanded) - - if !casted { - if dk.Talents.HeartStrike { - dk.HeartStrike.Cast(sim, target) - } else { - dk.BloodStrike.Cast(sim, target) - } - } - - dk.sr.recastedFF = casted && advance - s.ConditionalAdvance(casted && advance) - return -1 -} - -// Custom PS callback for tracking recasts for pestilence disease sync -func (dk *DpsDeathknight) RotationActionBL_PS_Custom(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - casted := dk.PlagueStrike.Cast(sim, target) - advance := dk.LastOutcome.Matches(core.OutcomeLanded) - - dk.sr.recastedBP = casted && advance - s.ConditionalAdvance(casted && advance) - return -1 -} - -// Custom IT callback for tracking recasts for pestilence disease sync -func (dk *DpsDeathknight) RotationActionBL_IT_Custom(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - casted := dk.IcyTouch.Cast(sim, target) - advance := dk.LastOutcome.Matches(core.OutcomeLanded) - dk.sr.recastedFF = casted && advance - s.ConditionalAdvance(casted && advance) - return -1 -} - -func (dk *DpsDeathknight) RotationActionBL_FF_ClipCheck(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - dot := dk.FrostFeverSpell.Dot(target) - gracePeriod := dk.FrostRuneGraceRemaining(sim) - return dk.RotationActionBL_DiseaseClipCheck(dot, gracePeriod, sim, target, s) -} - -func (dk *DpsDeathknight) RotationActionBL_BP_ClipCheck(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - dot := dk.BloodPlagueSpell.Dot(target) - gracePeriod := dk.UnholyRuneGraceRemaining(sim) - return dk.RotationActionBL_DiseaseClipCheck(dot, gracePeriod, sim, target, s) -} - -// Check if we have enough rune grace period to delay the disease cast -// so we get more ticks without losing on rune cd -func (dk *DpsDeathknight) RotationActionBL_DiseaseClipCheck(dot *core.Dot, gracePeriod time.Duration, sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - // TODO: Play around with allowing rune cd to be wasted - // for more disease ticks and see if its a worth option for the ui - //runeCdWaste := 0 * time.Millisecond - var waitUntil time.Duration - if dot.TickCount < dot.NumberOfTicks-1 { - nextTickAt := dot.ExpiresAt() - dot.TickLength*time.Duration((dot.NumberOfTicks-1)-dot.TickCount) - if nextTickAt > sim.CurrentTime && (nextTickAt < sim.CurrentTime+gracePeriod || nextTickAt < sim.CurrentTime+400*time.Millisecond) { - // Delay disease for next tick - dk.LastOutcome = core.OutcomeMiss - waitUntil = nextTickAt + 50*time.Millisecond - } else { - waitUntil = sim.CurrentTime - } - } else { - waitUntil = sim.CurrentTime - } - - s.Advance() - return waitUntil -} diff --git a/sim/deathknight/dps/rotation_blood_helper.go b/sim/deathknight/dps/rotation_blood_helper.go deleted file mode 100644 index 50e1e93a20..0000000000 --- a/sim/deathknight/dps/rotation_blood_helper.go +++ /dev/null @@ -1,213 +0,0 @@ -package dps - -import ( - "time" - - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/core/proto" - "github.com/wowsims/wotlk/sim/deathknight" -) - -type BloodRotation struct { - dk *DpsDeathknight - - drwSnapshot *core.SnapshotManager - drwMaxDelay time.Duration - - bloodSpell *core.Spell - - activatingDrw bool - dsGlyphed bool -} - -func (br *BloodRotation) Reset(_ *core.Simulation) { - br.activatingDrw = false - if br.drwSnapshot != nil { - br.drwSnapshot.ResetProcTrackers() - } - br.drwMaxDelay = -1 -} - -func (br *BloodRotation) Initialize(dk *DpsDeathknight) { - if dk.Talents.DancingRuneWeapon { - dk.br.drwSnapshot = core.NewSnapshotManager(dk.GetCharacter()) - dk.setupDrwProcTrackers() - } - - br.dsGlyphed = dk.HasMajorGlyph(proto.DeathknightMajorGlyph_GlyphOfDeathStrike) -} - -func (dk *DpsDeathknight) blBloodRuneAction() deathknight.RotationAction { - if dk.Env.GetNumTargets() > 1 { - return dk.RotationActionCallback_Pesti - } else { - return dk.RotationActionBL_BS - } -} - -func (dk *DpsDeathknight) blDiseaseCheck(sim *core.Simulation, target *core.Unit, spell *core.Spell, costRunes bool, casts int) bool { - // Early exit at end of fight - if sim.GetRemainingDuration() < 10*time.Second { - return true - } - - ffRemaining := dk.FrostFeverSpell.Dot(target).RemainingDuration(sim) - bpRemaining := dk.BloodPlagueSpell.Dot(target).RemainingDuration(sim) - castGcd := core.GCDDefault * time.Duration(casts) - - // FF is not active or will drop before Gcd is ready after this cast - if !dk.FrostFeverSpell.Dot(target).IsActive() || ffRemaining <= castGcd { - return false - } - // BP is not active or will drop before Gcd is ready after this cast - if !dk.BloodPlagueSpell.Dot(target).IsActive() || bpRemaining <= castGcd { - return false - } - - // If the ability we want to cast spends runes we check for possible disease drops - // in the time we won't have runes to recast the disease - if spell.CanCast(sim, nil) && costRunes { - ffExpiresAt := ffRemaining + sim.CurrentTime - bpExpiresAt := bpRemaining + sim.CurrentTime - - afterCastTime := sim.CurrentTime + castGcd - if ffExpiresAt <= afterCastTime || bpExpiresAt <= afterCastTime { - return false - } - - spellCost := dk.OptimalRuneCost(core.RuneCost(spell.DefaultCast.Cost)) - - crpb := dk.Predictor() - crpb.SpendRuneCost(sim, spellCost) - - if dk.sr.hasGod { - currentBloodRunes := crpb.CurrentBloodRunes() - nextBloodRuneAt := crpb.BloodRuneReadyAt(sim) - - // If FF is gonna drop while our runes are on CD - if dk.shRecastAvailableCheck(ffExpiresAt, afterCastTime, int(spellCost.Blood()), int32(currentBloodRunes), nextBloodRuneAt) { - return false - } - - // If BP is gonna drop while our runes are on CD - if dk.shRecastAvailableCheck(bpExpiresAt, afterCastTime, int(spellCost.Blood()), int32(currentBloodRunes), nextBloodRuneAt) { - return false - } - } else { - currentFrostRunes := crpb.CurrentFrostRunes() - currentUnholyRunes := crpb.CurrentUnholyRunes() - nextFrostRuneAt := crpb.FrostRuneReadyAt(sim) - nextUnholyRuneAt := crpb.UnholyRuneReadyAt(sim) - - // If FF is gonna drop while our runes are on CD - if dk.shRecastAvailableCheck(ffExpiresAt, afterCastTime, int(spellCost.Frost()), int32(currentFrostRunes), nextFrostRuneAt) { - return false - } - - // If BP is gonna drop while our runes are on CD - if dk.shRecastAvailableCheck(bpExpiresAt, afterCastTime, int(spellCost.Unholy()), int32(currentUnholyRunes), nextUnholyRuneAt) { - return false - } - } - } - - return true -} - -func (dk *DpsDeathknight) blSpreadDiseases(sim *core.Simulation, target *core.Unit, _ *deathknight.Sequence) time.Duration { - if dk.blDiseaseCheck(sim, target, dk.Pestilence, true, 1) { - casted := dk.Pestilence.Cast(sim, target) - landed := dk.LastOutcome.Matches(core.OutcomeLanded) - - // Reset flags on succesfull cast - dk.sr.recastedFF = !(casted && landed) - dk.sr.recastedBP = !(casted && landed) - return -1 - } else { - dk.blRecastDiseasesSequence(sim) - return sim.CurrentTime - } -} - -// Save up Runic Power for DRW - Allow casts above 100 RP when DRW is ready or above 65 (for death strike glyph) when not -func (dk *DpsDeathknight) blDeathCoilCheck(sim *core.Simulation) bool { - canCastDrw := dk.Talents.DancingRuneWeapon && dk.DancingRuneWeapon != nil && (dk.DancingRuneWeapon.IsReady(sim) || dk.DancingRuneWeapon.CD.TimeToReady(sim) < 5*time.Second) - currentRP := dk.CurrentRunicPower() - willCastDS := dk.CurrentFrostRunes() > 0 && dk.CurrentUnholyRunes() > 1 && dk.CurrentBloodRunes() == 0 - return (!canCastDrw && currentRP >= float64(core.TernaryInt(dk.br.dsGlyphed && willCastDS, 65, 40))) || (canCastDrw && currentRP >= 100) -} - -func (dk *DpsDeathknight) blBloodTapCheck(sim *core.Simulation, target *core.Unit) bool { - if dk.CurrentBloodRunes() > 0 { - return false - } - - if (!dk.Talents.DancingRuneWeapon || dk.RuneWeapon.IsEnabled()) && dk.BloodTap.IsReady(sim) { - return dk.BloodTap.Cast(sim, target) - } - - return false -} - -// Combined checks for casting gargoyle sequence & going back to blood presence after -func (dk *DpsDeathknight) blDrwCheck(sim *core.Simulation, target *core.Unit, castTime time.Duration) bool { - if dk.blDrwCanCast(sim, castTime) { - - dk.br.activatingDrw = true - dk.br.drwSnapshot.ActivateMajorCooldowns(sim) - dk.UpdateMajorCooldowns() - dk.br.activatingDrw = false - - if dk.DancingRuneWeapon.Cast(sim, target) { - dk.br.drwSnapshot.ResetProcTrackers() - dk.br.drwMaxDelay = -1 - } - return true - } - - return false -} - -func (dk *DpsDeathknight) blDrwCanCast(sim *core.Simulation, castTime time.Duration) bool { - if !dk.Talents.DancingRuneWeapon { - return false - } - if !dk.Rotation.UseDancingRuneWeapon { - return false - } - if !dk.DancingRuneWeapon.IsReady(sim) { - return false - } - if dk.CurrentRunicPower() < 60 { - return false - } - // Setup max delay possible - if dk.br.drwMaxDelay == -1 { - drwCd := dk.DancingRuneWeapon.CD.Duration - timeLeft := sim.GetRemainingDuration() - for timeLeft > drwCd { - timeLeft = timeLeft - (drwCd + time.Second) - } - dk.br.drwMaxDelay = timeLeft - time.Second - } - // Cast it if holding will result in less total DRWs for the encounter - if sim.CurrentTime > dk.br.drwMaxDelay { - return true - } - // Cast it if holding will take from its duration - if sim.GetRemainingDuration() < 20*time.Second { - return true - } - // Make sure we can instantly put diseases up with the rune weapon - if !dk.sr.hasGod && dk.Rotation.DrwDiseases == proto.Deathknight_Rotation_Normal && (dk.CurrentFrostRunes() < 1 || dk.CurrentUnholyRunes() < 1) { - return false - } - if dk.sr.hasGod && dk.Rotation.DrwDiseases == proto.Deathknight_Rotation_Pestilence && dk.CurrentBloodRunes() < 1 { - return false - } - if !dk.br.drwSnapshot.CanSnapShot(sim, castTime) { - return false - } - - return true -} diff --git a/sim/deathknight/dps/rotation_frost.go b/sim/deathknight/dps/rotation_frost.go deleted file mode 100644 index 04c11d34ee..0000000000 --- a/sim/deathknight/dps/rotation_frost.go +++ /dev/null @@ -1,203 +0,0 @@ -package dps - -import ( - "time" - - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/deathknight" -) - -type FrostRotation struct { - oblitCount int32 - - // CDS - hyperSpeedMCD *core.MajorCooldown - stoneformMCD *core.MajorCooldown - bloodfuryMCD *core.MajorCooldown - berserkingMCD *core.MajorCooldown - potionOfSpeedMCD *core.MajorCooldown - indestructiblePotionMCD *core.MajorCooldown - potionUsed bool - - onUseTrinkets []*core.MajorCooldown - - oblitRPRegen float64 - - fuSpellPriority []*core.Spell - bloodSpell *core.Spell -} - -func (fr *FrostRotation) Initialize(dk *DpsDeathknight) { - fr.oblitRPRegen = core.TernaryFloat64(dk.HasSetBonus(deathknight.ItemSetScourgeborneBattlegear, 4), 25.0, 20.0) - fr.onUseTrinkets = make([]*core.MajorCooldown, 0) - - if dk.Env.GetNumTargets() > 2 { - fr.fuSpellPriority = []*core.Spell{dk.HowlingBlast, dk.Obliterate} - fr.bloodSpell = dk.BloodBoil - } else { - fr.fuSpellPriority = []*core.Spell{dk.Obliterate} - fr.bloodSpell = dk.BloodStrike - } -} - -func (fr *FrostRotation) Reset(_ *core.Simulation) { - fr.oblitCount = 0 - - fr.hyperSpeedMCD = nil - fr.stoneformMCD = nil - fr.bloodfuryMCD = nil - fr.berserkingMCD = nil - fr.potionOfSpeedMCD = nil - fr.indestructiblePotionMCD = nil - fr.onUseTrinkets = nil - fr.potionUsed = false -} - -func (dk *DpsDeathknight) addOnUseTrinketCooldown(actionID core.ActionID) { - if majorCd := dk.Character.GetMajorCooldown(actionID); majorCd != nil { - majorCd.Disable() - dk.fr.onUseTrinkets = append(dk.fr.onUseTrinkets, majorCd) - } -} - -func (dk *DpsDeathknight) getMajorCooldown(actionID core.ActionID) *core.MajorCooldown { - if majorCd := dk.Character.GetMajorCooldown(actionID); majorCd != nil { - majorCd.Disable() - return majorCd - } - return nil -} - -func (dk *DpsDeathknight) setupUnbreakableArmorCooldowns() { - fr := &dk.fr - - // hyperspeed accelerators - fr.hyperSpeedMCD = dk.getMajorCooldown(core.ActionID{SpellID: 54758}) - - // stoneform (dwarf) - fr.stoneformMCD = dk.getMajorCooldown(core.ActionID{SpellID: 20594}) - - // bloodfury (orc) - fr.bloodfuryMCD = dk.getMajorCooldown(core.ActionID{SpellID: 33697}) - - // berserking (troll) - fr.berserkingMCD = dk.getMajorCooldown(core.ActionID{SpellID: 26297}) - - // potion of speed - fr.potionOfSpeedMCD = dk.getMajorCooldown(core.ActionID{ItemID: 40211}) - - // indestructible potion - fr.indestructiblePotionMCD = dk.getMajorCooldown(core.ActionID{ItemID: 40093}) - - // On use trinkets - dk.addOnUseTrinketCooldown(core.ActionID{ItemID: 40531}) // Mark of nogganon - dk.addOnUseTrinketCooldown(core.ActionID{ItemID: 37166}) // Sphere of Red Dragon's Blood - dk.addOnUseTrinketCooldown(core.ActionID{ItemID: 37723}) // Incisor Fragment - dk.addOnUseTrinketCooldown(core.ActionID{ItemID: 39257}) // Loatheb's Shadow - dk.addOnUseTrinketCooldown(core.ActionID{ItemID: 44014}) // Fezzik's Pocketwatch -} - -func (dk *DpsDeathknight) castMajorCooldown(mcd *core.MajorCooldown, sim *core.Simulation, target *core.Unit) { - if mcd != nil { - if mcd.Spell.IsReady(sim) && (dk.GCD.IsReady(sim) || mcd.Spell.DefaultCast.GCD == 0) { - mcd.Spell.Cast(sim, target) - } - } -} - -func (dk *DpsDeathknight) castMajorCooldownConditional(mcd *core.MajorCooldown, conditionalMCDs []*core.MajorCooldown, sim *core.Simulation, target *core.Unit) { - if mcd != nil && !dk.fr.potionUsed { - if mcd.Spell.IsReady(sim) && dk.GCD.IsReady(sim) { - allReady := true - for i := range conditionalMCDs { - if conditionalMCDs[i] != nil && allReady { - spell := conditionalMCDs[i].Spell - allReady = allReady && spell.CD.IsReady(sim) - //// TODO: Find a way to get the racial aura durations - if !allReady { - if dk.Env.Encounter.Duration < time.Duration(float64(spell.CD.ReadyAt())*1.25) { - allReady = true - } - } - } - } - - if allReady { - mcd.Spell.Cast(sim, target) - - dk.fr.potionUsed = true - } - } - } -} - -func (dk *DpsDeathknight) castAllMajorCooldowns(sim *core.Simulation) { - fr := &dk.fr - target := dk.CurrentTarget - - racialConditionals := []*core.MajorCooldown{fr.bloodfuryMCD, fr.berserkingMCD, fr.stoneformMCD} - - dk.castMajorCooldownConditional(fr.potionOfSpeedMCD, racialConditionals, sim, target) - dk.castMajorCooldownConditional(fr.indestructiblePotionMCD, racialConditionals, sim, target) - dk.castMajorCooldown(fr.hyperSpeedMCD, sim, target) - dk.castMajorCooldown(fr.stoneformMCD, sim, target) - dk.castMajorCooldown(fr.bloodfuryMCD, sim, target) - dk.castMajorCooldown(fr.berserkingMCD, sim, target) - - for _, trinket := range fr.onUseTrinkets { - dk.castMajorCooldown(trinket, sim, target) - } -} - -func (dk *DpsDeathknight) RotationActionCallback_UA_Frost(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - if dk.UnbreakableArmor != nil { - if !dk.LeftBloodRuneReady() && dk.BloodTap.CanCast(sim, nil) { - dk.BloodTap.Cast(sim, nil) - } - casted := dk.UnbreakableArmor.Cast(sim, target) - - if casted { - dk.castAllMajorCooldowns(sim) - s.ConditionalAdvance(casted) - return sim.CurrentTime - } else { - s.ConditionalAdvance(casted) - return -1 - } - } else { - casted := dk.BloodStrike.Cast(sim, target) - if casted { - dk.castAllMajorCooldowns(sim) - s.ConditionalAdvance(casted) - return sim.CurrentTime - } else { - s.ConditionalAdvance(casted) - return -1 - } - } -} - -func (dk *DpsDeathknight) RotationActionCallback_Frost_FS_HB(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - if dk.FreezingFogAura.IsActive() && dk.Talents.HowlingBlast { - dk.HowlingBlast.Cast(sim, target) - } else if dk.Talents.FrostStrike { - dk.FrostStrike.Cast(sim, target) - } - - s.Advance() - return -1 -} - -func (dk *DpsDeathknight) RotationActionCallback_Frost_Pesti_ERW(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - // Casts Pesti then ERW in the same GCD (rather than chaining them sequentially which will cause ERW to be delayed by pesti GCD) - // This is a DPS increase since it allows rune grace to start as soon as possible - casted := dk.Pestilence.Cast(sim, target) - advance := casted && dk.LastOutcome.Matches(core.OutcomeLanded) - - if advance { - casted = dk.EmpowerRuneWeapon.Cast(sim, target) - advance = casted && advance - s.ConditionalAdvance(advance) - } - return -1 -} diff --git a/sim/deathknight/dps/rotation_frost_aoe.go b/sim/deathknight/dps/rotation_frost_aoe.go deleted file mode 100644 index a0749e8ece..0000000000 --- a/sim/deathknight/dps/rotation_frost_aoe.go +++ /dev/null @@ -1,185 +0,0 @@ -package dps - -import ( - "time" - - "github.com/wowsims/wotlk/sim/common" - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/core/proto" - "github.com/wowsims/wotlk/sim/deathknight" -) - -func (dk *DpsDeathknight) setupCustomRotations() { - dk.RotationSequence.NewAction(func(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - if dk.CustomRotation != nil { - if !dk.CustomRotation.Cast(sim) { - return -1 - } - } else { - dk.LastCast = nil - } - - if dk.LastCast == dk.EmpowerRuneWeapon || dk.LastCast == dk.BloodTap || dk.LastCast == dk.UnbreakableArmor { - return sim.CurrentTime - } - - return -1 - }) -} - -func (dk *DpsDeathknight) makeCustomRotation() *common.CustomRotation { - return common.NewCustomRotation(dk.Rotation.FrostCustomRotation, dk.GetCharacter(), map[int32]common.CustomSpell{ - int32(proto.Deathknight_Rotation_CustomIcyTouch): { - Action: func(sim *core.Simulation, target *core.Unit) (bool, float64) { - cost := dk.IcyTouch.CurCast.Cost - return dk.IcyTouch.Cast(sim, target), cost - }, - Condition: func(sim *core.Simulation) bool { - return !dk.FrostFeverSpell.Dot(dk.CurrentTarget).IsActive() && dk.IcyTouch.CanCast(sim, nil) - }, - }, - int32(proto.Deathknight_Rotation_CustomPlagueStrike): { - Action: func(sim *core.Simulation, target *core.Unit) (bool, float64) { - cost := dk.PlagueStrike.CurCast.Cost - return dk.PlagueStrike.Cast(sim, target), cost - }, - Condition: func(sim *core.Simulation) bool { - return !dk.BloodPlagueSpell.Dot(dk.CurrentTarget).IsActive() && dk.PlagueStrike.CanCast(sim, nil) - }, - }, - int32(proto.Deathknight_Rotation_CustomPestilence): { - Action: func(sim *core.Simulation, target *core.Unit) (bool, float64) { - cost := dk.Pestilence.CurCast.Cost - return dk.Pestilence.Cast(sim, target), cost - }, - Condition: func(sim *core.Simulation) bool { - if !dk.Pestilence.CanCast(sim, nil) { - return false - } - - ff := dk.FrostFeverSpell.Dot(dk.CurrentTarget).ExpiresAt() - sim.CurrentTime - bp := dk.BloodPlagueSpell.Dot(dk.CurrentTarget).ExpiresAt() - sim.CurrentTime - ffHalfDuration := time.Duration(0.5 * float64(dk.FrostFeverSpell.Dot(dk.CurrentTarget).Duration)) - bpHalfDuration := time.Duration(0.5 * float64(dk.BloodPlagueSpell.Dot(dk.CurrentTarget).Duration)) - if ff <= 2*time.Second && bp <= 2*time.Second && sim.GetRemainingDuration() >= ffHalfDuration && sim.GetRemainingDuration() >= bpHalfDuration { - return true - } - - numHits := dk.Env.GetNumTargets() - numDiseased := numHits - for i := int32(0); i < numHits; i++ { - target := &dk.Env.GetTarget(i).Unit - diseases := dk.FrostFeverSpell.Dot(target).IsActive() && dk.BloodPlagueSpell.Dot(target).IsActive() - - if !diseases { - numDiseased-- - } - } - - return float64(numDiseased)/float64(numHits) <= 0.5 - }, - }, - int32(proto.Deathknight_Rotation_CustomObliterate): { - Action: func(sim *core.Simulation, target *core.Unit) (bool, float64) { - cost := dk.Obliterate.CurCast.Cost - if dk.Deathchill != nil && dk.Deathchill.IsReady(sim) { - dk.Deathchill.Cast(sim, target) - } - return dk.Obliterate.Cast(sim, target), cost - }, - Condition: func(sim *core.Simulation) bool { - return dk.Obliterate.CanCast(sim, nil) - }, - }, - int32(proto.Deathknight_Rotation_CustomHowlingBlast): { - Action: func(sim *core.Simulation, target *core.Unit) (bool, float64) { - cost := dk.HowlingBlast.CurCast.Cost - return dk.HowlingBlast.Cast(sim, target), cost - }, - Condition: func(sim *core.Simulation) bool { - return dk.HowlingBlast.CanCast(sim, nil) - }, - }, - int32(proto.Deathknight_Rotation_CustomHowlingBlastRime): { - Action: func(sim *core.Simulation, target *core.Unit) (bool, float64) { - cost := dk.HowlingBlast.CurCast.Cost - return dk.HowlingBlast.Cast(sim, target), cost - }, - Condition: func(sim *core.Simulation) bool { - return dk.HowlingBlast.CanCast(sim, nil) && dk.FreezingFogAura.IsActive() - }, - }, - int32(proto.Deathknight_Rotation_CustomBloodBoil): { - Action: func(sim *core.Simulation, target *core.Unit) (bool, float64) { - cost := dk.BloodBoil.CurCast.Cost - return dk.BloodBoil.Cast(sim, target), cost - }, - Condition: func(sim *core.Simulation) bool { - return dk.BloodBoil.CanCast(sim, nil) - }, - }, - int32(proto.Deathknight_Rotation_CustomBloodStrike): { - Action: func(sim *core.Simulation, target *core.Unit) (bool, float64) { - cost := dk.BloodStrike.CurCast.Cost - return dk.BloodStrike.Cast(sim, target), cost - }, - Condition: func(sim *core.Simulation) bool { - return dk.BloodStrike.CanCast(sim, nil) - }, - }, - int32(proto.Deathknight_Rotation_CustomDeathAndDecay): { - Action: func(sim *core.Simulation, target *core.Unit) (bool, float64) { - cost := dk.DeathAndDecay.CurCast.Cost - return dk.DeathAndDecay.Cast(sim, target), cost - }, - Condition: func(sim *core.Simulation) bool { - return dk.DeathAndDecay.CanCast(sim, nil) - }, - }, - int32(proto.Deathknight_Rotation_CustomHornOfWinter): { - Action: func(sim *core.Simulation, target *core.Unit) (bool, float64) { - cost := dk.HornOfWinter.CurCast.Cost - return dk.HornOfWinter.Cast(sim, target), cost - }, - Condition: func(sim *core.Simulation) bool { - return dk.HornOfWinter.CanCast(sim, nil) - }, - }, - int32(proto.Deathknight_Rotation_CustomUnbreakableArmor): { - Action: func(sim *core.Simulation, target *core.Unit) (bool, float64) { - cost := dk.UnbreakableArmor.CurCast.Cost - return dk.UnbreakableArmor.Cast(sim, target), cost - }, - Condition: func(sim *core.Simulation) bool { - return dk.UnbreakableArmor.CanCast(sim, nil) - }, - }, - int32(proto.Deathknight_Rotation_CustomBloodTap): { - Action: func(sim *core.Simulation, target *core.Unit) (bool, float64) { - cost := dk.BloodTap.CurCast.Cost - return dk.BloodTap.Cast(sim, target), cost - }, - Condition: func(sim *core.Simulation) bool { - return dk.BloodTap.CanCast(sim, nil) - }, - }, - int32(proto.Deathknight_Rotation_CustomEmpoweredRuneWeapon): { - Action: func(sim *core.Simulation, target *core.Unit) (bool, float64) { - cost := dk.EmpowerRuneWeapon.CurCast.Cost - return dk.EmpowerRuneWeapon.Cast(sim, target), cost - }, - Condition: func(sim *core.Simulation) bool { - return dk.EmpowerRuneWeapon.CanCast(sim, nil) - }, - }, - int32(proto.Deathknight_Rotation_CustomFrostStrike): { - Action: func(sim *core.Simulation, target *core.Unit) (bool, float64) { - cost := dk.FrostStrike.CurCast.Cost - return dk.FrostStrike.Cast(sim, target), cost - }, - Condition: func(sim *core.Simulation) bool { - return dk.FrostStrike.CanCast(sim, nil) - }, - }, - }) -} diff --git a/sim/deathknight/dps/rotation_frost_helper.go b/sim/deathknight/dps/rotation_frost_helper.go deleted file mode 100644 index 37bd960337..0000000000 --- a/sim/deathknight/dps/rotation_frost_helper.go +++ /dev/null @@ -1,259 +0,0 @@ -package dps - -import ( - "time" - - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/deathknight" -) - -func (dk *DpsDeathknight) canCastFrostUnholySpell(sim *core.Simulation, target *core.Unit) bool { - for _, spell := range dk.fr.fuSpellPriority { - if spell.CanCast(sim, target) { - return true - } - } - return false -} - -func (dk *DpsDeathknight) castFrostUnholySpell(sim *core.Simulation, target *core.Unit) bool { - for _, spell := range dk.fr.fuSpellPriority { - if spell.CanCast(sim, target) { - return spell.Cast(sim, target) - } - } - return false -} - -func (dk *DpsDeathknight) canCastBloodSpell(sim *core.Simulation, target *core.Unit) bool { - return dk.fr.bloodSpell.CanCast(sim, target) -} - -func (dk *DpsDeathknight) castBloodSpell(sim *core.Simulation, target *core.Unit) bool { - return dk.fr.bloodSpell.Cast(sim, target) -} - -// end of fight oblit does not check diseases, it just presses it regardless, but will retry if fails to land. -func (dk *DpsDeathknight) RotationActionCallback_FrostSubUnh_EndOfFight_Obli(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - casted := false - advance := true - waitTime := time.Duration(-1) - if dk.canCastFrostUnholySpell(sim, target) { - if dk.Deathchill != nil && dk.Deathchill.IsReady(sim) { - dk.Deathchill.Cast(sim, target) - } - casted = dk.castFrostUnholySpell(sim, target) - advance = dk.LastOutcome.Matches(core.OutcomeLanded) - } - s.ConditionalAdvance(casted && advance) - return core.TernaryDuration(casted, -1, waitTime) -} - -func (dk *DpsDeathknight) RegularPrioPickSpell(sim *core.Simulation, _ *core.Unit, untilTime time.Duration) *core.Spell { - abGcd := 1500 * time.Millisecond - spGcd := dk.SpellGCD() - canCastAbility := sim.CurrentTime+abGcd <= untilTime - canCastSpell := sim.CurrentTime+spGcd <= untilTime - - km := dk.KillingMachineAura.IsActive() - rime := dk.FreezingFogAura.IsActive() - if canCastSpell && dk.RaiseDead.CanCast(sim, nil) && sim.GetRemainingDuration() >= time.Second*30 { - return dk.RaiseDead - } else if canCastSpell && dk.HowlingBlast.CanCast(sim, nil) && rime { - return dk.HowlingBlast - } else if canCastAbility && dk.FrostStrike.CanCast(sim, nil) && km { - return dk.FrostStrike - } else if canCastAbility && dk.FrostStrike.CanCast(sim, nil) && dk.CurrentRunicPower() >= 100.0 { - return dk.FrostStrike - } else if canCastAbility && dk.FrostStrike.CanCast(sim, nil) { - return dk.FrostStrike - } else if canCastSpell && dk.HornOfWinter.CanCast(sim, nil) { - return dk.HornOfWinter - } else { - return nil - } -} - -//end of fight functions - -func (dk *DpsDeathknight) RotationActionCallback_EndOfFightCheck(sim *core.Simulation, _ *core.Unit, s *deathknight.Sequence) time.Duration { - simDur := sim.CurrentTime + sim.GetRemainingDuration() - - if sim.CurrentTime+7000*time.Millisecond > simDur { - s.Clear().NewAction(dk.RotationActionCallback_EndOfFightPrio) - } else { - s.Advance() - } - return sim.CurrentTime -} - -func (dk *DpsDeathknight) RotationActionCallback_EndOfFightPrio(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - simDur := sim.CurrentTime + sim.GetRemainingDuration() - simTimeLeft := sim.GetRemainingDuration() - ffExpiresAt := dk.FrostFeverSpell.Dot(target).ExpiresAt() - bpExpiresAt := dk.BloodPlagueSpell.Dot(target).ExpiresAt() - diseaseExpiresAt := min(ffExpiresAt, bpExpiresAt) - abGcd := 1500 * time.Millisecond - spGcd := dk.SpellGCD() - frAt := dk.NormalFrostRuneReadyAt(sim) - uhAt := dk.NormalUnholyRuneReadyAt(sim) - obAt := max(frAt, uhAt) - fsCost := float64(core.RuneCost(dk.FrostStrike.CurCast.Cost).RunicPower()) - bothblAt := dk.BloodDeathRuneBothReadyAt() - hasRime := dk.FreezingFogAura.IsActive() && dk.Talents.HowlingBlast - - if bothblAt == core.NeverExpires { - bothblAt = 1 - } - if bothblAt == -1 { - bothblAt = core.NeverExpires - } - - if dk.Talents.Epidemic == 2 || diseaseExpiresAt >= simDur { - obAt = min(obAt, bothblAt) - } - - if diseaseExpiresAt >= simDur { //diseases last until end of fight - if sim.CurrentTime >= obAt { //have runes to oblit - s.Clear(). - NewAction(dk.RotationActionCallback_FrostSubUnh_EndOfFight_Obli). - NewAction(dk.RotationActionCallback_EndOfFightCheck) - } else if spGcd > simTimeLeft && (obAt <= simDur || bothblAt <= simDur) { //cant fit a spell GCD before end of fight, and will be able to oblit - s.Clear(). - NewAction(dk.RotationActionCallback_FrostSubUnh_EndOfFight_Obli). - NewAction(dk.RotationActionCallback_EndOfFightCheck) - } else if spGcd < simTimeLeft && abGcd > simTimeLeft && obAt < simDur && hasRime { //can fit a spell but not melee ability before last GCD of fight and have rime - s.Clear(). - NewAction(dk.RotationActionCallback_HB). - NewAction(dk.RotationActionCallback_EndOfFightCheck) - } else if (abGcd > simTimeLeft || sim.CurrentTime+abGcd > obAt) && obAt < simDur { //oblit can be used, it's the last GCD or it goes over oblit - s.Clear(). - NewAction(dk.RotationActionCallback_FrostSubUnh_EndOfFight_Obli). - NewAction(dk.RotationActionCallback_EndOfFightCheck) - } else if dk.CurrentRunicPower() >= fsCost && sim.CurrentTime+abGcd < obAt { //can FS and wont cross oblit - s.Clear(). - NewAction(dk.RotationActionCallback_FS). - NewAction(dk.RotationActionCallback_EndOfFightCheck) - } else if hasRime && sim.CurrentTime+spGcd < obAt { //can rime and wont cross oblit - s.Clear(). - NewAction(dk.RotationActionCallback_HB). - NewAction(dk.RotationActionCallback_EndOfFightCheck) - } else if (dk.CurrentBloodRunes() >= 1 || dk.CurrentDeathRunes() == 1) && (sim.CurrentTime+abGcd < obAt) { //have runes for BS, and it cant be used for oblit instead - s.Clear(). - NewAction(dk.RotationActionCallback_BS). - NewAction(dk.RotationActionCallback_EndOfFightCheck) - } else if dk.HornOfWinter.IsReady(sim) && sim.CurrentTime+spGcd < obAt && simTimeLeft > spGcd { //can horn and wont cross oblit - s.Clear(). - NewAction(dk.RotationActionCallback_HW). - NewAction(dk.RotationActionCallback_EndOfFightCheck) - } else { //cant do anything, wait to oblit - s.Clear(). - NewAction(dk.RotationActionCallback_FrostSubUnh_EndOfFight_Obli). - NewAction(dk.RotationActionCallback_EndOfFightCheck) - } - } else if diseaseExpiresAt >= simDur-abGcd { //disease expires less than 1 gcd before end of fight - if sim.CurrentTime >= obAt || (sim.CurrentTime >= bothblAt && dk.CurrentDeathRunes() >= 2) { //have runes to oblit, will not refresh diseases - s.Clear(). - NewAction(dk.RotationActionCallback_FrostSubUnh_EndOfFight_Obli). - NewAction(dk.RotationActionCallback_EndOfFightCheck) - } else if spGcd > simTimeLeft && obAt < simDur { //cant fit a spell GCD before end of fight, and will be able to oblit - s.Clear(). - NewAction(dk.RotationActionCallback_FrostSubUnh_EndOfFight_Obli). - NewAction(dk.RotationActionCallback_EndOfFightCheck) - } else if spGcd < simTimeLeft && abGcd > simTimeLeft && obAt < simDur && hasRime { //can fit a spell but not melee ability before last GCD of fight and have rime - s.Clear(). - NewAction(dk.RotationActionCallback_HB). - NewAction(dk.RotationActionCallback_EndOfFightCheck) - } else if abGcd > simTimeLeft && obAt < simDur { //oblit can be used, it's the last GCD or it goes over oblit - s.Clear(). - NewAction(dk.RotationActionCallback_FrostSubUnh_EndOfFight_Obli). - NewAction(dk.RotationActionCallback_EndOfFightCheck) - } else if dk.CurrentRunicPower() >= fsCost && sim.CurrentTime+abGcd < obAt { //can FS and wont cross oblit - s.Clear(). - NewAction(dk.RotationActionCallback_FS). - NewAction(dk.RotationActionCallback_EndOfFightCheck) - } else if hasRime && sim.CurrentTime+spGcd < obAt { //can rime and wont cross oblit - s.Clear(). - NewAction(dk.RotationActionCallback_HB). - NewAction(dk.RotationActionCallback_EndOfFightCheck) - } else if dk.CurrentBloodRunes() >= 1 || sim.CurrentTime < diseaseExpiresAt { //can pesti and diseases are still up, this serves to pesti if there's nothing more valuable to press - s.Clear(). - NewAction(dk.RotationActionCallback_Pesti). - NewAction(dk.RotationActionCallback_EndOfFightCheck) - } else if dk.HornOfWinter.IsReady(sim) && simTimeLeft > spGcd { //can't do anything but horn - s.Clear(). - NewAction(dk.RotationActionCallback_HW). - NewAction(dk.RotationActionCallback_EndOfFightCheck) - } - } else if sim.CurrentTime+spGcd < diseaseExpiresAt && sim.CurrentTime+abGcd > diseaseExpiresAt && dk.CurrentRunicPower() < 100 && (hasRime || dk.HornOfWinter.IsReady(sim)) { //if you can fit a spellgcd before disease dropping, and only if spell hit cap is reached - if hasRime && dk.CurrentRunicPower() < 100 { //rime prio - s.Clear(). - NewAction(dk.RotationActionCallback_HB). - NewAction(dk.RotationActionCallback_EndOfFightCheck) - } else if dk.HornOfWinter.IsReady(sim) && dk.CurrentRunicPower() < 100 { //fit a horn in if you can - s.Clear(). - NewAction(dk.RotationActionCallback_HW). - NewAction(dk.RotationActionCallback_EndOfFightCheck) - } - } else if sim.CurrentTime+2*abGcd < diseaseExpiresAt { //there's at least 2 physical GCDs until disease fall so press normal prio, but do not double death oblit as you need it for pesti - if sim.CurrentTime >= obAt && (dk.Talents.Epidemic == 2 || (dk.CurrentFrostRunes() >= 1 && dk.CurrentUnholyRunes() >= 1)) { //can oblit, either be unh sub or have frost/unh runes ready - s.Clear(). - NewAction(dk.RotationActionCallback_FrostSubUnh_EndOfFight_Obli). - NewAction(dk.RotationActionCallback_EndOfFightCheck) - } else if sim.CurrentTime+spGcd > obAt && (dk.Talents.Epidemic == 2 || (dk.CurrentFrostRunes() >= 1 && dk.CurrentUnholyRunes() >= 1)) { //same as above, no time to spellGCD before oblit - s.Clear(). - NewAction(dk.RotationActionCallback_FrostSubUnh_EndOfFight_Obli). - NewAction(dk.RotationActionCallback_EndOfFightCheck) - } else if sim.CurrentTime+spGcd < obAt && sim.CurrentTime+abGcd > obAt && (hasRime || dk.CurrentRunicPower() < fsCost*4-2*dk.fr.oblitRPRegen && dk.HornOfWinter.IsReady(sim)) { //if you can fit a spGcd before oblit and won't overcap RP with horn - if hasRime { - s.Clear(). - NewAction(dk.RotationActionCallback_HB). - NewAction(dk.RotationActionCallback_EndOfFightCheck) - } else if dk.CurrentRunicPower() < fsCost*4-2*dk.fr.oblitRPRegen && dk.HornOfWinter.IsReady(sim) { //if u wont overflow RP - s.Clear(). - NewAction(dk.RotationActionCallback_HW). - NewAction(dk.RotationActionCallback_EndOfFightCheck) - } - } else if sim.CurrentTime+abGcd > obAt { //if no time to abGcd before oblit - s.Clear(). - NewAction(dk.RotationActionCallback_FrostSubUnh_EndOfFight_Obli). - NewAction(dk.RotationActionCallback_EndOfFightCheck) - } else if dk.CurrentRunicPower() >= fsCost { //fs if can - s.Clear(). - NewAction(dk.RotationActionCallback_FS). - NewAction(dk.RotationActionCallback_EndOfFightCheck) - } else if hasRime { //rime if can - s.Clear(). - NewAction(dk.RotationActionCallback_HB). - NewAction(dk.RotationActionCallback_EndOfFightCheck) - } else if (dk.CurrentBloodRunes() >= 1 || dk.CurrentDeathRunes() == 1) && diseaseExpiresAt > simDur-abGcd { //if can BS and there's only 1 gcd left - s.Clear(). - NewAction(dk.RotationActionCallback_BS). - NewAction(dk.RotationActionCallback_EndOfFightCheck) - } else if (dk.CurrentBloodRunes() >= 1 || dk.CurrentDeathRunes() == 1) && diseaseExpiresAt < simDur-abGcd { //if can pesti and there's more than 1 gcd left - s.Clear(). - NewAction(dk.RotationActionCallback_Pesti). - NewAction(dk.RotationActionCallback_EndOfFightCheck) - } else if dk.HornOfWinter.IsReady(sim) && simTimeLeft > spGcd { //if can horn - s.Clear(). - NewAction(dk.RotationActionCallback_HW). - NewAction(dk.RotationActionCallback_EndOfFightCheck) - } else { //wait for oblit - dk.WaitUntil(sim, obAt) - s.NewAction(dk.RotationActionCallback_EndOfFightCheck) - } - } else if sim.CurrentTime+2*abGcd > diseaseExpiresAt { //if u can only fit 1 spGcd + 1 abGcd before disease falls, do pesti first as it might miss - s.Clear(). - NewAction(dk.RotationActionCallback_Pesti). - NewAction(dk.RotationActionCallback_EndOfFightCheck) - } else { - return -1 - } - return sim.CurrentTime -} - -func (dk *DpsDeathknight) RotationActionCallback_BS_Frost(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - dk.castBloodSpell(sim, target) - s.Advance() - return -1 -} diff --git a/sim/deathknight/dps/rotation_frost_sub_blood.go b/sim/deathknight/dps/rotation_frost_sub_blood.go deleted file mode 100644 index 8d167b3e75..0000000000 --- a/sim/deathknight/dps/rotation_frost_sub_blood.go +++ /dev/null @@ -1,417 +0,0 @@ -package dps - -import ( - "time" - - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/deathknight" -) - -func (dk *DpsDeathknight) RotationActionCallback_FrostSubBlood_Obli(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - casted := false - advance := true - waitTime := time.Duration(-1) - - ffExpiresAt := dk.FrostFeverSpell.Dot(target).ExpiresAt() - bpExpiresAt := dk.BloodPlagueSpell.Dot(target).ExpiresAt() - if sim.CurrentTime+1500*time.Millisecond < min(ffExpiresAt, bpExpiresAt) { - if dk.canCastFrostUnholySpell(sim, target) { - if dk.Deathchill != nil && dk.Deathchill.IsReady(sim) { - dk.Deathchill.Cast(sim, target) - } - casted = dk.castFrostUnholySpell(sim, target) - advance = dk.LastOutcome.Matches(core.OutcomeLanded) - } - - s.ConditionalAdvance(casted && advance) - } else { - waitTime = sim.CurrentTime - s.Advance() - } - - return core.TernaryDuration(casted, -1, waitTime) -} - -func (dk *DpsDeathknight) RotationActionCallback_LastSecondsCast(sim *core.Simulation, target *core.Unit) bool { - casted := false - - ffActive := dk.FrostFeverSpell.Dot(target).IsActive() - bpActive := dk.BloodPlagueSpell.Dot(target).IsActive() - ffExpiresAt := dk.FrostFeverSpell.Dot(target).ExpiresAt() - bpExpiresAt := dk.BloodPlagueSpell.Dot(target).ExpiresAt() - fsCost := float64(core.RuneCost(dk.FrostStrike.CurCast.Cost).RunicPower()) - - km := dk.KillingMachineAura.IsActive() - if min(ffExpiresAt, bpExpiresAt) > sim.CurrentTime+sim.GetRemainingDuration() { - if dk.canCastFrostUnholySpell(sim, target) && ffActive && bpActive { - if dk.Deathchill != nil && dk.Deathchill.IsReady(sim) { - dk.Deathchill.Cast(sim, target) - } - casted = dk.castFrostUnholySpell(sim, target) - } else if dk.FrostStrike.CanCast(sim, nil) && km { - casted = dk.FrostStrike.Cast(sim, target) - } else if dk.canCastFrostUnholySpell(sim, target) { - if dk.Deathchill != nil && dk.Deathchill.IsReady(sim) { - dk.Deathchill.Cast(sim, target) - } - casted = dk.castFrostUnholySpell(sim, target) - } else if dk.FrostStrike.CanCast(sim, nil) { - casted = dk.FrostStrike.Cast(sim, target) - } else if dk.HowlingBlast.CanCast(sim, nil) { - casted = dk.HowlingBlast.Cast(sim, target) - } else if dk.canCastBloodSpell(sim, target) { - casted = dk.castBloodSpell(sim, target) - } else if dk.HornOfWinter.CanCast(sim, nil) && dk.CurrentRunicPower() < fsCost && sim.GetRemainingDuration() > dk.SpellGCD() { - casted = dk.HornOfWinter.Cast(sim, target) - } - } - - return casted -} - -// TODO: Improve this -func (dk *DpsDeathknight) RotationActionCallback_FrostSubBlood_FS_KM(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - casted := false - ffExpiresAt := dk.FrostFeverSpell.Dot(target).ExpiresAt() - bpExpiresAt := dk.BloodPlagueSpell.Dot(target).ExpiresAt() - - casted = dk.RotationActionCallback_LastSecondsCast(sim, target) - if !casted { - km := dk.KillingMachineAura.IsActive() - if km && sim.CurrentTime+1500*time.Millisecond < min(ffExpiresAt, bpExpiresAt) { - if dk.FrostStrike.CanCast(sim, nil) { - dk.FrostStrike.Cast(sim, target) - } - } - - s.Advance() - } - - return core.TernaryDuration(casted, -1, sim.CurrentTime) -} - -func (dk *DpsDeathknight) RotationActionCallback_FrostSubBlood_Dump_UntilBR(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - casted := false - waitUntil := time.Duration(-1) - - casted = dk.RotationActionCallback_LastSecondsCast(sim, target) - if !casted { - br := dk.CurrentBloodRunes() + dk.CurrentDeathRunes() - - if br == 0 { - spell := dk.RegularPrioPickSpell(sim, target, core.NeverExpires) - if spell != nil { - casted = spell.Cast(sim, target) - } - } else if br >= 1 { - km := dk.KillingMachineAura.IsActive() - if km { - if dk.FrostStrike.CanCast(sim, nil) { - casted = dk.FrostStrike.Cast(sim, target) - } - } - - s.Advance() - waitUntil = sim.CurrentTime - } - } - - return core.TernaryDuration(casted, -1, waitUntil) -} -func (dk *DpsDeathknight) RotationActionCallback_FrostSubBlood_FS_Dump_UntilUA(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - casted := false - waitUntil := time.Duration(-1) - - casted = dk.RotationActionCallback_LastSecondsCast(sim, target) - if !casted { - if !dk.UnbreakableArmor.IsReady(sim) { - spell := dk.RegularPrioPickSpell(sim, target, core.NeverExpires) - if spell != nil { - casted = spell.Cast(sim, target) - } else { - s.Advance() - waitUntil = dk.UnbreakableArmor.ReadyAt() - } - } else { - s.Advance() - waitUntil = sim.CurrentTime - } - } - - return core.TernaryDuration(casted, -1, waitUntil) -} - -func (dk *DpsDeathknight) getOblitDrift(sim *core.Simulation, castIn time.Duration) time.Duration { - spendAt := sim.CurrentTime + castIn - oblit1 := max(dk.RuneReadyAt(sim, 2), dk.RuneReadyAt(sim, 3)) - oblit2 := max(dk.SpendRuneReadyAt(4, spendAt), dk.SpendRuneReadyAt(5, spendAt)) - return oblit2 - oblit1 -} - -func (dk *DpsDeathknight) RotationActionCallback_FrostSubBlood_FS_Dump(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - casted := false - waitUntil := time.Duration(-1) - - casted = dk.RotationActionCallback_LastSecondsCast(sim, target) - if !casted { - fr := dk.CurrentFrostRunes() - uh := dk.CurrentUnholyRunes() - bAt := dk.BloodRuneReadyAt(sim) - frAt := dk.NormalFrostRuneReadyAt(sim) - uhAt := dk.NormalUnholyRuneReadyAt(sim) - obAt := max(frAt, uhAt) - abGCD := core.GCDDefault - allowedObDrift := 3000 * time.Millisecond - - if fr == 2 && uh == 2 { - casted := false - waitTime := time.Duration(-1) - - ffExpiresAt := dk.FrostFeverSpell.Dot(target).ExpiresAt() - bpExpiresAt := dk.BloodPlagueSpell.Dot(target).ExpiresAt() - if sim.CurrentTime+1500*time.Millisecond < min(ffExpiresAt, bpExpiresAt) { - if dk.canCastFrostUnholySpell(sim, target) { - if dk.Deathchill != nil && dk.Deathchill.IsReady(sim) { - dk.Deathchill.Cast(sim, target) - } - casted = dk.castFrostUnholySpell(sim, target) - if casted && dk.LastOutcome.Matches(core.OutcomeLanded) { - dk.fr.oblitCount += 1 - } - } - } else { - waitTime = sim.CurrentTime - s.Advance() - } - - return core.TernaryDuration(casted, -1, waitTime) - } else if fr > 0 && uh > 0 { - casted := false - ffExpiresAt := dk.FrostFeverSpell.Dot(target).ExpiresAt() - bpExpiresAt := dk.BloodPlagueSpell.Dot(target).ExpiresAt() - km := dk.KillingMachineAura.IsActive() - if dk.fr.oblitCount == 1 && dk.FrostStrike.CanCast(sim, nil) && km && sim.CurrentTime+1500*time.Millisecond < min(ffExpiresAt, bpExpiresAt) && dk.getOblitDrift(sim, abGCD) <= allowedObDrift { - casted = dk.FrostStrike.Cast(sim, target) - } else { - if dk.canCastFrostUnholySpell(sim, target) { - dndIn := max(bAt-sim.CurrentTime, dk.DeathAndDecay.TimeToReady(sim)) - if dk.Rotation.UseDeathAndDecay && dk.Env.GetNumTargets() >= 3 && dndIn < 3*time.Second && !dk.UnbreakableArmorAura.IsActive() && dk.UnbreakableArmor.TimeToReady(sim) > 8*time.Second { - if dk.DeathAndDecay.CanCast(sim, target) { - casted = dk.DeathAndDecay.Cast(sim, target) - dk.fr.oblitCount += 1 - } else { - waitUntil = sim.CurrentTime + dndIn - } - } else { - if dk.Deathchill != nil && dk.Deathchill.IsReady(sim) { - dk.Deathchill.Cast(sim, target) - } - casted = dk.castFrostUnholySpell(sim, target) - advance := dk.LastOutcome.Matches(core.OutcomeLanded) - if casted && advance { - dk.fr.oblitCount += 1 - } - } - if dk.fr.oblitCount == 2 { - s.Advance() - dk.fr.oblitCount = 0 - } - } else { - s.Advance() - } - } - } else { - spell := dk.RegularPrioPickSpell(sim, target, obAt+2500*time.Millisecond) - if spell != nil { - casted = spell.Cast(sim, target) - } else { - waitUntil = obAt - } - } - } - return core.TernaryDuration(casted, -1, waitUntil) -} - -type FrostSubBloodUAState uint8 - -const ( - FrostSubBloodUAState_Now FrostSubBloodUAState = iota - FrostSubBloodUAState_Soon - FrostSubBloodUAState_CD -) - -func (dk *DpsDeathknight) frCheckForUATime(sim *core.Simulation) FrostSubBloodUAState { - if dk.UnbreakableArmor.IsReady(sim) { - return FrostSubBloodUAState_Now - } else { - if dk.UnbreakableArmor.ReadyAt() < sim.CurrentTime+dk.SpellGCD()*2 { - return FrostSubBloodUAState_Soon - } else { - return FrostSubBloodUAState_CD - } - } -} - -func (dk *DpsDeathknight) RotationActionCallback_FrostSubBlood_UA_Check(sim *core.Simulation, _ *core.Unit, s *deathknight.Sequence) time.Duration { - uaState := dk.frCheckForUATime(sim) - - if uaState == FrostSubBloodUAState_CD { - s.Clear().NewAction(dk.RotationActionCallback_FrostSubBlood_Obli_Check) - } else { - s.Clear(). - NewAction(dk.RotationActionCallback_FrostSubBlood_FS_Dump_UntilUA). - NewAction(dk.RotationActionCallback_FrostSubBlood_Dump_UntilBR). - NewAction(dk.RotationActionCallback_UA_Frost). - NewAction(dk.RotationActionCallback_FrostSubBlood_Sequence_Pesti). - NewAction(dk.RotationActionCallback_FrostSubBlood_SequenceRotation) - } - - return sim.CurrentTime -} - -func (dk *DpsDeathknight) RotationActionCallback_FrostSubBlood_Obli_Check(sim *core.Simulation, _ *core.Unit, s *deathknight.Sequence) time.Duration { - if dk.BloodTap.IsReady(sim) { - s.Clear(). - NewAction(dk.RotationActionCallback_FrostSubBlood_Dump_UntilBR). - NewAction(dk.RotationActionCallback_FrostSubBlood_Sequence_Pesti). - NewAction(dk.RotationActionCallback_BT). - NewAction(dk.RotationActionCallback_FrostSubBlood_Obli). - NewAction(dk.RotationActionCallback_FrostSubBlood_SequenceRotation) - } else { - s.Clear(). - NewAction(dk.RotationActionCallback_FrostSubBlood_Dump_UntilBR). - NewAction(dk.RotationActionCallback_FrostSubBlood_Sequence_Pesti). - NewAction(dk.RotationActionCallback_FrostSubBlood_FS_KM). - NewAction(dk.RotationActionCallback_BS_Frost). - NewAction(dk.RotationActionCallback_FrostSubBlood_SequenceRotation) - } - return sim.CurrentTime -} - -func (dk *DpsDeathknight) RotationActionCallback_FrostSubBlood_SequenceRotation(sim *core.Simulation, _ *core.Unit, s *deathknight.Sequence) time.Duration { - s.Clear(). - NewAction(dk.RotationActionCallback_FrostSubBlood_FS_Dump) - - if dk.UnbreakableArmor != nil { - s.NewAction(dk.RotationActionCallback_FrostSubBlood_UA_Check) - } else { - s.NewAction(dk.RotationActionCallback_FrostSubBlood_Obli_Check) - } - - return sim.CurrentTime -} - -func (dk *DpsDeathknight) setupFrostSubBloodERWOpener() { - dk.setupUnbreakableArmorCooldowns() - - dk.RotationSequence. - NewAction(dk.RotationActionCallback_IT). - NewAction(dk.RotationActionCallback_PS). - NewAction(dk.RotationActionCallback_UA_Frost). - NewAction(dk.RotationActionCallback_BT). - NewAction(dk.RotationActionCallback_FrostSubBlood_Obli). - NewAction(dk.RotationActionCallback_Frost_FS_HB). - NewAction(dk.RotationActionCallback_Frost_Pesti_ERW). - NewAction(dk.RotationActionCallback_FrostSubBlood_Obli). - NewAction(dk.RotationActionCallback_Frost_FS_HB). - NewAction(dk.RotationActionCallback_FrostSubBlood_Obli). - NewAction(dk.RotationActionCallback_FrostSubBlood_Obli). - NewAction(dk.RotationActionCallback_RD). - NewAction(dk.RotationActionCallback_Frost_FS_HB). - NewAction(dk.RotationActionCallback_Frost_FS_HB). - NewAction(dk.RotationActionCallback_FrostSubBlood_Obli). - NewAction(dk.RotationActionCallback_FrostSubBlood_Obli). - NewAction(dk.RotationActionCallback_FrostSubBlood_Sequence_Pesti). - NewAction(dk.RotationActionCallback_Frost_FS_HB). - NewAction(dk.RotationActionCallback_BS_Frost). - NewAction(dk.RotationActionCallback_Frost_FS_HB). - NewAction(dk.RotationActionCallback_FrostSubBlood_SequenceRotation) -} - -func (dk *DpsDeathknight) setupFrostSubBloodNoERWOpener() { - dk.setupUnbreakableArmorCooldowns() - - dk.RotationSequence. - NewAction(dk.RotationActionCallback_IT). - NewAction(dk.RotationActionCallback_PS). - NewAction(dk.RotationActionCallback_FrostSubBlood_Obli). - NewAction(dk.RotationActionCallback_BS_Frost). - NewAction(dk.RotationActionCallback_BT). - NewAction(dk.RotationActionCallback_UA_Frost). - NewAction(dk.RotationActionCallback_FrostSubBlood_Sequence_Pesti). - NewAction(dk.RotationActionCallback_Frost_FS_HB). - NewAction(dk.RotationActionCallback_RD). - NewAction(dk.RotationActionCallback_Frost_FS_HB). - NewAction(dk.RotationActionCallback_FrostSubBlood_Obli). - NewAction(dk.RotationActionCallback_FrostSubBlood_Obli). - NewAction(dk.RotationActionCallback_Frost_FS_HB). - NewAction(dk.RotationActionCallback_BS_Frost). - NewAction(dk.RotationActionCallback_Frost_FS_HB). - NewAction(dk.RotationActionCallback_FrostSubBlood_Sequence_Pesti). - NewAction(dk.RotationActionCallback_FrostSubBlood_SequenceRotation) -} - -func (dk *DpsDeathknight) RotationActionCallback_FrostSubBlood_RecoverFromPestiMiss(sim *core.Simulation, _ *core.Unit, s *deathknight.Sequence) time.Duration { - if dk.LastCast == dk.fr.bloodSpell { - s.Clear(). - NewAction(dk.RotationActionCallback_BS_Frost). - NewAction(dk.RotationActionCallback_FS). - NewAction(dk.RotationActionCallback_IT). - NewAction(dk.RotationActionCallback_PS). - NewAction(dk.RotationActionCallback_FrostSubBlood_Obli). - NewAction(dk.RotationActionCallback_Frost_FS_HB). - NewAction(dk.RotationActionCallback_BS_Frost). - NewAction(dk.RotationActionCallback_Frost_FS_HB). - NewAction(dk.RotationActionCallback_FrostSubBlood_Sequence_Pesti). - NewAction(dk.RotationActionCallback_FrostSubBlood_SequenceRotation) - } else { - s.Clear(). - NewAction(dk.RotationActionCallback_BS_Frost). - NewAction(dk.RotationActionCallback_BS_Frost). - NewAction(dk.RotationActionCallback_FS). - NewAction(dk.RotationActionCallback_IT). - NewAction(dk.RotationActionCallback_PS). - NewAction(dk.RotationActionCallback_FrostSubBlood_Obli). - NewAction(dk.RotationActionCallback_Frost_FS_HB). - NewAction(dk.RotationActionCallback_BS_Frost). - NewAction(dk.RotationActionCallback_Frost_FS_HB). - NewAction(dk.RotationActionCallback_FrostSubBlood_Sequence_Pesti). - NewAction(dk.RotationActionCallback_FrostSubBlood_SequenceRotation) - } - - dk.NextCast = nil - return sim.CurrentTime -} - -func (dk *DpsDeathknight) RotationActionCallback_FrostSubBlood_Sequence_Pesti(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - casted := false - waitUntil := time.Duration(-1) - - ffActive := dk.FrostFeverSpell.Dot(target).IsActive() - bpActive := dk.BloodPlagueSpell.Dot(target).IsActive() - ffExpiresAt := dk.FrostFeverSpell.Dot(target).ExpiresAt() - bpExpiresAt := dk.BloodPlagueSpell.Dot(target).ExpiresAt() - - if dk.RotationActionCallback_LastSecondsCast(sim, target) { - return -1 - } - - if !ffActive || !bpActive { - return dk.RotationActionCallback_FrostSubBlood_RecoverFromPestiMiss(sim, target, s) - } else { - casted = dk.Pestilence.Cast(sim, target) - advance := dk.LastOutcome.Matches(core.OutcomeLanded) - if !casted || (casted && !dk.LastOutcome.Matches(core.OutcomeLanded)) { - - if sim.CurrentTime+dk.SpellGCD() > ffExpiresAt || sim.CurrentTime+dk.SpellGCD() > bpExpiresAt { - return dk.RotationActionCallback_FrostSubBlood_RecoverFromPestiMiss(sim, target, s) - } else { - s.ConditionalAdvance(casted && advance) - return core.TernaryDuration(casted, -1, waitUntil) - } - } else { - s.ConditionalAdvance(casted && advance) - return core.TernaryDuration(casted, -1, waitUntil) - } - } -} diff --git a/sim/deathknight/dps/rotation_frost_sub_blood_desync.go b/sim/deathknight/dps/rotation_frost_sub_blood_desync.go deleted file mode 100644 index 78ac5cd873..0000000000 --- a/sim/deathknight/dps/rotation_frost_sub_blood_desync.go +++ /dev/null @@ -1,243 +0,0 @@ -package dps - -import ( - "time" - - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/deathknight" -) - -func (dk *DpsDeathknight) RotationActionCallback_FrostDesync_Obli(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - if dk.Deathchill != nil && dk.Deathchill.IsReady(sim) { - dk.Deathchill.Cast(sim, target) - } - casted := dk.castFrostUnholySpell(sim, target) - advance := dk.LastOutcome.Matches(core.OutcomeLanded) - s.ConditionalAdvance(casted && advance) - return -1 -} - -func (dk *DpsDeathknight) setupFrostSubBloodDesyncOpener() { - if dk.Rotation.UseEmpowerRuneWeapon { - dk.setupFrostSubBloodDesyncERWOpener() - } else { - dk.setupFrostSubBloodDesyncNoERWOpener() - } -} - -func (dk *DpsDeathknight) setupFrostSubBloodDesyncERWOpener() { - dk.setupUnbreakableArmorCooldowns() - - dk.RotationSequence. - // Start standard sub-blood opener - NewAction(dk.RotationActionCallback_IT). - NewAction(dk.RotationActionCallback_PS). - NewAction(dk.RotationActionCallback_UA_Frost). - NewAction(dk.RotationActionCallback_BT). - NewAction(dk.RotationActionCallback_FrostDesync_Obli). - NewAction(dk.RotationActionCallback_Frost_FS_HB). - NewAction(dk.RotationActionCallback_Frost_Pesti_ERW). - NewAction(dk.RotationActionCallback_FrostDesync_Obli). - NewAction(dk.RotationActionCallback_Frost_FS_HB). - NewAction(dk.RotationActionCallback_FrostDesync_Obli). - NewAction(dk.RotationActionCallback_FrostDesync_Obli). - NewAction(dk.RotationActionCallback_RD). - NewAction(dk.RotationActionCallback_Frost_FS_HB). - NewAction(dk.RotationActionCallback_Frost_FS_HB). - NewAction(dk.RotationActionCallback_FrostDesync_Obli). - NewAction(dk.RotationActionCallback_FrostDesync_Obli). - NewAction(dk.RotationAction_CancelBT). - NewAction(dk.RotationActionCallback_FrostSubBlood_Sequence_Pesti). - NewAction(dk.RotationActionCallback_Frost_FS_HB). - NewAction(dk.RotationActionCallback_BS). - NewAction(dk.RotationActionCallback_Frost_FS_HB). - // End standard sub-blood opener - - NewAction(dk.RotationActionCallback_FrostDesync_Obli). - NewAction(dk.RotationActionCallback_Frost_FS_HB). - NewAction(dk.RotationActionCallback_FrostDesync_Obli). - - // Get death runes again - NewAction(dk.RotationActionCallback_BS). - NewAction(dk.RotationActionCallback_FrostSubBlood_Sequence_Pesti). - NewAction(dk.RotationActionCallback_Frost_FS_HB). - NewAction(dk.RotationActionCallback_Frost_FS_HB). - - // Re-cast IT then desync f1 u1 runes - NewAction(dk.RotationActionCallback_IT). - NewAction(dk.RotationActionCallback_Force_Desync). - NewAction(dk.RotationActionCallback_FrostDesync_Obli). - NewAction(dk.RotationActionCallback_Frost_FS_HB). - NewAction(dk.RotationActionCallback_FrostSubBlood_Sequence_Pesti). - - // Continue desync rotation - NewAction(dk.RotationActionCallback_FrostSubBlood_Desync_Sequence1) -} - -func (dk *DpsDeathknight) setupFrostSubBloodDesyncNoERWOpener() { - dk.setupUnbreakableArmorCooldowns() - - dk.RotationSequence. - NewAction(dk.RotationActionCallback_IT). - NewAction(dk.RotationActionCallback_PS). - NewAction(dk.RotationActionCallback_UA_Frost). - NewAction(dk.RotationActionCallback_BT). - NewAction(dk.RotationActionCallback_FrostSubBlood_Obli). - NewAction(dk.RotationAction_CancelBT). - NewAction(dk.RotationActionCallback_Pesti). - NewAction(dk.RotationActionCallback_Frost_FS_HB). - NewAction(dk.RotationActionCallback_RD). - NewAction(dk.RotationActionCallback_FS). - NewAction(dk.RotationActionCallback_FrostSubBlood_Desync_Sequence1) -} - -// We need to keep the B2 and F1 runes in sync and immediately use them for obliterate -// otherwise if an unholy rune comes up then we can't continue the Desync rotation without -// re-casting IT + PS -func (dk *DpsDeathknight) firstOblitAt(sim *core.Simulation) time.Duration { - return max(dk.RuneReadyAt(sim, 1), dk.RuneReadyAt(sim, 2)) -} - -func (dk *DpsDeathknight) RotationActionCallback_Force_Desync(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - frostReadyAt := dk.RuneReadyAt(sim, 2) - unholyReadyAt := dk.SpendRuneReadyAt(4, sim.CurrentTime) - drift := unholyReadyAt - frostReadyAt - desiredDrift := 1000 * time.Millisecond - - if drift >= desiredDrift { - dk.Obliterate.Cast(sim, target) - s.Advance() - return -1 - } else { - dk.FrostStrike.Cast(sim, target) - } - - return -1 -} - -func (dk *DpsDeathknight) RotationActionCallback_FrostSubBlood_Desync_Obli(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - casted := dk.RotationActionCallback_LastSecondsCast(sim, target) - if casted { - return -1 - } - - casted = false - advance := true - - ff := dk.FrostFeverSpell.Dot(target).IsActive() - bp := dk.BloodPlagueSpell.Dot(target).IsActive() - - if ff && bp { - if dk.canCastFrostUnholySpell(sim, target) { - if dk.Deathchill != nil && dk.Deathchill.IsReady(sim) { - dk.Deathchill.Cast(sim, target) - } - casted = dk.castFrostUnholySpell(sim, target) - advance = dk.LastOutcome.Matches(core.OutcomeLanded) - s.ConditionalAdvance(casted && advance) - } else { - dk.desync_Filler(sim, target) - } - } else if !ff { - casted = dk.IcyTouch.Cast(sim, target) - advance = dk.LastOutcome.Matches(core.OutcomeLanded) - s.ConditionalAdvance(casted && advance) - } else { - casted = dk.PlagueStrike.Cast(sim, target) - advance = dk.LastOutcome.Matches(core.OutcomeLanded) - s.ConditionalAdvance(casted && advance) - } - - return -1 -} - -func (dk *DpsDeathknight) RotationActionCallback_FrostSubBlood_Desync_UA(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - runeGrace := dk.RuneGraceAt(0, sim.CurrentTime) - waitFor := 5 * time.Millisecond - - if dk.UnbreakableArmor.IsReady(sim) && dk.BloodTap.IsReady(sim) { - dk.BloodTap.Cast(sim, target) - return sim.CurrentTime + waitFor - } else if dk.UnbreakableArmor.IsReady(sim) && runeGrace >= waitFor { - dk.castAllMajorCooldowns(sim) - dk.UnbreakableArmor.Cast(sim, target) - } - - s.Advance() - return -1 -} - -func (dk *DpsDeathknight) RotationActionCallback_FrostSubBlood_Detect_Broken_Desync(sim *core.Simulation, _ *core.Unit, s *deathknight.Sequence) time.Duration { - frost := dk.FrostRuneReadyAt(sim) - unholy := dk.UnholyRuneReadyAt(sim) - - if frost == unholy { - s.Clear().NewAction(dk.RotationActionCallback_FrostSubBlood_SequenceRotation) - } else { - s.Advance() - } - return sim.CurrentTime -} - -func (dk *DpsDeathknight) RotationActionCallback_FrostSubBlood_Desync_Pesti(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - casted := dk.RotationActionCallback_LastSecondsCast(sim, target) - if casted { - return -1 - } - casted = dk.Pestilence.Cast(sim, target) - advance := dk.LastOutcome.Matches(core.OutcomeLanded) - s.ConditionalAdvance(casted && advance) - return -1 -} - -func (dk *DpsDeathknight) RotationActionCallback_FrostSubBlood_Desync_Sequence1(sim *core.Simulation, _ *core.Unit, s *deathknight.Sequence) time.Duration { - s.Clear(). - // f1 u1 - NewAction(dk.RotationActionCallback_FrostSubBlood_Desync_Obli). - // f2 u2 - NewAction(dk.RotationActionCallback_FrostSubBlood_Desync_Obli). - NewAction(dk.RotationActionCallback_FrostSubBlood_Desync_FS_Dump). - NewAction(dk.RotationActionCallback_FrostSubBlood_Desync_Pesti). - NewAction(dk.RotationActionCallback_FrostSubBlood_Desync_Sequence2) - return sim.CurrentTime -} - -func (dk *DpsDeathknight) RotationActionCallback_FrostSubBlood_Desync_Sequence2(sim *core.Simulation, _ *core.Unit, s *deathknight.Sequence) time.Duration { - s.Clear(). - NewAction(dk.RotationActionCallback_FrostSubBlood_Detect_Broken_Desync). - // d2 f1 - NewAction(dk.RotationActionCallback_FrostSubBlood_Desync_Obli). - // f2 u1 - NewAction(dk.RotationActionCallback_FrostSubBlood_Desync_Obli). - // u2 d1 - NewAction(dk.RotationActionCallback_FrostSubBlood_Desync_Obli). - NewAction(dk.RotationActionCallback_FrostSubBlood_Desync_UA). - NewAction(dk.RotationActionCallback_FrostSubBlood_Desync_FS_Dump). - NewAction(dk.RotationActionCallback_FrostSubBlood_Desync_Pesti). - NewAction(dk.RotationAction_CancelBT). - NewAction(dk.RotationActionCallback_FrostSubBlood_Desync_Sequence1) - return sim.CurrentTime -} - -func (dk *DpsDeathknight) desync_Filler(sim *core.Simulation, target *core.Unit) { - spell := dk.RegularPrioPickSpell(sim, target, dk.firstOblitAt(sim)) - if spell != nil { - spell.Cast(sim, target) - } -} - -func (dk *DpsDeathknight) RotationActionCallback_FrostSubBlood_Desync_FS_Dump(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - casted := dk.RotationActionCallback_LastSecondsCast(sim, target) - if casted { - return -1 - } - - if !dk.AllRunesSpent() { - s.Advance() - return sim.CurrentTime - } - - dk.desync_Filler(sim, target) - - return -1 -} diff --git a/sim/deathknight/dps/rotation_frost_sub_unholy.go b/sim/deathknight/dps/rotation_frost_sub_unholy.go deleted file mode 100644 index b07eddfce1..0000000000 --- a/sim/deathknight/dps/rotation_frost_sub_unholy.go +++ /dev/null @@ -1,267 +0,0 @@ -package dps - -import ( - "time" - - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/deathknight" -) - -func (dk *DpsDeathknight) setupFrostSubUnholyERWOpener() { - dk.setupUnbreakableArmorCooldowns() - - dk.RotationSequence. - NewAction(dk.RotationActionCallback_IT). - NewAction(dk.RotationActionCallback_PS). - NewAction(dk.RotationActionCallback_BT). - NewAction(dk.RotationActionCallback_Pesti). - NewAction(dk.RotationActionCallback_UA_Frost). - NewAction(dk.RotationActionCallback_FrostSubUnholy_Obli). - NewAction(dk.RotationActionCallback_ERW). - NewAction(dk.RotationActionCallback_FrostSubUnholy_FS_HB). - NewAction(dk.RotationActionCallback_FrostSubUnholy_Obli). - NewAction(dk.RotationActionCallback_FrostSubUnholy_Obli). - NewAction(dk.RotationActionCallback_FrostSubUnholy_FS_HB). - NewAction(dk.RotationActionCallback_FrostSubUnholy_Obli). - NewAction(dk.RotationAction_CancelBT). - NewAction(dk.RotationActionCallback_RD). - NewAction(dk.RotationActionCallback_FrostSubUnholy_FS_HB). - NewAction(dk.RotationActionCallback_FrostSubUnholy_Obli). - NewAction(dk.RotationActionCallback_FrostSubUnholy_Obli). - NewAction(dk.RotationActionCallback_FrostSubUnholy_FS_HB). - NewAction(dk.RotationActionCallback_FrostSubUnholy_FS_HB). - NewAction(dk.RotationActionCallback_Pesti). - NewAction(dk.RotationActionCallback_BS). - NewAction(dk.RotationActionCallback_FrostSubUnholy_Sequence1) -} - -func (dk *DpsDeathknight) RotationActionCallback_FrostSubUnholy_FS_HB(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - if !dk.canCastAbilityBeforeDiseasesExpire(sim, target) { - s.Advance() - return sim.CurrentTime - } - return dk.RotationActionCallback_Frost_FS_HB(sim, target, s) -} - -func (dk *DpsDeathknight) canCastAbilityBeforeDiseasesExpire(sim *core.Simulation, target *core.Unit) bool { - ffExpiresAt := dk.FrostFeverSpell.Dot(target).ExpiresAt() - bpExpiresAt := dk.BloodPlagueSpell.Dot(target).ExpiresAt() - return sim.CurrentTime+1500*time.Millisecond < min(ffExpiresAt, bpExpiresAt) -} - -func (dk *DpsDeathknight) RotationActionCallback_FrostSubUnholy_Obli(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - casted := false - advance := true - waitTime := time.Duration(-1) - - if dk.canCastAbilityBeforeDiseasesExpire(sim, target) { - if dk.canCastFrostUnholySpell(sim, target) { - if dk.Deathchill != nil && dk.Deathchill.IsReady(sim) { - dk.Deathchill.Cast(sim, target) - } - casted = dk.castFrostUnholySpell(sim, target) - advance = dk.LastOutcome.Matches(core.OutcomeLanded) - } - - s.ConditionalAdvance(casted && advance) - } else { - if dk.canCastFrostUnholySpell(sim, target) { - if dk.Deathchill != nil && dk.Deathchill.IsReady(sim) { - dk.Deathchill.Cast(sim, target) - } - casted = dk.castFrostUnholySpell(sim, target) - advance = dk.LastOutcome.Matches(core.OutcomeLanded) - - if casted && advance { - return dk.RotationActionCallback_FrostSubUnholy_RecoverFromPestiMiss(sim, target, s) - } - } - } - - return core.TernaryDuration(casted, -1, waitTime) -} - -func (dk *DpsDeathknight) RotationActionCallback_FrostSubUnholy_FS_KM(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - casted := dk.RotationActionCallback_LastSecondsCast(sim, target) - - if !casted { - if !dk.canCastAbilityBeforeDiseasesExpire(sim, target) { - s.Advance() - return sim.CurrentTime - } - - spell := dk.RegularPrioPickSpell(sim, target, core.NeverExpires) - if spell != nil { - casted = spell.Cast(sim, target) - } - - s.Advance() - } - - return core.TernaryDuration(casted, -1, sim.CurrentTime) -} - -func (dk *DpsDeathknight) RotationActionCallback_FrostSubUnholy_Dump_Until_Deaths(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - /* - We need to have the first death up before we UA + BT + Oblit, since if only the 2nd - death rune is up, UA then Blood Tap will convert and refresh the first and the second will have a 10s CD from UA - */ - if dk.LeftBloodRuneReady() { - s.Advance() - return sim.CurrentTime - } - - spell := dk.RegularPrioPickSpell(sim, target, dk.DeathRuneRegenAt(1)) - - if spell != nil { - spell.Cast(sim, target) - } - - return -1 -} - -func (dk *DpsDeathknight) RotationActionCallback_FrostSubUnholy_UA_Check1(sim *core.Simulation, _ *core.Unit, s *deathknight.Sequence) time.Duration { - if dk.UnbreakableArmor.CanCast(sim, nil) && dk.BloodTap.CanCast(sim, nil) { - s.Clear(). - NewAction(dk.RotationActionCallback_FrostSubUnholy_Dump_Until_Deaths). - NewAction(dk.RotationActionCallback_UA_Frost). - NewAction(dk.RotationActionCallback_BT). - NewAction(dk.RotationActionCallback_FrostSubUnholy_Obli). - NewAction(dk.RotationActionCallback_FrostSubUnholy_Sequence2) - } else { - s.Advance() - } - return sim.CurrentTime -} - -func (dk *DpsDeathknight) RotationActionCallback_FrostSubUnholy_UA_Check2(sim *core.Simulation, _ *core.Unit, s *deathknight.Sequence) time.Duration { - if dk.UnbreakableArmor.CanCast(sim, nil) && dk.BloodTap.CanCast(sim, nil) { - s.Clear(). - NewAction(dk.RotationActionCallback_UA_Frost). - NewAction(dk.RotationActionCallback_BT). - NewAction(dk.RotationActionCallback_FrostSubUnholy_Sequence2) - } else { - s.Advance() - } - return sim.CurrentTime -} - -func (dk *DpsDeathknight) RotationActionCallback_FrostSubUnholy_UA_Check3(sim *core.Simulation, _ *core.Unit, s *deathknight.Sequence) time.Duration { - if (dk.UnbreakableArmor.TimeToReady(sim) < 2500*time.Millisecond+sim.CurrentTime) && (dk.BloodTap.TimeToReady(sim) < 2500*time.Millisecond+sim.CurrentTime) { - s.Clear(). - NewAction(dk.RotationActionCallback_BT). - NewAction(dk.RotationActionCallback_UA_Frost). - NewAction(dk.RotationActionCallback_BS). - NewAction(dk.RotationActionCallback_FrostSubUnholy_Sequence1) - } else { - s.Advance() - } - return sim.CurrentTime -} - -func (dk *DpsDeathknight) RotationActionCallback_FrostSubUnholy_Sequence1(sim *core.Simulation, _ *core.Unit, s *deathknight.Sequence) time.Duration { - s.Clear(). - NewAction(dk.RotationActionCallback_EndOfFightCheck). - NewAction(dk.RotationActionCallback_FrostSubUnholy_FS_Dump). - NewAction(dk.RotationActionCallback_FrostSubUnholy_Obli). - NewAction(dk.RotationActionCallback_FrostSubUnholy_Obli). - NewAction(dk.RotationActionCallback_FS). - NewAction(dk.RotationActionCallback_FrostSubUnholy_UA_Check1). - NewAction(dk.RotationActionCallback_FrostSubUnholy_Obli). - NewAction(dk.RotationActionCallback_FrostSubUnholy_Sequence2) - return sim.CurrentTime -} - -func (dk *DpsDeathknight) RotationActionCallback_FrostSubUnholy_Pesti(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - desiredGrace := 10 * time.Millisecond - currentGrace := dk.RuneGraceAt(0, sim.CurrentTime) - ffExpiresAt := dk.FrostFeverSpell.Dot(target).ExpiresAt() - bpExpiresAt := dk.BloodPlagueSpell.Dot(target).ExpiresAt() - diseaseExpiresAt := min(ffExpiresAt, bpExpiresAt) - waitUntil := sim.CurrentTime + (desiredGrace - currentGrace) - - if diseaseExpiresAt <= sim.CurrentTime { - return dk.RotationActionCallback_FrostSubUnholy_RecoverFromPestiMiss(sim, target, s) - } - if currentGrace < desiredGrace && diseaseExpiresAt > waitUntil { - return waitUntil - } - casted := dk.Pestilence.Cast(sim, target) - s.ConditionalAdvance(casted && dk.LastOutcome.Matches(core.OutcomeLanded)) - return -1 -} - -func (dk *DpsDeathknight) RotationActionCallback_FrostSubUnholy_Sequence2(sim *core.Simulation, _ *core.Unit, s *deathknight.Sequence) time.Duration { - s.Clear(). - NewAction(dk.RotationAction_CancelBT). - NewAction(dk.RotationActionCallback_EndOfFightCheck). - NewAction(dk.RotationActionCallback_FrostSubUnholy_FS_Dump). - NewAction(dk.RotationActionCallback_FrostSubUnholy_Obli). - NewAction(dk.RotationActionCallback_FrostSubUnholy_Obli). - NewAction(dk.RotationActionCallback_FrostSubUnholy_FS_KM). - NewAction(dk.RotationActionCallback_EndOfFightCheck). - NewAction(dk.RotationActionCallback_FrostSubUnholy_Pesti). - //NewAction(dk.RotationActionCallback_FrostSubUnholy_UA_Check3). - NewAction(dk.RotationActionCallback_BS). - NewAction(dk.RotationActionCallback_FrostSubUnholy_Sequence1) - return sim.CurrentTime -} - -func (dk *DpsDeathknight) RotationActionCallback_FrostSubUnholy_RecoverFromPestiMiss(sim *core.Simulation, _ *core.Unit, s *deathknight.Sequence) time.Duration { - if dk.LastCast == dk.BloodStrike { - s.Clear(). - NewAction(dk.RotationActionCallback_BS). - NewAction(dk.RotationActionCallback_FS). - NewAction(dk.RotationActionCallback_IT). - NewAction(dk.RotationActionCallback_PS). - NewAction(dk.RotationActionCallback_FrostSubUnholy_Obli). - NewAction(dk.RotationActionCallback_FrostSubUnholy_Obli). - NewAction(dk.RotationActionCallback_Frost_FS_HB). - NewAction(dk.RotationActionCallback_FrostSubUnholy_FS_KM). - NewAction(dk.RotationActionCallback_FrostSubUnholy_Sequence1) - } else { - s.Clear(). - NewAction(dk.RotationActionCallback_BS). - NewAction(dk.RotationActionCallback_BS). - NewAction(dk.RotationActionCallback_FS). - NewAction(dk.RotationActionCallback_IT). - NewAction(dk.RotationActionCallback_PS). - NewAction(dk.RotationActionCallback_FrostSubUnholy_Obli). - NewAction(dk.RotationActionCallback_FrostSubUnholy_Obli). - NewAction(dk.RotationActionCallback_Frost_FS_HB). - NewAction(dk.RotationActionCallback_FrostSubUnholy_FS_KM). - NewAction(dk.RotationActionCallback_FrostSubUnholy_Sequence1) - } - - return sim.CurrentTime -} - -func (dk *DpsDeathknight) RotationActionCallback_FrostSubUnholy_FS_Dump(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - casted := false - waitUntil := time.Duration(-1) - - fr := dk.CurrentFrostRunes() - uh := dk.CurrentUnholyRunes() - - if fr > 0 && uh > 0 { - s.Advance() - return sim.CurrentTime - } - - casted = dk.RotationActionCallback_LastSecondsCast(sim, target) - if !casted { - frAt := dk.NormalFrostRuneReadyAt(sim) - uhAt := dk.NormalUnholyRuneReadyAt(sim) - obAt := max(frAt, uhAt) - delayAmount := time.Second - spell := dk.RegularPrioPickSpell(sim, target, obAt+delayAmount) - if spell != nil { - casted = spell.Cast(sim, target) - } else { - waitUntil = obAt - s.Advance() - } - } - - return core.TernaryDuration(casted, -1, waitUntil) -} diff --git a/sim/deathknight/dps/rotation_shared_helper.go b/sim/deathknight/dps/rotation_shared_helper.go deleted file mode 100644 index a770219183..0000000000 --- a/sim/deathknight/dps/rotation_shared_helper.go +++ /dev/null @@ -1,111 +0,0 @@ -package dps - -import ( - "time" - - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/core/proto" - "github.com/wowsims/wotlk/sim/deathknight" -) - -type SharedRotation struct { - dk *DpsDeathknight - recastedFF bool - recastedBP bool - - ffFirst bool - hasGod bool -} - -func (sr *SharedRotation) Reset(_ *core.Simulation) { - sr.recastedFF = false - sr.recastedBP = false -} - -func (sr *SharedRotation) Initialize(dk *DpsDeathknight) { - dk.sr.ffFirst = dk.Rotation.FirstDisease == proto.Deathknight_Rotation_FrostFever - dk.sr.hasGod = dk.HasMajorGlyph(proto.DeathknightMajorGlyph_GlyphOfDisease) -} - -func (dk *DpsDeathknight) shDiseaseCheck(sim *core.Simulation, target *core.Unit, spell *core.Spell, costRunes bool, casts int, ffSyncTime time.Duration) bool { - ffRemaining := dk.FrostFeverSpell.Dot(target).RemainingDuration(sim) - bpRemaining := dk.BloodPlagueSpell.Dot(target).RemainingDuration(sim) - castGcd := dk.SpellGCD() * time.Duration(casts) - - // FF is not active or will drop before Gcd is ready after this cast - if !dk.FrostFeverSpell.Dot(target).IsActive() || ffRemaining < castGcd { - return false - } - // BP is not active or will drop before Gcd is ready after this cast - if !dk.BloodPlagueSpell.Dot(target).IsActive() || bpRemaining < castGcd { - return false - } - - // If the ability we want to cast spends runes we check for possible disease drops - // in the time we won't have runes to recast the disease - if spell.CanCast(sim, nil) && costRunes { - ffExpiresAt := ffRemaining + sim.CurrentTime - bpExpiresAt := bpRemaining + sim.CurrentTime - - spellCost := dk.OptimalRuneCost(core.RuneCost(spell.DefaultCast.Cost)) - - crpb := dk.Predictor() - crpb.SpendRuneCost(sim, spellCost) - - afterCastTime := sim.CurrentTime + castGcd - currentFrostRunes := crpb.CurrentFrostRunes() - currentUnholyRunes := crpb.CurrentUnholyRunes() - nextFrostRuneAt := crpb.FrostRuneReadyAt(sim) - nextUnholyRuneAt := crpb.UnholyRuneReadyAt(sim) - - // If FF is gonna drop while our runes are on CD - if dk.shRecastAvailableCheck(ffExpiresAt-ffSyncTime, afterCastTime, int(spellCost.Frost()), int32(currentFrostRunes), nextFrostRuneAt) { - return false - } - - // If BP is gonna drop while our runes are on CD - if dk.shRecastAvailableCheck(bpExpiresAt, afterCastTime, int(spellCost.Unholy()), int32(currentUnholyRunes), nextUnholyRuneAt) { - return false - } - } - - return true -} - -func (dk *DpsDeathknight) shRecastAvailableCheck(expiresAt time.Duration, afterCastTime time.Duration, - spellCost int, currentRunes int32, nextRuneAt time.Duration) bool { - // Allow disease drops in unholy as its a dps increase sometimes - downTime := time.Duration(core.TernaryFloat64(dk.PrimaryTalentTree == 2, dk.Inputs.DiseaseDowntime, 0)) * time.Second - if spellCost > 0 && currentRunes == 0 { - if expiresAt+downTime <= nextRuneAt { - return true - } - } else if afterCastTime >= expiresAt+downTime { - return true - } - return false -} - -func (dk *DpsDeathknight) shShouldSpreadDisease(_ *core.Simulation) bool { - prioritizeSpread := dk.Env.GetNumTargets() > 1 - - // on 2 or 3 targets, we don't want to spread if we have diseases up on all targets already (to maximize Desolation uptime) - // on 4+ targets always spread to maximize disease and Wandering Plague uptime - if dk.Env.GetNumTargets() > 1 && dk.Env.GetNumTargets() < 4 { - for i := int32(1); i < dk.Env.GetNumTargets(); i++ { - target := dk.Env.GetTargetUnit(i) - if dk.FrostFeverSpell.Dot(target).IsActive() && dk.BloodPlagueSpell.Dot(target).IsActive() { - prioritizeSpread = false - break - } - } - } - - return dk.sr.recastedFF && dk.sr.recastedBP && prioritizeSpread -} - -func (dk *DpsDeathknight) RotationAction_CancelBT(sim *core.Simulation, _ *core.Unit, s *deathknight.Sequence) time.Duration { - dk.BloodTapAura.Deactivate(sim) - s.Advance() - return sim.CurrentTime -} diff --git a/sim/deathknight/dps/rotation_unholy.go b/sim/deathknight/dps/rotation_unholy.go deleted file mode 100644 index 27108d1bb0..0000000000 --- a/sim/deathknight/dps/rotation_unholy.go +++ /dev/null @@ -1,676 +0,0 @@ -package dps - -import ( - "time" - - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/core/proto" - "github.com/wowsims/wotlk/sim/deathknight" -) - -func (dk *DpsDeathknight) setupUnholyRotations() { - if dk.Rotation.BloodTap == proto.Deathknight_Rotation_GhoulFrenzy && !dk.Talents.GhoulFrenzy { - dk.Rotation.BloodTap = proto.Deathknight_Rotation_IcyTouch - } - - dk.Inputs.FuStrike = deathknight.FuStrike_ScourgeStrike - if dk.Talents.Annihilation > 0 { - dk.Inputs.FuStrike = deathknight.FuStrike_Obliterate - } - - if dk.Talents.SummonGargoyle && dk.Rotation.UseGargoyle { - dk.setupGargoyleCooldowns() - } - - dk.RotationSequence.Clear(). - NewAction(dk.RotationActionCallback_MindFreezeFiller). - NewAction(dk.getFirstDiseaseAction()). - NewAction(dk.getSecondDiseaseAction()). - NewAction(dk.uhBloodRuneAction(true)) - - fuStrikeAction := dk.RotationActionCallback_DS - if dk.Talents.ScourgeStrike { - fuStrikeAction = dk.RotationActionCallback_SS - } - - if dk.ur.sigil == Sigil_Virulence { - dk.RotationSequence. - NewAction(fuStrikeAction). - NewAction(dk.RotationActionUH_BS). - NewAction(dk.RotationActionUH_SS_Sigil). - NewAction(dk.RotationActionUH_BS). - NewAction(dk.RotationActionUH_SS_Sigil). - NewAction(dk.RotationActionUH_BS) - } else if dk.ur.sigil == Sigil_HangedMan { - dk.RotationSequence. - NewAction(fuStrikeAction). - NewAction(dk.RotationActionUH_BS). - NewAction(dk.RotationActionCallback_DC). - NewAction(dk.RotationActionCallback_ERW). - NewAction(fuStrikeAction). - NewAction(dk.RotationActionUH_BS). - NewAction(fuStrikeAction). - NewAction(dk.RotationActionUH_BS) - } - - if dk.Rotation.UseDeathAndDecay || (!dk.Talents.ScourgeStrike && dk.Talents.Annihilation == 0) { - if !dk.Talents.ScourgeStrike || dk.ur.sigil == Sigil_Other { - dk.RotationSequence. - NewAction(dk.RotationActionCallback_DND) - } - dk.RotationSequence. - NewAction(dk.RotationActionCallback_UnholyDndRotation) - } else { - dk.RotationSequence.NewAction(dk.RotationActionCallback_UnholySsRotation) - } -} - -func (dk *DpsDeathknight) setupWeaponSwap() { - if !dk.ItemSwap.IsEnabled() { - return - } - - if mh := dk.ItemSwap.GetItem(proto.ItemSlot_ItemSlotMainHand); mh != nil { - if mh.Enchant.EffectID == 3790 { - dk.ur.mhSwap = WeaponSwap_BlackMagic - } else if mh.Enchant.EffectID == 3789 { - dk.ur.mhSwap = WeaponSwap_Berserking - } else if mh.Enchant.EffectID == 3368 { - dk.ur.mhSwap = WeaponSwap_FallenCrusader - } - } - - if oh := dk.ItemSwap.GetItem(proto.ItemSlot_ItemSlotOffHand); oh != nil { - if oh.Enchant.EffectID == 3790 { - dk.ur.ohSwap = WeaponSwap_BlackMagic - } else if oh.Enchant.EffectID == 3789 { - dk.ur.ohSwap = WeaponSwap_Berserking - } else if oh.Enchant.EffectID == 3368 { - dk.ur.ohSwap = WeaponSwap_FallenCrusader - } - } - - if dk.ur.mhSwap != WeaponSwap_None || dk.ur.ohSwap != WeaponSwap_None { - core.MakePermanent(dk.GetOrRegisterAura(core.Aura{ - Label: "Weapon Swap Check", - OnCastComplete: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell) { - if dk.GCD.TimeToReady(sim) >= time.Second && dk.Hardcast.Expires < sim.CurrentTime { - if sim.Log != nil { - sim.Log("Swap Check: %0.2f", dk.GCD.TimeToReady(sim).Seconds()) - } - dk.weaponSwapCheck(sim) - } - }, - })) - } -} - -func (dk *DpsDeathknight) RotationActionCallback_UnholyDndRotation(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - if dk.uhGargoyleCheck(sim, target, 100*time.Millisecond) { - dk.uhAfterGargoyleSequence(sim) - return sim.CurrentTime - } - - if dk.CurrentRunicPower() > 100 && dk.GCD.IsReady(sim) && dk.DeathCoil.Cast(sim, target) { - return -1 - } - - if dk.Talents.GhoulFrenzy && !dk.uhShouldWaitForDnD(sim, false, true, true) { - if dk.uhGhoulFrenzyCheck(sim, target) { - return sim.CurrentTime - } - } - - if dk.uhBloodTap(sim, target) { - return sim.CurrentTime - } - - if dk.uhEmpoweredRuneWeapon(sim, target) { - return sim.CurrentTime - } - - if dk.uhMindFreeze(sim, target) { - return sim.CurrentTime - } - - cast := false - if dk.uhDiseaseCheck(sim, target, dk.DeathAndDecay, true, 1) { - if dk.uhVirulenceRotationCheck(sim, dk.Talents.SummonGargoyle) { - if dk.uhGargoyleCheck(sim, target, core.GCDDefault*2+50*time.Millisecond) { - dk.uhAfterGargoyleSequence(sim) - return sim.CurrentTime - } - cast = dk.uhCastVirulenceStrike(sim, target) - if cast { - if dk.LastOutcome.Matches(core.OutcomeLanded) { - dk.RotationSequence.Clear(). - NewAction(dk.RotationActionUH_BS). - NewAction(dk.RotationActionCallback_UnholyDndRotation) - } - } - } else { - if dk.uhGargoyleCheck(sim, target, dk.SpellGCD()+50*time.Millisecond) { - dk.uhAfterGargoyleSequence(sim) - return sim.CurrentTime - } - if cast = dk.DeathAndDecay.CanCast(sim, target); cast { - dk.DeathAndDecay.Cast(sim, target) - } - } - } else { - if dk.uhGargoyleCheck(sim, target, dk.SpellGCD()+core.GCDDefault+50*time.Millisecond) { - dk.uhAfterGargoyleSequence(sim) - return sim.CurrentTime - } - dk.uhRecastDiseasesSequence(sim) - return sim.CurrentTime - } - - if !cast { - if dk.uhDiseaseCheck(sim, target, dk.ScourgeStrike, true, 1) { - if !dk.uhShouldWaitForDnD(sim, true, true, true) { - if dk.uhVirulenceRotationCheck(sim, false) && dk.DeathStrike.IsReady(sim) { - if dk.uhGargoyleCheck(sim, target, core.GCDDefault*2+50*time.Millisecond) { - dk.uhAfterGargoyleSequence(sim) - return sim.CurrentTime - } - cast = dk.uhCastVirulenceStrike(sim, target) - if cast { - if dk.LastOutcome.Matches(core.OutcomeLanded) { - dk.RotationSequence.Clear(). - NewAction(dk.RotationActionUH_BS). - NewAction(dk.RotationActionCallback_UnholyDndRotation) - } - } - } else if dk.CurrentDeathRunes() > 0 { - dk.RotationSequence.Clear(). - NewAction(dk.RotationActionUH_BS). - NewAction(dk.RotationActionCallback_UnholyDndRotation) - return sim.CurrentTime - } else if dk.IcyTouch.CanCast(sim, nil) && dk.PlagueStrike.CanCast(sim, nil) { - if dk.uhGargoyleCheck(sim, target, dk.SpellGCD()+core.GCDDefault*2+50*time.Millisecond) { - dk.uhAfterGargoyleSequence(sim) - return sim.CurrentTime - } - dk.uhRecastDiseasesSequence(sim) - return sim.CurrentTime - } - } - } else { - dk.uhRecastDiseasesSequence(sim) - return sim.CurrentTime - } - if !cast { - gargCheck := dk.uhGargoyleCheck(sim, target, dk.SpellGCD()+50*time.Millisecond) - if dk.shShouldSpreadDisease(sim) { - if !dk.uhShouldWaitForDnD(sim, true, false, false) { - if gargCheck { - dk.uhAfterGargoyleSequence(sim) - return sim.CurrentTime - } - cast = dk.uhSpreadDiseases(sim, target, s) - } - } - if !cast { - if dk.uhDeathCoilCheck(sim) { - if gargCheck { - dk.uhAfterGargoyleSequence(sim) - return sim.CurrentTime - } - cast = dk.DeathCoil.Cast(sim, target) - } - if !cast { - if gargCheck { - dk.uhAfterGargoyleSequence(sim) - return sim.CurrentTime - } - - if dk.HornOfWinter.CanCast(sim, nil) { - dk.HornOfWinter.Cast(sim, target) - } - } - } - } - } - - // Gargoyle cast needs to be checked more often then default rotation on gcd/resource gain checks - if dk.Rotation.UseGargoyle && dk.SummonGargoyle.IsReady(sim) && dk.GCD.IsReady(sim) { - return sim.CurrentTime + 100*time.Millisecond - } - - return -1 -} - -func (dk *DpsDeathknight) RotationActionCallback_UnholySsRotation(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - if dk.uhGargoyleCheck(sim, target, 100*time.Millisecond) { - dk.uhAfterGargoyleSequence(sim) - return sim.CurrentTime - } - - if dk.Talents.GhoulFrenzy { - if dk.uhGhoulFrenzyCheck(sim, target) { - return sim.CurrentTime - } - } - - if dk.uhBloodTap(sim, target) { - return sim.CurrentTime - } - - if dk.uhEmpoweredRuneWeapon(sim, target) { - return sim.CurrentTime - } - - if dk.uhMindFreeze(sim, target) { - return sim.CurrentTime - } - - casted := false - fuStrike := dk.ScourgeStrike - if dk.Inputs.FuStrike == deathknight.FuStrike_Obliterate { - fuStrike = dk.Obliterate - } - if dk.uhDiseaseCheck(sim, target, fuStrike, true, 1) { - if dk.uhGargoyleCheck(sim, target, core.GCDDefault+50*time.Millisecond) { - dk.uhAfterGargoyleSequence(sim) - return sim.CurrentTime - } - casted = fuStrike.Cast(sim, target) - } else { - if dk.uhGargoyleCheck(sim, target, dk.SpellGCD()+core.GCDDefault*2+50*time.Millisecond) { - dk.uhAfterGargoyleSequence(sim) - return sim.CurrentTime - } - dk.uhRecastDiseasesSequence(sim) - return sim.CurrentTime - } - if !casted { - gargCheck := dk.uhGargoyleCheck(sim, target, dk.SpellGCD()+50*time.Millisecond) - if dk.shShouldSpreadDisease(sim) { - if gargCheck { - dk.uhAfterGargoyleSequence(sim) - return sim.CurrentTime - } - casted = dk.uhSpreadDiseases(sim, target, s) - } else { - if dk.uhDiseaseCheck(sim, target, dk.BloodStrike, true, 1) { - if dk.uhGargoyleCheck(sim, target, core.GCDDefault+50*time.Millisecond) { - dk.uhAfterGargoyleSequence(sim) - return sim.CurrentTime - } - if dk.desolationAuraCheck(sim) { - casted = dk.BloodStrike.Cast(sim, target) - } else { - casted = dk.BloodBoil.Cast(sim, target) - } - } else { - if dk.uhGargoyleCheck(sim, target, dk.SpellGCD()+core.GCDDefault*2+50*time.Millisecond) { - dk.uhAfterGargoyleSequence(sim) - return sim.CurrentTime - } - dk.uhRecastDiseasesSequence(sim) - return sim.CurrentTime - } - } - if !casted { - if dk.uhDeathCoilCheck(sim) { - if gargCheck { - dk.uhAfterGargoyleSequence(sim) - return sim.CurrentTime - } - casted = dk.DeathCoil.Cast(sim, target) - } - if !casted { - if gargCheck { - dk.uhAfterGargoyleSequence(sim) - return sim.CurrentTime - } - - if dk.HornOfWinter.CanCast(sim, nil) { - dk.HornOfWinter.Cast(sim, target) - } - } - } - } - - // Gargoyle cast needs to be checked more often then default rotation on gcd/resource gain checks - if dk.Rotation.UseGargoyle && dk.SummonGargoyle.IsReady(sim) && dk.GCD.IsReady(sim) { - return sim.CurrentTime + 100*time.Millisecond - } - - return -1 -} - -func (dk *DpsDeathknight) uhAfterGargoyleSequence(sim *core.Simulation) { - if dk.Rotation.UseEmpowerRuneWeapon && dk.EmpowerRuneWeapon.IsReady(sim) { - dk.RotationSequence.Clear() - - if dk.BloodTapAura.IsActive() { - dk.RotationSequence.NewAction(dk.RotationAction_CancelBT) - } - - didErw := false - if dk.Inputs.ArmyOfTheDeadType != proto.Deathknight_Rotation_DoNotUse && dk.ArmyOfTheDead.IsReady(sim) { - // If not enough runes for aotd cast ERW - if dk.CurrentBloodRunes() < 1 || dk.CurrentFrostRunes() < 1 || dk.CurrentUnholyRunes() < 1 { - dk.RotationSequence.NewAction(dk.RotationActionCallback_ERW) - didErw = true - } - dk.RotationSequence. - NewAction(dk.RotationActionCallback_AOTD) - } - - if dk.Rotation.BlPresence == proto.Deathknight_Rotation_Blood && !dk.PresenceMatches(deathknight.BloodPresence) && (dk.Rotation.PreNerfedGargoyle || dk.Rotation.GargoylePresence == proto.Deathknight_Rotation_Blood) { - if didErw || dk.CurrentBloodRunes() > 0 { - dk.RotationSequence.NewAction(dk.RotationActionCallback_BP) - } else if !didErw && !dk.Rotation.BtGhoulFrenzy && dk.BloodTap.IsReady(sim) { - dk.RotationSequence. - NewAction(dk.RotationActionCallback_BT). - NewAction(dk.RotationActionCallback_BP). - NewAction(dk.RotationAction_CancelBT) - } - } - - if dk.Rotation.UseDeathAndDecay || (!dk.Talents.ScourgeStrike && dk.Talents.Annihilation == 0) { - dk.RotationSequence.NewAction(dk.RotationActionUH_ResetToDndMain) - } else { - dk.RotationSequence.NewAction(dk.RotationActionUH_ResetToSsMain) - } - } else if dk.Inputs.ArmyOfTheDeadType == proto.Deathknight_Rotation_AsMajorCd && dk.ArmyOfTheDead.IsReady(sim) { - dk.RotationSequence.Clear() - dk.RotationSequence. - NewAction(dk.RotationActionCallback_Haste_Snapshot). - NewAction(dk.RotationActionCallback_AOTD) - - if dk.Rotation.UseDeathAndDecay || (!dk.Talents.ScourgeStrike && dk.Talents.Annihilation == 0) { - dk.RotationSequence.NewAction(dk.RotationActionUH_ResetToDndMain) - } else { - dk.RotationSequence.NewAction(dk.RotationActionUH_ResetToSsMain) - } - } -} - -func (dk *DpsDeathknight) RotationActionCallback_Haste_Snapshot(sim *core.Simulation, _ *core.Unit, s *deathknight.Sequence) time.Duration { - dk.ur.gargoyleSnapshot.ActivateMajorCooldowns(sim) - dk.UpdateMajorCooldowns() - s.Advance() - return sim.CurrentTime -} - -func (dk *DpsDeathknight) uhGhoulFrenzySequence(_ *core.Simulation, bloodTap bool) { - if bloodTap { - dk.RotationSequence.Clear(). - NewAction(dk.RotationActionCallback_BT). - NewAction(dk.RotationActionCallback_GF). - NewAction(dk.RotationAction_CancelBT) - } else { - if dk.sr.ffFirst { - dk.RotationSequence.Clear(). - NewAction(dk.RotationActionUH_IT_SetSync). - NewAction(dk.RotationActionCallback_GF). - NewAction(dk.RotationActionUH_BS) - } else { - dk.RotationSequence.Clear(). - NewAction(dk.RotationActionCallback_GF). - NewAction(dk.RotationActionUH_IT_SetSync). - NewAction(dk.RotationActionUH_BS) - } - } - - if dk.Rotation.UseDeathAndDecay || (!dk.Talents.ScourgeStrike && dk.Talents.Annihilation == 0) { - dk.RotationSequence.NewAction(dk.RotationActionUH_ResetToDndMain) - } else { - dk.RotationSequence.NewAction(dk.RotationActionUH_ResetToSsMain) - } -} - -func (dk *DpsDeathknight) uhRecastDiseasesSequence(_ *core.Simulation) { - dk.RotationSequence.Clear() - - // If we have glyph of Disease and both dots active try to refresh with pesti - didPesti := false - if dk.sr.hasGod { - if dk.FrostFeverSpell.Dot(dk.CurrentTarget).IsActive() && dk.BloodPlagueSpell.Dot(dk.CurrentTarget).IsActive() { - didPesti = true - dk.RotationSequence.NewAction(dk.RotationActionCallback_Pesti_Custom) - } - } - - // If we did not pesti queue normal dot refresh - if !didPesti { - if dk.sr.ffFirst { - dk.RotationSequence. - NewAction(dk.RotationActionUH_FF_ClipCheck). - NewAction(dk.RotationActionUH_IT_Custom). - NewAction(dk.RotationActionUH_BP_ClipCheck). - NewAction(dk.RotationActionUH_PS_Custom). - NewAction(dk.RotationActionUH_BS) - } else { - dk.RotationSequence. - NewAction(dk.RotationActionUH_BP_ClipCheck). - NewAction(dk.RotationActionUH_PS_Custom). - NewAction(dk.RotationActionUH_FF_ClipCheck). - NewAction(dk.RotationActionUH_IT_Custom). - NewAction(dk.RotationActionUH_BS) - } - } - - if dk.Rotation.UseDeathAndDecay || (!dk.Talents.ScourgeStrike && dk.Talents.Annihilation == 0) { - dk.RotationSequence.NewAction(dk.RotationActionUH_ResetToDndMain) - } else { - dk.RotationSequence.NewAction(dk.RotationActionUH_ResetToSsMain) - } -} - -func (dk *DpsDeathknight) RotationActionCallback_MindFreezeFiller(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - // Use Mind Freeze off GCD to proc extra effects in the opener - if dk.Talents.EndlessWinter == 2 && dk.SummonGargoyle.IsReady(sim) { - if dk.MindFreezeSpell.IsReady(sim) { - dk.MindFreezeSpell.Cast(sim, target) - } - } - s.Advance() - return sim.CurrentTime -} - -// Custom BS Callback -func (dk *DpsDeathknight) RotationActionUH_BS(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - if dk.CurrentBloodRunes()+dk.CurrentDeathRunes() == 0 { - s.Advance() - return sim.CurrentTime - } - - bloodPresenceSwitch := false - // Go back to Blood Presence after Gargoyle - if !dk.Rotation.PreNerfedGargoyle && !dk.SummonGargoyle.IsReady(sim) && dk.Rotation.Presence == proto.Deathknight_Rotation_Blood && dk.Rotation.GargoylePresence == proto.Deathknight_Rotation_Unholy && dk.PresenceMatches(deathknight.UnholyPresence) && !dk.SummonGargoyleAura.IsActive() { - bloodPresenceSwitch = true - } - - // Do not switch presences if gargoyle is still up if it's nerfed gargoyle - if !dk.Rotation.PreNerfedGargoyle && !dk.SummonGargoyleAura.IsActive() { - // Go back to Blood Presence after Bloodlust - if dk.Rotation.Presence == proto.Deathknight_Rotation_Blood && dk.Rotation.BlPresence == proto.Deathknight_Rotation_Unholy && dk.PresenceMatches(deathknight.UnholyPresence) && !dk.HasActiveAuraWithTag("Bloodlust") { - bloodPresenceSwitch = true - } - - // Go back to Blood Presence after gargoyle cast - if dk.Rotation.BlPresence == proto.Deathknight_Rotation_Blood && dk.PresenceMatches(deathknight.UnholyPresence) && !dk.SummonGargoyle.IsReady(sim) && dk.HasActiveAuraWithTag("Bloodlust") { - bloodPresenceSwitch = true - } - } - - if bloodPresenceSwitch { - if dk.BloodTapAura.IsActive() { - dk.BloodTapAura.Deactivate(sim) - } - dk.BloodPresence.Cast(sim, target) - s.Advance() - return sim.CurrentTime - } - - if dk.shShouldSpreadDisease(sim) { - casted := dk.uhSpreadDiseases(sim, target, s) - advance := dk.LastOutcome.Matches(core.OutcomeLanded) - s.ConditionalAdvance(casted && advance) - } else { - bloodSpell := dk.BloodBoil - prioBs := dk.unholyMightRotationChecks(sim) - if dk.desolationAuraCheck(sim) || prioBs { - bloodSpell = dk.BloodStrike - } - casted := bloodSpell.Cast(sim, target) - advance := dk.LastOutcome.Matches(core.OutcomeLanded) - s.ConditionalAdvance(casted && advance) - } - - return -1 -} - -// Custom SS Callback for when we have virulence sigil -func (dk *DpsDeathknight) RotationActionUH_SS_Sigil(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - if dk.HasActiveAura("Sigil of Virulence Proc") || !dk.Rotation.UseEmpowerRuneWeapon { - dk.RotationSequence.Clear() - if dk.Rotation.UseDeathAndDecay || (!dk.Talents.ScourgeStrike && dk.Talents.Annihilation == 0) { - dk.RotationSequence.NewAction(dk.RotationActionUH_ResetToDndMain) - } else { - dk.RotationSequence.NewAction(dk.RotationActionUH_ResetToSsMain) - } - return sim.CurrentTime - } - - if dk.EmpowerRuneWeapon.IsReady(sim) { - dk.EmpowerRuneWeapon.Cast(sim, target) - } - - casted := dk.uhCastVirulenceStrike(sim, target) - advance := dk.LastOutcome.Matches(core.OutcomeLanded) - - s.ConditionalAdvance(casted && advance) - return -1 -} - -func (dk *DpsDeathknight) RotationActionCallback_Pesti_Custom(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - // If we have both dots active try to refresh with pesti and move to normal rotation - if dk.FrostFeverSpell.Dot(dk.CurrentTarget).IsActive() && dk.BloodPlagueSpell.Dot(dk.CurrentTarget).IsActive() { - dk.Pestilence.Cast(sim, target) - s.Advance() - - return -1 - } else { - // If a disease has dropped do normal reapply - dk.RotationSequence.Clear() - - if dk.sr.ffFirst { - dk.RotationSequence. - NewAction(dk.RotationActionUH_FF_ClipCheck). - NewAction(dk.RotationActionUH_IT_Custom). - NewAction(dk.RotationActionUH_BP_ClipCheck). - NewAction(dk.RotationActionUH_PS_Custom). - NewAction(dk.RotationActionUH_BS) - } else { - dk.RotationSequence. - NewAction(dk.RotationActionUH_BP_ClipCheck). - NewAction(dk.RotationActionUH_PS_Custom). - NewAction(dk.RotationActionUH_FF_ClipCheck). - NewAction(dk.RotationActionUH_IT_Custom). - NewAction(dk.RotationActionUH_BS) - } - return sim.CurrentTime - } -} - -func (dk *DpsDeathknight) RotationActionUH_ResetToSsMain(sim *core.Simulation, _ *core.Unit, _ *deathknight.Sequence) time.Duration { - dk.RotationSequence.Clear(). - NewAction(dk.RotationActionCallback_UnholySsRotation) - return sim.CurrentTime -} - -func (dk *DpsDeathknight) RotationActionUH_ResetToDndMain(sim *core.Simulation, _ *core.Unit, _ *deathknight.Sequence) time.Duration { - dk.RotationSequence.Clear(). - NewAction(dk.RotationActionCallback_UnholyDndRotation) - return sim.CurrentTime -} - -// Custom PS callback for tracking recasts for pestilence disease sync -func (dk *DpsDeathknight) RotationActionUH_PS_Custom(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - if dk.uhGargoyleCheck(sim, target, dk.SpellGCD()+50*time.Millisecond) { - dk.uhAfterGargoyleSequence(sim) - return sim.CurrentTime - } - casted := dk.PlagueStrike.Cast(sim, target) - advance := dk.LastOutcome.Matches(core.OutcomeLanded) - - dk.sr.recastedBP = casted && advance - s.ConditionalAdvance(casted && advance) - return -1 -} - -// Custom IT callback for tracking recasts for pestilence disease sync -func (dk *DpsDeathknight) RotationActionUH_IT_Custom(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - if dk.uhGargoyleCheck(sim, target, dk.SpellGCD()+50*time.Millisecond) { - dk.uhAfterGargoyleSequence(sim) - return sim.CurrentTime - } - casted := dk.IcyTouch.Cast(sim, target) - advance := dk.LastOutcome.Matches(core.OutcomeLanded) - if casted && advance { - dk.sr.recastedFF = true - dk.ur.syncTimeFF = 0 - } - s.ConditionalAdvance(casted && advance) - return -1 -} - -// Custom IT callback for ghoul frenzy frost rune sync -func (dk *DpsDeathknight) RotationActionUH_IT_SetSync(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - ffRemaining := dk.FrostFeverSpell.Dot(target).RemainingDuration(sim) - dk.RotationActionCallback_IT(sim, target, s) - advance := dk.LastOutcome.Matches(core.OutcomeLanded) - if !dk.GCD.IsReady(sim) && advance { - dk.ur.syncTimeFF = dk.FrostFeverSpell.Dot(target).Duration - ffRemaining - } - - return -1 -} - -func (dk *DpsDeathknight) RotationActionUH_FF_ClipCheck(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - dot := dk.FrostFeverSpell.Dot(target) - gracePeriod := dk.FrostRuneGraceRemaining(sim) - return dk.RotationActionUH_DiseaseClipCheck(dot, gracePeriod, sim, target, s) -} - -func (dk *DpsDeathknight) RotationActionUH_BP_ClipCheck(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - dot := dk.BloodPlagueSpell.Dot(target) - gracePeriod := dk.UnholyRuneGraceRemaining(sim) - return dk.RotationActionUH_DiseaseClipCheck(dot, gracePeriod, sim, target, s) -} - -// Check if we have enough rune grace period to delay the disease cast -// so we get more ticks without losing on rune cd -func (dk *DpsDeathknight) RotationActionUH_DiseaseClipCheck(dot *core.Dot, gracePeriod time.Duration, sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - // TODO: Play around with allowing rune cd to be wasted - // for more disease ticks and see if its a worth option for the ui - //runeCdWaste := 0 * time.Millisecond - waitTime := sim.CurrentTime - if dot.TickCount < dot.NumberOfTicks-1 { - nextTickAt := dot.ExpiresAt() - dot.TickLength*time.Duration((dot.NumberOfTicks-1)-dot.TickCount) - if nextTickAt > sim.CurrentTime && (nextTickAt < sim.CurrentTime+gracePeriod || nextTickAt < sim.CurrentTime+400*time.Millisecond) { - // Delay disease for next tick - dk.LastOutcome = core.OutcomeMiss - - if dk.uhGargoyleCheck(sim, target, nextTickAt-sim.CurrentTime+50*time.Millisecond) { - dk.uhAfterGargoyleSequence(sim) - return waitTime - } - - waitTime = nextTickAt + 50*time.Millisecond - } else { - waitTime = sim.CurrentTime - } - } else { - waitTime = sim.CurrentTime - } - - s.Advance() - return waitTime -} diff --git a/sim/deathknight/dps/rotation_unholy_helper.go b/sim/deathknight/dps/rotation_unholy_helper.go deleted file mode 100644 index e02f8015b1..0000000000 --- a/sim/deathknight/dps/rotation_unholy_helper.go +++ /dev/null @@ -1,457 +0,0 @@ -package dps - -import ( - "math" - "time" - - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/core/proto" - "github.com/wowsims/wotlk/sim/deathknight" -) - -type WeaponSwapType int32 - -const ( - WeaponSwap_None WeaponSwapType = iota - WeaponSwap_BlackMagic - WeaponSwap_Berserking - WeaponSwap_FallenCrusader -) - -type SigilType int32 - -const ( - Sigil_Other SigilType = iota - Sigil_Virulence - Sigil_HangedMan -) - -type UnholyRotation struct { - dk *DpsDeathknight - - syncTimeFF time.Duration - - gargoyleSnapshot *core.SnapshotManager - activatingGargoyle bool - gargoyleMaxDelay time.Duration - gargoyleMinTime time.Duration - - mhSwap WeaponSwapType - mhSwapped bool - - ohSwap WeaponSwapType - ohSwapped bool - - bmIcd time.Duration - - sigil SigilType - unholyMight bool - - virulenceAura *core.Aura - unholyMightAura *core.Aura - blackMagicProc *core.Aura - fallenCrusaderProc *core.Aura - berserkingMh *core.Aura - berserkingOh *core.Aura -} - -func (ur *UnholyRotation) Reset(_ *core.Simulation) { - ur.syncTimeFF = 0 - ur.activatingGargoyle = false - ur.gargoyleMaxDelay = -1 - - ur.mhSwapped = false - ur.ohSwapped = false - ur.bmIcd = -1 - - if ur.dk.Talents.SummonGargoyle { - gargMcd := ur.dk.getMajorCooldown(ur.dk.SummonGargoyle.ActionID) - if gargMcd != nil { - timings := gargMcd.GetTimings() - if len(timings) > 0 { - ur.gargoyleMinTime = timings[0] - } - } - - ur.gargoyleSnapshot.ResetProcTrackers() - } -} - -func (ur *UnholyRotation) Initialize(dk *DpsDeathknight) { - dk.ur.gargoyleSnapshot = core.NewSnapshotManager(dk.GetCharacter()) - dk.setupGargProcTrackers() - - if dk.Talents.SummonGargoyle && dk.Rotation.UseGargoyle { - dk.setupWeaponSwap() - ur.blackMagicProc = dk.GetAura("Black Magic Proc") - ur.fallenCrusaderProc = dk.GetAura("Rune Of The Fallen Crusader Proc") - ur.berserkingMh = dk.GetAura("Berserking MH Proc") - ur.berserkingOh = dk.GetAura("Berserking OH Proc") - } - - // Init Sigil of Virulence Rotation - if dk.Ranged().ID == 47673 { - ur.sigil = Sigil_Virulence - ur.virulenceAura = dk.GetAura("Sigil of Virulence Proc") - } - - // Init T9 2P Proc - if dk.HasSetBonus(deathknight.ItemSetThassariansBattlegear, 2) { - ur.unholyMight = true - ur.unholyMightAura = dk.GetAura("Unholy Might Proc") - } -} - -func (dk *DpsDeathknight) getFirstDiseaseAction() deathknight.RotationAction { - if dk.sr.ffFirst { - return dk.RotationActionCallback_IT - } - return dk.RotationActionCallback_PS -} - -func (dk *DpsDeathknight) getSecondDiseaseAction() deathknight.RotationAction { - if dk.sr.ffFirst { - return dk.RotationActionCallback_PS - } - return dk.RotationActionCallback_IT -} - -func (dk *DpsDeathknight) uhBloodRuneAction(isFirst bool) deathknight.RotationAction { - if isFirst { - if dk.Env.GetNumTargets() > 1 { - return dk.RotationActionCallback_Pesti - } else { - return dk.RotationActionCallback_BS - } - } else { - return dk.RotationActionCallback_BS - } -} - -func (dk *DpsDeathknight) uhCastVirulenceStrike(sim *core.Simulation, target *core.Unit) bool { - if dk.Talents.ScourgeStrike { - return dk.ScourgeStrike.Cast(sim, target) - } else { - return dk.DeathStrike.Cast(sim, target) - } -} - -func (dk *DpsDeathknight) uhVirulenceRotationCheck(sim *core.Simulation, gargCheck bool) bool { - // If we have sigil of virulence - // Higher prio SS then Dnd when gargoyle is ready - virulenceRefresh := math.Max(0, 10-dk.Inputs.VirulenceRefresh) - waitTime := time.Duration(virulenceRefresh) * time.Second - prioVirulenceStrike := false - if dk.ur.sigil == Sigil_Virulence && (!gargCheck || (dk.SummonGargoyle.IsReady(sim) || dk.SummonGargoyle.CD.TimeToReady(sim) < 10*time.Second)) { - prioVirulenceStrike = !dk.ur.virulenceAura.IsActive() || dk.ur.virulenceAura.RemainingDuration(sim) <= waitTime - } - return prioVirulenceStrike -} - -func (dk *DpsDeathknight) unholyMightRotationChecks(sim *core.Simulation) bool { - // If we have T9 2P we prio BS over BB for refreshing the buff when out of ICD - prioBs := false - if dk.ur.unholyMight { - prioBs = dk.ur.unholyMightAura.StartedAt() == 0 || dk.ur.unholyMightAura.StartedAt() < sim.CurrentTime-45*time.Second - } - return prioBs -} - -func (dk *DpsDeathknight) weaponSwapCheck(sim *core.Simulation) bool { - if !dk.ItemSwap.IsEnabled() { - return false - } - - // Swap if gargoyle will still be on CD for full ICD or if gargoyle is already active - shouldSwapBm := dk.ur.bmIcd < sim.CurrentTime && (dk.SummonGargoyle.CD.TimeToReady(sim) > 45*time.Second || dk.SummonGargoyleAura.IsActive()) - shouldSwapBackFromBm := dk.ur.blackMagicProc.IsActive() // || dk.GetAura("Rune Of The Fallen Crusader Proc").RemainingDuration(sim) < 5*time.Second - - if dk.ur.mhSwap == WeaponSwap_BlackMagic { - if !dk.ur.mhSwapped && shouldSwapBm { - // Swap to BM - dk.ItemSwap.SwapItems(sim, []proto.ItemSlot{proto.ItemSlot_ItemSlotMainHand}) - dk.ur.mhSwapped = true - } else if dk.ur.mhSwapped && shouldSwapBackFromBm { - // Swap to Normal set and set BM Icd tracker - dk.ur.bmIcd = dk.ur.blackMagicProc.ExpiresAt() + 35*time.Second - dk.ur.mhSwapped = false - dk.ItemSwap.SwapItems(sim, []proto.ItemSlot{proto.ItemSlot_ItemSlotMainHand}) - } - } - - if dk.ur.ohSwap == WeaponSwap_BlackMagic { - if !dk.ur.ohSwapped && shouldSwapBm { - // Swap to BM - dk.ItemSwap.SwapItems(sim, []proto.ItemSlot{proto.ItemSlot_ItemSlotOffHand}) - dk.ur.ohSwapped = true - } else if dk.ur.ohSwapped && shouldSwapBackFromBm { - // Swap to Normal set and set BM Icd tracker - dk.ur.bmIcd = dk.ur.blackMagicProc.ExpiresAt() + 35*time.Second - dk.ur.ohSwapped = false - dk.ItemSwap.SwapItems(sim, []proto.ItemSlot{proto.ItemSlot_ItemSlotOffHand}) - } - } - - shouldSwapBerserking := dk.ur.fallenCrusaderProc.IsActive() && - dk.ur.fallenCrusaderProc.RemainingDuration(sim) > time.Second*10 - - shouldSwapBackfromBerserking := false //dk.GetAura("Rune Of The Fallen Crusader Proc").RemainingDuration(sim) < 5*time.Second - - if dk.ur.mhSwap == WeaponSwap_Berserking { - if !dk.ur.mhSwapped && !dk.ur.berserkingMh.IsActive() && shouldSwapBerserking { - // Swap to Berserking - dk.ItemSwap.SwapItems(sim, []proto.ItemSlot{proto.ItemSlot_ItemSlotMainHand}) - dk.ur.mhSwapped = true - } else if dk.ur.mhSwapped && (dk.ur.berserkingMh.IsActive() || shouldSwapBackfromBerserking) { - // Swap to Normal set - dk.ur.mhSwapped = false - dk.ItemSwap.SwapItems(sim, []proto.ItemSlot{proto.ItemSlot_ItemSlotMainHand}) - } - } - - if dk.ur.ohSwap == WeaponSwap_Berserking { - if !dk.ur.ohSwapped && !dk.ur.berserkingOh.IsActive() && shouldSwapBerserking { - // Swap to Berserking - dk.ItemSwap.SwapItems(sim, []proto.ItemSlot{proto.ItemSlot_ItemSlotOffHand}) - dk.ur.ohSwapped = true - } else if dk.ur.ohSwapped && (dk.ur.berserkingOh.IsActive() || shouldSwapBackfromBerserking) { - // Swap to Normal set - dk.ur.ohSwapped = false - dk.ItemSwap.SwapItems(sim, []proto.ItemSlot{proto.ItemSlot_ItemSlotOffHand}) - } - } - - return false -} - -func (dk *DpsDeathknight) desolationAuraCheck(sim *core.Simulation) bool { - return !dk.DesolationAura.IsActive() || dk.DesolationAura.RemainingDuration(sim) < 10*time.Second || - dk.Rotation.BloodRuneFiller == proto.Deathknight_Rotation_BloodStrike -} - -func (dk *DpsDeathknight) uhDiseaseCheck(sim *core.Simulation, target *core.Unit, spell *core.Spell, costRunes bool, casts int) bool { - return dk.shDiseaseCheck(sim, target, spell, costRunes, casts, 0) -} - -func (dk *DpsDeathknight) uhSpreadDiseases(sim *core.Simulation, target *core.Unit, _ *deathknight.Sequence) bool { - if dk.uhDiseaseCheck(sim, target, dk.Pestilence, true, 1) { - casted := dk.Pestilence.Cast(sim, target) - landed := dk.LastOutcome.Matches(core.OutcomeLanded) - - // Reset flags on successful cast - dk.sr.recastedFF = !(casted && landed) - dk.sr.recastedBP = !(casted && landed) - return casted - } else { - dk.uhRecastDiseasesSequence(sim) - return true - } -} - -// Simpler but somehow more effective for overall dps dnd check -func (dk *DpsDeathknight) uhShouldWaitForDnD(sim *core.Simulation, blood bool, frost bool, unholy bool) bool { - if dk.Talents.ImprovedUnholyPresence > 0 { - return dk.DeathAndDecay.IsReady(sim) || ((!blood || dk.CurrentBloodRunes() > 1) && (!frost || dk.CurrentFrostRunes() > 1) && (!unholy || dk.CurrentUnholyRunes() > 1)) - } else { - return !(!(dk.DeathAndDecay.CD.IsReady(sim) || dk.DeathAndDecay.CD.TimeToReady(sim) <= 4*time.Second) || ((!blood || dk.CurrentBloodRunes() > 1) && (!frost || dk.CurrentFrostRunes() > 1) && (!unholy || dk.CurrentUnholyRunes() > 1))) - } -} - -func (dk *DpsDeathknight) uhGhoulFrenzyCheck(sim *core.Simulation, target *core.Unit) bool { - if !dk.Ghoul.Pet.IsEnabled() { - return false - } - - // If no Ghoul Frenzy Aura or duration less then 10 seconds we try recasting - if !dk.GhoulFrenzyAura.IsActive() || dk.GhoulFrenzyAura.RemainingDuration(sim) < 10*time.Second { - // Use Ghoul Frenzy with a Blood Tap and Blood rune if all blood runes are on CD and Garg wont come off cd in less then a minute. - if (dk.Rotation.BloodTap == proto.Deathknight_Rotation_GhoulFrenzy || dk.Rotation.BtGhoulFrenzy) && dk.BloodTap.CanCast(sim, nil) && dk.GhoulFrenzy.IsReady(sim) && dk.CurrentBloodRunes() == 0 && dk.CurrentUnholyRunes() == 0 { - if dk.uhDiseaseCheck(sim, target, dk.GhoulFrenzy, true, 1) { - dk.uhGhoulFrenzySequence(sim, true) - return true - } else { - dk.uhRecastDiseasesSequence(sim) - return true - } - } else if !dk.Rotation.BtGhoulFrenzy && dk.GhoulFrenzy.CanCast(sim, nil) && dk.IcyTouch.CanCast(sim, nil) { - if dk.uhGargoyleCheck(sim, target, dk.SpellGCD()*2+50*time.Millisecond) { - dk.uhAfterGargoyleSequence(sim) - return true - } - // Use Ghoul Frenzy with an Unholy Rune and sync the frost rune with Icy Touch - if dk.uhDiseaseCheck(sim, target, dk.GhoulFrenzy, true, 5) && dk.uhDiseaseCheck(sim, target, dk.IcyTouch, true, 5) { - // TODO: This can spend runes that should be spent on DnD fix it! - dk.uhGhoulFrenzySequence(sim, false) - return true - } else { - dk.uhRecastDiseasesSequence(sim) - return true - } - } - } - return false -} - -func (dk *DpsDeathknight) uhBloodTap(sim *core.Simulation, target *core.Unit) bool { - if !dk.GCD.IsReady(sim) { - return false - } - - if dk.Rotation.BloodTap != proto.Deathknight_Rotation_GhoulFrenzy && dk.BloodTap.IsReady(sim) && dk.CurrentBloodRunes() == 0 { - switch dk.Rotation.BloodTap { - case proto.Deathknight_Rotation_IcyTouch: - if dk.CurrentFrostRunes() == 0 { - dk.BloodTap.Cast(sim, dk.CurrentTarget) - dk.IcyTouch.Cast(sim, target) - return true - } - case proto.Deathknight_Rotation_BloodStrikeBT: - dk.BloodTap.Cast(sim, dk.CurrentTarget) - dk.BloodStrike.Cast(sim, target) - return true - case proto.Deathknight_Rotation_BloodBoilBT: - dk.BloodTap.Cast(sim, dk.CurrentTarget) - dk.BloodBoil.Cast(sim, target) - return true - } - } - - return false -} - -func (dk *DpsDeathknight) uhEmpoweredRuneWeapon(sim *core.Simulation, target *core.Unit) bool { - if !dk.Rotation.UseEmpowerRuneWeapon { - return false - } - - if !dk.EmpowerRuneWeapon.IsReady(sim) { - return false - } - - // Save ERW for best Army Snapshot after Garg - if dk.Inputs.ArmyOfTheDeadType == proto.Deathknight_Rotation_AsMajorCd && dk.Rotation.HoldErwArmy && dk.ArmyOfTheDead.IsReady(sim) { - return false - } - - if !dk.AllRunesSpent() { - return false - } - - timeToNextRune := dk.AnyRuneReadyAt(sim) - sim.CurrentTime - if timeToNextRune < 2*time.Second { - return false - } - - dk.EmpowerRuneWeapon.Cast(sim, target) - return true -} - -func (dk *DpsDeathknight) uhMindFreeze(sim *core.Simulation, target *core.Unit) bool { - if dk.Talents.EndlessWinter == 2 && dk.SummonGargoyle.IsReady(sim) { - if dk.MindFreezeSpell.IsReady(sim) { - dk.MindFreezeSpell.Cast(sim, target) - return true - } - } - return false -} - -// Save up Runic Power for Summon Gargoyle - Allow casts above 100 rp or garg CD > 5 sec -func (dk *DpsDeathknight) uhDeathCoilCheck(sim *core.Simulation) bool { - return !dk.Talents.SummonGargoyle || !(dk.SummonGargoyle.IsReady(sim) || dk.SummonGargoyle.CD.TimeToReady(sim) < 5*time.Second) || sim.CurrentTime < dk.ur.gargoyleMinTime-5*time.Second || dk.CurrentRunicPower() >= 100 || !dk.Rotation.UseGargoyle -} - -// Combined checks for casting gargoyle sequence & going back to blood presence after -func (dk *DpsDeathknight) uhGargoyleCheck(sim *core.Simulation, target *core.Unit, castTime time.Duration) bool { - if !dk.Rotation.UseGargoyle { - return false - } - - if dk.uhGargoyleCanCast(sim, castTime) { - if !dk.PresenceMatches(deathknight.UnholyPresence) && (dk.Rotation.PreNerfedGargoyle || dk.Rotation.GargoylePresence == proto.Deathknight_Rotation_Unholy) { - if dk.CurrentUnholyRunes() == 0 { - if dk.BloodTap.IsReady(sim) { - dk.BloodTap.Cast(sim, dk.CurrentTarget) - } else { - return false - } - } - dk.UnholyPresence.Cast(sim, dk.CurrentTarget) - } - - dk.ur.activatingGargoyle = true - dk.OnGargoyleStartFirstCast = func() { - dk.ur.gargoyleSnapshot.ActivateMajorCooldowns(sim) - dk.UpdateMajorCooldowns() - } - dk.ur.gargoyleSnapshot.ActivateMajorCooldowns(sim) - dk.UpdateMajorCooldowns() - dk.ur.activatingGargoyle = false - - if dk.SummonGargoyle.Cast(sim, target) { - dk.UpdateMajorCooldowns() - dk.ur.gargoyleSnapshot.ResetProcTrackers() - dk.ur.gargoyleMaxDelay = -1 - return true - } - } - - // Go back to Unholy Presence after Gargoyle - if !dk.Rotation.PreNerfedGargoyle && !dk.SummonGargoyle.IsReady(sim) && dk.Rotation.Presence == proto.Deathknight_Rotation_Unholy && dk.Rotation.GargoylePresence == proto.Deathknight_Rotation_Blood && dk.PresenceMatches(deathknight.BloodPresence) && !dk.SummonGargoyleAura.IsActive() { - if dk.BloodTapAura.IsActive() { - dk.BloodTapAura.Deactivate(sim) - } - return dk.UnholyPresence.Cast(sim, target) - } - - // Do not switch presences if gargoyle is still up if it's nerfed gargoyle - if !dk.Rotation.PreNerfedGargoyle && dk.SummonGargoyleAura.IsActive() { - return false - } - - // Go back to Unholy Presence after Bloodlust - if dk.Rotation.Presence == proto.Deathknight_Rotation_Unholy && dk.Rotation.BlPresence == proto.Deathknight_Rotation_Blood && dk.PresenceMatches(deathknight.BloodPresence) && !dk.HasActiveAuraWithTag("Bloodlust") { - if dk.BloodTapAura.IsActive() { - dk.BloodTapAura.Deactivate(sim) - } - return dk.UnholyPresence.Cast(sim, target) - } - return false -} - -func (dk *DpsDeathknight) uhGargoyleCanCast(sim *core.Simulation, castTime time.Duration) bool { - if !dk.SummonGargoyle.IsReady(sim) { - return false - } - if sim.CurrentTime < dk.ur.gargoyleMinTime { - return false - } - if dk.CurrentRunicPower() < 60 { - return false - } - // Setup max delay possible - if dk.ur.gargoyleMaxDelay == -1 { - gargCd := dk.SummonGargoyle.CD.Duration - timeLeft := sim.GetRemainingDuration() - for timeLeft > gargCd { - timeLeft = timeLeft - (gargCd + 2*time.Second) - } - dk.ur.gargoyleMaxDelay = sim.CurrentTime + timeLeft - 2*time.Second - } - // Cast it if holding will result in less total Gargoyles for the encounter - if sim.CurrentTime > dk.ur.gargoyleMaxDelay { - return true - } - // Cast it if holding will take from its duration - if sim.GetRemainingDuration() < 32*time.Second { - return true - } - if !dk.PresenceMatches(deathknight.UnholyPresence) && (!dk.BloodTap.CanCast(sim, nil) && dk.CurrentUnholyRunes() == 0) { - return false - } - if !dk.ur.gargoyleSnapshot.CanSnapShot(sim, castTime) { - return false - } - - return true -} diff --git a/sim/deathknight/frost_strike.go b/sim/deathknight/frost_strike.go index 1cc195f576..be66fea405 100644 --- a/sim/deathknight/frost_strike.go +++ b/sim/deathknight/frost_strike.go @@ -63,7 +63,6 @@ func (dk *Deathknight) newFrostStrikeHitSpell(isMH bool) *core.Spell { if isMH { spell.SpendRefundableCost(sim, result) - dk.LastOutcome = result.Outcome dk.threatOfThassarianProc(sim, result, dk.FrostStrikeOhHit) } diff --git a/sim/deathknight/ghoul_frenzy.go b/sim/deathknight/ghoul_frenzy.go index 3b65aa7bdc..7f58727694 100644 --- a/sim/deathknight/ghoul_frenzy.go +++ b/sim/deathknight/ghoul_frenzy.go @@ -65,24 +65,12 @@ func (dk *Deathknight) registerGhoulFrenzySpell() { ActionID: core.ActionID{SpellID: 63560}, Label: "Ghoul Frenzy", Duration: time.Second * 30.0, - OnReset: func(aura *core.Aura, sim *core.Simulation) { - if !dk.IsUsingAPL && dk.Inputs.PrecastGhoulFrenzy { - dk.GhoulFrenzyAura.Activate(sim) - dk.GhoulFrenzyAura.UpdateExpires(sim.CurrentTime + time.Second*20) - } - }, }) dk.Ghoul.GhoulFrenzyAura = dk.Ghoul.RegisterAura(core.Aura{ ActionID: core.ActionID{SpellID: 63560}, Label: "Ghoul Frenzy", Duration: time.Second * 30.0, - OnReset: func(aura *core.Aura, sim *core.Simulation) { - if !dk.IsUsingAPL && dk.Inputs.PrecastGhoulFrenzy { - dk.Ghoul.GhoulFrenzyAura.Activate(sim) - dk.Ghoul.GhoulFrenzyAura.UpdateExpires(sim.CurrentTime + time.Second*20) - } - }, OnGain: func(aura *core.Aura, sim *core.Simulation) { dk.Ghoul.MultiplyMeleeSpeed(sim, 1.25) }, diff --git a/sim/deathknight/heart_strike.go b/sim/deathknight/heart_strike.go index 28ea32f67e..1fa9ebf983 100644 --- a/sim/deathknight/heart_strike.go +++ b/sim/deathknight/heart_strike.go @@ -65,7 +65,6 @@ func (dk *Deathknight) newHeartStrikeSpell(isMainTarget bool, isDrw bool) *core. if dk.Env.GetNumTargets() > 1 { dk.HeartStrikeOffHit.Cast(sim, dk.Env.NextTargetUnit(target)) } - dk.LastOutcome = result.Outcome } } }, diff --git a/sim/deathknight/horn_of_winter.go b/sim/deathknight/horn_of_winter.go index 7cea15ace5..8554b8a488 100644 --- a/sim/deathknight/horn_of_winter.go +++ b/sim/deathknight/horn_of_winter.go @@ -20,11 +20,6 @@ func (dk *Deathknight) registerHornOfWinterSpell() { Label: "Horn of Winter", ActionID: actionID, Duration: duration, - OnReset: func(aura *core.Aura, sim *core.Simulation) { - if !dk.IsUsingAPL && dk.Inputs.PrecastHornOfWinter && dk.Inputs.RefreshHornOfWinter { - aura.Activate(sim) - } - }, OnGain: func(aura *core.Aura, sim *core.Simulation) { if !dk.OtherRelevantStrAgiActive { dk.HornOfWinterAura.Unit.AddStatsDynamic(sim, bonusStats) @@ -52,9 +47,6 @@ func (dk *Deathknight) registerHornOfWinterSpell() { IgnoreHaste: true, }, ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - if !dk.IsUsingAPL && dk.Inputs.RefreshHornOfWinter { - dk.HornOfWinterAura.Activate(sim) - } dk.AddRunicPower(sim, 10, rpMetrics) }, }) diff --git a/sim/deathknight/howling_blast.go b/sim/deathknight/howling_blast.go index 1662402f29..eb35f49173 100644 --- a/sim/deathknight/howling_blast.go +++ b/sim/deathknight/howling_blast.go @@ -44,8 +44,6 @@ func (dk *Deathknight) registerHowlingBlastSpell() { ThreatMultiplier: 1, ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - dk.AoESpellNumTargetsHit = 0 - for _, aoeTarget := range sim.Encounter.TargetUnits { baseDamage := (sim.Roll(518, 562) + 0.2*dk.getImpurityBonus(spell)) * dk.glacielRotBonus(aoeTarget) * @@ -55,13 +53,8 @@ func (dk *Deathknight) registerHowlingBlastSpell() { result := spell.CalcDamage(sim, aoeTarget, baseDamage, spell.OutcomeMagicHitAndCrit) - if result.Landed() { - dk.AoESpellNumTargetsHit++ - } - if aoeTarget == target { spell.SpendRefundableCost(sim, result) - dk.LastOutcome = result.Outcome } if rpBonus > 0 && result.Landed() { dk.AddRunicPower(sim, rpBonus, spell.RunicPowerMetrics()) diff --git a/sim/deathknight/icy_touch.go b/sim/deathknight/icy_touch.go index b450cf7c62..e622ee282b 100644 --- a/sim/deathknight/icy_touch.go +++ b/sim/deathknight/icy_touch.go @@ -40,7 +40,6 @@ func (dk *Deathknight) registerIcyTouchSpell() { result := spell.CalcDamage(sim, target, baseDamage, spell.OutcomeMagicHitAndCrit) spell.SpendRefundableCost(sim, result) - dk.LastOutcome = result.Outcome if result.Landed() { dk.FrostFeverExtended[target.Index] = 0 dk.FrostFeverSpell.Cast(sim, target) diff --git a/sim/deathknight/items.go b/sim/deathknight/items.go index 0bdc00211e..9bddfbaea6 100644 --- a/sim/deathknight/items.go +++ b/sim/deathknight/items.go @@ -495,6 +495,8 @@ func (dk *Deathknight) registerItems() { IcyTouchActionID, } + targetsHit := 0 + dk.RegisterAura(core.Aura{ ActionID: core.ActionID{SpellID: 53386}, Label: "Cinderglacier", @@ -513,9 +515,15 @@ func (dk *Deathknight) registerItems() { }, OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { if spell.ActionID == HowlingBlastActionID || spell.ActionID == BloodBoilActionID { + if result.Target.Index == 0 { + targetsHit = 0 + } + if result.Landed() { + targetsHit++ + } if result.Target.Index == sim.GetNumTargets()-1 { // Last target, consume a stack for every target hit - for i := int32(0); i < dk.AoESpellNumTargetsHit; i++ { + for i := 0; i < targetsHit; i++ { if aura.IsActive() { aura.RemoveStack(sim) } @@ -524,7 +532,7 @@ func (dk *Deathknight) registerItems() { return } - if !result.Outcome.Matches(core.OutcomeLanded) { + if !result.Landed() { return } diff --git a/sim/deathknight/obliterate.go b/sim/deathknight/obliterate.go index a296c34e41..249e517bfc 100644 --- a/sim/deathknight/obliterate.go +++ b/sim/deathknight/obliterate.go @@ -63,7 +63,6 @@ func (dk *Deathknight) newObliterateHitSpell(isMH bool) *core.Spell { if isMH { spell.SpendRefundableCostAndConvertFrostOrUnholyRune(sim, result, deathConvertChance) - dk.LastOutcome = result.Outcome dk.threatOfThassarianProc(sim, result, dk.ObliterateOhHit) if sim.RandomFloat("Annihilation") < diseaseConsumptionChance { diff --git a/sim/deathknight/pestilence.go b/sim/deathknight/pestilence.go index 1cd2c962d3..f469766812 100644 --- a/sim/deathknight/pestilence.go +++ b/sim/deathknight/pestilence.go @@ -38,7 +38,6 @@ func (dk *Deathknight) registerPestilenceSpell() { if aoeTarget == target { spell.SpendRefundableCostAndConvertBloodRune(sim, result, deathConvertChance) - dk.LastOutcome = result.Outcome } if result.Landed() { refreshCFEP := false diff --git a/sim/deathknight/plague_strike.go b/sim/deathknight/plague_strike.go index 5695c3e7e3..d6635013c5 100644 --- a/sim/deathknight/plague_strike.go +++ b/sim/deathknight/plague_strike.go @@ -53,7 +53,6 @@ func (dk *Deathknight) newPlagueStrikeSpell(isMH bool) *core.Spell { if isMH { spell.SpendRefundableCost(sim, result) dk.threatOfThassarianProc(sim, result, dk.PlagueStrikeOhHit) - dk.LastOutcome = result.Outcome if result.Landed() { dk.BloodPlagueExtended[target.Index] = 0 dk.BloodPlagueSpell.Cast(sim, target) diff --git a/sim/deathknight/rotation.go b/sim/deathknight/rotation.go deleted file mode 100644 index 7937106d56..0000000000 --- a/sim/deathknight/rotation.go +++ /dev/null @@ -1,296 +0,0 @@ -package deathknight - -import ( - "time" - - "github.com/wowsims/wotlk/sim/core" -) - -func (dk *Deathknight) OnAutoAttack(_ *core.Simulation, _ *core.Spell) { -} - -func (dk *Deathknight) OnGCDReady(sim *core.Simulation) { - dk.tryUseGCD(sim) -} - -func (dk *Deathknight) tryUseGCD(sim *core.Simulation) { - dk.DoRotation(sim) -} - -func (dk *Deathknight) RotationActionCallback_IT(sim *core.Simulation, target *core.Unit, s *Sequence) time.Duration { - casted := dk.IcyTouch.Cast(sim, target) - advance := dk.LastOutcome.Matches(core.OutcomeLanded) - - s.ConditionalAdvance(casted && advance) - return -1 -} - -func (dk *Deathknight) RotationActionCallback_PS(sim *core.Simulation, target *core.Unit, s *Sequence) time.Duration { - casted := dk.PlagueStrike.Cast(sim, target) - advance := dk.LastOutcome.Matches(core.OutcomeLanded) - - s.ConditionalAdvance(casted && advance) - return -1 -} - -func (dk *Deathknight) RotationActionCallback_HW(sim *core.Simulation, target *core.Unit, s *Sequence) time.Duration { - dk.HornOfWinter.Cast(sim, target) - - s.Advance() - return -1 -} - -func (dk *Deathknight) RotationActionCallback_DRW(sim *core.Simulation, target *core.Unit, s *Sequence) time.Duration { - casted := dk.DancingRuneWeapon.Cast(sim, target) - - s.ConditionalAdvance(casted) - return -1 -} - -func (dk *Deathknight) RotationActionCallback_UF(sim *core.Simulation, target *core.Unit, s *Sequence) time.Duration { - casted := dk.UnholyFrenzy.Cast(sim, target) - - s.ConditionalAdvance(casted) - return -1 -} - -func (dk *Deathknight) RotationActionCallback_DS(sim *core.Simulation, target *core.Unit, s *Sequence) time.Duration { - casted := dk.DeathStrike.Cast(sim, target) - advance := dk.LastOutcome.Matches(core.OutcomeLanded) - - s.ConditionalAdvance(casted && advance) - return -1 -} - -func (dk *Deathknight) RotationActionCallback_HS(sim *core.Simulation, target *core.Unit, s *Sequence) time.Duration { - casted := false - if dk.Talents.HeartStrike { - casted = dk.HeartStrike.Cast(sim, target) - } else { - casted = dk.BloodStrike.Cast(sim, target) - } - advance := dk.LastOutcome.Matches(core.OutcomeLanded) - - s.ConditionalAdvance(casted && advance) - return -1 -} - -func (dk *Deathknight) RotationActionCallback_BT(sim *core.Simulation, target *core.Unit, s *Sequence) time.Duration { - casted := dk.BloodTap.Cast(sim, target) - s.ConditionalAdvance(casted) - return sim.CurrentTime -} - -func (dk *Deathknight) RotationActionCallback_ERW(sim *core.Simulation, target *core.Unit, s *Sequence) time.Duration { - casted := dk.EmpowerRuneWeapon.Cast(sim, target) - s.ConditionalAdvance(casted) - return sim.CurrentTime -} - -func (dk *Deathknight) RotationActionCallback_Obli(sim *core.Simulation, target *core.Unit, s *Sequence) time.Duration { - if dk.Deathchill != nil && dk.Deathchill.IsReady(sim) { - dk.Deathchill.Cast(sim, target) - } - casted := dk.Obliterate.Cast(sim, target) - advance := dk.LastOutcome.Matches(core.OutcomeLanded) - s.ConditionalAdvance(casted && advance) - return -1 -} - -func (dk *Deathknight) RotationActionCallback_FS(sim *core.Simulation, target *core.Unit, s *Sequence) time.Duration { - dk.FrostStrike.Cast(sim, target) - - s.Advance() - return -1 -} - -func (dk *Deathknight) RotationActionCallback_HB(sim *core.Simulation, target *core.Unit, s *Sequence) time.Duration { - dk.HowlingBlast.Cast(sim, target) - - s.Advance() - return -1 -} - -func (dk *Deathknight) RotationActionCallback_Pesti(sim *core.Simulation, target *core.Unit, s *Sequence) time.Duration { - casted := dk.Pestilence.Cast(sim, target) - advance := dk.LastOutcome.Matches(core.OutcomeLanded) - s.ConditionalAdvance(casted && advance) - return -1 -} - -func (dk *Deathknight) RotationActionCallback_BS(sim *core.Simulation, target *core.Unit, s *Sequence) time.Duration { - casted := dk.BloodStrike.Cast(sim, target) - advance := dk.LastOutcome.Matches(core.OutcomeLanded) - s.ConditionalAdvance(casted && advance) - return -1 -} - -func (dk *Deathknight) RotationActionCallback_BB(sim *core.Simulation, target *core.Unit, s *Sequence) time.Duration { - casted := dk.BloodBoil.Cast(sim, target) - advance := dk.LastOutcome.Matches(core.OutcomeLanded) - s.ConditionalAdvance(casted && advance) - return -1 -} - -func (dk *Deathknight) RotationActionCallback_SS(sim *core.Simulation, target *core.Unit, s *Sequence) time.Duration { - casted := dk.ScourgeStrike.Cast(sim, target) - advance := dk.LastOutcome.Matches(core.OutcomeLanded) - s.ConditionalAdvance(casted && advance) - return -1 -} - -func (dk *Deathknight) RotationActionCallback_DND(sim *core.Simulation, target *core.Unit, s *Sequence) time.Duration { - casted := dk.DeathAndDecay.Cast(sim, target) - s.ConditionalAdvance(casted) - return -1 -} - -func (dk *Deathknight) RotationActionCallback_GF(sim *core.Simulation, target *core.Unit, s *Sequence) time.Duration { - casted := dk.GhoulFrenzy.Cast(sim, target) - s.ConditionalAdvance(casted) - return -1 -} - -func (dk *Deathknight) RotationActionCallback_DC(sim *core.Simulation, target *core.Unit, s *Sequence) time.Duration { - dk.DeathCoil.Cast(sim, target) - s.Advance() - return -1 -} - -func (dk *Deathknight) RotationActionCallback_AOTD(sim *core.Simulation, target *core.Unit, s *Sequence) time.Duration { - casted := dk.ArmyOfTheDead.Cast(sim, target) - s.ConditionalAdvance(casted) - return -1 -} - -func (dk *Deathknight) RotationActionCallback_Garg(sim *core.Simulation, target *core.Unit, s *Sequence) time.Duration { - casted := dk.SummonGargoyle.Cast(sim, target) - s.ConditionalAdvance(casted) - return -1 -} - -func (dk *Deathknight) RotationActionCallback_BP(sim *core.Simulation, target *core.Unit, s *Sequence) time.Duration { - casted := dk.BloodPresence.Cast(sim, target) - - waitTime := time.Duration(-1) - if !casted && !dk.BloodPresence.IsReady(sim) { - if dk.BloodPresence.CD.ReadyAt() != sim.CurrentTime { - waitTime = dk.BloodPresence.CD.ReadyAt() - } - } - - s.ConditionalAdvance(casted) - return waitTime -} - -func (dk *Deathknight) RotationActionCallback_FP(sim *core.Simulation, target *core.Unit, s *Sequence) time.Duration { - casted := dk.FrostPresence.Cast(sim, target) - - waitTime := time.Duration(-1) - if !casted && !dk.FrostPresence.IsReady(sim) { - if dk.FrostPresence.CD.ReadyAt() != sim.CurrentTime { - waitTime = dk.FrostPresence.CD.ReadyAt() - } - } - s.ConditionalAdvance(casted) - return waitTime -} - -func (dk *Deathknight) RotationActionCallback_UP(sim *core.Simulation, target *core.Unit, s *Sequence) time.Duration { - casted := dk.UnholyPresence.Cast(sim, target) - - waitTime := time.Duration(-1) - if !casted && !dk.UnholyPresence.IsReady(sim) { - if dk.UnholyPresence.CD.ReadyAt() != sim.CurrentTime { - waitTime = dk.UnholyPresence.CD.ReadyAt() - } - } - s.ConditionalAdvance(casted) - return waitTime -} - -func (dk *Deathknight) RotationActionCallback_RD(sim *core.Simulation, target *core.Unit, s *Sequence) time.Duration { - if !dk.Talents.MasterOfGhouls { - dk.RaiseDead.Cast(sim, target) - } - - s.Advance() - return -1 -} - -func (s *Sequence) DoAction(sim *core.Simulation, target *core.Unit, _ *Deathknight) time.Duration { - action := s.actions[s.idx] - return action(sim, target, s) -} - -func (dk *Deathknight) Wait(sim *core.Simulation) { - waitUntil := sim.CurrentTime + time.Millisecond*200 - - anyRuneAt := dk.AnyRuneReadyAt(sim) - if anyRuneAt != sim.CurrentTime { - waitUntil = min(waitUntil, anyRuneAt) - } else { - waitUntil = min(waitUntil, dk.AnySpentRuneReadyAt()) - } - if sim.Log != nil { - dk.Log(sim, "DK Wait: %s, any at: %s, any spent at: %s", waitUntil, anyRuneAt, dk.AnySpentRuneReadyAt()) - } - - if dk.ButcheryPA != nil { - waitUntil = min(dk.ButcheryPA.NextActionAt, waitUntil) - } - waitUntil = max(sim.CurrentTime, waitUntil) - - if !dk.Inputs.IsDps { - target := dk.CurrentTarget - if dk.IsMainTank() { - if targetSwingAt := target.AutoAttacks.NextAttackAt(); targetSwingAt > sim.CurrentTime { - waitUntil = min(waitUntil, targetSwingAt) - } - } - } - - dk.WaitUntil(sim, waitUntil) -} - -func (dk *Deathknight) IsMainTank() bool { - return dk.CurrentTarget.CurrentTarget == &dk.Unit -} - -func (dk *Deathknight) DoRotation(sim *core.Simulation) { - if dk.IsUsingAPL { - return - } - - target := dk.CurrentTarget - - optWait := time.Duration(-1) - if dk.RotationSequence.IsOngoing() { - if sim.Log != nil { - dk.Log(sim, "DoSequenceAction") - } - optWait = dk.RotationSequence.DoAction(sim, target, dk) - } - - if dk.GCD.IsReady(sim) { - if sim.Log != nil { - dk.Log(sim, "DoGCD") - } - for optWait == 0 && dk.GCD.IsReady(sim) { - if sim.Log != nil { - dk.Log(sim, "DoAction") - } - optWait = dk.RotationSequence.DoAction(sim, target, dk) - } - - if optWait != -1 { - if optWait < sim.CurrentTime { - dk.Wait(sim) - } else { - dk.WaitUntil(sim, optWait) - } - } else if dk.GCD.IsReady(sim) { - dk.Wait(sim) - } - } -} diff --git a/sim/deathknight/rotation_helper.go b/sim/deathknight/rotation_helper.go deleted file mode 100644 index f65e5d1003..0000000000 --- a/sim/deathknight/rotation_helper.go +++ /dev/null @@ -1,53 +0,0 @@ -package deathknight - -import ( - "time" - - "github.com/wowsims/wotlk/sim/core" -) - -// return bool is if its on GCD -// return duration is an optional wait time -type RotationAction func(sim *core.Simulation, target *core.Unit, s *Sequence) time.Duration - -// Add your UH rotation Actions here and then on the DoNext function - -type Sequence struct { - idx int - actions []RotationAction -} - -func (s *Sequence) IsOngoing() bool { - return s.idx < len(s.actions) -} - -func (s *Sequence) Advance() { - s.idx += 1 -} - -func (s *Sequence) ConditionalAdvance(condition bool) { - if condition { - s.idx += 1 - } -} - -func (s *Sequence) NewAction(action RotationAction) *Sequence { - s.actions = append(s.actions, action) - return s -} - -func (s *Sequence) Clear() *Sequence { - s.actions = s.actions[:0] - s.idx = 0 - return s -} - -type RotationHelper struct { - RotationSequence *Sequence - - LastOutcome core.HitOutcome - LastCast *core.Spell - NextCast *core.Spell - - AoESpellNumTargetsHit int32 -} diff --git a/sim/deathknight/scourge_strike.go b/sim/deathknight/scourge_strike.go index 4bec2961ca..ad72c18a5e 100644 --- a/sim/deathknight/scourge_strike.go +++ b/sim/deathknight/scourge_strike.go @@ -82,7 +82,6 @@ func (dk *Deathknight) registerScourgeStrikeSpell() { spell.SpendRefundableCost(sim, result) - dk.LastOutcome = result.Outcome if result.Landed() && dk.DiseasesAreActive(target) { dk.LastScourgeStrikeDamage = result.Damage shadowDamageSpell.Cast(sim, target) diff --git a/sim/deathknight/tank/openers.go b/sim/deathknight/tank/openers.go deleted file mode 100644 index 9496f9940b..0000000000 --- a/sim/deathknight/tank/openers.go +++ /dev/null @@ -1,130 +0,0 @@ -package tank - -import ( - "github.com/wowsims/wotlk/sim/core/proto" - "slices" - "time" - - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/deathknight" -) - -const threatOpenerCastsBeforeBloodTap = 2 -const normalOpenerCastsBeforeBloodTap = 3 - -func (dk *TankDeathknight) TankRA_BloodSpell(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - casted := dk.BloodSpell.Cast(sim, target) - advance := dk.LastOutcome.Matches(core.OutcomeLanded) - s.ConditionalAdvance(casted && advance) - return -1 -} - -func (dk *TankDeathknight) TankRA_FuSpell(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - casted := dk.FuSpell.Cast(sim, target) - advance := dk.LastOutcome.Matches(core.OutcomeLanded) - s.ConditionalAdvance(casted && advance) - return -1 -} - -func (dk *TankDeathknight) TankRA_IT(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - casted := dk.IcyTouch.Cast(sim, target) - if !casted && dk.Talents.UnbreakableArmor && !dk.UnbreakableArmor.IsReady(sim) { - s.Advance() - return -1 - } - advance := dk.LastOutcome.Matches(core.OutcomeLanded) - - s.ConditionalAdvance(casted && advance) - return -1 -} - -func shouldUseBloodTapInOpener(dk *TankDeathknight) bool { - bloodTapDefensiveCd := dk.GetMajorCooldown(dk.BloodTap.ActionID) - if bloodTapDefensiveCd != nil { - timings := bloodTapDefensiveCd.GetTimings() - slices.Sort(timings) - if len(timings) == 0 || - (len(timings) > 0 && timings[0] < - dk.BloodTap.CD.Duration+getPlannedOpenerBloodTapUsageTime(dk)) { - return false - } else { - return true - } - } - return true -} - -func getPlannedOpenerBloodTapUsageTime(dk *TankDeathknight) time.Duration { - if dk.Rotation.Opener == proto.TankDeathknight_Rotation_Threat { - return threatOpenerCastsBeforeBloodTap * core.GCDDefault - } - return normalOpenerCastsBeforeBloodTap * core.GCDDefault -} - -func (dk *TankDeathknight) setupTankRegularERWOpener() { - if shouldUseBloodTapInOpener(dk) { - dk.setupTankRegularERWOpenerWithBloodTap() - } else { - dk.setupTankRegularERWOpenerWithoutBloodTap() - } -} - -func (dk *TankDeathknight) setupTankRegularERWOpenerWithBloodTap() { - dk.RotationSequence. - NewAction(dk.TankRA_IT). - NewAction(dk.RotationActionCallback_PS). - NewAction(dk.TankRA_FuSpell). - NewAction(dk.RotationActionCallback_BT). - NewAction(dk.TankRA_IT). - NewAction(dk.TankRA_BloodSpell). - NewAction(dk.RotationActionCallback_ERW). - NewAction(dk.RotationActionCallback_Pesti). - NewAction(dk.TankRA_IT). - NewAction(dk.TankRA_IT). - NewAction(dk.TankRA_IT). - NewAction(dk.RotationActionCallback_RD). - NewAction(dk.TankRA_FuSpell) -} - -func (dk *TankDeathknight) setupTankRegularERWOpenerWithoutBloodTap() { - dk.RotationSequence. - NewAction(dk.TankRA_IT). - NewAction(dk.RotationActionCallback_PS). - NewAction(dk.TankRA_FuSpell). - NewAction(dk.TankRA_BloodSpell). - NewAction(dk.RotationActionCallback_ERW). - NewAction(dk.RotationActionCallback_Pesti). - NewAction(dk.TankRA_IT). - NewAction(dk.TankRA_IT). - NewAction(dk.TankRA_IT). - NewAction(dk.RotationActionCallback_RD). - NewAction(dk.TankRA_FuSpell) -} - -func (dk *TankDeathknight) setupTankThreatERWOpener() { - if shouldUseBloodTapInOpener(dk) { - dk.setupTankThreatERWOpenerWithBloodTap() - } else { - dk.setupTankThreatERWOpenerWithoutBloodTap() - } -} - -func (dk *TankDeathknight) setupTankThreatERWOpenerWithBloodTap() { - dk.RotationSequence. - NewAction(dk.TankRA_IT). - NewAction(dk.TankRA_IT). - NewAction(dk.RotationActionCallback_BT). - NewAction(dk.TankRA_IT). - NewAction(dk.RotationActionCallback_ERW). - NewAction(dk.TankRA_IT). - NewAction(dk.TankRA_IT). - NewAction(dk.TankRA_IT). - NewAction(dk.RotationActionCallback_PS). - NewAction(dk.TankRA_BloodSpell) -} - -// If maintaining GCD parity is desired, the threat opener without BT should cast DS with -// the GCD previously allocated to the Blood Tapped IT before using ERW -func (dk *TankDeathknight) setupTankThreatERWOpenerWithoutBloodTap() { - dk.setupTankRegularERWOpenerWithoutBloodTap() -} diff --git a/sim/deathknight/tank/rotation_hps.go b/sim/deathknight/tank/rotation_hps.go deleted file mode 100644 index 9aca447a84..0000000000 --- a/sim/deathknight/tank/rotation_hps.go +++ /dev/null @@ -1,46 +0,0 @@ -package tank - -import ( - "time" - - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/core/proto" - "github.com/wowsims/wotlk/sim/deathknight" -) - -func (dk *TankDeathknight) TankRA_Hps(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - if !dk.GCD.IsReady(sim) { - return dk.NextGCDAt() - } - - if dk.DoDiseaseChecks(sim, target, s) { - return -1 - } - - fd := dk.CurrentFrostRunes() + dk.CurrentDeathRunes() - ud := dk.CurrentUnholyRunes() + dk.CurrentDeathRunes() - - if fd > 0 && ud > 0 && dk.FuSpell.CanCast(sim, target) && (dk.CurrentHealthPercent() < 0.75 || dk.FuSpell == dk.Obliterate) { - dk.FuSpell.Cast(sim, target) - return -1 - } - - if dk.Rotation.BloodTapPrio == proto.TankDeathknight_Rotation_Offensive { - if dk.BloodTap.CanCast(sim, target) { - dk.BloodTap.Cast(sim, target) - dk.IcyTouch.Cast(sim, target) - dk.CancelBloodTap(sim) - return -1 - } - } - - if dk.DoFrostCast(sim, target, s) { - return -1 - } - - if dk.DoBloodCast(sim, target, s) { - return -1 - } - - return -1 -} diff --git a/sim/deathknight/tank/rotation_shared.go b/sim/deathknight/tank/rotation_shared.go deleted file mode 100644 index 0dd5778384..0000000000 --- a/sim/deathknight/tank/rotation_shared.go +++ /dev/null @@ -1,63 +0,0 @@ -package tank - -import ( - "time" - - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/deathknight" -) - -func (dk *TankDeathknight) DoDiseaseChecks(sim *core.Simulation, target *core.Unit, _ *deathknight.Sequence) bool { - t := sim.CurrentTime - recast := 3 * time.Second // 2 GCDs for miss - ff := dk.FrostFeverSpell.Dot(target).ExpiresAt() - t - bp := dk.BloodPlagueSpell.Dot(target).ExpiresAt() - t - - if ff <= 0 && dk.IcyTouch.CanCast(sim, target) { - dk.IcyTouch.Cast(sim, target) - return true - } - - if bp <= 0 && dk.PlagueStrike.CanCast(sim, target) { - dk.PlagueStrike.Cast(sim, target) - return true - } - - if ff <= recast || bp <= recast && dk.Pestilence.CanCast(sim, target) { - dk.Pestilence.Cast(sim, target) - return true - } - - return false -} - -func (dk *TankDeathknight) DoFrostCast(sim *core.Simulation, target *core.Unit, _ *deathknight.Sequence) bool { - if dk.Talents.FrostStrike && dk.FrostStrike.CanCast(sim, target) { - dk.FrostStrike.Cast(sim, target) - return true - } - - if dk.Talents.HowlingBlast && dk.FreezingFogAura.IsActive() && dk.HowlingBlast.CanCast(sim, target) { - dk.HowlingBlast.Cast(sim, target) - return true - } - - return false -} - -func (dk *TankDeathknight) DoBloodCast(sim *core.Simulation, target *core.Unit, _ *deathknight.Sequence) bool { - t := sim.CurrentTime - recast := 3 * time.Second // 2 GCDs for miss - ff := dk.FrostFeverSpell.Dot(target).ExpiresAt() - t - bp := dk.BloodPlagueSpell.Dot(target).ExpiresAt() - t - b := dk.CurrentBloodRunes() - - if b >= 1 { - if dk.NormalSpentBloodRuneReadyAt(sim)-t < ff-recast && dk.NormalSpentBloodRuneReadyAt(sim)-t < bp-recast { - dk.BloodSpell.Cast(sim, target) - return true - } - } - - return false -} diff --git a/sim/deathknight/tank/rotation_tps.go b/sim/deathknight/tank/rotation_tps.go deleted file mode 100644 index fe7f80afe6..0000000000 --- a/sim/deathknight/tank/rotation_tps.go +++ /dev/null @@ -1,73 +0,0 @@ -package tank - -import ( - "time" - - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/core/proto" - "github.com/wowsims/wotlk/sim/deathknight" -) - -func (dk *TankDeathknight) TankRA_Tps(sim *core.Simulation, target *core.Unit, s *deathknight.Sequence) time.Duration { - if !dk.GCD.IsReady(sim) { - return dk.NextGCDAt() - } - - t := sim.CurrentTime - ff := dk.FrostFeverSpell.Dot(target).ExpiresAt() - t - bp := dk.BloodPlagueSpell.Dot(target).ExpiresAt() - t - - if ff <= 0 && dk.IcyTouch.CanCast(sim, target) { - dk.IcyTouch.Cast(sim, target) - return -1 - } - - if bp <= 0 && dk.PlagueStrike.CanCast(sim, target) { - dk.PlagueStrike.Cast(sim, target) - return -1 - } - - if ff <= 2*time.Second || bp <= 2*time.Second && dk.Pestilence.CanCast(sim, target) { - dk.Pestilence.Cast(sim, target) - return -1 - } - - if dk.switchIT && dk.IcyTouch.CanCast(sim, target) { - dk.IcyTouch.Cast(sim, target) - - if dk.DeathRunesInFU() == 0 { - dk.switchIT = false - } - - return -1 - } - - if !dk.switchIT && dk.FuSpell.CanCast(sim, target) { - dk.FuSpell.Cast(sim, target) - - if dk.DeathRunesInFU() == 4 { - dk.switchIT = true - } - - return -1 - } - - if dk.Rotation.BloodTapPrio == proto.TankDeathknight_Rotation_Offensive { - if dk.BloodTap.CanCast(sim, target) { - dk.BloodTap.Cast(sim, target) - dk.IcyTouch.Cast(sim, target) - dk.CancelBloodTap(sim) - return -1 - } - } - - if dk.DoFrostCast(sim, target, s) { - return -1 - } - - if dk.DoBloodCast(sim, target, s) { - return -1 - } - - return -1 -} diff --git a/sim/deathknight/tank/tank_deathknight.go b/sim/deathknight/tank/tank_deathknight.go index 8483a3a40d..6ede0bec8e 100644 --- a/sim/deathknight/tank/tank_deathknight.go +++ b/sim/deathknight/tank/tank_deathknight.go @@ -29,8 +29,6 @@ type TankDeathknight struct { switchIT bool BloodSpell *core.Spell FuSpell *core.Spell - - Rotation *proto.TankDeathknight_Rotation } func NewTankDeathknight(character *core.Character, options *proto.Player) *TankDeathknight { @@ -41,7 +39,6 @@ func NewTankDeathknight(character *core.Character, options *proto.Player) *TankD IsDps: false, StartingRunicPower: dkOptions.Options.StartingRunicPower, }, options.TalentsString, false), - Rotation: dkOptions.Rotation, } tankDk.Inputs.UnholyFrenzyTarget = dkOptions.Options.UnholyFrenzyTarget @@ -51,7 +48,7 @@ func NewTankDeathknight(character *core.Character, options *proto.Player) *TankD OffHand: tankDk.WeaponFromOffHand(tankDk.DefaultMeleeCritMultiplier()), AutoSwingMelee: true, ReplaceMHSwing: func(sim *core.Simulation, mhSwingSpell *core.Spell) *core.Spell { - if (!tankDk.IsUsingAPL || tankDk.RuneStrikeQueued) && tankDk.RuneStrike.CanCast(sim, nil) { + if tankDk.RuneStrikeQueued && tankDk.RuneStrike.CanCast(sim, nil) { return tankDk.RuneStrike } else { return mhSwingSpell @@ -77,40 +74,6 @@ func (dk *TankDeathknight) Initialize() { dk.Deathknight.Initialize() } -func (dk *TankDeathknight) SetupRotations() { - dk.RotationSequence.Clear() - - if dk.Rotation.Opener == proto.TankDeathknight_Rotation_Regular { - dk.setupTankRegularERWOpener() - } else if dk.Rotation.Opener == proto.TankDeathknight_Rotation_Threat { - dk.setupTankThreatERWOpener() - } - - if dk.Rotation.OptimizationSetting == proto.TankDeathknight_Rotation_Hps { - dk.RotationSequence.NewAction(dk.TankRA_Hps) - } else if dk.Rotation.OptimizationSetting == proto.TankDeathknight_Rotation_Tps { - dk.RotationSequence.NewAction(dk.TankRA_Tps) - } - - if dk.Rotation.BloodSpell == proto.TankDeathknight_Rotation_BloodStrike { - dk.BloodSpell = dk.BloodStrike - } else if dk.Rotation.BloodSpell == proto.TankDeathknight_Rotation_BloodBoil { - dk.BloodSpell = dk.BloodBoil - } else if dk.Rotation.BloodSpell == proto.TankDeathknight_Rotation_HeartStrike { - if dk.HeartStrike != nil { - dk.BloodSpell = dk.HeartStrike - } else { - dk.BloodSpell = dk.BloodStrike - } - } - - if dk.Talents.Annihilation == 3 { - dk.FuSpell = dk.Obliterate - } else { - dk.FuSpell = dk.DeathStrike - } -} - func (dk *TankDeathknight) Reset(sim *core.Simulation) { dk.Deathknight.Reset(sim) @@ -118,18 +81,4 @@ func (dk *TankDeathknight) Reset(sim *core.Simulation) { dk.Presence = deathknight.UnsetPresence dk.Deathknight.PseudoStats.Stunned = false - - if dk.IsUsingAPL { - return - } - - if dk.Rotation.Presence == proto.TankDeathknight_Rotation_Blood { - dk.ChangePresence(sim, deathknight.BloodPresence) - } else if dk.Rotation.Presence == proto.TankDeathknight_Rotation_Frost { - dk.ChangePresence(sim, deathknight.FrostPresence) - } else if dk.Rotation.Presence == proto.TankDeathknight_Rotation_Unholy { - dk.ChangePresence(sim, deathknight.UnholyPresence) - } - - dk.SetupRotations() } diff --git a/sim/deathknight/unholy_frenzy.go b/sim/deathknight/unholy_frenzy.go index f3635e752c..08a15f2538 100644 --- a/sim/deathknight/unholy_frenzy.go +++ b/sim/deathknight/unholy_frenzy.go @@ -13,7 +13,7 @@ func (dk *Deathknight) registerUnholyFrenzyCD() { actionID := core.ActionID{SpellID: 49016, Tag: dk.Index} unholyFrenzyTarget := dk.GetUnit(dk.Inputs.UnholyFrenzyTarget) - if unholyFrenzyTarget == nil && dk.IsUsingAPL { + if unholyFrenzyTarget == nil { unholyFrenzyTarget = &dk.Unit } diff --git a/sim/hunter/hunter.go b/sim/hunter/hunter.go index 617fec6ac6..a215250b50 100644 --- a/sim/hunter/hunter.go +++ b/sim/hunter/hunter.go @@ -32,9 +32,8 @@ func RegisterHunter() { type Hunter struct { core.Character - Talents *proto.HunterTalents - Options *proto.Hunter_Options - Rotation *proto.Hunter_Rotation + Talents *proto.HunterTalents + Options *proto.Hunter_Options pet *HunterPet @@ -154,10 +153,6 @@ func NewHunter(character *core.Character, options *proto.Player) *Hunter { Character: *character, Talents: &proto.HunterTalents{}, Options: hunterOptions.Options, - Rotation: hunterOptions.Rotation, - } - if hunter.Rotation == nil { - hunter.Rotation = &proto.Hunter_Rotation{} } core.FillTalentsProto(hunter.Talents.ProtoReflect(), options.TalentsString, TalentTreeSizes) hunter.EnableManaBar() From 93a32c0966a343c85ff9a444b23d70c65b8e12c9 Mon Sep 17 00:00:00 2001 From: James Tanner Date: Thu, 4 Jan 2024 19:38:09 -0800 Subject: [PATCH 06/28] Another commit before making a separate fix --- sim/core/attack.go | 2 +- sim/deathknight/dps/TestBlood.results | 12 +- sim/deathknight/dps/TestUnholy.results | 568 ++++++++++++------------- sim/druid/balance/balance.go | 84 +--- sim/druid/balance/rotation.go | 256 ----------- sim/druid/berserk.go | 10 +- sim/druid/druid.go | 7 +- sim/druid/feral/feral.go | 20 +- sim/druid/feral/rotation.go | 98 +---- sim/druid/hurricane.go | 3 +- sim/druid/maul.go | 16 +- sim/druid/talents.go | 2 +- sim/druid/tank/rotation.go | 88 ---- sim/druid/tank/tank.go | 10 +- 14 files changed, 316 insertions(+), 860 deletions(-) delete mode 100644 sim/druid/balance/rotation.go delete mode 100644 sim/druid/tank/rotation.go diff --git a/sim/core/attack.go b/sim/core/attack.go index aa601b5b16..4827d143eb 100644 --- a/sim/core/attack.go +++ b/sim/core/attack.go @@ -275,7 +275,7 @@ func (wa *WeaponAttack) swing(sim *Simulation) time.Duration { wa.swingAt = sim.CurrentTime + wa.curSwingDuration attackSpell.Cast(sim, wa.unit.CurrentTarget) - if !sim.Options.Interactive { + if !sim.Options.Interactive && wa.unit.Rotation != nil { wa.unit.Rotation.DoNextAction(sim) } diff --git a/sim/deathknight/dps/TestBlood.results b/sim/deathknight/dps/TestBlood.results index 5102649157..a4f19e677b 100644 --- a/sim/deathknight/dps/TestBlood.results +++ b/sim/deathknight/dps/TestBlood.results @@ -287,8 +287,8 @@ dps_results: { dps_results: { key: "TestBlood-AllItems-EphemeralSnowflake-50260" value: { - dps: 10467.28296 - tps: 5296.53902 + dps: 10443.90447 + tps: 5277.80696 } } dps_results: { @@ -666,8 +666,8 @@ dps_results: { dps_results: { key: "TestBlood-AllItems-SphereofRedDragon'sBlood-37166" value: { - dps: 10350.69235 - tps: 5235.5789 + dps: 10383.49361 + tps: 5254.72979 } } dps_results: { @@ -778,8 +778,8 @@ dps_results: { dps_results: { key: "TestBlood-AllItems-TomeofArcanePhenomena-36972" value: { - dps: 10317.50284 - tps: 5211.82802 + dps: 10379.62764 + tps: 5242.10503 } } dps_results: { diff --git a/sim/deathknight/dps/TestUnholy.results b/sim/deathknight/dps/TestUnholy.results index e31fee5d05..b00336dda8 100644 --- a/sim/deathknight/dps/TestUnholy.results +++ b/sim/deathknight/dps/TestUnholy.results @@ -46,984 +46,984 @@ character_stats_results: { dps_results: { key: "TestUnholy-AllItems-Althor'sAbacus-50359" value: { - dps: 9680.47429 - tps: 5704.45855 + dps: 9710.58503 + tps: 5711.54761 hps: 63.52617 } } dps_results: { key: "TestUnholy-AllItems-Althor'sAbacus-50366" value: { - dps: 9680.47429 - tps: 5704.45855 + dps: 9710.58503 + tps: 5711.54761 hps: 66.3402 } } dps_results: { key: "TestUnholy-AllItems-AustereEarthsiegeDiamond" value: { - dps: 10217.92511 - tps: 5880.532 + dps: 10248.30721 + tps: 5886.95782 hps: 42.71551 } } dps_results: { key: "TestUnholy-AllItems-Bandit'sInsignia-40371" value: { - dps: 9893.9745 - tps: 5859.94867 + dps: 9924.17016 + tps: 5866.99266 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-BaubleofTrueBlood-50354" value: { - dps: 9680.48618 - tps: 5704.5175 + dps: 9710.59693 + tps: 5711.60656 hps: 134.78881 } } dps_results: { key: "TestUnholy-AllItems-BaubleofTrueBlood-50726" value: { - dps: 9680.48618 - tps: 5704.5175 + dps: 9710.59693 + tps: 5711.60656 hps: 134.78881 } } dps_results: { key: "TestUnholy-AllItems-BeamingEarthsiegeDiamond" value: { - dps: 10240.42421 - tps: 5900.33685 + dps: 10270.83734 + tps: 5906.78165 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Beast-tamer'sShoulders-30892" value: { - dps: 9561.27606 - tps: 5428.86625 + dps: 9590.63003 + tps: 5434.59411 hps: 40.4349 } } dps_results: { key: "TestUnholy-AllItems-BlessedBattlegearofUndeadSlaying" value: { - dps: 7500.6957 - tps: 4266.20781 + dps: 7528.9716 + tps: 4272.7715 hps: 34.38394 } } dps_results: { key: "TestUnholy-AllItems-BlessedGarboftheUndeadSlayer" value: { - dps: 7390.28759 - tps: 4234.65809 + dps: 7417.57124 + tps: 4240.52367 hps: 32.96775 } } dps_results: { key: "TestUnholy-AllItems-BlessedRegaliaofUndeadCleansing" value: { - dps: 7173.57707 - tps: 4090.382 + dps: 7201.24066 + tps: 4096.56066 hps: 32.72866 } } dps_results: { key: "TestUnholy-AllItems-BracingEarthsiegeDiamond" value: { - dps: 10217.92511 - tps: 5762.92136 + dps: 10248.30721 + tps: 5769.21867 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Bryntroll,theBoneArbiter-50415" value: { - dps: 10346.91539 - tps: 5989.61257 + dps: 10377.44167 + tps: 5996.15064 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Bryntroll,theBoneArbiter-50709" value: { - dps: 10346.91539 - tps: 5989.61257 + dps: 10377.44167 + tps: 5996.15064 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ChaoticSkyflareDiamond" value: { - dps: 10353.5962 - tps: 5995.41414 + dps: 10384.12635 + tps: 6001.95118 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-CorpseTongueCoin-50349" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-CorpseTongueCoin-50352" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-CorrodedSkeletonKey-50356" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 110.32034 } } dps_results: { key: "TestUnholy-AllItems-DarkmoonCard:Berserker!-42989" value: { - dps: 9811.44494 - tps: 5817.02786 + dps: 9841.85262 + tps: 5824.32161 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-DarkmoonCard:Death-42990" value: { - dps: 9873.64594 - tps: 5864.21871 + dps: 9904.01516 + tps: 5871.41583 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-DarkmoonCard:Greatness-44255" value: { - dps: 9986.29823 - tps: 5844.5239 + dps: 10016.40898 + tps: 5851.61296 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-DarkrunedBattlegear" value: { - dps: 8313.25385 - tps: 4722.11602 + dps: 8342.40652 + tps: 4728.74456 hps: 38.90837 } } dps_results: { key: "TestUnholy-AllItems-DarkrunedPlate" value: { - dps: 7427.64393 - tps: 4189.2183 + dps: 7455.04498 + tps: 4195.27998 hps: 40.98666 } } dps_results: { key: "TestUnholy-AllItems-DeadlyGladiator'sSigilofStrife-42620" value: { - dps: 10398.41427 - tps: 6019.99796 + dps: 10428.94056 + tps: 6026.53603 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-DeathKnight'sAnguish-38212" value: { - dps: 9784.41797 - tps: 5793.32415 + dps: 9814.76517 + tps: 5800.54798 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Deathbringer'sWill-50362" value: { - dps: 10212.23545 - tps: 6011.7831 + dps: 10244.26393 + tps: 6019.38836 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Deathbringer'sWill-50363" value: { - dps: 10304.74071 - tps: 6126.35152 + dps: 10336.93352 + tps: 6134.04278 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Defender'sCode-40257" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-DestructiveSkyflareDiamond" value: { - dps: 10245.17112 - tps: 5903.63941 + dps: 10275.66073 + tps: 5910.13257 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-DislodgedForeignObject-50348" value: { - dps: 10027.7374 - tps: 5913.21833 + dps: 10058.86423 + tps: 5920.2823 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-DislodgedForeignObject-50353" value: { - dps: 10015.90074 - tps: 5863.92416 + dps: 10045.90755 + tps: 5870.04449 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-EffulgentSkyflareDiamond" value: { - dps: 10217.92511 - tps: 5880.532 + dps: 10248.30721 + tps: 5886.95782 hps: 42.71551 } } dps_results: { key: "TestUnholy-AllItems-EmberSkyflareDiamond" value: { - dps: 10217.92511 - tps: 5880.532 + dps: 10248.30721 + tps: 5886.95782 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-EnigmaticSkyflareDiamond" value: { - dps: 10240.42421 - tps: 5900.33685 + dps: 10270.83734 + tps: 5906.78165 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-EnigmaticStarflareDiamond" value: { - dps: 10238.88528 - tps: 5898.8624 + dps: 10269.30196 + tps: 5905.31005 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-EphemeralSnowflake-50260" value: { - dps: 9957.51073 - tps: 5686.58021 + dps: 9960.43305 + tps: 5713.77531 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-EssenceofGossamer-37220" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 44.16848 } } dps_results: { key: "TestUnholy-AllItems-EternalEarthsiegeDiamond" value: { - dps: 10217.92511 - tps: 5880.532 + dps: 10248.30721 + tps: 5886.95782 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ExtractofNecromanticPower-40373" value: { - dps: 9854.14952 - tps: 5848.27771 + dps: 9884.46426 + tps: 5855.45523 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-EyeoftheBroodmother-45308" value: { - dps: 9799.48063 - tps: 5805.4028 + dps: 9829.83582 + tps: 5812.66149 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Figurine-SapphireOwl-42413" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ForethoughtTalisman-40258" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ForgeEmber-37660" value: { - dps: 9778.71591 - tps: 5788.07856 + dps: 9809.03194 + tps: 5795.31409 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ForlornSkyflareDiamond" value: { - dps: 10217.92511 - tps: 5880.532 + dps: 10248.30721 + tps: 5886.95782 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ForlornStarflareDiamond" value: { - dps: 10217.92511 - tps: 5880.532 + dps: 10248.30721 + tps: 5886.95782 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-FuriousGladiator'sSigilofStrife-42621" value: { - dps: 10408.71405 - tps: 6026.07503 + dps: 10439.24034 + tps: 6032.61311 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-FuryoftheFiveFlights-40431" value: { - dps: 9905.69267 - tps: 5871.20429 + dps: 9935.80342 + tps: 5878.29335 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-FuturesightRune-38763" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-GlowingTwilightScale-54573" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-GlowingTwilightScale-54589" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-GnomishLightningGenerator-41121" value: { - dps: 9832.05026 - tps: 5830.41915 + dps: 9862.40069 + tps: 5837.60588 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-HatefulGladiator'sSigilofStrife-42619" value: { - dps: 10376.42406 - tps: 6005.85502 + dps: 10406.95035 + tps: 6012.39309 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-IllustrationoftheDragonSoul-40432" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ImpassiveSkyflareDiamond" value: { - dps: 10240.42421 - tps: 5900.33685 + dps: 10270.83734 + tps: 5906.78165 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ImpassiveStarflareDiamond" value: { - dps: 10238.88528 - tps: 5898.8624 + dps: 10269.30196 + tps: 5905.31005 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-IncisorFragment-37723" value: { - dps: 9858.84411 - tps: 5841.99589 + dps: 9889.84971 + tps: 5849.80123 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-InsightfulEarthsiegeDiamond" value: { - dps: 10217.92511 - tps: 5880.532 + dps: 10248.30721 + tps: 5886.95782 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-InvigoratingEarthsiegeDiamond" value: { - dps: 10250.43861 - tps: 5903.12227 + dps: 10280.82071 + tps: 5909.54809 hps: 58.71565 } } dps_results: { key: "TestUnholy-AllItems-LastWord-50179" value: { - dps: 10346.91539 - tps: 5989.61257 + dps: 10377.44167 + tps: 5996.15064 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-LastWord-50708" value: { - dps: 10346.91539 - tps: 5989.61257 + dps: 10377.44167 + tps: 5996.15064 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Lavanthor'sTalisman-37872" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-MajesticDragonFigurine-40430" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-MeteoriteWhetstone-37390" value: { - dps: 10002.66676 - tps: 5837.61294 + dps: 10032.0625 + tps: 5843.61227 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-NevermeltingIceCrystal-50259" value: { - dps: 9829.70588 - tps: 5834.98049 + dps: 9859.78621 + tps: 5842.11561 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-OfferingofSacrifice-37638" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-PersistentEarthshatterDiamond" value: { - dps: 10244.24556 - tps: 5898.81936 + dps: 10274.62766 + tps: 5905.24519 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-PersistentEarthsiegeDiamond" value: { - dps: 10250.43861 - tps: 5903.12227 + dps: 10280.82071 + tps: 5909.54809 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-PetrifiedScarab-21685" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-PetrifiedTwilightScale-54571" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-PetrifiedTwilightScale-54591" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-PowerfulEarthshatterDiamond" value: { - dps: 10217.92511 - tps: 5880.532 + dps: 10248.30721 + tps: 5886.95782 hps: 42.60516 } } dps_results: { key: "TestUnholy-AllItems-PowerfulEarthsiegeDiamond" value: { - dps: 10217.92511 - tps: 5880.532 + dps: 10248.30721 + tps: 5886.95782 hps: 42.71551 } } dps_results: { key: "TestUnholy-AllItems-PurifiedShardoftheGods" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ReignoftheDead-47316" value: { - dps: 9754.94571 - tps: 5763.56884 + dps: 9785.06353 + tps: 5770.6385 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ReignoftheDead-47477" value: { - dps: 9762.03411 - tps: 5769.56958 + dps: 9792.15193 + tps: 5776.63924 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-RelentlessEarthsiegeDiamond" value: { - dps: 10346.91539 - tps: 5989.61257 + dps: 10377.44167 + tps: 5996.15064 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-RelentlessGladiator'sSigilofStrife-42622" value: { - dps: 10420.73045 - tps: 6033.16496 + dps: 10451.25674 + tps: 6039.70303 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-RevitalizingSkyflareDiamond" value: { - dps: 10217.92511 - tps: 5880.532 + dps: 10248.30721 + tps: 5886.95782 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-RuneofRepulsion-40372" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SavageGladiator'sSigilofStrife-42618" value: { - dps: 10373.08345 - tps: 6004.01625 + dps: 10403.60974 + tps: 6010.55432 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ScourgeborneBattlegear" value: { - dps: 8000.74515 - tps: 4559.84406 + dps: 8029.52875 + tps: 4566.12376 hps: 36.48062 } } dps_results: { key: "TestUnholy-AllItems-ScourgebornePlate" value: { - dps: 7338.02073 - tps: 4115.32448 + dps: 7364.82744 + tps: 4120.861 hps: 38.04394 } } dps_results: { key: "TestUnholy-AllItems-Scourgelord'sBattlegear" value: { - dps: 9330.42072 - tps: 5515.28971 + dps: 9358.46371 + tps: 5521.64302 hps: 44.60989 } } dps_results: { key: "TestUnholy-AllItems-Scourgelord'sPlate" value: { - dps: 8192.96648 - tps: 4636.93277 + dps: 8219.42444 + tps: 4642.08454 hps: 48.06758 } } dps_results: { key: "TestUnholy-AllItems-SealofthePantheon-36993" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Shadowmourne-49623" value: { - dps: 10346.91539 - tps: 5989.61257 + dps: 10377.44167 + tps: 5996.15064 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ShinyShardoftheGods" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SigilofDeflection-45144" value: { - dps: 10346.91539 - tps: 5989.61257 + dps: 10377.44167 + tps: 5996.15064 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SigilofHauntedDreams-40715" value: { - dps: 10376.62308 - tps: 6015.42194 + dps: 10407.04323 + tps: 6021.87725 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SigilofInsolence-47672" value: { - dps: 10346.91539 - tps: 5989.61257 + dps: 10377.44167 + tps: 5996.15064 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SigiloftheBoneGryphon-50462" value: { - dps: 10346.91539 - tps: 5989.61257 + dps: 10377.44167 + tps: 5996.15064 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SigiloftheHangedMan-50459" value: { - dps: 10346.91539 - tps: 5989.61257 + dps: 10377.44167 + tps: 5996.15064 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SigiloftheUnfalteringKnight-40714" value: { - dps: 10346.91539 - tps: 5989.61257 + dps: 10377.44167 + tps: 5996.15064 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Sindragosa'sFlawlessFang-50361" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 46.32034 } } dps_results: { key: "TestUnholy-AllItems-SliverofPureIce-50339" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SliverofPureIce-50346" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SoulPreserver-37111" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SouloftheDead-40382" value: { - dps: 9802.43285 - tps: 5808.86704 + dps: 9832.82416 + tps: 5816.15563 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SparkofLife-37657" value: { - dps: 9832.06089 - tps: 5797.8349 + dps: 9862.05029 + tps: 5804.30139 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SphereofRedDragon'sBlood-37166" value: { - dps: 9800.6582 - tps: 5811.52763 + dps: 9913.75663 + tps: 5850.97982 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-StormshroudArmor" value: { - dps: 7067.22499 - tps: 4050.80338 + dps: 7095.52999 + tps: 4057.87955 hps: 30.7975 } } dps_results: { key: "TestUnholy-AllItems-SwiftSkyflareDiamond" value: { - dps: 10250.43861 - tps: 5903.12227 + dps: 10280.82071 + tps: 5909.54809 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SwiftStarflareDiamond" value: { - dps: 10244.24556 - tps: 5898.81936 + dps: 10274.62766 + tps: 5905.24519 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SwiftWindfireDiamond" value: { - dps: 10233.40773 - tps: 5891.28927 + dps: 10263.78983 + tps: 5897.7151 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TalismanofTrollDivinity-37734" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TearsoftheVanquished-47215" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Thassarian'sBattlegear" value: { - dps: 8590.35604 - tps: 4952.61627 + dps: 8618.51653 + tps: 4958.8001 hps: 38.68766 } } dps_results: { key: "TestUnholy-AllItems-Thassarian'sPlate" value: { - dps: 7458.635 - tps: 4188.82468 + dps: 7486.10663 + tps: 4194.90667 hps: 40.30616 } } dps_results: { key: "TestUnholy-AllItems-TheGeneral'sHeart-45507" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TheTwinBladesofAzzinoth" value: { - dps: 8979.88721 - tps: 5025.14863 + dps: 9010.98248 + tps: 5032.12724 hps: 40.74757 } } dps_results: { key: "TestUnholy-AllItems-ThunderingSkyflareDiamond" value: { - dps: 10275.22899 - tps: 5912.27746 + dps: 10305.50604 + tps: 5918.26645 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TinyAbominationinaJar-50351" value: { - dps: 9924.59603 - tps: 5907.08552 + dps: 9954.00729 + tps: 5913.58867 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TinyAbominationinaJar-50706" value: { - dps: 9890.45908 - tps: 5873.52857 + dps: 9920.42339 + tps: 5880.41645 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TirelessSkyflareDiamond" value: { - dps: 10217.92511 - tps: 5880.532 + dps: 10248.30721 + tps: 5886.95782 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TirelessStarflareDiamond" value: { - dps: 10217.92511 - tps: 5880.532 + dps: 10248.30721 + tps: 5886.95782 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TomeofArcanePhenomena-36972" value: { - dps: 9826.9966 - tps: 5751.9898 + dps: 9840.77218 + tps: 5774.12915 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TrenchantEarthshatterDiamond" value: { - dps: 10217.92511 - tps: 5880.532 + dps: 10248.30721 + tps: 5886.95782 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TrenchantEarthsiegeDiamond" value: { - dps: 10217.92511 - tps: 5880.532 + dps: 10248.30721 + tps: 5886.95782 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-UndeadSlayer'sBlessedArmor" value: { - dps: 7395.21167 - tps: 4250.00861 + dps: 7423.03446 + tps: 4256.35867 hps: 33.68504 } } dps_results: { key: "TestUnholy-AllItems-Val'anyr,HammerofAncientKings-46017" value: { - dps: 9602.82536 - tps: 5420.6152 + dps: 9633.49282 + tps: 5427.26413 hps: 42.81036 } } dps_results: { key: "TestUnholy-AllItems-WingedTalisman-37844" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-WrathfulGladiator'sSigilofStrife-51417" value: { - dps: 10434.46349 - tps: 6041.26773 + dps: 10464.98978 + tps: 6047.8058 hps: 42.12697 } } dps_results: { key: "TestUnholy-Average-Default" value: { - dps: 10279.57916 - tps: 5964.26539 + dps: 10310.79563 + tps: 5971.29709 hps: 42.14164 } } @@ -1174,152 +1174,152 @@ dps_results: { dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_2h_ss-FullBuffs-LongMultiTarget" value: { - dps: 14275.55112 - tps: 9275.62941 + dps: 14312.2404 + tps: 9287.052 hps: 42.12697 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_2h_ss-FullBuffs-LongSingleTarget" value: { - dps: 10346.91539 - tps: 5989.61257 + dps: 10377.44167 + tps: 5996.15064 hps: 42.12697 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_2h_ss-FullBuffs-ShortSingleTarget" value: { - dps: 15451.74278 - tps: 7165.07213 + dps: 15559.83451 + tps: 7162.15963 hps: 210.63484 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_2h_ss-NoBuffs-LongMultiTarget" value: { - dps: 6761.4395 - tps: 4575.413 + dps: 6783.40918 + tps: 4583.6299 hps: 27.7272 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_2h_ss-NoBuffs-LongSingleTarget" value: { - dps: 5085.97636 - tps: 3172.95627 + dps: 5103.61606 + tps: 3177.62391 hps: 27.7272 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_2h_ss-NoBuffs-ShortSingleTarget" value: { - dps: 6701.62049 - tps: 3491.63258 + dps: 6757.40436 + tps: 3489.08968 hps: 138.636 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_dnd_aoe-FullBuffs-LongMultiTarget" value: { - dps: 59321.04606 - tps: 61361.65332 + dps: 59452.42669 + tps: 61476.73056 hps: 236.33229 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_dnd_aoe-FullBuffs-LongSingleTarget" value: { - dps: 11318.78456 - tps: 7472.9393 + dps: 11354.57131 + tps: 7485.7125 hps: 236.33229 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_dnd_aoe-FullBuffs-ShortSingleTarget" value: { - dps: 16412.5451 - tps: 8686.56163 + dps: 16535.42503 + tps: 8698.33633 hps: 337.01574 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_dnd_aoe-NoBuffs-LongMultiTarget" value: { - dps: 35117.90018 - tps: 37478.75367 + dps: 35212.15599 + tps: 37565.37369 hps: 155.82686 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_dnd_aoe-NoBuffs-LongSingleTarget" value: { - dps: 5750.84606 - tps: 4175.86894 + dps: 5772.20815 + tps: 4185.27192 hps: 155.27232 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_dnd_aoe-NoBuffs-ShortSingleTarget" value: { - dps: 7280.02322 - tps: 4471.44132 + dps: 7347.6605 + tps: 4481.15645 hps: 221.8176 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-unholy_dw_ss-FullBuffs-LongMultiTarget" value: { - dps: 36238.79517 - tps: 43195.85148 + dps: 36324.85779 + tps: 43276.25499 hps: 236.33229 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-unholy_dw_ss-FullBuffs-LongSingleTarget" value: { - dps: 11434.83628 - tps: 7578.90963 + dps: 11470.17283 + tps: 7591.32914 hps: 236.33229 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-unholy_dw_ss-FullBuffs-ShortSingleTarget" value: { - dps: 16487.2343 - tps: 8798.61633 + dps: 16608.09173 + tps: 8808.92846 hps: 339.12209 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-unholy_dw_ss-NoBuffs-LongMultiTarget" value: { - dps: 18696.93865 - tps: 22871.51167 + dps: 18749.83496 + tps: 22923.25478 hps: 155.82686 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-unholy_dw_ss-NoBuffs-LongSingleTarget" value: { - dps: 5876.43297 - tps: 4281.49641 + dps: 5897.73441 + tps: 4290.70565 hps: 155.27232 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-unholy_dw_ss-NoBuffs-ShortSingleTarget" value: { - dps: 7351.97253 - tps: 4548.398 + dps: 7417.6708 + tps: 4556.06307 hps: 221.8176 } } dps_results: { key: "TestUnholy-SwitchInFrontOfTarget-Default" value: { - dps: 9815.01951 - tps: 5629.20041 + dps: 9845.43373 + tps: 5635.64895 hps: 42.12697 } } diff --git a/sim/druid/balance/balance.go b/sim/druid/balance/balance.go index f5206e3878..d0cea4e797 100644 --- a/sim/druid/balance/balance.go +++ b/sim/druid/balance/balance.go @@ -32,9 +32,8 @@ func NewBalanceDruid(character *core.Character, options *proto.Player) *BalanceD selfBuffs := druid.SelfBuffs{} moonkin := &BalanceDruid{ - Druid: druid.New(character, druid.Moonkin, selfBuffs, options.TalentsString), - Options: balanceOptions.Options, - Rotation: balanceOptions.Rotation, + Druid: druid.New(character, druid.Moonkin, selfBuffs, options.TalentsString), + Options: balanceOptions.Options, } moonkin.SelfBuffs.InnervateTarget = &proto.UnitReference{} @@ -42,7 +41,6 @@ func NewBalanceDruid(character *core.Character, options *proto.Player) *BalanceD moonkin.SelfBuffs.InnervateTarget = balanceOptions.Options.InnervateTarget } - moonkin.EnableResumeAfterManaWait(moonkin.tryUseGCD) wotlk.ConstructValkyrPets(&moonkin.Character) return moonkin } @@ -55,19 +53,7 @@ type BalanceOnUseTrinket struct { type BalanceDruid struct { *druid.Druid - Options *proto.BalanceDruid_Options - Rotation *proto.BalanceDruid_Rotation - CooldownsAvailable []*core.MajorCooldown - LastCast *druid.DruidSpell - - // CDS - hyperSpeedMCD *core.MajorCooldown - potionSpeedMCD *core.MajorCooldown - potionWildMagicMCD *core.MajorCooldown - powerInfusion *core.MajorCooldown - onUseTrinket1 BalanceOnUseTrinket - onUseTrinket2 BalanceOnUseTrinket - potionUsed bool + Options *proto.BalanceDruid_Options } func (moonkin *BalanceDruid) GetDruid() *druid.Druid { @@ -78,70 +64,14 @@ func (moonkin *BalanceDruid) Initialize() { moonkin.Druid.Initialize() moonkin.RegisterBalanceSpells() - moonkin.Env.RegisterPreFinalizeEffect(func() { - if moonkin.OwlkinFrenzyAura != nil && moonkin.Options.OkfUptime > 0 { + if moonkin.OwlkinFrenzyAura != nil && moonkin.Options.OkfUptime > 0 { + moonkin.Env.RegisterPreFinalizeEffect(func() { core.ApplyFixedUptimeAura(moonkin.OwlkinFrenzyAura, float64(moonkin.Options.OkfUptime), time.Second*5, 0) - } - }) + }) + } } func (moonkin *BalanceDruid) Reset(sim *core.Simulation) { moonkin.Druid.Reset(sim) moonkin.RebirthTiming = moonkin.Env.BaseDuration.Seconds() * sim.RandomFloat("Rebirth Timing") - - if moonkin.Rotation.Type == proto.BalanceDruid_Rotation_Default { - moonkin.Rotation.MfUsage = proto.BalanceDruid_Rotation_BeforeLunar - moonkin.Rotation.IsUsage = proto.BalanceDruid_Rotation_OptimizeIs - moonkin.Rotation.WrathUsage = proto.BalanceDruid_Rotation_RegularWrath - moonkin.Rotation.UseBattleRes = false - moonkin.Rotation.UseStarfire = true - moonkin.Rotation.UseTyphoon = false - moonkin.Rotation.UseHurricane = false - moonkin.Rotation.UseSmartCooldowns = true - moonkin.Rotation.MaintainFaerieFire = true - moonkin.Rotation.PlayerLatency = 200 - } - - if moonkin.Rotation.UseSmartCooldowns { - moonkin.potionUsed = false - consumes := moonkin.Consumes - - if consumes.DefaultPotion == proto.Potions_PotionOfSpeed { - moonkin.potionSpeedMCD = moonkin.getBalanceMajorCooldown(core.ActionID{ItemID: 40211}) - } - if consumes.DefaultPotion == proto.Potions_PotionOfWildMagic { - moonkin.potionWildMagicMCD = moonkin.getBalanceMajorCooldown(core.ActionID{ItemID: 40212}) - } - if moonkin.HasProfession(proto.Profession_Engineering) { - moonkin.hyperSpeedMCD = moonkin.getBalanceMajorCooldown(core.ActionID{SpellID: 54758}) - } - moonkin.powerInfusion = moonkin.getBalanceMajorCooldown(core.ActionID{SpellID: 10060}) - moonkin.onUseTrinket1 = BalanceOnUseTrinket{ - Cooldown: moonkin.getBalanceMajorCooldown(core.ActionID{ItemID: moonkin.Trinket1().ID}), - Stat: getOnUseTrinketStat(moonkin.Trinket1().ID), - } - moonkin.onUseTrinket2 = BalanceOnUseTrinket{ - Cooldown: moonkin.getBalanceMajorCooldown(core.ActionID{ItemID: moonkin.Trinket2().ID}), - Stat: getOnUseTrinketStat(moonkin.Trinket2().ID), - } - } -} - -// Takes out a Cooldown from the generic MajorCooldownManager and adds it to a custom Slice of Cooldowns -func (moonkin *BalanceDruid) getBalanceMajorCooldown(actionID core.ActionID) *core.MajorCooldown { - if majorCd := moonkin.Character.GetMajorCooldownIgnoreTag(actionID); majorCd != nil { - majorCd.Disable() - return majorCd - } - return nil -} - -func getOnUseTrinketStat(itemId int32) stats.Stat { - if itemId == 45466 || itemId == 48722 || itemId == 47726 || itemId == 47946 || itemId == 36972 { - return stats.SpellHaste - } - if itemId == 50259 { - return stats.SpellCrit - } - return stats.SpellPower } diff --git a/sim/druid/balance/rotation.go b/sim/druid/balance/rotation.go deleted file mode 100644 index e0a633aad4..0000000000 --- a/sim/druid/balance/rotation.go +++ /dev/null @@ -1,256 +0,0 @@ -package balance - -import ( - "time" - - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/core/proto" - "github.com/wowsims/wotlk/sim/core/stats" - "github.com/wowsims/wotlk/sim/druid" -) - -func (moonkin *BalanceDruid) OnGCDReady(sim *core.Simulation) { - moonkin.tryUseGCD(sim) -} - -func (moonkin *BalanceDruid) tryUseGCD(sim *core.Simulation) { - spell, target := moonkin.rotation(sim) - if success := spell.Cast(sim, target); !success { - moonkin.WaitForMana(sim, spell.CurCast.Cost) - } - moonkin.LastCast = spell -} - -func (moonkin *BalanceDruid) rotation(sim *core.Simulation) (*druid.DruidSpell, *core.Unit) { - moonkin.CurrentTarget = sim.Environment.GetTargetUnit(0) - rotation := moonkin.Rotation - target := moonkin.CurrentTarget - - if rotation.MaintainFaerieFire && moonkin.ShouldFaerieFire(sim, moonkin.CurrentTarget) { - return moonkin.FaerieFire, target - } - - if sim.GetRemainingDuration() < 15*time.Second { - moonkin.castMajorCooldown(moonkin.hyperSpeedMCD, sim, target) - moonkin.castMajorCooldown(moonkin.potionSpeedMCD, sim, target) - moonkin.castMajorCooldown(moonkin.potionWildMagicMCD, sim, target) - moonkin.useTrinkets(stats.SpellHaste, sim, target) - moonkin.useTrinkets(stats.SpellPower, sim, target) - moonkin.useTrinkets(stats.SpellCrit, sim, target) - } - - if rotation.SnapshotMf { - flareProc := moonkin.GetAura("Flare of the Heavens Proc") - pleaProc := moonkin.GetAura("Pandora's Plea Proc") - wildMagicProc := moonkin.GetAura("Potion of Wild Magic") - shouldCheckForSnapshot := flareProc.IsActive() || pleaProc.IsActive() || (wildMagicProc.IsActive() && sim.CurrentTime > 60*time.Second) - if shouldCheckForSnapshot { - if moonkin.shouldSnapshotMf(sim, flareProc) || moonkin.shouldSnapshotMf(sim, wildMagicProc) || moonkin.shouldSnapshotMf(sim, pleaProc) { - return moonkin.Moonfire, target - } - } - } - - var lunarUptime time.Duration - shouldRefreshMf := moonkin.Moonfire.CurDot().RemainingDuration(sim) <= 0 - hasLunarFury := core.Ternary(moonkin.Ranged().ID == 47670, true, false) - lunarIsActive := moonkin.LunarEclipseProcAura.IsActive() - maximizeMf := !(rotation.MfUsage == proto.BalanceDruid_Rotation_NoMf) && !(rotation.MfUsage == proto.BalanceDruid_Rotation_BeforeLunar) && !(rotation.SnapshotMf) - - if moonkin.LunarEclipseProcAura != nil { - lunarUptime = moonkin.LunarEclipseProcAura.RemainingDuration(sim) - } - if moonkin.MoonkinT84PCAura.IsActive() && moonkin.MoonkinT84PCAura.RemainingDuration(sim) < moonkin.SpellGCD() { - return moonkin.Starfire, target - } else if rotation.UseBattleRes && sim.GetRemainingDuration().Seconds() < moonkin.RebirthTiming && moonkin.Rebirth.IsReady(sim) { - return moonkin.Rebirth, target - } else if maximizeMf && shouldRefreshMf && hasLunarFury { - return moonkin.Moonfire, target - } else if moonkin.Talents.ForceOfNature && moonkin.ForceOfNature.IsReady(sim) && !lunarIsActive { - moonkin.useTrinkets(stats.SpellPower, sim, target) - return moonkin.ForceOfNature, target - } else if moonkin.Starfall.IsReady(sim) && !lunarIsActive { - moonkin.useTrinkets(stats.SpellPower, sim, target) - return moonkin.Starfall, target - } else if moonkin.Typhoon.IsReady(sim) && rotation.UseTyphoon { - return moonkin.Typhoon, target - } else if rotation.UseHurricane { - return moonkin.Hurricane, target - } - - shouldHoldIs := core.Ternary(moonkin.MoonkinT84PCAura == nil, lunarIsActive, lunarIsActive && moonkin.HasActiveAura("Bloodlust-"+core.BloodlustActionID.WithTag(-1).String())) - - // Max IS uptime - if rotation.IsUsage == proto.BalanceDruid_Rotation_OptimizeIs && !shouldHoldIs { - if moonkin.InsectSwarm.CurDot().RemainingDuration(sim) <= 0 { - return moonkin.InsectSwarm, target - } - } else if rotation.IsUsage == proto.BalanceDruid_Rotation_MultidotIs { - for range sim.Encounter.Targets { - if moonkin.InsectSwarm.CurDot().RemainingDuration(sim) <= 0 { - return moonkin.InsectSwarm, moonkin.CurrentTarget - } - moonkin.CurrentTarget = sim.Environment.NextTargetUnit(moonkin.CurrentTarget) - } - } - - // Max MF uptime - if rotation.MfUsage == proto.BalanceDruid_Rotation_MaximizeMf && shouldRefreshMf { - return moonkin.Moonfire, target - } else if rotation.MfUsage == proto.BalanceDruid_Rotation_MultidotMf { - for range sim.Encounter.Targets { - if moonkin.Moonfire.CurDot().RemainingDuration(sim) <= 0 { - return moonkin.Moonfire, moonkin.CurrentTarget - } - moonkin.CurrentTarget = sim.Environment.NextTargetUnit(moonkin.CurrentTarget) - } - } - - // Player "brain" latency - playerLatency := time.Duration(max(rotation.PlayerLatency, 0)) * time.Millisecond - lunarICD := moonkin.LunarICD.Timer.TimeToReady(sim) - solarICD := moonkin.SolarICD.Timer.TimeToReady(sim) - canExtendMf := rotation.MfExtension == proto.BalanceDruid_Rotation_ExtendAlways || rotation.MfExtension == proto.BalanceDruid_Rotation_ExtendOutsideSolar - - if moonkin.Talents.Eclipse > 0 { - solarUptime := moonkin.SolarEclipseProcAura.ExpiresAt() - sim.CurrentTime - solarIsActive := moonkin.SolarEclipseProcAura.IsActive() - - //"Dispelling" eclipse effects before casting if needed - if float64(lunarUptime-moonkin.Starfire.CurCast.CastTime) <= 0 { - moonkin.LunarEclipseProcAura.Deactivate(sim) - lunarIsActive = false - } - if float64(solarUptime-moonkin.Wrath.CurCast.CastTime) <= 0 { - moonkin.SolarEclipseProcAura.Deactivate(sim) - solarIsActive = false - } - // Player latency adjustments - if lunarIsActive { - lunarIsActive = lunarUptime < (moonkin.LunarEclipseProcAura.Duration - playerLatency) - } - if solarIsActive { - solarIsActive = solarUptime < (moonkin.SolarEclipseProcAura.Duration - playerLatency) - solarICD = 0 - } - - // Eclipse - if solarIsActive || lunarIsActive { - if lunarIsActive { - if canExtendMf && moonkin.ExtendingMoonfireStacks == 0 { - if extendTarget := moonkin.tryExtendMoonfire(sim); extendTarget != nil { - return moonkin.Moonfire, extendTarget - } - } - if (rotation.UseSmartCooldowns && lunarUptime > 10*time.Second) || sim.GetRemainingDuration() < 15*time.Second { - moonkin.castMajorCooldown(moonkin.hyperSpeedMCD, sim, target) - moonkin.castMajorCooldown(moonkin.potionSpeedMCD, sim, target) - moonkin.useTrinkets(stats.SpellHaste, sim, target) - if !moonkin.HasActiveAura("Bloodlust-" + core.BloodlustActionID.WithTag(-1).String()) { - moonkin.castMajorCooldown(moonkin.powerInfusion, sim, target) - } - } - return moonkin.Starfire, target - } else if solarIsActive { - if moonkin.MoonkinT84PCAura.IsActive() { - if moonkin.MoonkinT84PCAura.RemainingDuration(sim) < solarUptime { - return moonkin.Starfire, target - } - } - if canExtendMf && moonkin.ExtendingMoonfireStacks == 0 { - if extendTarget := moonkin.tryExtendMoonfire(sim); extendTarget != nil { - return moonkin.Moonfire, extendTarget - } - } - if (rotation.UseSmartCooldowns && solarUptime > 10*time.Second) || sim.GetRemainingDuration() < 15*time.Second { - moonkin.castMajorCooldown(moonkin.potionWildMagicMCD, sim, target) - moonkin.useTrinkets(stats.SpellCrit, sim, target) - } - if rotation.WrathUsage == proto.BalanceDruid_Rotation_RegularWrath { - return moonkin.Wrath, target - } - } - } - if rotation.MfUsage == proto.BalanceDruid_Rotation_BeforeLunar && lunarICD < 2*time.Second && shouldRefreshMf { - return moonkin.Moonfire, target - } - shouldRefreshIs := moonkin.InsectSwarm.CurDot().RemainingDuration(sim) <= 0 - if rotation.IsUsage == proto.BalanceDruid_Rotation_BeforeSolar && solarICD < 2*time.Second && shouldRefreshIs { - return moonkin.InsectSwarm, target - } - } - - fishingForLunar := lunarICD <= solarICD - if rotation.EclipsePrio == proto.BalanceDruid_Rotation_Solar { - fishingForLunar = lunarICD < solarICD - } - - if canExtendMf && moonkin.ExtendingMoonfireStacks == 0 { - if extendTarget := moonkin.tryExtendMoonfire(sim); extendTarget != nil { - return moonkin.Moonfire, extendTarget - } - } - - // Non-Eclipse - eclipseShuffle := rotation.EclipseShuffling && lunarICD == 0 && solarICD == 0 - if eclipseShuffle && moonkin.LastCast == moonkin.Wrath && rotation.UseStarfire { - return moonkin.Starfire, target - } - if (fishingForLunar || eclipseShuffle) && rotation.WrathUsage != proto.BalanceDruid_Rotation_NoWrath { - return moonkin.Wrath, target - } else { - return moonkin.Starfire, target - } -} - -func (moonkin *BalanceDruid) castMajorCooldown(mcd *core.MajorCooldown, sim *core.Simulation, target *core.Unit) { - if mcd != nil && mcd.Spell.IsReady(sim) { - isOffensivePotion := mcd.Spell.SameAction(core.ActionID{ItemID: 40211}) || mcd.Spell.SameAction(core.ActionID{ItemID: 40212}) - willUseOffensivePotion := isOffensivePotion && !moonkin.potionUsed - - // Use Potion if we can - if isOffensivePotion && moonkin.potionUsed { - return - } - mcd.Spell.Cast(sim, target) - - if willUseOffensivePotion { - moonkin.potionUsed = true - } - moonkin.UpdateMajorCooldowns() - } -} - -func (moonkin *BalanceDruid) useTrinkets(stat stats.Stat, sim *core.Simulation, target *core.Unit) { - if moonkin.onUseTrinket1.Stat == stat { - moonkin.castMajorCooldown(moonkin.onUseTrinket1.Cooldown, sim, target) - } - if moonkin.onUseTrinket2.Stat == stat { - moonkin.castMajorCooldown(moonkin.onUseTrinket2.Cooldown, sim, target) - } -} - -func (moonkin *BalanceDruid) tryExtendMoonfire(sim *core.Simulation) *core.Unit { - if len(sim.Encounter.Targets) < 2 { - return nil - } - minTarget := moonkin.CurrentTarget - minTimer := moonkin.Moonfire.CurDot().RemainingDuration(sim) - for range sim.Encounter.Targets { - if moonkin.Moonfire.CurDot().RemainingDuration(sim) < minTimer { - minTarget = moonkin.CurrentTarget - minTimer = moonkin.Moonfire.CurDot().RemainingDuration(sim) - } - moonkin.CurrentTarget = sim.Environment.NextTargetUnit(moonkin.CurrentTarget) - } - return minTarget -} - -func (moonkin *BalanceDruid) shouldSnapshotMf(sim *core.Simulation, aura *core.Aura) bool { - if aura.IsActive() && aura.RemainingDuration(sim) < moonkin.Moonfire.CurDot().RemainingDuration(sim) { - if moonkin.Moonfire.CurDot().SnapshotBaseDamage < (200 + 0.13*moonkin.Moonfire.CurDot().Spell.SpellPower()) { - return true - } - } - return false -} diff --git a/sim/druid/berserk.go b/sim/druid/berserk.go index 9c189f8c2c..cd58cb4966 100644 --- a/sim/druid/berserk.go +++ b/sim/druid/berserk.go @@ -62,10 +62,8 @@ func (druid *Druid) registerBerserkCD() { }, }) - if druid.IsUsingAPL { - druid.AddMajorCooldown(core.MajorCooldown{ - Spell: druid.Berserk.Spell, - Type: core.CooldownTypeDPS, - }) - } + druid.AddMajorCooldown(core.MajorCooldown{ + Spell: druid.Berserk.Spell, + Type: core.CooldownTypeDPS, + }) } diff --git a/sim/druid/druid.go b/sim/druid/druid.go index c27551ed99..5bd1c29bf1 100644 --- a/sim/druid/druid.go +++ b/sim/druid/druid.go @@ -23,7 +23,6 @@ type Druid struct { StartingForm DruidForm RebirthUsed bool - MaulRageThreshold float64 RebirthTiming float64 BleedsActive int AssumeBleedActive bool @@ -226,7 +225,7 @@ func (druid *Druid) RegisterFeralCatSpells() { druid.registerFerociousBiteSpell() druid.registerMangleBearSpell() druid.registerMangleCatSpell() - druid.registerMaulSpell(0) + druid.registerMaulSpell() druid.registerLacerateSpell() druid.registerRakeSpell() druid.registerRipSpell() @@ -237,7 +236,7 @@ func (druid *Druid) RegisterFeralCatSpells() { druid.registerTigersFurySpell() } -func (druid *Druid) RegisterFeralTankSpells(maulRageThreshold float64) { +func (druid *Druid) RegisterFeralTankSpells() { druid.registerBarkskinCD() druid.registerBerserkCD() druid.registerBearFormSpell() @@ -245,7 +244,7 @@ func (druid *Druid) RegisterFeralTankSpells(maulRageThreshold float64) { druid.registerEnrageSpell() druid.registerFrenziedRegenerationCD() druid.registerMangleBearSpell() - druid.registerMaulSpell(maulRageThreshold) + druid.registerMaulSpell() druid.registerLacerateSpell() druid.registerRakeSpell() druid.registerRipSpell() diff --git a/sim/druid/feral/feral.go b/sim/druid/feral/feral.go index 13e085a5e8..1608d06272 100644 --- a/sim/druid/feral/feral.go +++ b/sim/druid/feral/feral.go @@ -45,9 +45,9 @@ func NewFeralDruid(character *core.Character, options *proto.Player) *FeralDruid cat.PrePopBerserk = feralOptions.Rotation.PrePopBerserk cat.setupRotation(feralOptions.Rotation) - cat.EnableEnergyBar(100.0, cat.OnEnergyGain) + cat.EnableEnergyBar(100.0) - cat.EnableRageBar(core.RageBarOptions{RageMultiplier: 1, MHSwingSpeed: 2.5}, func(sim *core.Simulation) {}) + cat.EnableRageBar(core.RageBarOptions{RageMultiplier: 1, MHSwingSpeed: 2.5}) cat.EnableAutoAttacks(cat, core.AutoAttackOptions{ // Base paw weapon. @@ -96,22 +96,6 @@ func (cat *FeralDruid) MissChance() float64 { func (cat *FeralDruid) Initialize() { cat.Druid.Initialize() cat.RegisterFeralCatSpells() - - if cat.IsUsingAPL { - return - } - - if cat.prepopOoc && cat.Talents.OmenOfClarity { - cat.RegisterPrepullAction(-time.Second, func(sim *core.Simulation) { - cat.ProcOoc(sim) - }) - } - - if cat.PrePopBerserk && cat.Talents.Berserk { - cat.RegisterPrepullAction(-time.Second, func(sim *core.Simulation) { - cat.Berserk.Cast(sim, nil) - }) - } } func (cat *FeralDruid) Reset(sim *core.Simulation) { diff --git a/sim/druid/feral/rotation.go b/sim/druid/feral/rotation.go index 5fa1b6a1df..4694a15739 100644 --- a/sim/druid/feral/rotation.go +++ b/sim/druid/feral/rotation.go @@ -9,30 +9,11 @@ import ( "github.com/wowsims/wotlk/sim/druid" ) -func (cat *FeralDruid) OnEnergyGain(sim *core.Simulation) { - if cat.IsUsingAPL && !cat.usingHardcodedAPL { - return - } - - if sim.CurrentTime < 0 { - return - } - - cat.TryUseCooldowns(sim) - if cat.InForm(druid.Cat) && !cat.readyToShift { - cat.doTigersFury(sim) - } -} - func (cat *FeralDruid) OnGCDReady(sim *core.Simulation) { - if cat.IsUsingAPL && !cat.usingHardcodedAPL { + if !cat.usingHardcodedAPL { return } - if !cat.IsUsingAPL { - cat.TryUseCooldowns(sim) - } - if !cat.GCD.IsReady(sim) { return } @@ -56,33 +37,12 @@ func (cat *FeralDruid) OnGCDReady(sim *core.Simulation) { // Replace gcd event with our own if we casted a spell if !cat.GCD.IsReady(sim) { nextGcd := cat.NextGCDAt() - cat.DoNothing() cat.CancelGCDTimer(sim) cat.NextRotationAction(sim, nextGcd) } } -func (cat *FeralDruid) OnAutoAttack(sim *core.Simulation, _ *core.Spell) { - if cat.IsUsingAPL { - return - } - - if cat.InForm(druid.Humanoid) { - panic("auto attack out of form?") - } - - // If the swing resulted in an Omen proc, then schedule the - // next player decision based on latency. - - if cat.Talents.OmenOfClarity && cat.ClearcastingAura.RemainingDuration(sim) == cat.ClearcastingAura.Duration { - // Kick gcd loop, also need to account for any gcd 'left' - // otherwise it breaks gcd logic - kickTime := max(cat.NextGCDAt(), sim.CurrentTime+cat.latency) - cat.NextRotationAction(sim, kickTime) - } -} - func (cat *FeralDruid) NextRotationAction(sim *core.Simulation, kickAt time.Duration) { if cat.rotationAction != nil { cat.rotationAction.Cancel(sim) @@ -97,62 +57,8 @@ func (cat *FeralDruid) NextRotationAction(sim *core.Simulation, kickAt time.Dura sim.AddPendingAction(cat.rotationAction) } -// Ported from https://github.com/NerdEgghead/WOTLK_cat_sim - func (cat *FeralDruid) checkReplaceMaul(sim *core.Simulation, mhSwingSpell *core.Spell) *core.Spell { - if cat.IsUsingAPL { - return mhSwingSpell - } - - // If we have enough time and Energy leeway to stay in - // Dire Bear Form once the GCD expires, then only Maul if we - // will be left with enough Rage to cast Mangle or Lacerate - // on that global. - - ripDot := cat.Rip.CurDot() - - furorCap := min(20.0*float64(cat.Talents.Furor), 85.0) - ripRefreshPending := ripDot.IsActive() && (ripDot.RemainingDuration(sim) < sim.GetRemainingDuration()-time.Second*10) - gcdTimeToRdy := cat.GCD.TimeToReady(sim) - energyLeeway := furorCap - 15.0 - float64((gcdTimeToRdy+cat.latency)/core.EnergyTickDuration) - shiftNext := cat.CurrentEnergy() > energyLeeway - - if ripRefreshPending { - shiftNext = shiftNext || (ripDot.RemainingDuration(sim) < (gcdTimeToRdy + time.Second*3)) - } - - lacerateNext := false - emergencyLacerateNext := false - mangleNext := false - - lacerateDot := cat.Lacerate.CurDot() - if cat.Rotation.BearweaveType == proto.FeralDruid_Rotation_Lacerate { - lacerateLeeway := cat.Rotation.LacerateTime + gcdTimeToRdy - lacerateNext = !lacerateDot.IsActive() || (lacerateDot.GetStacks() < 5) || (lacerateDot.RemainingDuration(sim) <= lacerateLeeway) - emergencyLeeway := gcdTimeToRdy + (3 * time.Second) + (2 * cat.latency) - emergencyLacerateNext = lacerateDot.IsActive() && (lacerateDot.RemainingDuration(sim) <= emergencyLeeway) - mangleNext = cat.MangleBear != nil && !lacerateNext && (!cat.bleedAura.IsActive() || (cat.bleedAura.RemainingDuration(sim) < gcdTimeToRdy+time.Second*3) || (sim.CurrentTime-cat.lastShift < time.Duration(1500*time.Millisecond))) - } else { - mangleNext = cat.MangleBear != nil && cat.MangleBear.TimeToReady(sim) < gcdTimeToRdy - lacerateNext = lacerateDot.IsActive() && (lacerateDot.GetStacks() < 5 || lacerateDot.RemainingDuration(sim) < gcdTimeToRdy+(time.Second*4)) - } - - maulRageThresh := 10.0 - if emergencyLacerateNext { - maulRageThresh += cat.Lacerate.DefaultCast.Cost - } else if shiftNext { - maulRageThresh = 10.0 - } else if mangleNext { - maulRageThresh += cat.MangleBear.DefaultCast.Cost - } else if lacerateNext { - maulRageThresh += cat.Lacerate.DefaultCast.Cost - } - - if cat.CurrentRage() >= maulRageThresh { - return cat.Maul.Spell - } else { - return mhSwingSpell - } + return mhSwingSpell } func (cat *FeralDruid) shiftBearCat(sim *core.Simulation, powershift bool) bool { diff --git a/sim/druid/hurricane.go b/sim/druid/hurricane.go index 7ccedd3433..b13106b6d1 100644 --- a/sim/druid/hurricane.go +++ b/sim/druid/hurricane.go @@ -37,8 +37,7 @@ func (druid *Druid) registerHurricaneSpell() { }, Cast: core.CastConfig{ DefaultCast: core.Cast{ - GCD: core.GCDDefault, - ChannelTime: time.Second * 10, + GCD: core.GCDDefault, }, }, Dot: core.DotConfig{ diff --git a/sim/druid/maul.go b/sim/druid/maul.go index 600d2399e4..cf82c24d2b 100644 --- a/sim/druid/maul.go +++ b/sim/druid/maul.go @@ -5,7 +5,7 @@ import ( "github.com/wowsims/wotlk/sim/core/proto" ) -func (druid *Druid) registerMaulSpell(rageThreshold float64) { +func (druid *Druid) registerMaulSpell() { flatBaseDamage := 578.0 if druid.Ranged().ID == 23198 { // Idol of Brutality flatBaseDamage += 50 @@ -87,11 +87,6 @@ func (druid *Druid) registerMaulSpell(rageThreshold float64) { druid.MaulQueueAura.Activate(sim) }, }) - - druid.MaulRageThreshold = max(druid.Maul.DefaultCast.Cost, rageThreshold) - if druid.IsUsingAPL { - druid.MaulRageThreshold = 0 - } } func (druid *Druid) QueueMaul(sim *core.Simulation) { @@ -106,11 +101,6 @@ func (druid *Druid) MaulReplaceMH(sim *core.Simulation, mhSwingSpell *core.Spell return mhSwingSpell } - if druid.CurrentRage() < druid.MaulRageThreshold { - druid.MaulQueueAura.Deactivate(sim) - return mhSwingSpell - } - if !druid.Maul.Spell.CanCast(sim, druid.CurrentTarget) { druid.MaulQueueAura.Deactivate(sim) return mhSwingSpell @@ -118,7 +108,3 @@ func (druid *Druid) MaulReplaceMH(sim *core.Simulation, mhSwingSpell *core.Spell return druid.Maul.Spell } - -func (druid *Druid) ShouldQueueMaul(_ *core.Simulation) bool { - return druid.CurrentRage() >= druid.MaulRageThreshold -} diff --git a/sim/druid/talents.go b/sim/druid/talents.go index b3d944c3c7..3a63ceadc1 100644 --- a/sim/druid/talents.go +++ b/sim/druid/talents.go @@ -399,7 +399,7 @@ func (druid *Druid) applyOmenOfClarity() { // https://github.com/JamminL/wotlk-classic-bugs/issues/66#issuecomment-1182017571 if druid.HurricaneTickSpell.IsEqual(spell) { - curCastTickSpeed := spell.CurCast.ChannelTime.Seconds() / 10 + curCastTickSpeed := spell.CurDot().TickPeriod().Seconds() / 10 hurricaneCoeff := 1.0 - (7.0 / 9.0) spellCoeff := hurricaneCoeff * curCastTickSpeed chanceToProc := ((1.5 / 60) * 3.5) * spellCoeff diff --git a/sim/druid/tank/rotation.go b/sim/druid/tank/rotation.go deleted file mode 100644 index f1c75829b8..0000000000 --- a/sim/druid/tank/rotation.go +++ /dev/null @@ -1,88 +0,0 @@ -package tank - -import ( - "time" - - "github.com/wowsims/wotlk/sim/core" -) - -func (bear *FeralTankDruid) OnGCDReady(sim *core.Simulation) { - bear.doRotation(sim) -} - -func (bear *FeralTankDruid) OnAutoAttack(sim *core.Simulation, _ *core.Spell) { - bear.tryQueueMaul(sim) -} - -func (bear *FeralTankDruid) doRotation(sim *core.Simulation) { - if bear.GCD.IsReady(sim) { - if bear.shouldSaveLacerateStacks(sim) && bear.Lacerate.CanCast(sim, bear.CurrentTarget) { - bear.Lacerate.Cast(sim, bear.CurrentTarget) - } else if bear.shouldDemoRoar(sim) { - bear.DemoralizingRoar.Cast(sim, bear.CurrentTarget) - } else if bear.Berserk.IsReady(sim) { - bear.Berserk.Cast(sim, nil) - } else if bear.MangleBear.CanCast(sim, bear.CurrentTarget) { - bear.MangleBear.Cast(sim, bear.CurrentTarget) - } else if bear.shouldFaerieFire(sim) { - bear.FaerieFire.Cast(sim, bear.CurrentTarget) - } else if bear.shouldLacerate(sim) { - bear.Lacerate.Cast(sim, bear.CurrentTarget) - } else if bear.shouldSwipe(sim) { - bear.SwipeBear.Cast(sim, bear.CurrentTarget) - } - } - - if bear.GCD.IsReady(sim) { - nextAction := bear.FaerieFire.ReadyAt() - - if bear.MangleBear == nil { - bear.WaitUntil(sim, nextAction) - } else if !bear.MangleBear.IsReady(sim) { - nextAction = max(nextAction, sim.CurrentTime) - nextMangle := bear.MangleBear.ReadyAt() - - if nextMangle < nextAction+time.Second { - nextAction = nextMangle - } - - if nextAction > sim.CurrentTime { - bear.WaitUntil(sim, nextAction) - } - } - } - - bear.tryQueueMaul(sim) - bear.DoNothing() // means we intionally have no other action if all else fails. -} - -func (bear *FeralTankDruid) shouldSaveLacerateStacks(sim *core.Simulation) bool { - lacerateDot := bear.Lacerate.CurDot() - return lacerateDot.GetStacks() == 5 && - lacerateDot.RemainingDuration(sim) <= time.Millisecond*1500 -} - -func (bear *FeralTankDruid) shouldSwipe(sim *core.Simulation) bool { - return bear.SwipeBear.CanCast(sim, bear.CurrentTarget) && - ((bear.MangleBear == nil) || (bear.MangleBear.ReadyAt() >= sim.CurrentTime+core.GCDDefault)) && - bear.CurrentRage()-bear.SwipeBear.DefaultCast.Cost >= bear.MaulRageThreshold -} - -func (bear *FeralTankDruid) tryQueueMaul(sim *core.Simulation) { - if bear.ShouldQueueMaul(sim) { - bear.QueueMaul(sim) - } -} - -func (bear *FeralTankDruid) shouldDemoRoar(sim *core.Simulation) bool { - return bear.ShouldDemoralizingRoar(sim, false, bear.Rotation.MaintainDemoralizingRoar) -} - -func (bear *FeralTankDruid) shouldFaerieFire(sim *core.Simulation) bool { - return bear.FaerieFire.IsReady(sim) && ((bear.MangleBear == nil) || (bear.MangleBear.ReadyAt() >= sim.CurrentTime+time.Second)) -} - -func (bear *FeralTankDruid) shouldLacerate(sim *core.Simulation) bool { - lacerateDot := bear.Lacerate.CurDot() - return bear.Lacerate.CanCast(sim, bear.CurrentTarget) && ((bear.MangleBear == nil) || (bear.MangleBear.ReadyAt() >= sim.CurrentTime+core.GCDDefault)) && ((lacerateDot.GetStacks() < 5) || (lacerateDot.RemainingDuration(sim) <= time.Duration(bear.Rotation.LacerateTime*float64(time.Second)))) -} diff --git a/sim/druid/tank/tank.go b/sim/druid/tank/tank.go index cd8e1f895a..21fab7ceeb 100644 --- a/sim/druid/tank/tank.go +++ b/sim/druid/tank/tank.go @@ -28,9 +28,8 @@ func NewFeralTankDruid(character *core.Character, options *proto.Player) *FeralT selfBuffs := druid.SelfBuffs{} bear := &FeralTankDruid{ - Druid: druid.New(character, druid.Bear, selfBuffs, options.TalentsString), - Rotation: tankOptions.Rotation, - Options: tankOptions.Options, + Druid: druid.New(character, druid.Bear, selfBuffs, options.TalentsString), + Options: tankOptions.Options, } bear.SelfBuffs.InnervateTarget = &proto.UnitReference{} @@ -64,8 +63,7 @@ func NewFeralTankDruid(character *core.Character, options *proto.Player) *FeralT type FeralTankDruid struct { *druid.Druid - Rotation *proto.FeralTankDruid_Rotation - Options *proto.FeralTankDruid_Options + Options *proto.FeralTankDruid_Options } func (bear *FeralTankDruid) GetDruid() *druid.Druid { @@ -74,7 +72,7 @@ func (bear *FeralTankDruid) GetDruid() *druid.Druid { func (bear *FeralTankDruid) Initialize() { bear.Druid.Initialize() - bear.RegisterFeralTankSpells(float64(bear.Rotation.MaulRageThreshold)) + bear.RegisterFeralTankSpells() } func (bear *FeralTankDruid) Reset(sim *core.Simulation) { From 3ec99cc8ef3c6eb38dd9e5a5fa11ab639980e6a9 Mon Sep 17 00:00:00 2001 From: James Tanner Date: Thu, 4 Jan 2024 19:57:23 -0800 Subject: [PATCH 07/28] Finish druid and mage --- sim/deathknight/dps/TestBlood.results | 12 +- sim/deathknight/dps/TestUnholy.results | 568 ++++++++++++------------- sim/druid/druid.go | 1 - sim/druid/feral/feral.go | 1 - sim/druid/restoration/restoration.go | 6 +- sim/druid/restoration/rotation.go | 15 - sim/hunter/aspects.go | 2 +- sim/lib/library.go | 2 - sim/mage/TestArcane.results | 4 +- sim/mage/TestFire.results | 8 +- sim/mage/TestFrost.results | 416 +++++++++--------- sim/mage/arcane_blast.go | 3 - sim/mage/arcane_missiles.go | 3 +- sim/mage/blizzard.go | 3 +- sim/mage/evocation.go | 3 +- sim/mage/mage.go | 30 +- sim/mage/rotations.go | 155 ------- 17 files changed, 511 insertions(+), 721 deletions(-) delete mode 100644 sim/druid/restoration/rotation.go delete mode 100644 sim/mage/rotations.go diff --git a/sim/deathknight/dps/TestBlood.results b/sim/deathknight/dps/TestBlood.results index a4f19e677b..5102649157 100644 --- a/sim/deathknight/dps/TestBlood.results +++ b/sim/deathknight/dps/TestBlood.results @@ -287,8 +287,8 @@ dps_results: { dps_results: { key: "TestBlood-AllItems-EphemeralSnowflake-50260" value: { - dps: 10443.90447 - tps: 5277.80696 + dps: 10467.28296 + tps: 5296.53902 } } dps_results: { @@ -666,8 +666,8 @@ dps_results: { dps_results: { key: "TestBlood-AllItems-SphereofRedDragon'sBlood-37166" value: { - dps: 10383.49361 - tps: 5254.72979 + dps: 10350.69235 + tps: 5235.5789 } } dps_results: { @@ -778,8 +778,8 @@ dps_results: { dps_results: { key: "TestBlood-AllItems-TomeofArcanePhenomena-36972" value: { - dps: 10379.62764 - tps: 5242.10503 + dps: 10317.50284 + tps: 5211.82802 } } dps_results: { diff --git a/sim/deathknight/dps/TestUnholy.results b/sim/deathknight/dps/TestUnholy.results index b00336dda8..e31fee5d05 100644 --- a/sim/deathknight/dps/TestUnholy.results +++ b/sim/deathknight/dps/TestUnholy.results @@ -46,984 +46,984 @@ character_stats_results: { dps_results: { key: "TestUnholy-AllItems-Althor'sAbacus-50359" value: { - dps: 9710.58503 - tps: 5711.54761 + dps: 9680.47429 + tps: 5704.45855 hps: 63.52617 } } dps_results: { key: "TestUnholy-AllItems-Althor'sAbacus-50366" value: { - dps: 9710.58503 - tps: 5711.54761 + dps: 9680.47429 + tps: 5704.45855 hps: 66.3402 } } dps_results: { key: "TestUnholy-AllItems-AustereEarthsiegeDiamond" value: { - dps: 10248.30721 - tps: 5886.95782 + dps: 10217.92511 + tps: 5880.532 hps: 42.71551 } } dps_results: { key: "TestUnholy-AllItems-Bandit'sInsignia-40371" value: { - dps: 9924.17016 - tps: 5866.99266 + dps: 9893.9745 + tps: 5859.94867 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-BaubleofTrueBlood-50354" value: { - dps: 9710.59693 - tps: 5711.60656 + dps: 9680.48618 + tps: 5704.5175 hps: 134.78881 } } dps_results: { key: "TestUnholy-AllItems-BaubleofTrueBlood-50726" value: { - dps: 9710.59693 - tps: 5711.60656 + dps: 9680.48618 + tps: 5704.5175 hps: 134.78881 } } dps_results: { key: "TestUnholy-AllItems-BeamingEarthsiegeDiamond" value: { - dps: 10270.83734 - tps: 5906.78165 + dps: 10240.42421 + tps: 5900.33685 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Beast-tamer'sShoulders-30892" value: { - dps: 9590.63003 - tps: 5434.59411 + dps: 9561.27606 + tps: 5428.86625 hps: 40.4349 } } dps_results: { key: "TestUnholy-AllItems-BlessedBattlegearofUndeadSlaying" value: { - dps: 7528.9716 - tps: 4272.7715 + dps: 7500.6957 + tps: 4266.20781 hps: 34.38394 } } dps_results: { key: "TestUnholy-AllItems-BlessedGarboftheUndeadSlayer" value: { - dps: 7417.57124 - tps: 4240.52367 + dps: 7390.28759 + tps: 4234.65809 hps: 32.96775 } } dps_results: { key: "TestUnholy-AllItems-BlessedRegaliaofUndeadCleansing" value: { - dps: 7201.24066 - tps: 4096.56066 + dps: 7173.57707 + tps: 4090.382 hps: 32.72866 } } dps_results: { key: "TestUnholy-AllItems-BracingEarthsiegeDiamond" value: { - dps: 10248.30721 - tps: 5769.21867 + dps: 10217.92511 + tps: 5762.92136 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Bryntroll,theBoneArbiter-50415" value: { - dps: 10377.44167 - tps: 5996.15064 + dps: 10346.91539 + tps: 5989.61257 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Bryntroll,theBoneArbiter-50709" value: { - dps: 10377.44167 - tps: 5996.15064 + dps: 10346.91539 + tps: 5989.61257 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ChaoticSkyflareDiamond" value: { - dps: 10384.12635 - tps: 6001.95118 + dps: 10353.5962 + tps: 5995.41414 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-CorpseTongueCoin-50349" value: { - dps: 9710.60578 - tps: 5711.54461 + dps: 9680.49504 + tps: 5704.45555 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-CorpseTongueCoin-50352" value: { - dps: 9710.60578 - tps: 5711.54461 + dps: 9680.49504 + tps: 5704.45555 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-CorrodedSkeletonKey-50356" value: { - dps: 9710.60578 - tps: 5711.54461 + dps: 9680.49504 + tps: 5704.45555 hps: 110.32034 } } dps_results: { key: "TestUnholy-AllItems-DarkmoonCard:Berserker!-42989" value: { - dps: 9841.85262 - tps: 5824.32161 + dps: 9811.44494 + tps: 5817.02786 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-DarkmoonCard:Death-42990" value: { - dps: 9904.01516 - tps: 5871.41583 + dps: 9873.64594 + tps: 5864.21871 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-DarkmoonCard:Greatness-44255" value: { - dps: 10016.40898 - tps: 5851.61296 + dps: 9986.29823 + tps: 5844.5239 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-DarkrunedBattlegear" value: { - dps: 8342.40652 - tps: 4728.74456 + dps: 8313.25385 + tps: 4722.11602 hps: 38.90837 } } dps_results: { key: "TestUnholy-AllItems-DarkrunedPlate" value: { - dps: 7455.04498 - tps: 4195.27998 + dps: 7427.64393 + tps: 4189.2183 hps: 40.98666 } } dps_results: { key: "TestUnholy-AllItems-DeadlyGladiator'sSigilofStrife-42620" value: { - dps: 10428.94056 - tps: 6026.53603 + dps: 10398.41427 + tps: 6019.99796 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-DeathKnight'sAnguish-38212" value: { - dps: 9814.76517 - tps: 5800.54798 + dps: 9784.41797 + tps: 5793.32415 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Deathbringer'sWill-50362" value: { - dps: 10244.26393 - tps: 6019.38836 + dps: 10212.23545 + tps: 6011.7831 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Deathbringer'sWill-50363" value: { - dps: 10336.93352 - tps: 6134.04278 + dps: 10304.74071 + tps: 6126.35152 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Defender'sCode-40257" value: { - dps: 9710.60578 - tps: 5711.54461 + dps: 9680.49504 + tps: 5704.45555 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-DestructiveSkyflareDiamond" value: { - dps: 10275.66073 - tps: 5910.13257 + dps: 10245.17112 + tps: 5903.63941 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-DislodgedForeignObject-50348" value: { - dps: 10058.86423 - tps: 5920.2823 + dps: 10027.7374 + tps: 5913.21833 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-DislodgedForeignObject-50353" value: { - dps: 10045.90755 - tps: 5870.04449 + dps: 10015.90074 + tps: 5863.92416 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-EffulgentSkyflareDiamond" value: { - dps: 10248.30721 - tps: 5886.95782 + dps: 10217.92511 + tps: 5880.532 hps: 42.71551 } } dps_results: { key: "TestUnholy-AllItems-EmberSkyflareDiamond" value: { - dps: 10248.30721 - tps: 5886.95782 + dps: 10217.92511 + tps: 5880.532 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-EnigmaticSkyflareDiamond" value: { - dps: 10270.83734 - tps: 5906.78165 + dps: 10240.42421 + tps: 5900.33685 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-EnigmaticStarflareDiamond" value: { - dps: 10269.30196 - tps: 5905.31005 + dps: 10238.88528 + tps: 5898.8624 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-EphemeralSnowflake-50260" value: { - dps: 9960.43305 - tps: 5713.77531 + dps: 9957.51073 + tps: 5686.58021 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-EssenceofGossamer-37220" value: { - dps: 9710.60578 - tps: 5711.54461 + dps: 9680.49504 + tps: 5704.45555 hps: 44.16848 } } dps_results: { key: "TestUnholy-AllItems-EternalEarthsiegeDiamond" value: { - dps: 10248.30721 - tps: 5886.95782 + dps: 10217.92511 + tps: 5880.532 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ExtractofNecromanticPower-40373" value: { - dps: 9884.46426 - tps: 5855.45523 + dps: 9854.14952 + tps: 5848.27771 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-EyeoftheBroodmother-45308" value: { - dps: 9829.83582 - tps: 5812.66149 + dps: 9799.48063 + tps: 5805.4028 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Figurine-SapphireOwl-42413" value: { - dps: 9710.60578 - tps: 5711.54461 + dps: 9680.49504 + tps: 5704.45555 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ForethoughtTalisman-40258" value: { - dps: 9710.60578 - tps: 5711.54461 + dps: 9680.49504 + tps: 5704.45555 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ForgeEmber-37660" value: { - dps: 9809.03194 - tps: 5795.31409 + dps: 9778.71591 + tps: 5788.07856 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ForlornSkyflareDiamond" value: { - dps: 10248.30721 - tps: 5886.95782 + dps: 10217.92511 + tps: 5880.532 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ForlornStarflareDiamond" value: { - dps: 10248.30721 - tps: 5886.95782 + dps: 10217.92511 + tps: 5880.532 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-FuriousGladiator'sSigilofStrife-42621" value: { - dps: 10439.24034 - tps: 6032.61311 + dps: 10408.71405 + tps: 6026.07503 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-FuryoftheFiveFlights-40431" value: { - dps: 9935.80342 - tps: 5878.29335 + dps: 9905.69267 + tps: 5871.20429 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-FuturesightRune-38763" value: { - dps: 9710.60578 - tps: 5711.54461 + dps: 9680.49504 + tps: 5704.45555 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-GlowingTwilightScale-54573" value: { - dps: 9710.60578 - tps: 5711.54461 + dps: 9680.49504 + tps: 5704.45555 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-GlowingTwilightScale-54589" value: { - dps: 9710.60578 - tps: 5711.54461 + dps: 9680.49504 + tps: 5704.45555 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-GnomishLightningGenerator-41121" value: { - dps: 9862.40069 - tps: 5837.60588 + dps: 9832.05026 + tps: 5830.41915 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-HatefulGladiator'sSigilofStrife-42619" value: { - dps: 10406.95035 - tps: 6012.39309 + dps: 10376.42406 + tps: 6005.85502 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-IllustrationoftheDragonSoul-40432" value: { - dps: 9710.60578 - tps: 5711.54461 + dps: 9680.49504 + tps: 5704.45555 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ImpassiveSkyflareDiamond" value: { - dps: 10270.83734 - tps: 5906.78165 + dps: 10240.42421 + tps: 5900.33685 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ImpassiveStarflareDiamond" value: { - dps: 10269.30196 - tps: 5905.31005 + dps: 10238.88528 + tps: 5898.8624 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-IncisorFragment-37723" value: { - dps: 9889.84971 - tps: 5849.80123 + dps: 9858.84411 + tps: 5841.99589 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-InsightfulEarthsiegeDiamond" value: { - dps: 10248.30721 - tps: 5886.95782 + dps: 10217.92511 + tps: 5880.532 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-InvigoratingEarthsiegeDiamond" value: { - dps: 10280.82071 - tps: 5909.54809 + dps: 10250.43861 + tps: 5903.12227 hps: 58.71565 } } dps_results: { key: "TestUnholy-AllItems-LastWord-50179" value: { - dps: 10377.44167 - tps: 5996.15064 + dps: 10346.91539 + tps: 5989.61257 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-LastWord-50708" value: { - dps: 10377.44167 - tps: 5996.15064 + dps: 10346.91539 + tps: 5989.61257 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Lavanthor'sTalisman-37872" value: { - dps: 9710.60578 - tps: 5711.54461 + dps: 9680.49504 + tps: 5704.45555 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-MajesticDragonFigurine-40430" value: { - dps: 9710.60578 - tps: 5711.54461 + dps: 9680.49504 + tps: 5704.45555 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-MeteoriteWhetstone-37390" value: { - dps: 10032.0625 - tps: 5843.61227 + dps: 10002.66676 + tps: 5837.61294 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-NevermeltingIceCrystal-50259" value: { - dps: 9859.78621 - tps: 5842.11561 + dps: 9829.70588 + tps: 5834.98049 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-OfferingofSacrifice-37638" value: { - dps: 9710.60578 - tps: 5711.54461 + dps: 9680.49504 + tps: 5704.45555 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-PersistentEarthshatterDiamond" value: { - dps: 10274.62766 - tps: 5905.24519 + dps: 10244.24556 + tps: 5898.81936 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-PersistentEarthsiegeDiamond" value: { - dps: 10280.82071 - tps: 5909.54809 + dps: 10250.43861 + tps: 5903.12227 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-PetrifiedScarab-21685" value: { - dps: 9710.60578 - tps: 5711.54461 + dps: 9680.49504 + tps: 5704.45555 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-PetrifiedTwilightScale-54571" value: { - dps: 9710.60578 - tps: 5711.54461 + dps: 9680.49504 + tps: 5704.45555 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-PetrifiedTwilightScale-54591" value: { - dps: 9710.60578 - tps: 5711.54461 + dps: 9680.49504 + tps: 5704.45555 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-PowerfulEarthshatterDiamond" value: { - dps: 10248.30721 - tps: 5886.95782 + dps: 10217.92511 + tps: 5880.532 hps: 42.60516 } } dps_results: { key: "TestUnholy-AllItems-PowerfulEarthsiegeDiamond" value: { - dps: 10248.30721 - tps: 5886.95782 + dps: 10217.92511 + tps: 5880.532 hps: 42.71551 } } dps_results: { key: "TestUnholy-AllItems-PurifiedShardoftheGods" value: { - dps: 9710.60578 - tps: 5711.54461 + dps: 9680.49504 + tps: 5704.45555 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ReignoftheDead-47316" value: { - dps: 9785.06353 - tps: 5770.6385 + dps: 9754.94571 + tps: 5763.56884 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ReignoftheDead-47477" value: { - dps: 9792.15193 - tps: 5776.63924 + dps: 9762.03411 + tps: 5769.56958 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-RelentlessEarthsiegeDiamond" value: { - dps: 10377.44167 - tps: 5996.15064 + dps: 10346.91539 + tps: 5989.61257 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-RelentlessGladiator'sSigilofStrife-42622" value: { - dps: 10451.25674 - tps: 6039.70303 + dps: 10420.73045 + tps: 6033.16496 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-RevitalizingSkyflareDiamond" value: { - dps: 10248.30721 - tps: 5886.95782 + dps: 10217.92511 + tps: 5880.532 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-RuneofRepulsion-40372" value: { - dps: 9710.60578 - tps: 5711.54461 + dps: 9680.49504 + tps: 5704.45555 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SavageGladiator'sSigilofStrife-42618" value: { - dps: 10403.60974 - tps: 6010.55432 + dps: 10373.08345 + tps: 6004.01625 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ScourgeborneBattlegear" value: { - dps: 8029.52875 - tps: 4566.12376 + dps: 8000.74515 + tps: 4559.84406 hps: 36.48062 } } dps_results: { key: "TestUnholy-AllItems-ScourgebornePlate" value: { - dps: 7364.82744 - tps: 4120.861 + dps: 7338.02073 + tps: 4115.32448 hps: 38.04394 } } dps_results: { key: "TestUnholy-AllItems-Scourgelord'sBattlegear" value: { - dps: 9358.46371 - tps: 5521.64302 + dps: 9330.42072 + tps: 5515.28971 hps: 44.60989 } } dps_results: { key: "TestUnholy-AllItems-Scourgelord'sPlate" value: { - dps: 8219.42444 - tps: 4642.08454 + dps: 8192.96648 + tps: 4636.93277 hps: 48.06758 } } dps_results: { key: "TestUnholy-AllItems-SealofthePantheon-36993" value: { - dps: 9710.60578 - tps: 5711.54461 + dps: 9680.49504 + tps: 5704.45555 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Shadowmourne-49623" value: { - dps: 10377.44167 - tps: 5996.15064 + dps: 10346.91539 + tps: 5989.61257 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ShinyShardoftheGods" value: { - dps: 9710.60578 - tps: 5711.54461 + dps: 9680.49504 + tps: 5704.45555 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SigilofDeflection-45144" value: { - dps: 10377.44167 - tps: 5996.15064 + dps: 10346.91539 + tps: 5989.61257 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SigilofHauntedDreams-40715" value: { - dps: 10407.04323 - tps: 6021.87725 + dps: 10376.62308 + tps: 6015.42194 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SigilofInsolence-47672" value: { - dps: 10377.44167 - tps: 5996.15064 + dps: 10346.91539 + tps: 5989.61257 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SigiloftheBoneGryphon-50462" value: { - dps: 10377.44167 - tps: 5996.15064 + dps: 10346.91539 + tps: 5989.61257 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SigiloftheHangedMan-50459" value: { - dps: 10377.44167 - tps: 5996.15064 + dps: 10346.91539 + tps: 5989.61257 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SigiloftheUnfalteringKnight-40714" value: { - dps: 10377.44167 - tps: 5996.15064 + dps: 10346.91539 + tps: 5989.61257 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Sindragosa'sFlawlessFang-50361" value: { - dps: 9710.60578 - tps: 5711.54461 + dps: 9680.49504 + tps: 5704.45555 hps: 46.32034 } } dps_results: { key: "TestUnholy-AllItems-SliverofPureIce-50339" value: { - dps: 9710.60578 - tps: 5711.54461 + dps: 9680.49504 + tps: 5704.45555 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SliverofPureIce-50346" value: { - dps: 9710.60578 - tps: 5711.54461 + dps: 9680.49504 + tps: 5704.45555 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SoulPreserver-37111" value: { - dps: 9710.60578 - tps: 5711.54461 + dps: 9680.49504 + tps: 5704.45555 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SouloftheDead-40382" value: { - dps: 9832.82416 - tps: 5816.15563 + dps: 9802.43285 + tps: 5808.86704 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SparkofLife-37657" value: { - dps: 9862.05029 - tps: 5804.30139 + dps: 9832.06089 + tps: 5797.8349 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SphereofRedDragon'sBlood-37166" value: { - dps: 9913.75663 - tps: 5850.97982 + dps: 9800.6582 + tps: 5811.52763 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-StormshroudArmor" value: { - dps: 7095.52999 - tps: 4057.87955 + dps: 7067.22499 + tps: 4050.80338 hps: 30.7975 } } dps_results: { key: "TestUnholy-AllItems-SwiftSkyflareDiamond" value: { - dps: 10280.82071 - tps: 5909.54809 + dps: 10250.43861 + tps: 5903.12227 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SwiftStarflareDiamond" value: { - dps: 10274.62766 - tps: 5905.24519 + dps: 10244.24556 + tps: 5898.81936 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SwiftWindfireDiamond" value: { - dps: 10263.78983 - tps: 5897.7151 + dps: 10233.40773 + tps: 5891.28927 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TalismanofTrollDivinity-37734" value: { - dps: 9710.60578 - tps: 5711.54461 + dps: 9680.49504 + tps: 5704.45555 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TearsoftheVanquished-47215" value: { - dps: 9710.60578 - tps: 5711.54461 + dps: 9680.49504 + tps: 5704.45555 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Thassarian'sBattlegear" value: { - dps: 8618.51653 - tps: 4958.8001 + dps: 8590.35604 + tps: 4952.61627 hps: 38.68766 } } dps_results: { key: "TestUnholy-AllItems-Thassarian'sPlate" value: { - dps: 7486.10663 - tps: 4194.90667 + dps: 7458.635 + tps: 4188.82468 hps: 40.30616 } } dps_results: { key: "TestUnholy-AllItems-TheGeneral'sHeart-45507" value: { - dps: 9710.60578 - tps: 5711.54461 + dps: 9680.49504 + tps: 5704.45555 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TheTwinBladesofAzzinoth" value: { - dps: 9010.98248 - tps: 5032.12724 + dps: 8979.88721 + tps: 5025.14863 hps: 40.74757 } } dps_results: { key: "TestUnholy-AllItems-ThunderingSkyflareDiamond" value: { - dps: 10305.50604 - tps: 5918.26645 + dps: 10275.22899 + tps: 5912.27746 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TinyAbominationinaJar-50351" value: { - dps: 9954.00729 - tps: 5913.58867 + dps: 9924.59603 + tps: 5907.08552 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TinyAbominationinaJar-50706" value: { - dps: 9920.42339 - tps: 5880.41645 + dps: 9890.45908 + tps: 5873.52857 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TirelessSkyflareDiamond" value: { - dps: 10248.30721 - tps: 5886.95782 + dps: 10217.92511 + tps: 5880.532 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TirelessStarflareDiamond" value: { - dps: 10248.30721 - tps: 5886.95782 + dps: 10217.92511 + tps: 5880.532 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TomeofArcanePhenomena-36972" value: { - dps: 9840.77218 - tps: 5774.12915 + dps: 9826.9966 + tps: 5751.9898 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TrenchantEarthshatterDiamond" value: { - dps: 10248.30721 - tps: 5886.95782 + dps: 10217.92511 + tps: 5880.532 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TrenchantEarthsiegeDiamond" value: { - dps: 10248.30721 - tps: 5886.95782 + dps: 10217.92511 + tps: 5880.532 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-UndeadSlayer'sBlessedArmor" value: { - dps: 7423.03446 - tps: 4256.35867 + dps: 7395.21167 + tps: 4250.00861 hps: 33.68504 } } dps_results: { key: "TestUnholy-AllItems-Val'anyr,HammerofAncientKings-46017" value: { - dps: 9633.49282 - tps: 5427.26413 + dps: 9602.82536 + tps: 5420.6152 hps: 42.81036 } } dps_results: { key: "TestUnholy-AllItems-WingedTalisman-37844" value: { - dps: 9710.60578 - tps: 5711.54461 + dps: 9680.49504 + tps: 5704.45555 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-WrathfulGladiator'sSigilofStrife-51417" value: { - dps: 10464.98978 - tps: 6047.8058 + dps: 10434.46349 + tps: 6041.26773 hps: 42.12697 } } dps_results: { key: "TestUnholy-Average-Default" value: { - dps: 10310.79563 - tps: 5971.29709 + dps: 10279.57916 + tps: 5964.26539 hps: 42.14164 } } @@ -1174,152 +1174,152 @@ dps_results: { dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_2h_ss-FullBuffs-LongMultiTarget" value: { - dps: 14312.2404 - tps: 9287.052 + dps: 14275.55112 + tps: 9275.62941 hps: 42.12697 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_2h_ss-FullBuffs-LongSingleTarget" value: { - dps: 10377.44167 - tps: 5996.15064 + dps: 10346.91539 + tps: 5989.61257 hps: 42.12697 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_2h_ss-FullBuffs-ShortSingleTarget" value: { - dps: 15559.83451 - tps: 7162.15963 + dps: 15451.74278 + tps: 7165.07213 hps: 210.63484 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_2h_ss-NoBuffs-LongMultiTarget" value: { - dps: 6783.40918 - tps: 4583.6299 + dps: 6761.4395 + tps: 4575.413 hps: 27.7272 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_2h_ss-NoBuffs-LongSingleTarget" value: { - dps: 5103.61606 - tps: 3177.62391 + dps: 5085.97636 + tps: 3172.95627 hps: 27.7272 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_2h_ss-NoBuffs-ShortSingleTarget" value: { - dps: 6757.40436 - tps: 3489.08968 + dps: 6701.62049 + tps: 3491.63258 hps: 138.636 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_dnd_aoe-FullBuffs-LongMultiTarget" value: { - dps: 59452.42669 - tps: 61476.73056 + dps: 59321.04606 + tps: 61361.65332 hps: 236.33229 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_dnd_aoe-FullBuffs-LongSingleTarget" value: { - dps: 11354.57131 - tps: 7485.7125 + dps: 11318.78456 + tps: 7472.9393 hps: 236.33229 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_dnd_aoe-FullBuffs-ShortSingleTarget" value: { - dps: 16535.42503 - tps: 8698.33633 + dps: 16412.5451 + tps: 8686.56163 hps: 337.01574 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_dnd_aoe-NoBuffs-LongMultiTarget" value: { - dps: 35212.15599 - tps: 37565.37369 + dps: 35117.90018 + tps: 37478.75367 hps: 155.82686 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_dnd_aoe-NoBuffs-LongSingleTarget" value: { - dps: 5772.20815 - tps: 4185.27192 + dps: 5750.84606 + tps: 4175.86894 hps: 155.27232 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_dnd_aoe-NoBuffs-ShortSingleTarget" value: { - dps: 7347.6605 - tps: 4481.15645 + dps: 7280.02322 + tps: 4471.44132 hps: 221.8176 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-unholy_dw_ss-FullBuffs-LongMultiTarget" value: { - dps: 36324.85779 - tps: 43276.25499 + dps: 36238.79517 + tps: 43195.85148 hps: 236.33229 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-unholy_dw_ss-FullBuffs-LongSingleTarget" value: { - dps: 11470.17283 - tps: 7591.32914 + dps: 11434.83628 + tps: 7578.90963 hps: 236.33229 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-unholy_dw_ss-FullBuffs-ShortSingleTarget" value: { - dps: 16608.09173 - tps: 8808.92846 + dps: 16487.2343 + tps: 8798.61633 hps: 339.12209 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-unholy_dw_ss-NoBuffs-LongMultiTarget" value: { - dps: 18749.83496 - tps: 22923.25478 + dps: 18696.93865 + tps: 22871.51167 hps: 155.82686 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-unholy_dw_ss-NoBuffs-LongSingleTarget" value: { - dps: 5897.73441 - tps: 4290.70565 + dps: 5876.43297 + tps: 4281.49641 hps: 155.27232 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-unholy_dw_ss-NoBuffs-ShortSingleTarget" value: { - dps: 7417.6708 - tps: 4556.06307 + dps: 7351.97253 + tps: 4548.398 hps: 221.8176 } } dps_results: { key: "TestUnholy-SwitchInFrontOfTarget-Default" value: { - dps: 9845.43373 - tps: 5635.64895 + dps: 9815.01951 + tps: 5629.20041 hps: 42.12697 } } diff --git a/sim/druid/druid.go b/sim/druid/druid.go index 5bd1c29bf1..cab2a21f2f 100644 --- a/sim/druid/druid.go +++ b/sim/druid/druid.go @@ -26,7 +26,6 @@ type Druid struct { RebirthTiming float64 BleedsActive int AssumeBleedActive bool - PrePopBerserk bool ReplaceBearMHFunc core.ReplaceMHSwing diff --git a/sim/druid/feral/feral.go b/sim/druid/feral/feral.go index 1608d06272..d30579fe0a 100644 --- a/sim/druid/feral/feral.go +++ b/sim/druid/feral/feral.go @@ -42,7 +42,6 @@ func NewFeralDruid(character *core.Character, options *proto.Player) *FeralDruid cat.AssumeBleedActive = feralOptions.Options.AssumeBleedActive cat.maxRipTicks = cat.MaxRipTicks() cat.prepopOoc = feralOptions.Rotation.PrePopOoc - cat.PrePopBerserk = feralOptions.Rotation.PrePopBerserk cat.setupRotation(feralOptions.Rotation) cat.EnableEnergyBar(100.0) diff --git a/sim/druid/restoration/restoration.go b/sim/druid/restoration/restoration.go index 428160c8d9..d0d6137a65 100644 --- a/sim/druid/restoration/restoration.go +++ b/sim/druid/restoration/restoration.go @@ -28,8 +28,7 @@ func NewRestorationDruid(character *core.Character, options *proto.Player) *Rest selfBuffs := druid.SelfBuffs{} resto := &RestorationDruid{ - Druid: druid.New(character, druid.Tree, selfBuffs, options.TalentsString), - Rotation: restoOptions.Rotation, + Druid: druid.New(character, druid.Tree, selfBuffs, options.TalentsString), } resto.SelfBuffs.InnervateTarget = &proto.UnitReference{} @@ -37,14 +36,11 @@ func NewRestorationDruid(character *core.Character, options *proto.Player) *Rest resto.SelfBuffs.InnervateTarget = restoOptions.Options.InnervateTarget } - resto.EnableResumeAfterManaWait(resto.tryUseGCD) return resto } type RestorationDruid struct { *druid.Druid - - Rotation *proto.RestorationDruid_Rotation } func (resto *RestorationDruid) GetDruid() *druid.Druid { diff --git a/sim/druid/restoration/rotation.go b/sim/druid/restoration/rotation.go deleted file mode 100644 index 5a59ad57f2..0000000000 --- a/sim/druid/restoration/rotation.go +++ /dev/null @@ -1,15 +0,0 @@ -package restoration - -import ( - "time" - - "github.com/wowsims/wotlk/sim/core" -) - -func (resto *RestorationDruid) OnGCDReady(sim *core.Simulation) { - resto.tryUseGCD(sim) -} - -func (resto *RestorationDruid) tryUseGCD(sim *core.Simulation) { - resto.WaitUntil(sim, sim.CurrentTime+time.Second*5) -} diff --git a/sim/hunter/aspects.go b/sim/hunter/aspects.go index 9788a2058c..8b5fa83e3e 100644 --- a/sim/hunter/aspects.go +++ b/sim/hunter/aspects.go @@ -134,7 +134,7 @@ func (hunter *Hunter) registerAspectOfTheViperSpell() { } func (hunter *Hunter) applySharedAspectConfig(isHawk bool, aura *core.Aura) { - if isHawk != (hunter.Rotation.ViperStartManaPercent >= 1) { + if isHawk { aura.OnReset = func(aura *core.Aura, sim *core.Simulation) { aura.Activate(sim) } diff --git a/sim/lib/library.go b/sim/lib/library.go index 74b37c17fe..9539c478bd 100644 --- a/sim/lib/library.go +++ b/sim/lib/library.go @@ -193,8 +193,6 @@ func trySpell(act int) bool { //export doNothing func doNothing() bool { - player := _active_sim.Raid.Parties[0].Players[0] - player.GetCharacter().DoNothing() return true } diff --git a/sim/mage/TestArcane.results b/sim/mage/TestArcane.results index 4a70f5b230..5f0cf2c0be 100644 --- a/sim/mage/TestArcane.results +++ b/sim/mage/TestArcane.results @@ -252,8 +252,8 @@ dps_results: { dps_results: { key: "TestArcane-AllItems-EphemeralSnowflake-50260" value: { - dps: 10738.79708 - tps: 6577.6561 + dps: 10727.16841 + tps: 6570.11619 } } dps_results: { diff --git a/sim/mage/TestFire.results b/sim/mage/TestFire.results index d26760097b..b939817bf9 100644 --- a/sim/mage/TestFire.results +++ b/sim/mage/TestFire.results @@ -770,8 +770,8 @@ dps_results: { dps_results: { key: "TestFire-Settings-Troll-p3_fire_alliance-Fire-fire-FullBuffs-LongMultiTarget" value: { - dps: 38085.36222 - tps: 32980.78258 + dps: 38064.82304 + tps: 32963.64697 } } dps_results: { @@ -791,8 +791,8 @@ dps_results: { dps_results: { key: "TestFire-Settings-Troll-p3_fire_alliance-Fire-fire-NoBuffs-LongMultiTarget" value: { - dps: 22222.81509 - tps: 20575.92958 + dps: 22173.53497 + tps: 20541.48297 } } dps_results: { diff --git a/sim/mage/TestFrost.results b/sim/mage/TestFrost.results index dc582270eb..cc1f38bac4 100644 --- a/sim/mage/TestFrost.results +++ b/sim/mage/TestFrost.results @@ -46,277 +46,277 @@ character_stats_results: { dps_results: { key: "TestFrost-AllItems-Althor'sAbacus-50359" value: { - dps: 7928.24208 - tps: 6453.45112 + dps: 7933.66277 + tps: 6459.8041 } } dps_results: { key: "TestFrost-AllItems-Althor'sAbacus-50366" value: { - dps: 7962.77382 - tps: 6481.89515 + dps: 7968.21694 + tps: 6488.27328 } } dps_results: { key: "TestFrost-AllItems-AustereEarthsiegeDiamond" value: { - dps: 7760.1538 - tps: 6318.09095 + dps: 7765.31653 + tps: 6324.30567 } } dps_results: { key: "TestFrost-AllItems-Bandit'sInsignia-40371" value: { - dps: 7647.27929 - tps: 6222.02013 + dps: 7652.51748 + tps: 6228.1685 } } dps_results: { key: "TestFrost-AllItems-BaubleofTrueBlood-50354" value: { - dps: 7646.41564 - tps: 6221.07535 - hps: 92.57675 + dps: 7652.00052 + tps: 6227.57151 + hps: 92.573 } } dps_results: { key: "TestFrost-AllItems-BaubleofTrueBlood-50726" value: { - dps: 7646.41564 - tps: 6221.07535 - hps: 92.57675 + dps: 7652.00052 + tps: 6227.57151 + hps: 92.573 } } dps_results: { key: "TestFrost-AllItems-BeamingEarthsiegeDiamond" value: { - dps: 7782.85819 - tps: 6339.33425 + dps: 7783.7779 + tps: 6341.22794 } } dps_results: { key: "TestFrost-AllItems-BlessedRegaliaofUndeadCleansing" value: { - dps: 6005.44274 - tps: 4826.77708 + dps: 6024.87702 + tps: 4845.65031 } } dps_results: { key: "TestFrost-AllItems-Bloodmage'sRegalia" value: { - dps: 8143.08775 - tps: 6688.26693 + dps: 8140.05763 + tps: 6685.8876 } } dps_results: { key: "TestFrost-AllItems-BracingEarthsiegeDiamond" value: { - dps: 7798.72055 - tps: 6223.09271 + dps: 7803.91273 + tps: 6229.21586 } } dps_results: { key: "TestFrost-AllItems-ChaoticSkyflareDiamond" value: { - dps: 8003.40047 - tps: 6538.31272 + dps: 8004.42685 + tps: 6540.31281 } } dps_results: { key: "TestFrost-AllItems-CorpseTongueCoin-50349" value: { - dps: 7647.27929 - tps: 6222.02013 + dps: 7652.51748 + tps: 6228.1685 } } dps_results: { key: "TestFrost-AllItems-CorpseTongueCoin-50352" value: { - dps: 7647.27929 - tps: 6222.02013 + dps: 7652.51748 + tps: 6228.1685 } } dps_results: { key: "TestFrost-AllItems-CorrodedSkeletonKey-50356" value: { - dps: 7647.27929 - tps: 6222.02013 + dps: 7652.51748 + tps: 6228.1685 hps: 64 } } dps_results: { key: "TestFrost-AllItems-DarkmoonCard:Berserker!-42989" value: { - dps: 7721.01592 - tps: 6287.16324 + dps: 7727.10393 + tps: 6294.20537 } } dps_results: { key: "TestFrost-AllItems-DarkmoonCard:Death-42990" value: { - dps: 7731.37855 - tps: 6303.73706 + dps: 7734.47564 + tps: 6306.31917 } } dps_results: { key: "TestFrost-AllItems-DarkmoonCard:Greatness-44255" value: { - dps: 7684.58603 - tps: 6266.86577 + dps: 7690.85322 + tps: 6274.32423 } } dps_results: { key: "TestFrost-AllItems-Death'sChoice-47464" value: { - dps: 7647.27929 - tps: 6222.02013 + dps: 7652.51748 + tps: 6228.1685 } } dps_results: { key: "TestFrost-AllItems-DeathKnight'sAnguish-38212" value: { - dps: 7678.84495 - tps: 6246.81867 + dps: 7685.02105 + tps: 6253.78087 } } dps_results: { key: "TestFrost-AllItems-Deathbringer'sWill-50362" value: { - dps: 7647.27929 - tps: 6222.02013 + dps: 7652.51748 + tps: 6228.1685 } } dps_results: { key: "TestFrost-AllItems-Deathbringer'sWill-50363" value: { - dps: 7647.27929 - tps: 6222.02013 + dps: 7652.51748 + tps: 6228.1685 } } dps_results: { key: "TestFrost-AllItems-Defender'sCode-40257" value: { - dps: 7647.27929 - tps: 6222.02013 + dps: 7652.51748 + tps: 6228.1685 } } dps_results: { key: "TestFrost-AllItems-DestructiveSkyflareDiamond" value: { - dps: 7783.55414 - tps: 6340.66928 + dps: 7784.47384 + tps: 6342.56315 } } dps_results: { key: "TestFrost-AllItems-DislodgedForeignObject-50348" value: { - dps: 8381.41843 - tps: 6873.3235 + dps: 8384.30782 + tps: 6875.40602 } } dps_results: { key: "TestFrost-AllItems-DislodgedForeignObject-50353" value: { - dps: 8297.80523 - tps: 6789.83899 + dps: 8289.8124 + tps: 6783.32805 } } dps_results: { key: "TestFrost-AllItems-EffulgentSkyflareDiamond" value: { - dps: 7760.1538 - tps: 6318.09095 + dps: 7765.31653 + tps: 6324.30567 } } dps_results: { key: "TestFrost-AllItems-EmberSkyflareDiamond" value: { - dps: 7812.27004 - tps: 6362.69935 + dps: 7813.94105 + tps: 6365.39795 } } dps_results: { key: "TestFrost-AllItems-EnigmaticSkyflareDiamond" value: { - dps: 7782.89356 - tps: 6340.06823 + dps: 7783.81326 + tps: 6341.9621 } } dps_results: { key: "TestFrost-AllItems-EnigmaticStarflareDiamond" value: { - dps: 7777.85554 - tps: 6335.57176 + dps: 7778.77525 + tps: 6337.46563 } } dps_results: { key: "TestFrost-AllItems-EphemeralSnowflake-50260" value: { - dps: 7759.64948 - tps: 6319.89085 + dps: 7755.40406 + tps: 6315.42295 } } dps_results: { key: "TestFrost-AllItems-EssenceofGossamer-37220" value: { - dps: 7647.27929 - tps: 6222.02013 + dps: 7652.51748 + tps: 6228.1685 } } dps_results: { key: "TestFrost-AllItems-EternalEarthsiegeDiamond" value: { - dps: 7760.1538 - tps: 6318.09095 + dps: 7765.31653 + tps: 6324.30567 } } dps_results: { key: "TestFrost-AllItems-ExtractofNecromanticPower-40373" value: { - dps: 7723.41199 - tps: 6291.61522 + dps: 7727.1541 + tps: 6295.38387 } } dps_results: { key: "TestFrost-AllItems-EyeoftheBroodmother-45308" value: { - dps: 7906.80366 - tps: 6452.50593 + dps: 7913.07517 + tps: 6459.71001 } } dps_results: { key: "TestFrost-AllItems-Figurine-SapphireOwl-42413" value: { - dps: 7668.23295 - tps: 6239.78194 + dps: 7673.31368 + tps: 6245.89566 } } dps_results: { key: "TestFrost-AllItems-ForethoughtTalisman-40258" value: { - dps: 7821.50761 - tps: 6365.5332 + dps: 7826.85897 + tps: 6371.80846 } } dps_results: { key: "TestFrost-AllItems-ForgeEmber-37660" value: { - dps: 7824.55194 - tps: 6374.99683 + dps: 7831.62918 + tps: 6382.78835 } } dps_results: { key: "TestFrost-AllItems-ForlornSkyflareDiamond" value: { - dps: 7798.72055 - tps: 6349.7974 + dps: 7803.91273 + tps: 6356.04504 } } dps_results: { key: "TestFrost-AllItems-ForlornStarflareDiamond" value: { - dps: 7791.0072 - tps: 6343.45611 + dps: 7796.19349 + tps: 6349.69717 } } dps_results: { @@ -329,15 +329,15 @@ dps_results: { dps_results: { key: "TestFrost-AllItems-FuryoftheFiveFlights-40431" value: { - dps: 7647.27929 - tps: 6222.02013 + dps: 7652.51748 + tps: 6228.1685 } } dps_results: { key: "TestFrost-AllItems-FuturesightRune-38763" value: { - dps: 7744.89597 - tps: 6301.18733 + dps: 7750.19737 + tps: 6307.40657 } } dps_results: { @@ -350,85 +350,85 @@ dps_results: { dps_results: { key: "TestFrost-AllItems-GlowingTwilightScale-54573" value: { - dps: 7945.50795 - tps: 6467.67314 + dps: 7950.93986 + tps: 6474.03869 } } dps_results: { key: "TestFrost-AllItems-GlowingTwilightScale-54589" value: { - dps: 7984.74857 - tps: 6499.9959 + dps: 7990.20596 + tps: 6506.39003 } } dps_results: { key: "TestFrost-AllItems-GnomishLightningGenerator-41121" value: { - dps: 7726.20314 - tps: 6306.13936 + dps: 7712.63873 + tps: 6291.8092 } } dps_results: { key: "TestFrost-AllItems-Heartpierce-49982" value: { - dps: 8003.40047 - tps: 6538.31272 + dps: 8004.42685 + tps: 6540.31281 } } dps_results: { key: "TestFrost-AllItems-Heartpierce-50641" value: { - dps: 8003.40047 - tps: 6538.31272 + dps: 8004.42685 + tps: 6540.31281 } } dps_results: { key: "TestFrost-AllItems-IllustrationoftheDragonSoul-40432" value: { - dps: 7930.51116 - tps: 6474.17485 + dps: 7936.00618 + tps: 6480.54928 } } dps_results: { key: "TestFrost-AllItems-ImpassiveSkyflareDiamond" value: { - dps: 7782.89356 - tps: 6340.06823 + dps: 7783.81326 + tps: 6341.9621 } } dps_results: { key: "TestFrost-AllItems-ImpassiveStarflareDiamond" value: { - dps: 7777.85554 - tps: 6335.57176 + dps: 7778.77525 + tps: 6337.46563 } } dps_results: { key: "TestFrost-AllItems-IncisorFragment-37723" value: { - dps: 7647.27929 - tps: 6222.02013 + dps: 7652.51748 + tps: 6228.1685 } } dps_results: { key: "TestFrost-AllItems-InsightfulEarthsiegeDiamond" value: { - dps: 7772.45693 - tps: 6333.79039 + dps: 7774.27285 + tps: 6336.45718 } } dps_results: { key: "TestFrost-AllItems-InvigoratingEarthsiegeDiamond" value: { - dps: 7760.1538 - tps: 6318.09095 + dps: 7765.31653 + tps: 6324.30567 } } dps_results: { key: "TestFrost-AllItems-Khadgar'sRegalia" value: { - dps: 6580.00377 - tps: 5309.1505 + dps: 6575.79129 + tps: 5306.49837 } } dps_results: { @@ -441,239 +441,239 @@ dps_results: { dps_results: { key: "TestFrost-AllItems-Lavanthor'sTalisman-37872" value: { - dps: 7647.27929 - tps: 6222.02013 + dps: 7652.51748 + tps: 6228.1685 } } dps_results: { key: "TestFrost-AllItems-MajesticDragonFigurine-40430" value: { - dps: 7647.59946 - tps: 6219.47581 + dps: 7652.83765 + tps: 6225.62283 } } dps_results: { key: "TestFrost-AllItems-MeteoriteWhetstone-37390" value: { - dps: 7691.79354 - tps: 6256.75774 + dps: 7698.15546 + tps: 6263.90226 } } dps_results: { key: "TestFrost-AllItems-NevermeltingIceCrystal-50259" value: { - dps: 7847.31458 - tps: 6384.09669 + dps: 7848.80614 + tps: 6384.95591 } } dps_results: { key: "TestFrost-AllItems-Nibelung-49992" value: { - dps: 8003.40047 - tps: 6538.31272 + dps: 8004.42685 + tps: 6540.31281 } } dps_results: { key: "TestFrost-AllItems-Nibelung-50648" value: { - dps: 8003.40047 - tps: 6538.31272 + dps: 8004.42685 + tps: 6540.31281 } } dps_results: { key: "TestFrost-AllItems-OfferingofSacrifice-37638" value: { - dps: 7647.27929 - tps: 6222.02013 + dps: 7652.51748 + tps: 6228.1685 } } dps_results: { key: "TestFrost-AllItems-PersistentEarthshatterDiamond" value: { - dps: 7760.1538 - tps: 6318.09095 + dps: 7765.31653 + tps: 6324.30567 } } dps_results: { key: "TestFrost-AllItems-PersistentEarthsiegeDiamond" value: { - dps: 7760.1538 - tps: 6318.09095 + dps: 7765.31653 + tps: 6324.30567 } } dps_results: { key: "TestFrost-AllItems-PetrifiedScarab-21685" value: { - dps: 7646.26897 - tps: 6221.11085 + dps: 7651.50716 + tps: 6227.25922 } } dps_results: { key: "TestFrost-AllItems-PetrifiedTwilightScale-54571" value: { - dps: 7647.27929 - tps: 6222.02013 + dps: 7652.51748 + tps: 6228.1685 } } dps_results: { key: "TestFrost-AllItems-PetrifiedTwilightScale-54591" value: { - dps: 7647.27929 - tps: 6222.02013 + dps: 7652.51748 + tps: 6228.1685 } } dps_results: { key: "TestFrost-AllItems-PowerfulEarthshatterDiamond" value: { - dps: 7760.1538 - tps: 6318.09095 + dps: 7765.31653 + tps: 6324.30567 } } dps_results: { key: "TestFrost-AllItems-PowerfulEarthsiegeDiamond" value: { - dps: 7760.1538 - tps: 6318.09095 + dps: 7765.31653 + tps: 6324.30567 } } dps_results: { key: "TestFrost-AllItems-PurifiedShardoftheGods" value: { - dps: 7647.27929 - tps: 6222.02013 + dps: 7652.51748 + tps: 6228.1685 } } dps_results: { key: "TestFrost-AllItems-ReignoftheDead-47316" value: { - dps: 7998.96913 - tps: 6538.92968 + dps: 7998.48484 + tps: 6538.10806 } } dps_results: { key: "TestFrost-AllItems-ReignoftheDead-47477" value: { - dps: 8048.33749 - tps: 6583.34161 + dps: 8047.7877 + tps: 6582.45344 } } dps_results: { key: "TestFrost-AllItems-RelentlessEarthsiegeDiamond" value: { - dps: 7978.38291 - tps: 6514.28941 + dps: 7984.09185 + tps: 6521.00509 } } dps_results: { key: "TestFrost-AllItems-RevitalizingSkyflareDiamond" value: { - dps: 7760.12417 - tps: 6316.94905 + dps: 7765.2869 + tps: 6323.1634 } } dps_results: { key: "TestFrost-AllItems-RuneofRepulsion-40372" value: { - dps: 7647.27929 - tps: 6222.02013 + dps: 7652.51748 + tps: 6228.1685 } } dps_results: { key: "TestFrost-AllItems-SealofthePantheon-36993" value: { - dps: 7647.27929 - tps: 6222.02013 + dps: 7652.51748 + tps: 6228.1685 } } dps_results: { key: "TestFrost-AllItems-ShinyShardoftheGods" value: { - dps: 7647.27929 - tps: 6222.02013 + dps: 7652.51748 + tps: 6228.1685 } } dps_results: { key: "TestFrost-AllItems-Sindragosa'sFlawlessFang-50361" value: { - dps: 7647.27929 - tps: 6222.02013 + dps: 7652.51748 + tps: 6228.1685 } } dps_results: { key: "TestFrost-AllItems-SliverofPureIce-50339" value: { - dps: 7895.33302 - tps: 6429.12257 + dps: 7900.7323 + tps: 6435.45003 } } dps_results: { key: "TestFrost-AllItems-SliverofPureIce-50346" value: { - dps: 7926.72551 - tps: 6455.23432 + dps: 7932.14518 + tps: 6461.58463 } } dps_results: { key: "TestFrost-AllItems-SoulPreserver-37111" value: { - dps: 7765.00113 - tps: 6318.98842 + dps: 7770.31579 + tps: 6325.22253 } } dps_results: { key: "TestFrost-AllItems-SouloftheDead-40382" value: { - dps: 7719.6486 - tps: 6289.29418 + dps: 7725.7366 + tps: 6296.32776 } } dps_results: { key: "TestFrost-AllItems-SparkofLife-37657" value: { - dps: 7755.89541 - tps: 6324.01321 + dps: 7757.64893 + tps: 6327.51453 } } dps_results: { key: "TestFrost-AllItems-SphereofRedDragon'sBlood-37166" value: { - dps: 7706.01629 - tps: 6281.8047 + dps: 7696.99765 + tps: 6273.70353 } } dps_results: { key: "TestFrost-AllItems-SwiftSkyflareDiamond" value: { - dps: 7760.1538 - tps: 6318.09095 + dps: 7765.31653 + tps: 6324.30567 } } dps_results: { key: "TestFrost-AllItems-SwiftStarflareDiamond" value: { - dps: 7760.1538 - tps: 6318.09095 + dps: 7765.31653 + tps: 6324.30567 } } dps_results: { key: "TestFrost-AllItems-SwiftWindfireDiamond" value: { - dps: 7760.1538 - tps: 6318.09095 + dps: 7765.31653 + tps: 6324.30567 } } dps_results: { key: "TestFrost-AllItems-TalismanofTrollDivinity-37734" value: { - dps: 7647.57925 - tps: 6220.68724 + dps: 7652.81744 + tps: 6226.83399 } } dps_results: { key: "TestFrost-AllItems-TearsoftheVanquished-47215" value: { - dps: 7686.34035 - tps: 6255.4996 + dps: 7691.42109 + tps: 6261.64718 } } dps_results: { @@ -686,106 +686,106 @@ dps_results: { dps_results: { key: "TestFrost-AllItems-TheGeneral'sHeart-45507" value: { - dps: 7647.27929 - tps: 6222.02013 + dps: 7652.51748 + tps: 6228.1685 } } dps_results: { key: "TestFrost-AllItems-TheTwinBladesofAzzinoth" value: { - dps: 6369.89154 - tps: 5180.72909 + dps: 6372.08189 + tps: 5180.43316 } } dps_results: { key: "TestFrost-AllItems-ThunderingSkyflareDiamond" value: { - dps: 7760.1538 - tps: 6318.09095 + dps: 7765.31653 + tps: 6324.30567 } } dps_results: { key: "TestFrost-AllItems-TinyAbominationinaJar-50351" value: { - dps: 7706.01629 - tps: 6281.8047 + dps: 7696.99765 + tps: 6273.70353 } } dps_results: { key: "TestFrost-AllItems-TinyAbominationinaJar-50706" value: { - dps: 7706.01629 - tps: 6281.8047 + dps: 7696.99765 + tps: 6273.70353 } } dps_results: { key: "TestFrost-AllItems-TirelessSkyflareDiamond" value: { - dps: 7798.72055 - tps: 6349.7974 + dps: 7803.91273 + tps: 6356.04504 } } dps_results: { key: "TestFrost-AllItems-TirelessStarflareDiamond" value: { - dps: 7791.0072 - tps: 6343.45611 + dps: 7796.19349 + tps: 6349.69717 } } dps_results: { key: "TestFrost-AllItems-TomeofArcanePhenomena-36972" value: { - dps: 7784.88807 - tps: 6332.07288 + dps: 7779.60815 + tps: 6327.85299 } } dps_results: { key: "TestFrost-AllItems-TrenchantEarthshatterDiamond" value: { - dps: 7791.0072 - tps: 6343.45611 + dps: 7796.19349 + tps: 6349.69717 } } dps_results: { key: "TestFrost-AllItems-TrenchantEarthsiegeDiamond" value: { - dps: 7798.72055 - tps: 6349.7974 + dps: 7803.91273 + tps: 6356.04504 } } dps_results: { key: "TestFrost-AllItems-WingedTalisman-37844" value: { - dps: 7749.91677 - tps: 6314.13796 + dps: 7755.11162 + tps: 6320.25051 } } dps_results: { key: "TestFrost-Average-Default" value: { - dps: 8088.27706 - tps: 6619.63625 + dps: 8088.78057 + tps: 6620.05808 } } dps_results: { key: "TestFrost-Settings-Troll-p3_frost_alliance-Frost-frost-FullBuffs-LongMultiTarget" value: { - dps: 8003.40047 - tps: 6815.93838 + dps: 8004.42685 + tps: 6818.27786 } } dps_results: { key: "TestFrost-Settings-Troll-p3_frost_alliance-Frost-frost-FullBuffs-LongSingleTarget" value: { - dps: 8003.40047 - tps: 6538.31272 + dps: 8004.42685 + tps: 6540.31281 } } dps_results: { key: "TestFrost-Settings-Troll-p3_frost_alliance-Frost-frost-FullBuffs-ShortSingleTarget" value: { - dps: 10069.72226 - tps: 8272.31852 + dps: 10047.18185 + tps: 8250.71555 } } dps_results: { @@ -848,7 +848,7 @@ dps_results: { dps_results: { key: "TestFrost-SwitchInFrontOfTarget-Default" value: { - dps: 8003.40047 - tps: 6538.31272 + dps: 8004.42685 + tps: 6540.31281 } } diff --git a/sim/mage/arcane_blast.go b/sim/mage/arcane_blast.go index 2833bfc057..9db24bfdf9 100644 --- a/sim/mage/arcane_blast.go +++ b/sim/mage/arcane_blast.go @@ -23,9 +23,6 @@ func (mage *Mage) registerArcaneBlastSpell() { mage.PseudoStats.SchoolDamageDealtMultiplier[stats.SchoolIndexArcane] *= newMultiplier / oldMultiplier mage.ArcaneBlast.CostMultiplier += 1.75 * float64(newStacks-oldStacks) }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - mage.arcaneBlastStreak = 0 - }, }) actionID := core.ActionID{SpellID: 42897} diff --git a/sim/mage/arcane_missiles.go b/sim/mage/arcane_missiles.go index 8b2cd71ea5..f9fae720ea 100644 --- a/sim/mage/arcane_missiles.go +++ b/sim/mage/arcane_missiles.go @@ -49,8 +49,7 @@ func (mage *Mage) registerArcaneMissilesSpell() { }, Cast: core.CastConfig{ DefaultCast: core.Cast{ - GCD: core.GCDDefault, - ChannelTime: time.Second * 5, + GCD: core.GCDDefault, }, }, Dot: core.DotConfig{ diff --git a/sim/mage/blizzard.go b/sim/mage/blizzard.go index 1b64af2720..f0b1831039 100644 --- a/sim/mage/blizzard.go +++ b/sim/mage/blizzard.go @@ -57,8 +57,7 @@ func (mage *Mage) registerBlizzardSpell() { }, Cast: core.CastConfig{ DefaultCast: core.Cast{ - GCD: core.GCDDefault, - ChannelTime: time.Second * 8, + GCD: core.GCDDefault, }, }, Dot: core.DotConfig{ diff --git a/sim/mage/evocation.go b/sim/mage/evocation.go index de0e5f0733..b3025f9c10 100644 --- a/sim/mage/evocation.go +++ b/sim/mage/evocation.go @@ -18,8 +18,7 @@ func (mage *Mage) registerEvocation() { Cast: core.CastConfig{ DefaultCast: core.Cast{ - GCD: core.GCDDefault, - ChannelTime: time.Duration(maxTicks) * time.Second * 2, + GCD: core.GCDDefault, }, CD: core.Cooldown{ Timer: mage.NewTimer(), diff --git a/sim/mage/mage.go b/sim/mage/mage.go index 763b09a0fe..f8daa71777 100644 --- a/sim/mage/mage.go +++ b/sim/mage/mage.go @@ -1,8 +1,6 @@ package mage import ( - "time" - "github.com/wowsims/wotlk/sim/common/wotlk" "github.com/wowsims/wotlk/sim/core" @@ -38,12 +36,8 @@ func RegisterMage() { type Mage struct { core.Character - Talents *proto.MageTalents - Options *proto.Mage_Options - Rotation *proto.Mage_Rotation - - arcaneBlastStreak int32 - arcanePowerMCD *core.MajorCooldown + Talents *proto.MageTalents + Options *proto.Mage_Options waterElemental *WaterElemental mirrorImage *MirrorImage @@ -137,20 +131,9 @@ func (mage *Mage) Initialize() { mage.registerMirrorImageCD() mage.registerBlastWaveSpell() mage.registerDragonsBreathSpell() - - mage.RegisterPrepullAction(-2000*time.Millisecond, func(sim *core.Simulation) { - if mirrorImageMCD := mage.GetMajorCooldownIgnoreTag(mage.MirrorImage.ActionID); !mage.IsUsingAPL && mirrorImageMCD != nil { - if len(mirrorImageMCD.GetTimings()) == 0 { - mage.MirrorImage.Cast(sim, nil) - mage.UpdateMajorCooldowns() - } - } - }) } func (mage *Mage) Reset(sim *core.Simulation) { - mage.arcaneBlastStreak = 0 - mage.arcanePowerMCD = mage.GetMajorCooldown(core.ActionID{SpellID: 12042}) } func NewMage(character *core.Character, options *proto.Player) *Mage { @@ -160,20 +143,11 @@ func NewMage(character *core.Character, options *proto.Player) *Mage { Character: *character, Talents: &proto.MageTalents{}, Options: mageOptions.Options, - Rotation: mageOptions.Rotation, } core.FillTalentsProto(mage.Talents.ProtoReflect(), options.TalentsString, TalentTreeSizes) mage.bonusCritDamage = .25*float64(mage.Talents.SpellPower) + .1*float64(mage.Talents.Burnout) mage.EnableManaBar() - mage.EnableResumeAfterManaWait(mage.tryUseGCD) - - if !mage.Talents.ArcaneBarrage { - mage.Rotation.UseArcaneBarrage = false - } - if mage.Talents.ImprovedScorch == 0 { - mage.Rotation.MaintainImprovedScorch = false - } if mage.Options.Armor == proto.Mage_Options_MageArmor { mage.PseudoStats.SpiritRegenRateCasting += .5 diff --git a/sim/mage/rotations.go b/sim/mage/rotations.go deleted file mode 100644 index 42d2b9f248..0000000000 --- a/sim/mage/rotations.go +++ /dev/null @@ -1,155 +0,0 @@ -package mage - -import ( - "time" - - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/core/proto" -) - -func (mage *Mage) OnGCDReady(sim *core.Simulation) { - mage.tryUseGCD(sim) -} - -func (mage *Mage) tryUseGCD(sim *core.Simulation) { - if mage.IsUsingAPL { - return - } - - spell := mage.chooseSpell(sim) - if spell != nil { - if success := spell.Cast(sim, mage.CurrentTarget); !success { - mage.WaitForMana(sim, spell.CurCast.Cost) - } - } -} - -func (mage *Mage) chooseSpell(sim *core.Simulation) *core.Spell { - if mage.Rotation.MaintainImprovedScorch && (!mage.CritDebuffCategories.Get(mage.CurrentTarget).AnyActive() || (mage.ScorchAuras.Get(mage.CurrentTarget).IsActive() && mage.ScorchAuras.Get(mage.CurrentTarget).RemainingDuration(sim) < time.Millisecond*4000)) { - return mage.Scorch - } - - if mage.PrimaryTalentTree == 0 { - spell := mage.doArcaneRotation(sim) - if spell == mage.ArcaneBlast { - mage.arcaneBlastStreak++ - } - return spell - } else if mage.PrimaryTalentTree == 1 { - return mage.doFireRotation(sim) - } else { - return mage.doFrostRotation(sim) - } -} - -func (mage *Mage) doArcaneRotation(sim *core.Simulation) *core.Spell { - // AB until the end. - if mage.canBlast(sim) { - return mage.ArcaneBlast - } - - // Extra ABs before first AP. - if sim.CurrentTime < time.Second*10 && !mage.ArcanePowerAura.IsActive() && mage.arcanePowerMCD != nil && mage.arcanePowerMCD.TimeToNextCast(sim) < time.Second*5 { - return mage.ArcaneBlast - } - - // Extra ABs during first AP. - if sim.CurrentTime < time.Second*60 && mage.ArcanePowerAura.IsActive() && mage.arcaneBlastStreak < mage.Rotation.ExtraBlastsDuringFirstAp+4 { - return mage.ArcaneBlast - } - - abStacks := mage.ArcaneBlastAura.GetStacks() - hasMissileBarrage := mage.MissileBarrageAura.IsActive() && mage.MissileBarrageAura.TimeActive(sim) > mage.ReactionTime - - // AM if we have MB and below n AB stacks. - if hasMissileBarrage && abStacks < mage.Rotation.MissileBarrageBelowArcaneBlastStacks { - return mage.ArcaneMissiles - } - - // AM if we have MB and below mana %. - manaPercent := mage.CurrentManaPercent() - if hasMissileBarrage && manaPercent < mage.Rotation.MissileBarrageBelowManaPercent { - return mage.ArcaneMissiles - } - - // AM if we don't have barrage and over mana %. - if !hasMissileBarrage && manaPercent > mage.Rotation.BlastWithoutMissileBarrageAboveManaPercent { - return mage.ArcaneBlast - } - - // If we've reached max desired stacks, use AM / ABarr. Otherwise blast. - maxAbStacks := int32(4) - if manaPercent < mage.Rotation.Only_3ArcaneBlastStacksBelowManaPercent { - maxAbStacks = 3 - } - if abStacks < maxAbStacks { - return mage.ArcaneBlast - } else if mage.Rotation.UseArcaneBarrage && mage.ArcaneBarrage.IsReady(sim) { - return mage.ArcaneBarrage - } else { - return mage.ArcaneMissiles - } -} - -func (mage *Mage) canBlast(sim *core.Simulation) bool { - // Save computation by assuming we can't blast for 30+ seconds. - remainingDur := sim.GetRemainingDuration() - if remainingDur > time.Second*30 { - return false - } - - castTime := mage.ApplyCastSpeed(ArcaneBlastBaseCastTime) - manaCost := mage.ArcaneBlast.DefaultCast.Cost - - stacks := float64(mage.ArcaneBlastAura.GetStacks()) - curMana := mage.CurrentMana() - for curTime := time.Duration(0); curTime <= remainingDur; curTime += castTime { - if stacks < 4 { - stacks++ - } - curMana -= manaCost * 1.75 * stacks - if curMana < 0 { - return false - } - } - return true -} - -func (mage *Mage) doFireRotation(sim *core.Simulation) *core.Spell { - noBomb := mage.LivingBomb != nil && !mage.LivingBomb.Dot(mage.CurrentTarget).IsActive() && sim.GetRemainingDuration() > time.Second*12 - if noBomb && mage.hotStreakCritAura.GetStacks() == 0 { - return mage.LivingBomb - } - - hasHotStreak := mage.HotStreakAura.IsActive() && mage.HotStreakAura.TimeActive(sim) > mage.ReactionTime - if hasHotStreak && mage.Pyroblast != nil { - return mage.Pyroblast - } - - if noBomb { - return mage.LivingBomb - } - - if mage.Rotation.PrimaryFireSpell == proto.Mage_Rotation_Fireball { - return mage.Fireball - } else if mage.Rotation.PrimaryFireSpell == proto.Mage_Rotation_FrostfireBolt { - return mage.FrostfireBolt - } else { - return mage.Scorch - } -} - -func (mage *Mage) doFrostRotation(sim *core.Simulation) *core.Spell { - hasBrainFreeze := mage.BrainFreezeAura.IsActive() && mage.BrainFreezeAura.TimeActive(sim) > mage.ReactionTime - if mage.FingersOfFrostAura.IsActive() { - if mage.DeepFreeze != nil && mage.DeepFreeze.IsReady(sim) { - return mage.DeepFreeze - } else if hasBrainFreeze { - return mage.FrostfireBolt - } else if mage.Rotation.UseIceLance { - return mage.IceLance - } - } - - return mage.Frostbolt -} From ffd4730343dacbeeddf377cdb39676393a6dbb4b Mon Sep 17 00:00:00 2001 From: James Tanner Date: Thu, 4 Jan 2024 20:12:13 -0800 Subject: [PATCH 08/28] Update priest --- sim/common/custom_rotation.go | 144 -- sim/paladin/protection/protection.go | 44 +- sim/paladin/protection/rotation.go | 209 --- .../retribution/TestRetribution.results | 664 +++++----- sim/paladin/retribution/retribution.go | 105 +- sim/paladin/retribution/rotation.go | 355 ----- sim/priest/healing/TestDisc.results | 2 +- sim/priest/healing/TestHoly.results | 4 +- sim/priest/healing/healing_priest.go | 34 +- sim/priest/healing/rotation.go | 115 -- sim/priest/holy_fire.go | 4 +- sim/priest/hymn_of_hope.go | 7 +- sim/priest/mind_flay.go | 32 +- sim/priest/mind_sear.go | 4 +- sim/priest/penance.go | 3 +- sim/priest/priest.go | 6 +- sim/priest/shadow/TestShadow.results | 4 +- sim/priest/shadow/rotation.go | 1173 ----------------- sim/priest/shadow/shadow_priest.go | 45 +- sim/priest/shadowfiend.go | 8 - sim/priest/smite.go | 8 +- sim/priest/smite/TestSmite.results | 454 +++---- sim/priest/smite/rotation.go | 91 -- sim/priest/smite/smite_priest.go | 17 +- sim/priest/talents.go | 4 +- 25 files changed, 593 insertions(+), 2943 deletions(-) delete mode 100644 sim/common/custom_rotation.go delete mode 100644 sim/paladin/protection/rotation.go delete mode 100644 sim/paladin/retribution/rotation.go delete mode 100644 sim/priest/healing/rotation.go delete mode 100644 sim/priest/shadow/rotation.go delete mode 100644 sim/priest/smite/rotation.go diff --git a/sim/common/custom_rotation.go b/sim/common/custom_rotation.go deleted file mode 100644 index 89ce3b4157..0000000000 --- a/sim/common/custom_rotation.go +++ /dev/null @@ -1,144 +0,0 @@ -package common - -import ( - "time" - - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/core/proto" -) - -type CustomRotationType byte - -const ( - Basic CustomRotationType = iota - CPM -) - -// Custom condition for an action. -type CustomCondition func(*core.Simulation) bool - -// Custom action based on a condition. Returns a bool and the CurCast cost. -type CustomAction func(*core.Simulation, *core.Unit) (bool, float64) - -type CustomSpell struct { - Spell *core.Spell // Might be nil if this is not a spell action. - Action CustomAction - Condition CustomCondition - DesiredCPM float64 - - casts int // Number of casts thus far in the current iteration. -} - -type CustomRotation struct { - rotationType CustomRotationType - character *core.Character - spells []CustomSpell -} - -func NewCustomRotation(crProto *proto.CustomRotation, character *core.Character, spellsMap map[int32]CustomSpell) *CustomRotation { - if crProto == nil || len(crProto.Spells) == 0 { - return nil - } - - cr := &CustomRotation{ - rotationType: Basic, - character: character, - } - - for _, customSpellProto := range crProto.Spells { - customSpell := spellsMap[customSpellProto.Spell] - customSpell.DesiredCPM = customSpellProto.CastsPerMinute - if customSpell.DesiredCPM > 0 { - cr.rotationType = CPM - } - if customSpell.Action == nil && customSpell.Spell != nil { - spell := customSpell.Spell - customSpell.Action = func(sim *core.Simulation, target *core.Unit) (bool, float64) { - success := spell.Cast(sim, target) - return success, spell.CurCast.Cost - } - } - if customSpell.Condition == nil { - spell := customSpell.Spell - customSpell.Condition = func(sim *core.Simulation) bool { - return spell.CanCast(sim, character.CurrentTarget) - } - } - if customSpell.Action != nil { - cr.spells = append(cr.spells, customSpell) - } - } - - if len(cr.spells) == 0 { - return nil - } else { - cr.character.RegisterResetEffect(func(sim *core.Simulation) { - cr.reset(sim) - }) - return cr - } -} - -func (cr *CustomRotation) reset(_ *core.Simulation) { - for i := range cr.spells { - cr.spells[i].casts = 0 - } -} - -func (cr *CustomRotation) ChooseSpell(sim *core.Simulation) *CustomSpell { - if cr.rotationType == Basic { - return cr.chooseSpellBasic(sim) - } else { - return cr.chooseSpellCPM(sim) - } -} - -func (cr *CustomRotation) chooseSpellBasic(sim *core.Simulation) *CustomSpell { - for _, customSpell := range cr.spells { - if customSpell.Condition(sim) { - return &customSpell - } - } - return nil -} - -func (cr *CustomRotation) chooseSpellCPM(sim *core.Simulation) *CustomSpell { - for i := range cr.spells { - customSpell := &cr.spells[i] - if customSpell.CPM(sim) <= customSpell.DesiredCPM && customSpell.Condition(sim) { - return customSpell - } - } - return nil -} - -func (cs *CustomSpell) CPM(sim *core.Simulation) float64 { - if sim.CurrentTime == 0 { - return 0 - } - return float64(cs.casts) / (float64(sim.CurrentTime) / float64(time.Minute)) -} - -func (cr *CustomRotation) Cast(sim *core.Simulation) bool { - if cr == nil { - panic("Custom Rotation is empty") - } - - spell := cr.ChooseSpell(sim) - - if spell == nil { - cr.character.WaitUntil(sim, sim.CurrentTime+time.Millisecond*100) - return false - } - - success, cost := spell.Action(sim, cr.character.CurrentTarget) - if success { - spell.casts++ - } else { - if cr.character.HasManaBar() { - cr.character.WaitForMana(sim, cost) - } - } - - return true -} diff --git a/sim/paladin/protection/protection.go b/sim/paladin/protection/protection.go index ddb9f64720..befda73549 100644 --- a/sim/paladin/protection/protection.go +++ b/sim/paladin/protection/protection.go @@ -1,8 +1,6 @@ package protection import ( - "time" - "github.com/wowsims/wotlk/sim/core" "github.com/wowsims/wotlk/sim/core/proto" "github.com/wowsims/wotlk/sim/paladin" @@ -29,23 +27,11 @@ func NewProtectionPaladin(character *core.Character, options *proto.Player) *Pro protOptions := options.GetProtectionPaladin() prot := &ProtectionPaladin{ - Paladin: paladin.NewPaladin(character, options.TalentsString), - Rotation: protOptions.Rotation, - Options: protOptions.Options, - Seal: protOptions.Options.Seal, + Paladin: paladin.NewPaladin(character, options.TalentsString), + Options: protOptions.Options, + Seal: protOptions.Options.Seal, } - var rotationInput = protOptions.Rotation.CustomRotation - - if rotationInput != nil { - prot.RotationInput = make([]int32, len(rotationInput.Spells)) - for i, customSpellProto := range rotationInput.Spells { - prot.RotationInput[i] = customSpellProto.Spell - } - } - - prot.SelectedRotation = prot.customRotation - prot.PaladinAura = protOptions.Options.Aura prot.HasGlyphAS = prot.HasMajorGlyph(proto.PaladinMajorGlyph_GlyphOfAvengerSShield) @@ -68,17 +54,13 @@ func NewProtectionPaladin(character *core.Character, options *proto.Player) *Pro type ProtectionPaladin struct { *paladin.Paladin - Rotation *proto.ProtectionPaladin_Rotation - Options *proto.ProtectionPaladin_Options + Options *proto.ProtectionPaladin_Options Judgement proto.PaladinJudgement Seal proto.PaladinSeal HasGlyphAS bool - - SelectedRotation func(*core.Simulation) - RotationInput []int32 } func (prot *ProtectionPaladin) GetPaladin() *paladin.Paladin { @@ -92,29 +74,11 @@ func (prot *ProtectionPaladin) Initialize() { if prot.Options.UseAvengingWrath { prot.RegisterAvengingWrathCD() } - - if !prot.IsUsingAPL { - prot.RegisterPrepullAction(-3*time.Second, func(sim *core.Simulation) { - prot.HolyShield.Cast(sim, nil) - }) - } - - if !prot.IsUsingAPL { - prot.RegisterPrepullAction(-1500*time.Millisecond, func(sim *core.Simulation) { - prot.DivinePlea.Cast(sim, nil) - }) - } } func (prot *ProtectionPaladin) Reset(sim *core.Simulation) { prot.Paladin.Reset(sim) - sim.RegisterExecutePhaseCallback(func(sim *core.Simulation, isExecute int32) { - if isExecute == 20 { - prot.OnGCDReady(sim) - } - }) - switch prot.Seal { case proto.PaladinSeal_Vengeance: prot.CurrentSeal = prot.SealOfVengeanceAura diff --git a/sim/paladin/protection/rotation.go b/sim/paladin/protection/rotation.go deleted file mode 100644 index b129a3eebd..0000000000 --- a/sim/paladin/protection/rotation.go +++ /dev/null @@ -1,209 +0,0 @@ -package protection - -import ( - "math" - "time" - - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/core/proto" -) - -func (prot *ProtectionPaladin) OnGCDReady(sim *core.Simulation) { - if prot.IsUsingAPL { - return - } - - prot.SelectedRotation(sim) - - if prot.GCD.IsReady(sim) { - prot.DoNothing() - } -} - -func (prot *ProtectionPaladin) customRotation(sim *core.Simulation) { - // Setup - target := prot.CurrentTarget - - isExecutePhase := sim.IsExecutePhase20() - - // Forced CD remaining on HotR/ShoR to cast the other. Can't be exactly 3sec or lusted consecration GCDs will desync us. - gapSlack := time.Millisecond * 4000 - - // Allowed time to wait for HotR/ShoR to come off cooldown so we can cast them on cooldown and maintain 969. - maxWait := time.Duration(prot.Rotation.WaitSlack) * time.Millisecond - - // Helper vars since we call these repeatedly in many cases - nextHammer := prot.HammerOfTheRighteous.TimeToReady(sim) - nextShield := prot.ShieldOfRighteousness.TimeToReady(sim) - - if prot.GCD.IsReady(sim) { - - if !prot.Rotation.UseCustomPrio { - - // Standard rotation. Enforce 6sec CDs to have 1 GCD between, filling with 9sec abilities. - // HammerFirst flag flips ShoR and HotR in the rotation prio order - if prot.Rotation.HammerFirst && prot.HammerOfTheRighteous.IsReady(sim) { - // Always cast HotR if ready - prot.HammerOfTheRighteous.Cast(sim, target) - } else if prot.Rotation.HammerFirst && - prot.ShieldOfRighteousness.IsReady(sim) && - (nextHammer < gapSlack) { - // Cast ShoR if ready but only if you've spent a global since HotR - prot.ShieldOfRighteousness.Cast(sim, target) - } else if !prot.Rotation.HammerFirst && prot.ShieldOfRighteousness.IsReady(sim) { - // Always cast ShoR if ready - prot.ShieldOfRighteousness.Cast(sim, target) - } else if !prot.Rotation.HammerFirst && - prot.HammerOfTheRighteous.IsReady(sim) && - (nextShield < gapSlack) { - // Cast HotR if ready but only if you've spent a global since ShoR - prot.HammerOfTheRighteous.Cast(sim, target) - - // Maximum WaitSlack checking here to see if we should delay casting anything else because it will clip our 6 - // This callback method is probably inefficient, TODO perf improvement - } else if (nextHammer < maxWait) && (nextShield < gapSlack-maxWait) { - if sim.Log != nil { - prot.Log(sim, "Waiting %d ms to cast HotR...", int32(nextHammer.Milliseconds())) - } - prot.waitUntilNextEvent(sim, prot.customRotation) - } else if (nextShield < maxWait) && (nextHammer < gapSlack-maxWait) { - if sim.Log != nil { - prot.Log(sim, "Waiting %d ms to cast ShoR...", int32(nextShield.Milliseconds())) - } - prot.waitUntilNextEvent(sim, prot.customRotation) - - } else if isExecutePhase && prot.HammerOfWrath.IsReady(sim) { - // TODO: Prio may depend on gear; consider Glyph behavior - prot.HammerOfWrath.Cast(sim, target) - } else if prot.HolyShield.IsReady(sim) { - // Top priority 9 is Holy Shield - prot.HolyShield.Cast(sim, target) - } else if prot.HasGlyphAS && prot.AvengersShield.IsReady(sim) { - // AS prio if glyphed. This will push out Cons/Judge which may not be ideal, but assumed desired based on the glyph choice - prot.AvengersShield.Cast(sim, target) - } else if prot.Consecration.IsReady(sim) { - prot.Consecration.Cast(sim, target) - } else if prot.Rotation.SqueezeHolyWrath && prot.HolyWrath.IsReady(sim) && (prot.Consecration.TimeToReady(sim) > time.Millisecond*6850) && (target.MobType == proto.MobType_MobTypeDemon || target.MobType == proto.MobType_MobTypeUndead) { - // Squeeze HW in open partial global after Consecration during bloodlust against Undead/Demon - prot.HolyWrath.Cast(sim, target) - } else if prot.JudgementOfWisdom.IsReady(sim) { - prot.JudgementOfWisdom.Cast(sim, target) - } - // Do not ever cast Exorcism or unglyphed AS - // TODO: Possible to dynamically affect Judgement<>AS priority based on Libram bonus at SBV softcap? - - } else { - - // Custom rotation - rotationLoop: - for _, spellNumber := range prot.RotationInput { - // In priority order, fire the first spell which is Ready - // Still enforce Hammer/Shield being separated by a GCD - switch spellNumber { - case int32(proto.ProtectionPaladin_Rotation_JudgementOfWisdom): - if prot.JudgementOfWisdom.IsReady(sim) { - prot.JudgementOfWisdom.Cast(sim, target) - break rotationLoop - } - case int32(proto.ProtectionPaladin_Rotation_HammerOfWrath): - if isExecutePhase && prot.HammerOfWrath.IsReady(sim) { - prot.HammerOfWrath.Cast(sim, target) - break rotationLoop - } - case int32(proto.ProtectionPaladin_Rotation_Consecration): - if prot.Consecration.IsReady(sim) { - prot.Consecration.Cast(sim, target) - break rotationLoop - } - case int32(proto.ProtectionPaladin_Rotation_HolyWrath): - if prot.HolyWrath.IsReady(sim) { - prot.HolyWrath.Cast(sim, target) - break rotationLoop - } - case int32(proto.ProtectionPaladin_Rotation_Exorcism): - if prot.Exorcism.IsReady(sim) { - prot.Exorcism.Cast(sim, target) - break rotationLoop - } - case int32(proto.ProtectionPaladin_Rotation_ShieldOfRighteousness): - if prot.ShieldOfRighteousness.IsReady(sim) && (nextHammer < gapSlack) { - prot.ShieldOfRighteousness.Cast(sim, target) - break rotationLoop - } else if (nextShield < maxWait) && (nextHammer < gapSlack-maxWait) { - if sim.Log != nil { - prot.Log(sim, "Waiting %d ms to cast ShoR...", int32(nextShield.Milliseconds())) - } - prot.waitUntilNextEvent(sim, prot.customRotation) - break rotationLoop - } - case int32(proto.ProtectionPaladin_Rotation_AvengersShield): - if prot.AvengersShield.IsReady(sim) { - prot.AvengersShield.Cast(sim, target) - break rotationLoop - } - case int32(proto.ProtectionPaladin_Rotation_HammerOfTheRighteous): - if prot.HammerOfTheRighteous.IsReady(sim) && (nextShield < gapSlack) { - prot.HammerOfTheRighteous.Cast(sim, target) - break rotationLoop - } else if nextHammer < maxWait && (nextShield < gapSlack-maxWait) { - if sim.Log != nil { - prot.Log(sim, "Waiting %d ms to cast HotR...", int32(nextHammer.Milliseconds())) - } - prot.waitUntilNextEvent(sim, prot.customRotation) - break rotationLoop - } - case int32(proto.ProtectionPaladin_Rotation_HolyShield): - if prot.HolyShield.IsReady(sim) { - prot.HolyShield.Cast(sim, target) - break rotationLoop - } - } - } - - } - - } - - prot.waitUntilNextEvent(sim, prot.customRotation) - -} - -// Helper function for finding the next event -func (prot *ProtectionPaladin) waitUntilNextEvent(sim *core.Simulation, rotationCallback func(*core.Simulation)) { - // Find the minimum possible next event that is greater than the current time - nextEventAt := time.Duration(math.MaxInt64) // any event will happen before forever. - - // All possible next events - events := []time.Duration{ - prot.AutoAttacks.NextAttackAt(), - prot.GCD.ReadyAt(), - prot.JudgementOfWisdom.ReadyAt(), - prot.HammerOfWrath.ReadyAt(), - prot.Consecration.ReadyAt(), - prot.HolyWrath.ReadyAt(), - prot.Exorcism.ReadyAt(), - prot.ShieldOfRighteousness.ReadyAt(), - prot.AvengersShield.ReadyAt(), - prot.HammerOfTheRighteous.ReadyAt(), - prot.HolyShield.ReadyAt(), - } - - for _, elem := range events { - if elem > sim.CurrentTime && elem < nextEventAt { - nextEventAt = elem - } - } - // If the next action is the GCD, just return - if nextEventAt == prot.GCD.ReadyAt() { - return - } - - // Otherwise add a pending action for the next time - pa := &core.PendingAction{ - Priority: core.ActionPriorityLow, - OnAction: rotationCallback, - NextActionAt: nextEventAt, - } - - sim.AddPendingAction(pa) -} diff --git a/sim/paladin/retribution/TestRetribution.results b/sim/paladin/retribution/TestRetribution.results index f2a5eba241..80ffc5e518 100644 --- a/sim/paladin/retribution/TestRetribution.results +++ b/sim/paladin/retribution/TestRetribution.results @@ -46,8 +46,8 @@ character_stats_results: { dps_results: { key: "TestRetribution-AllItems-AegisBattlegear" value: { - dps: 6267.52464 - tps: 6352.98416 + dps: 6268.37146 + tps: 6353.83098 dtps: 9.92959 } } @@ -62,48 +62,48 @@ dps_results: { dps_results: { key: "TestRetribution-AllItems-Althor'sAbacus-50359" value: { - dps: 6465.71452 - tps: 6551.19894 + dps: 6465.57257 + tps: 6551.05699 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-Althor'sAbacus-50366" value: { - dps: 6471.26908 - tps: 6556.75349 + dps: 6471.12751 + tps: 6556.61193 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-AshtongueTalismanofZeal-32489" value: { - dps: 6469.44227 - tps: 6554.92317 + dps: 6468.86887 + tps: 6554.34976 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-AustereEarthsiegeDiamond" value: { - dps: 6530.10682 - tps: 6615.59123 + dps: 6530.15775 + tps: 6615.64217 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-Bandit'sInsignia-40371" value: { - dps: 6628.55432 - tps: 6713.89603 + dps: 6628.55546 + tps: 6713.89718 dtps: 10.03858 } } dps_results: { key: "TestRetribution-AllItems-BaubleofTrueBlood-50354" value: { - dps: 6420.2583 - tps: 6505.74271 + dps: 6420.11322 + tps: 6505.59764 dtps: 9.48456 hps: 94.7032 } @@ -111,8 +111,8 @@ dps_results: { dps_results: { key: "TestRetribution-AllItems-BaubleofTrueBlood-50726" value: { - dps: 6420.2583 - tps: 6505.74271 + dps: 6420.11322 + tps: 6505.59764 dtps: 9.48456 hps: 94.7032 } @@ -120,96 +120,96 @@ dps_results: { dps_results: { key: "TestRetribution-AllItems-BeamingEarthsiegeDiamond" value: { - dps: 6545.05403 - tps: 6630.47856 + dps: 6544.91075 + tps: 6630.33528 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-Beast-tamer'sShoulders-30892" value: { - dps: 6399.15708 - tps: 6484.35433 + dps: 6398.97549 + tps: 6484.17274 dtps: 9.23882 } } dps_results: { key: "TestRetribution-AllItems-BlessedBattlegearofUndeadSlaying" value: { - dps: 5408.57284 - tps: 5491.81912 + dps: 5408.7184 + tps: 5491.96468 dtps: 9.23882 } } dps_results: { key: "TestRetribution-AllItems-BlessedGarboftheUndeadSlayer" value: { - dps: 5352.64254 - tps: 5435.94508 + dps: 5352.69147 + tps: 5435.99401 dtps: 9.23882 } } dps_results: { key: "TestRetribution-AllItems-BlessedRegaliaofUndeadCleansing" value: { - dps: 5184.81786 - tps: 5268.04033 + dps: 5184.95794 + tps: 5268.18041 dtps: 9.23882 } } dps_results: { key: "TestRetribution-AllItems-BracingEarthsiegeDiamond" value: { - dps: 6536.30717 - tps: 6491.06544 + dps: 6536.35928 + tps: 6491.11652 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-Bryntroll,theBoneArbiter-50415" value: { - dps: 6999.6297 - tps: 7085.11412 + dps: 6999.49261 + tps: 7084.97703 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-Bryntroll,theBoneArbiter-50709" value: { - dps: 7031.44182 - tps: 7116.92623 + dps: 7031.30525 + tps: 7116.78967 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-ChaoticSkyflareDiamond" value: { - dps: 6663.61419 - tps: 6749.09861 + dps: 6663.47166 + tps: 6748.95608 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-CorpseTongueCoin-50349" value: { - dps: 6420.52064 - tps: 6506.00506 + dps: 6420.37555 + tps: 6505.85997 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-CorpseTongueCoin-50352" value: { - dps: 6420.52064 - tps: 6506.00506 + dps: 6420.37555 + tps: 6505.85997 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-CorrodedSkeletonKey-50356" value: { - dps: 6420.52064 - tps: 6506.00506 + dps: 6420.37555 + tps: 6505.85997 dtps: 9.92959 hps: 64 } @@ -217,216 +217,216 @@ dps_results: { dps_results: { key: "TestRetribution-AllItems-DarkmoonCard:Berserker!-42989" value: { - dps: 6518.42139 - tps: 6603.90581 + dps: 6518.45383 + tps: 6603.93825 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-DarkmoonCard:Death-42990" value: { - dps: 6568.56742 - tps: 6653.91921 + dps: 6568.11706 + tps: 6653.46885 dtps: 9.77043 } } dps_results: { key: "TestRetribution-AllItems-DarkmoonCard:Greatness-44255" value: { - dps: 6420.52064 - tps: 6505.48174 + dps: 6420.37555 + tps: 6505.33665 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-Death'sChoice-47464" value: { - dps: 7001.57473 - tps: 7087.05915 + dps: 7001.45475 + tps: 7086.93917 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-DeathKnight'sAnguish-38212" value: { - dps: 6484.24836 - tps: 6569.73278 + dps: 6484.37787 + tps: 6569.86229 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-Deathbringer'sWill-50362" value: { - dps: 6755.26996 - tps: 6840.92204 + dps: 6754.79378 + tps: 6840.44585 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-Deathbringer'sWill-50363" value: { - dps: 6800.03362 - tps: 6885.65813 + dps: 6801.15779 + tps: 6886.7823 dtps: 10.29273 } } dps_results: { key: "TestRetribution-AllItems-Defender'sCode-40257" value: { - dps: 6420.52064 - tps: 6506.00506 + dps: 6420.37555 + tps: 6505.85997 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-DestructiveSkyflareDiamond" value: { - dps: 6547.98298 - tps: 6633.4674 + dps: 6547.8397 + tps: 6633.32412 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-DislodgedForeignObject-50348" value: { - dps: 6641.1179 - tps: 6727.31352 + dps: 6640.22126 + tps: 6726.41689 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-DislodgedForeignObject-50353" value: { - dps: 6609.03015 - tps: 6694.84443 + dps: 6607.8895 + tps: 6693.70378 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-EffulgentSkyflareDiamond" value: { - dps: 6530.10682 - tps: 6615.59123 + dps: 6530.15775 + tps: 6615.64217 dtps: 9.731 } } dps_results: { key: "TestRetribution-AllItems-EmberSkyflareDiamond" value: { - dps: 6536.30717 - tps: 6621.76208 + dps: 6536.35928 + tps: 6621.8142 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-EnigmaticSkyflareDiamond" value: { - dps: 6545.05403 - tps: 6630.53844 + dps: 6544.91075 + tps: 6630.39516 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-EnigmaticStarflareDiamond" value: { - dps: 6541.64166 - tps: 6627.12607 + dps: 6541.49838 + tps: 6626.98279 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-EphemeralSnowflake-50260" value: { - dps: 6540.15806 - tps: 6626.17348 + dps: 6540.37893 + tps: 6626.39435 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-EssenceofGossamer-37220" value: { - dps: 6420.52064 - tps: 6506.00506 + dps: 6420.37555 + tps: 6505.85997 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-EternalEarthsiegeDiamond" value: { - dps: 6530.10682 - tps: 6615.59123 + dps: 6530.15775 + tps: 6615.64217 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-ExtractofNecromanticPower-40373" value: { - dps: 6577.62612 - tps: 6663.13023 + dps: 6576.99883 + tps: 6662.50294 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-EyeoftheBroodmother-45308" value: { - dps: 6541.07166 - tps: 6626.55608 + dps: 6541.10959 + tps: 6626.59401 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-Figurine-SapphireOwl-42413" value: { - dps: 6420.52064 - tps: 6505.86929 + dps: 6420.37555 + tps: 6505.7242 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-ForethoughtTalisman-40258" value: { - dps: 6448.5459 - tps: 6534.03031 + dps: 6448.40275 + tps: 6533.88717 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-ForgeEmber-37660" value: { - dps: 6500.35794 - tps: 6585.84236 + dps: 6500.39038 + tps: 6585.8748 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-ForlornSkyflareDiamond" value: { - dps: 6536.30717 - tps: 6621.79159 + dps: 6536.35928 + tps: 6621.8437 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-ForlornStarflareDiamond" value: { - dps: 6535.0671 - tps: 6620.55151 + dps: 6535.11898 + tps: 6620.6034 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-FuriousGladiator'sLibramofFortitude-42853" value: { - dps: 6682.35485 - tps: 6767.83927 + dps: 6682.2126 + tps: 6767.69702 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-FuturesightRune-38763" value: { - dps: 6436.17439 - tps: 6521.65881 + dps: 6436.03038 + tps: 6521.5148 dtps: 9.92959 } } @@ -441,80 +441,80 @@ dps_results: { dps_results: { key: "TestRetribution-AllItems-GlowingTwilightScale-54573" value: { - dps: 6468.4918 - tps: 6553.97622 + dps: 6468.35004 + tps: 6553.83446 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-GlowingTwilightScale-54589" value: { - dps: 6474.80379 - tps: 6560.28821 + dps: 6474.66247 + tps: 6560.14689 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-GnomishLightningGenerator-41121" value: { - dps: 6541.36776 - tps: 6626.68068 + dps: 6540.91693 + tps: 6626.22985 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-HatefulGladiator'sLibramofFortitude-42851" value: { - dps: 6651.85055 - tps: 6737.33497 + dps: 6651.70785 + tps: 6737.19227 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-IllustrationoftheDragonSoul-40432" value: { - dps: 6431.41229 - tps: 6516.89671 + dps: 6431.2686 + tps: 6516.75301 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-ImpassiveSkyflareDiamond" value: { - dps: 6545.05403 - tps: 6630.53844 + dps: 6544.91075 + tps: 6630.39516 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-ImpassiveStarflareDiamond" value: { - dps: 6541.64166 - tps: 6627.12607 + dps: 6541.49838 + tps: 6626.98279 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-IncisorFragment-37723" value: { - dps: 6584.77153 - tps: 6670.25595 + dps: 6584.63506 + tps: 6670.11948 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-InsightfulEarthsiegeDiamond" value: { - dps: 6530.10682 - tps: 6617.19522 + dps: 6530.15775 + tps: 6617.24615 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-InvigoratingEarthsiegeDiamond" value: { - dps: 6562.40098 - tps: 6647.8854 + dps: 6562.45389 + tps: 6647.93831 dtps: 9.92959 hps: 12.10749 } @@ -522,72 +522,72 @@ dps_results: { dps_results: { key: "TestRetribution-AllItems-LastWord-50179" value: { - dps: 6862.09336 - tps: 6947.57778 + dps: 6861.95405 + tps: 6947.43847 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-LastWord-50708" value: { - dps: 6891.70956 - tps: 6977.19398 + dps: 6891.5707 + tps: 6977.05512 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-Lavanthor'sTalisman-37872" value: { - dps: 6420.52064 - tps: 6506.00506 + dps: 6420.37555 + tps: 6505.85997 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-LibramofFuriousBlows-37574" value: { - dps: 6594.26071 - tps: 6679.74513 + dps: 6594.19122 + tps: 6679.67564 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-LibramofObstruction-40707" value: { - dps: 6569.9109 - tps: 6655.39532 + dps: 6569.76696 + tps: 6655.25138 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-LibramofReciprocation-40706" value: { - dps: 6569.9109 - tps: 6655.39532 + dps: 6569.76696 + tps: 6655.25138 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-LibramofThreeTruths-50455" value: { - dps: 6989.10988 - tps: 7074.5943 + dps: 6988.96862 + tps: 7074.45304 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-LibramofValiance-47661" value: { - dps: 6956.32355 - tps: 7041.80797 + dps: 6956.365 + tps: 7041.84942 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-LibramoftheSacredShield-45145" value: { - dps: 6569.9109 - tps: 6655.39532 + dps: 6569.76696 + tps: 6655.25138 dtps: 9.92959 } } @@ -602,8 +602,8 @@ dps_results: { dps_results: { key: "TestRetribution-AllItems-LightswornBattlegear" value: { - dps: 7652.37702 - tps: 7739.88693 + dps: 7650.81686 + tps: 7738.32677 dtps: 9.92959 } } @@ -618,104 +618,104 @@ dps_results: { dps_results: { key: "TestRetribution-AllItems-MajesticDragonFigurine-40430" value: { - dps: 6420.52064 - tps: 6506.00506 + dps: 6420.37555 + tps: 6505.85997 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-MeteoriteWhetstone-37390" value: { - dps: 6554.05506 - tps: 6639.92597 + dps: 6553.90912 + tps: 6639.78002 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-NevermeltingIceCrystal-50259" value: { - dps: 6479.3976 - tps: 6564.88202 + dps: 6479.55694 + tps: 6565.04136 dtps: 10.29273 } } dps_results: { key: "TestRetribution-AllItems-OfferingofSacrifice-37638" value: { - dps: 6420.52064 - tps: 6506.00506 + dps: 6420.37555 + tps: 6505.85997 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-PersistentEarthshatterDiamond" value: { - dps: 6556.3074 - tps: 6641.79181 + dps: 6556.35971 + tps: 6641.84413 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-PersistentEarthsiegeDiamond" value: { - dps: 6562.47224 - tps: 6647.95666 + dps: 6562.52488 + tps: 6648.0093 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-PetrifiedScarab-21685" value: { - dps: 6420.52064 - tps: 6506.00506 + dps: 6420.37555 + tps: 6505.85997 dtps: 8.19524 } } dps_results: { key: "TestRetribution-AllItems-PetrifiedTwilightScale-54571" value: { - dps: 6420.52064 - tps: 6506.00506 + dps: 6420.37555 + tps: 6505.85997 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-PetrifiedTwilightScale-54591" value: { - dps: 6420.52064 - tps: 6506.00506 + dps: 6420.37555 + tps: 6505.85997 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-PowerfulEarthshatterDiamond" value: { - dps: 6530.10682 - tps: 6615.59123 + dps: 6530.15775 + tps: 6615.64217 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-PowerfulEarthsiegeDiamond" value: { - dps: 6530.10682 - tps: 6615.59123 + dps: 6530.15775 + tps: 6615.64217 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-PurifiedShardoftheGods" value: { - dps: 6420.52064 - tps: 6506.00506 + dps: 6420.37555 + tps: 6505.85997 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-RedemptionBattlegear" value: { - dps: 5847.91647 - tps: 5937.23562 + dps: 5847.28087 + tps: 5936.60002 dtps: 9.23882 } } @@ -730,136 +730,136 @@ dps_results: { dps_results: { key: "TestRetribution-AllItems-ReignoftheDead-47316" value: { - dps: 6682.32469 - tps: 6767.84107 + dps: 6683.04766 + tps: 6768.56404 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-ReignoftheDead-47477" value: { - dps: 6715.46847 - tps: 6800.98485 + dps: 6716.19926 + tps: 6801.71564 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-RelentlessEarthsiegeDiamond" value: { - dps: 6663.61419 - tps: 6749.09861 + dps: 6663.47166 + tps: 6748.95608 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-RelentlessGladiator'sLibramofFortitude-42854" value: { - dps: 6704.21895 - tps: 6789.70337 + dps: 6704.07703 + tps: 6789.56145 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-RevitalizingSkyflareDiamond" value: { - dps: 6530.10682 - tps: 6615.03035 + dps: 6530.15775 + tps: 6615.08129 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-RuneofRepulsion-40372" value: { - dps: 6420.52064 - tps: 6506.00506 + dps: 6420.37555 + tps: 6505.85997 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-SavageGladiator'sLibramofFortitude-42611" value: { - dps: 6642.57436 - tps: 6728.05878 + dps: 6642.43152 + tps: 6727.91594 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-SealofthePantheon-36993" value: { - dps: 6420.52064 - tps: 6506.00506 + dps: 6420.37555 + tps: 6505.85997 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-Shadowmourne-49623" value: { - dps: 7904.00969 - tps: 7989.33513 + dps: 7904.17373 + tps: 7989.49917 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-ShinyShardoftheGods" value: { - dps: 6420.52064 - tps: 6506.00506 + dps: 6420.37555 + tps: 6505.85997 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-Sindragosa'sFlawlessFang-50361" value: { - dps: 6420.52064 - tps: 6506.00506 + dps: 6420.37555 + tps: 6505.85997 dtps: 6.55074 } } dps_results: { key: "TestRetribution-AllItems-SliverofPureIce-50339" value: { - dps: 6460.41245 - tps: 6546.45908 + dps: 6460.27012 + tps: 6546.31676 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-SliverofPureIce-50346" value: { - dps: 6465.46204 - tps: 6551.50868 + dps: 6465.32007 + tps: 6551.36671 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-SoulPreserver-37111" value: { - dps: 6439.45662 - tps: 6524.94104 + dps: 6439.31285 + tps: 6524.79727 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-SouloftheDead-40382" value: { - dps: 6511.46767 - tps: 6598.66364 + dps: 6511.50012 + tps: 6598.69608 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-SparkofLife-37657" value: { - dps: 6505.76336 - tps: 6587.92798 + dps: 6506.70356 + tps: 6588.86818 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-SphereofRedDragon'sBlood-37166" value: { - dps: 6560.42813 - tps: 6645.82051 + dps: 6560.29702 + tps: 6645.6894 dtps: 9.92959 } } @@ -874,48 +874,48 @@ dps_results: { dps_results: { key: "TestRetribution-AllItems-SwiftSkyflareDiamond" value: { - dps: 6562.47224 - tps: 6647.95666 + dps: 6562.52488 + tps: 6648.0093 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-SwiftStarflareDiamond" value: { - dps: 6556.3074 - tps: 6641.79181 + dps: 6556.35971 + tps: 6641.84413 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-SwiftWindfireDiamond" value: { - dps: 6545.51892 - tps: 6631.00334 + dps: 6545.57067 + tps: 6631.05509 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-TalismanofTrollDivinity-37734" value: { - dps: 6420.52064 - tps: 6506.00506 + dps: 6420.37555 + tps: 6505.85997 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-TearsoftheVanquished-47215" value: { - dps: 6420.52064 - tps: 6505.53628 + dps: 6420.37555 + tps: 6505.39119 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-TheGeneral'sHeart-45507" value: { - dps: 6420.52064 - tps: 6506.00506 + dps: 6420.37555 + tps: 6505.85997 dtps: 9.92959 } } @@ -930,72 +930,72 @@ dps_results: { dps_results: { key: "TestRetribution-AllItems-ThunderingSkyflareDiamond" value: { - dps: 6578.78508 - tps: 6664.4151 + dps: 6578.68896 + tps: 6664.31897 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-TinyAbominationinaJar-50351" value: { - dps: 7024.62707 - tps: 7110.86472 + dps: 7023.73776 + tps: 7109.97541 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-TinyAbominationinaJar-50706" value: { - dps: 7123.34647 - tps: 7209.63541 + dps: 7123.31213 + tps: 7209.60107 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-TirelessSkyflareDiamond" value: { - dps: 6536.30717 - tps: 6621.79159 + dps: 6536.35928 + tps: 6621.8437 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-TirelessStarflareDiamond" value: { - dps: 6535.0671 - tps: 6620.55151 + dps: 6535.11898 + tps: 6620.6034 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-TomeofArcanePhenomena-36972" value: { - dps: 6536.78528 - tps: 6622.43424 + dps: 6535.26623 + tps: 6620.91519 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-TomeoftheLightbringer-32368" value: { - dps: 6569.9109 - tps: 6655.39532 + dps: 6569.76696 + tps: 6655.25138 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-TrenchantEarthshatterDiamond" value: { - dps: 6535.0671 - tps: 6620.55151 + dps: 6535.11898 + tps: 6620.6034 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-TrenchantEarthsiegeDiamond" value: { - dps: 6536.30717 - tps: 6621.79159 + dps: 6536.35928 + tps: 6621.8437 dtps: 9.92959 } } @@ -1018,64 +1018,64 @@ dps_results: { dps_results: { key: "TestRetribution-AllItems-UndeadSlayer'sBlessedArmor" value: { - dps: 5397.40235 - tps: 5480.95432 + dps: 5397.45216 + tps: 5481.00412 dtps: 9.23882 } } dps_results: { key: "TestRetribution-AllItems-Val'anyr,HammerofAncientKings-46017" value: { - dps: 5145.63201 - tps: 5230.49693 + dps: 5145.39682 + tps: 5230.26174 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-WingedTalisman-37844" value: { - dps: 6440.00643 - tps: 6525.49085 + dps: 6439.86531 + tps: 6525.34973 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-WrathfulGladiator'sLibramofFortitude-51478" value: { - dps: 6729.2065 - tps: 6814.69091 + dps: 6729.06495 + tps: 6814.54937 dtps: 9.92959 } } dps_results: { key: "TestRetribution-Average-Default" value: { - dps: 6668.69511 - tps: 6753.29762 + dps: 6668.56873 + tps: 6753.17123 dtps: 13.59845 } } dps_results: { key: "TestRetribution-Settings-BloodElf-p1-Retribution Paladin SOC-default-FullBuffs-LongMultiTarget" value: { - dps: 18965.75625 - tps: 20677.85589 + dps: 18965.91539 + tps: 20678.01503 dtps: 10.57482 } } dps_results: { key: "TestRetribution-Settings-BloodElf-p1-Retribution Paladin SOC-default-FullBuffs-LongSingleTarget" value: { - dps: 5477.65446 - tps: 5563.291 + dps: 5477.99131 + tps: 5563.62785 dtps: 11.82069 } } dps_results: { key: "TestRetribution-Settings-BloodElf-p1-Retribution Paladin SOC-default-FullBuffs-ShortSingleTarget" value: { - dps: 6191.11812 - tps: 6281.82806 + dps: 6192.80238 + tps: 6287.44359 dtps: 59.10347 } } @@ -1103,24 +1103,24 @@ dps_results: { dps_results: { key: "TestRetribution-Settings-BloodElf-p1-Retribution Paladin SOR-default-FullBuffs-LongMultiTarget" value: { - dps: 16956.62716 - tps: 18668.41273 + dps: 16956.30594 + tps: 18668.0915 dtps: 10.33353 } } dps_results: { key: "TestRetribution-Settings-BloodElf-p1-Retribution Paladin SOR-default-FullBuffs-LongSingleTarget" value: { - dps: 5849.24722 - tps: 5934.80017 + dps: 5849.18097 + tps: 5934.73392 dtps: 11.82069 } } dps_results: { key: "TestRetribution-Settings-BloodElf-p1-Retribution Paladin SOR-default-FullBuffs-ShortSingleTarget" value: { - dps: 6635.13703 - tps: 6725.70508 + dps: 6634.80579 + tps: 6729.31363 dtps: 59.10347 } } @@ -1148,24 +1148,24 @@ dps_results: { dps_results: { key: "TestRetribution-Settings-BloodElf-p1-Retribution Paladin SOV 2 Target Swapping-default-FullBuffs-LongMultiTarget" value: { - dps: 18992.27977 - tps: 20700.44093 + dps: 18993.19487 + tps: 20701.35603 dtps: 8.80605 } } dps_results: { key: "TestRetribution-Settings-BloodElf-p1-Retribution Paladin SOV 2 Target Swapping-default-FullBuffs-LongSingleTarget" value: { - dps: 6663.61419 - tps: 6749.09861 + dps: 6663.47166 + tps: 6748.95608 dtps: 9.92959 } } dps_results: { key: "TestRetribution-Settings-BloodElf-p1-Retribution Paladin SOV 2 Target Swapping-default-FullBuffs-ShortSingleTarget" value: { - dps: 7382.00712 - tps: 7472.77717 + dps: 7381.2945 + tps: 7473.81754 dtps: 49.64794 } } @@ -1193,24 +1193,24 @@ dps_results: { dps_results: { key: "TestRetribution-Settings-BloodElf-p1-Retribution Paladin SOV-default-FullBuffs-LongMultiTarget" value: { - dps: 18992.27977 - tps: 20700.44093 + dps: 18993.19487 + tps: 20701.35603 dtps: 8.80605 } } dps_results: { key: "TestRetribution-Settings-BloodElf-p1-Retribution Paladin SOV-default-FullBuffs-LongSingleTarget" value: { - dps: 6663.61419 - tps: 6749.09861 + dps: 6663.47166 + tps: 6748.95608 dtps: 9.92959 } } dps_results: { key: "TestRetribution-Settings-BloodElf-p1-Retribution Paladin SOV-default-FullBuffs-ShortSingleTarget" value: { - dps: 7382.00712 - tps: 7472.77717 + dps: 7381.2945 + tps: 7473.81754 dtps: 49.64794 } } @@ -1238,24 +1238,24 @@ dps_results: { dps_results: { key: "TestRetribution-Settings-Draenei-p1-Retribution Paladin SOC-default-FullBuffs-LongMultiTarget" value: { - dps: 19088.57134 - tps: 20780.2746 + dps: 19088.7306 + tps: 20780.43386 dtps: 10.14629 } } dps_results: { key: "TestRetribution-Settings-Draenei-p1-Retribution Paladin SOC-default-FullBuffs-LongSingleTarget" value: { - dps: 5488.35294 - tps: 5572.98793 + dps: 5488.69007 + tps: 5573.32505 dtps: 11.82069 } } dps_results: { key: "TestRetribution-Settings-Draenei-p1-Retribution Paladin SOC-default-FullBuffs-ShortSingleTarget" value: { - dps: 6195.09407 - tps: 6285.8247 + dps: 6196.77971 + tps: 6291.46684 dtps: 59.10347 } } @@ -1283,24 +1283,24 @@ dps_results: { dps_results: { key: "TestRetribution-Settings-Draenei-p1-Retribution Paladin SOR-default-FullBuffs-LongMultiTarget" value: { - dps: 17080.40494 - tps: 18773.12786 + dps: 17080.08349 + tps: 18772.80641 dtps: 9.95262 } } dps_results: { key: "TestRetribution-Settings-Draenei-p1-Retribution Paladin SOR-default-FullBuffs-LongSingleTarget" value: { - dps: 5863.37349 - tps: 5947.91779 + dps: 5863.30716 + tps: 5947.85146 dtps: 11.82069 } } dps_results: { key: "TestRetribution-Settings-Draenei-p1-Retribution Paladin SOR-default-FullBuffs-ShortSingleTarget" value: { - dps: 6647.69899 - tps: 6738.28782 + dps: 6647.36735 + tps: 6741.92039 dtps: 59.10347 } } @@ -1328,24 +1328,24 @@ dps_results: { dps_results: { key: "TestRetribution-Settings-Draenei-p1-Retribution Paladin SOV 2 Target Swapping-default-FullBuffs-LongMultiTarget" value: { - dps: 19118.75828 - tps: 20804.14482 + dps: 19119.70694 + tps: 20805.09347 dtps: 8.48862 } } dps_results: { key: "TestRetribution-Settings-Draenei-p1-Retribution Paladin SOV 2 Target Swapping-default-FullBuffs-LongSingleTarget" value: { - dps: 6676.86616 - tps: 6761.29993 + dps: 6676.72376 + tps: 6761.15752 dtps: 9.92959 } } dps_results: { key: "TestRetribution-Settings-Draenei-p1-Retribution Paladin SOV 2 Target Swapping-default-FullBuffs-ShortSingleTarget" value: { - dps: 7391.39147 - tps: 7482.18276 + dps: 7390.6795 + tps: 7483.24301 dtps: 49.64794 } } @@ -1373,24 +1373,24 @@ dps_results: { dps_results: { key: "TestRetribution-Settings-Draenei-p1-Retribution Paladin SOV-default-FullBuffs-LongMultiTarget" value: { - dps: 19118.75828 - tps: 20804.14482 + dps: 19119.70694 + tps: 20805.09347 dtps: 8.48862 } } dps_results: { key: "TestRetribution-Settings-Draenei-p1-Retribution Paladin SOV-default-FullBuffs-LongSingleTarget" value: { - dps: 6676.86616 - tps: 6761.29993 + dps: 6676.72376 + tps: 6761.15752 dtps: 9.92959 } } dps_results: { key: "TestRetribution-Settings-Draenei-p1-Retribution Paladin SOV-default-FullBuffs-ShortSingleTarget" value: { - dps: 7391.39147 - tps: 7482.18276 + dps: 7390.6795 + tps: 7483.24301 dtps: 49.64794 } } @@ -1418,24 +1418,24 @@ dps_results: { dps_results: { key: "TestRetribution-Settings-Dwarf-p1-Retribution Paladin SOC-default-FullBuffs-LongMultiTarget" value: { - dps: 19000.91274 - tps: 20693.50805 + dps: 19001.07213 + tps: 20693.66744 dtps: 10.14629 } } dps_results: { key: "TestRetribution-Settings-Dwarf-p1-Retribution Paladin SOC-default-FullBuffs-LongSingleTarget" value: { - dps: 5483.34399 - tps: 5568.03751 + dps: 5483.6814 + tps: 5568.37492 dtps: 11.82069 } } dps_results: { key: "TestRetribution-Settings-Dwarf-p1-Retribution Paladin SOC-default-FullBuffs-ShortSingleTarget" value: { - dps: 6191.23305 - tps: 6281.97057 + dps: 6192.92007 + tps: 6287.62251 dtps: 59.10347 } } @@ -1463,24 +1463,24 @@ dps_results: { dps_results: { key: "TestRetribution-Settings-Dwarf-p1-Retribution Paladin SOR-default-FullBuffs-LongMultiTarget" value: { - dps: 16989.15945 - tps: 18681.15785 + dps: 16988.83779 + tps: 18680.83618 dtps: 9.95262 } } dps_results: { key: "TestRetribution-Settings-Dwarf-p1-Retribution Paladin SOR-default-FullBuffs-LongSingleTarget" value: { - dps: 5860.25589 - tps: 5944.83467 + dps: 5860.18948 + tps: 5944.76826 dtps: 11.82069 } } dps_results: { key: "TestRetribution-Settings-Dwarf-p1-Retribution Paladin SOR-default-FullBuffs-ShortSingleTarget" value: { - dps: 6643.78035 - tps: 6734.3761 + dps: 6643.44831 + tps: 6738.01641 dtps: 59.10347 } } @@ -1508,24 +1508,24 @@ dps_results: { dps_results: { key: "TestRetribution-Settings-Dwarf-p1-Retribution Paladin SOV 2 Target Swapping-default-FullBuffs-LongMultiTarget" value: { - dps: 19034.21526 - tps: 20719.28799 + dps: 19035.16533 + tps: 20720.23806 dtps: 8.48862 } } dps_results: { key: "TestRetribution-Settings-Dwarf-p1-Retribution Paladin SOV 2 Target Swapping-default-FullBuffs-LongSingleTarget" value: { - dps: 6675.1274 - tps: 6759.55479 + dps: 6674.98513 + tps: 6759.41251 dtps: 9.92959 } } dps_results: { key: "TestRetribution-Settings-Dwarf-p1-Retribution Paladin SOV 2 Target Swapping-default-FullBuffs-ShortSingleTarget" value: { - dps: 7389.89531 - tps: 7480.69367 + dps: 7389.18398 + tps: 7481.76099 dtps: 49.64794 } } @@ -1553,24 +1553,24 @@ dps_results: { dps_results: { key: "TestRetribution-Settings-Dwarf-p1-Retribution Paladin SOV-default-FullBuffs-LongMultiTarget" value: { - dps: 19034.21526 - tps: 20719.28799 + dps: 19035.16533 + tps: 20720.23806 dtps: 8.48862 } } dps_results: { key: "TestRetribution-Settings-Dwarf-p1-Retribution Paladin SOV-default-FullBuffs-LongSingleTarget" value: { - dps: 6675.1274 - tps: 6759.55479 + dps: 6674.98513 + tps: 6759.41251 dtps: 9.92959 } } dps_results: { key: "TestRetribution-Settings-Dwarf-p1-Retribution Paladin SOV-default-FullBuffs-ShortSingleTarget" value: { - dps: 7389.89531 - tps: 7480.69367 + dps: 7389.18398 + tps: 7481.76099 dtps: 49.64794 } } @@ -1598,24 +1598,24 @@ dps_results: { dps_results: { key: "TestRetribution-Settings-Human-p1-Retribution Paladin SOC-default-FullBuffs-LongMultiTarget" value: { - dps: 18979.65129 - tps: 20672.08688 + dps: 18979.81052 + tps: 20672.24611 dtps: 10.14629 } } dps_results: { key: "TestRetribution-Settings-Human-p1-Retribution Paladin SOC-default-FullBuffs-LongSingleTarget" value: { - dps: 5479.89294 - tps: 5564.57868 + dps: 5480.23 + tps: 5564.91574 dtps: 11.82069 } } dps_results: { key: "TestRetribution-Settings-Human-p1-Retribution Paladin SOC-default-FullBuffs-ShortSingleTarget" value: { - dps: 6190.09544 - tps: 6280.82607 + dps: 6191.78073 + tps: 6286.46786 dtps: 59.10347 } } @@ -1643,24 +1643,24 @@ dps_results: { dps_results: { key: "TestRetribution-Settings-Human-p1-Retribution Paladin SOR-default-FullBuffs-LongMultiTarget" value: { - dps: 16969.93508 - tps: 18661.7792 + dps: 16969.61369 + tps: 18661.45781 dtps: 9.95262 } } dps_results: { key: "TestRetribution-Settings-Human-p1-Retribution Paladin SOR-default-FullBuffs-LongSingleTarget" value: { - dps: 5853.50398 - tps: 5938.07557 + dps: 5853.43767 + tps: 5938.00926 dtps: 11.82069 } } dps_results: { key: "TestRetribution-Settings-Human-p1-Retribution Paladin SOR-default-FullBuffs-ShortSingleTarget" value: { - dps: 6637.62044 - tps: 6728.20926 + dps: 6637.28889 + tps: 6731.84193 dtps: 59.10347 } } @@ -1688,24 +1688,24 @@ dps_results: { dps_results: { key: "TestRetribution-Settings-Human-p1-Retribution Paladin SOV 2 Target Swapping-default-FullBuffs-LongMultiTarget" value: { - dps: 19007.73945 - tps: 20692.68658 + dps: 19008.65557 + tps: 20693.6027 dtps: 8.48862 } } dps_results: { key: "TestRetribution-Settings-Human-p1-Retribution Paladin SOV 2 Target Swapping-default-FullBuffs-LongSingleTarget" value: { - dps: 6666.86363 - tps: 6751.28483 + dps: 6666.72119 + tps: 6751.1424 dtps: 9.92959 } } dps_results: { key: "TestRetribution-Settings-Human-p1-Retribution Paladin SOV 2 Target Swapping-default-FullBuffs-ShortSingleTarget" value: { - dps: 7383.71468 - tps: 7474.50596 + dps: 7383.00254 + tps: 7475.56606 dtps: 49.64794 } } @@ -1733,24 +1733,24 @@ dps_results: { dps_results: { key: "TestRetribution-Settings-Human-p1-Retribution Paladin SOV-default-FullBuffs-LongMultiTarget" value: { - dps: 19007.73945 - tps: 20692.68658 + dps: 19008.65557 + tps: 20693.6027 dtps: 8.48862 } } dps_results: { key: "TestRetribution-Settings-Human-p1-Retribution Paladin SOV-default-FullBuffs-LongSingleTarget" value: { - dps: 6666.86363 - tps: 6751.28483 + dps: 6666.72119 + tps: 6751.1424 dtps: 9.92959 } } dps_results: { key: "TestRetribution-Settings-Human-p1-Retribution Paladin SOV-default-FullBuffs-ShortSingleTarget" value: { - dps: 7383.71468 - tps: 7474.50596 + dps: 7383.00254 + tps: 7475.56606 dtps: 49.64794 } } @@ -1778,8 +1778,8 @@ dps_results: { dps_results: { key: "TestRetribution-SwitchInFrontOfTarget-Default" value: { - dps: 6317.26995 - tps: 6402.64627 + dps: 6317.40296 + tps: 6402.77929 dtps: 9.92959 } } diff --git a/sim/paladin/retribution/retribution.go b/sim/paladin/retribution/retribution.go index c619ce0f6a..a21aca2089 100644 --- a/sim/paladin/retribution/retribution.go +++ b/sim/paladin/retribution/retribution.go @@ -1,8 +1,6 @@ package retribution import ( - "time" - "github.com/wowsims/wotlk/sim/core" "github.com/wowsims/wotlk/sim/core/proto" "github.com/wowsims/wotlk/sim/paladin" @@ -31,20 +29,8 @@ func NewRetributionPaladin(character *core.Character, options *proto.Player) *Re pal := paladin.NewPaladin(character, options.TalentsString) ret := &RetributionPaladin{ - Paladin: pal, - Rotation: retOptions.Rotation, - Judgement: retOptions.Options.Judgement, - Seal: retOptions.Options.Seal, - UseDivinePlea: retOptions.Rotation.UseDivinePlea, - AvoidClippingConsecration: retOptions.Rotation.AvoidClippingConsecration, - HoldLastAvengingWrathUntilExecution: retOptions.Rotation.HoldLastAvengingWrathUntilExecution, - DivinePleaPercentage: retOptions.Rotation.DivinePleaPercentage, - CancelChaosBane: retOptions.Rotation.CancelChaosBane, - ExoSlack: retOptions.Rotation.ExoSlack, - ConsSlack: retOptions.Rotation.ConsSlack, - HolyWrathThreshold: retOptions.Rotation.HolyWrathThreshold, - MaxSoVTargets: retOptions.Rotation.SovTargets, - HasLightswornBattlegear2Pc: character.HasSetBonus(paladin.ItemSetLightswornBattlegear, 2), + Paladin: pal, + Seal: retOptions.Options.Seal, } pal.AvoidClippingConsecration = retOptions.Rotation.AvoidClippingConsecration @@ -53,55 +39,18 @@ func NewRetributionPaladin(character *core.Character, options *proto.Player) *Re ret.PaladinAura = retOptions.Options.Aura - ret.RotatioOption = retOptions.Rotation.CustomRotation - if retOptions.Rotation.Type == proto.RetributionPaladin_Rotation_Standard { - ret.SelectedRotation = ret.mainRotation - } else if retOptions.Rotation.Type == proto.RetributionPaladin_Rotation_Custom { - ret.SelectedRotation = ret.customRotation - } else if retOptions.Rotation.Type == proto.RetributionPaladin_Rotation_CastSequence { - ret.SelectedRotation = ret.castSequenceRotation - ret.CastSequenceIndex = 0 - ret.RotatioOption = retOptions.Rotation.CustomCastSequence - } else { - ret.SelectedRotation = ret.mainRotation - } - ret.EnableAutoAttacks(ret, core.AutoAttackOptions{ MainHand: ret.WeaponFromMainHand(0), // Set crit multiplier later when we have targets. AutoSwingMelee: true, }) - ret.EnableResumeAfterManaWait(ret.OnGCDReady) - return ret } type RetributionPaladin struct { *paladin.Paladin - Judgement proto.PaladinJudgement - Seal proto.PaladinSeal - UseDivinePlea bool - AvoidClippingConsecration bool - HoldLastAvengingWrathUntilExecution bool - CancelChaosBane bool - - DivinePleaPercentage float64 - ExoSlack int32 - ConsSlack int32 - HolyWrathThreshold int32 - MaxSoVTargets int32 - - HasLightswornBattlegear2Pc bool - - SelectedJudgement *core.Spell - - SelectedRotation func(*core.Simulation) - RotatioOption *proto.CustomRotation - RotationInput []*core.Spell - CastSequenceIndex int32 - - Rotation *proto.RetributionPaladin_Rotation + Seal proto.PaladinSeal } func (ret *RetributionPaladin) GetPaladin() *paladin.Paladin { @@ -111,54 +60,11 @@ func (ret *RetributionPaladin) GetPaladin() *paladin.Paladin { func (ret *RetributionPaladin) Initialize() { ret.Paladin.Initialize() ret.RegisterAvengingWrathCD() - - if ret.Seal != proto.PaladinSeal_Vengeance { - ret.DelayDPSCooldownsForArmorDebuffs(time.Second * 10) - } } func (ret *RetributionPaladin) Reset(sim *core.Simulation) { ret.Paladin.Reset(sim) - switch ret.Judgement { - case proto.PaladinJudgement_JudgementOfWisdom: - ret.SelectedJudgement = ret.JudgementOfWisdom - case proto.PaladinJudgement_JudgementOfLight: - ret.SelectedJudgement = ret.JudgementOfLight - } - - if ret.RotatioOption != nil { - ret.RotationInput = make([]*core.Spell, 0, len(ret.RotatioOption.Spells)) - for _, customSpellProto := range ret.RotatioOption.Spells { - switch customSpellProto.Spell { - case int32(proto.RetributionPaladin_Rotation_JudgementOfWisdom): - ret.RotationInput = append(ret.RotationInput, ret.SelectedJudgement) - case int32(proto.RetributionPaladin_Rotation_DivineStorm): - ret.RotationInput = append(ret.RotationInput, ret.DivineStorm) - case int32(proto.RetributionPaladin_Rotation_HammerOfWrath): - ret.RotationInput = append(ret.RotationInput, ret.HammerOfWrath) - case int32(proto.RetributionPaladin_Rotation_Consecration): - ret.RotationInput = append(ret.RotationInput, ret.Consecration) - case int32(proto.RetributionPaladin_Rotation_HolyWrath): - ret.RotationInput = append(ret.RotationInput, ret.HolyWrath) - case int32(proto.RetributionPaladin_Rotation_CrusaderStrike): - ret.RotationInput = append(ret.RotationInput, ret.CrusaderStrike) - case int32(proto.RetributionPaladin_Rotation_Exorcism): - ret.RotationInput = append(ret.RotationInput, ret.Exorcism) - case int32(proto.RetributionPaladin_Rotation_DivinePlea): - ret.RotationInput = append(ret.RotationInput, ret.DivinePlea) - } - } - } - - sim.RegisterExecutePhaseCallback(func(sim *core.Simulation, isExecute int32) { - if isExecute == 20 { - ret.OnGCDReady(sim) - } - }) - - ret.CastSequenceIndex = 0 - switch ret.Seal { case proto.PaladinSeal_Vengeance: ret.CurrentSeal = ret.SealOfVengeanceAura @@ -170,9 +76,4 @@ func (ret *RetributionPaladin) Reset(sim *core.Simulation) { ret.CurrentSeal = ret.SealOfRighteousnessAura ret.SealOfRighteousnessAura.Activate(sim) } - - if !ret.IsUsingAPL { - ret.DivinePleaAura.Activate(sim) - ret.DivinePlea.CD.Use(sim) - } } diff --git a/sim/paladin/retribution/rotation.go b/sim/paladin/retribution/rotation.go deleted file mode 100644 index 287010865d..0000000000 --- a/sim/paladin/retribution/rotation.go +++ /dev/null @@ -1,355 +0,0 @@ -package retribution - -import ( - "math" - "time" - - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/core/proto" -) - -func (ret *RetributionPaladin) OnAutoAttack(sim *core.Simulation, _ *core.Spell) { - if ret.SealOfVengeanceAura.IsActive() && min(ret.MaxSoVTargets, ret.Env.GetNumTargets()) > 1 { - minVengeanceDotDuration := time.Second * 15 - var minVengeanceDotDurationTarget *core.Unit - minVengeanceDotStacks := int32(5) - var minVengeanceDotStacksTarget *core.Unit - for i := int32(0); i < min(ret.MaxSoVTargets, ret.Env.GetNumTargets()); i++ { - target := ret.Env.GetTargetUnit(i) - dot := ret.SovDotSpell.Dot(target) - remainingDuration := dot.RemainingDuration(sim) - stackCount := dot.GetStacks() - - if remainingDuration < minVengeanceDotDuration && remainingDuration > 0 { - minVengeanceDotDuration = remainingDuration - minVengeanceDotDurationTarget = target - } - - if stackCount < minVengeanceDotStacks { - minVengeanceDotStacks = stackCount - minVengeanceDotStacksTarget = target - } - } - - if minVengeanceDotDuration < core.DurationFromSeconds(ret.AutoAttacks.MH().SwingSpeed*2) { - ret.CurrentTarget = minVengeanceDotDurationTarget - } else if ret.SovDotSpell.Dot(ret.CurrentTarget).GetStacks() == 5 && minVengeanceDotStacks < 5 { - ret.CurrentTarget = minVengeanceDotStacksTarget - } else { - ret.CurrentTarget = ret.Env.Encounter.TargetUnits[0] - } - } -} - -func (ret *RetributionPaladin) OnGCDReady(sim *core.Simulation) { - if ret.IsUsingAPL { - return - } - - ret.SelectedRotation(sim) - if ret.GCD.IsReady(sim) { - ret.DoNothing() // this means we had nothing to do and we are ok - } -} - -func (ret *RetributionPaladin) customRotation(sim *core.Simulation) { - // Setup - target := ret.Env.Encounter.TargetUnits[0] - - nextSwingAt := ret.AutoAttacks.NextAttackAt() - isExecutePhase := sim.IsExecutePhase20() - - if ret.HandOfReckoning != nil && ret.HandOfReckoning.IsReady(sim) { - ret.HandOfReckoning.Cast(sim, ret.CurrentTarget) - } - - if ret.GCD.IsReady(sim) { - rotationLoop: - for _, spell := range ret.RotationInput { - if spell == ret.HammerOfWrath && !isExecutePhase { - continue - } - - if spell == ret.HammerOfWrath && isExecutePhase && ret.HoldLastAvengingWrathUntilExecution { - if ret.AvengingWrath.IsReady(sim) { - success := ret.AvengingWrath.Cast(sim, target) - if !success { - ret.WaitForMana(sim, ret.AvengingWrath.CurCast.Cost) - } - } - } - - if spell == ret.HolyWrath { - // Holy Wrath isn't worth casting if it will reduce usages of CS/DS - if ret.CrusaderStrike.ReadyAt()-sim.CurrentTime < 500*time.Millisecond { - continue - } - if ret.DivineStorm.ReadyAt()-sim.CurrentTime < 500*time.Millisecond { - continue - } - } - - if spell == ret.Consecration && !ret.checkConsecrationClipping(sim) { - // This is a skip, so we take the opposite of the clip check. - continue - } - - if spell == ret.Exorcism && !ret.ArtOfWarInstantCast.IsActive() { - continue - } - - if spell == ret.DivinePlea && ret.CurrentMana() > (ret.MaxMana()*ret.DivinePleaPercentage) { - continue - } - - if spell.IsReady(sim) { - success := spell.Cast(sim, target) - if !success { - ret.WaitForMana(sim, spell.CurCast.Cost) - } - break rotationLoop - } - } - } - - // All possible next events - events := []time.Duration{ - nextSwingAt, - ret.GCD.ReadyAt(), - ret.SelectedJudgement.CD.ReadyAt(), - ret.DivineStorm.CD.ReadyAt(), - ret.HammerOfWrath.CD.ReadyAt(), - ret.HolyWrath.CD.ReadyAt(), - ret.CrusaderStrike.CD.ReadyAt(), - ret.Consecration.CD.ReadyAt(), - ret.Exorcism.CD.ReadyAt(), - ret.DivinePlea.CD.ReadyAt(), - } - - if ret.HandOfReckoning != nil { - events = append(events, ret.HandOfReckoning.CD.ReadyAt()) - } - - CancelChaosBane(ret, sim) - ret.waitUntilNextEvent(sim, events, ret.customRotation) -} - -func (ret *RetributionPaladin) castSequenceRotation(sim *core.Simulation) { - if len(ret.RotationInput) == 0 { - return - } - - // Setup - target := ret.Env.Encounter.TargetUnits[0] - isExecutePhase := sim.IsExecutePhase20() - - nextReadyAt := sim.CurrentTime - - if hc := ret.Hardcast; ret.HandOfReckoning != nil && ret.HandOfReckoning.IsReady(sim) && !(hc.Expires > sim.CurrentTime) { - ret.HandOfReckoning.Cast(sim, ret.CurrentTarget) - } - - if ret.GCD.IsReady(sim) { - if ret.UseDivinePlea && ret.DivinePlea.IsReady(sim) && ret.CurrentMana() < (ret.MaxMana()*ret.DivinePleaPercentage) { - ret.DivinePlea.Cast(sim, nil) - } else { - currentSpell := ret.RotationInput[ret.CastSequenceIndex] - - if currentSpell == ret.HammerOfWrath && !isExecutePhase { - return - } - - if currentSpell.IsReady(sim) { - success := currentSpell.Cast(sim, target) - if success { - ret.CastSequenceIndex = (ret.CastSequenceIndex + 1) % int32(len(ret.RotationInput)) - } else { - ret.WaitForMana(sim, currentSpell.CurCast.Cost) - } - } else { - nextReadyAt = currentSpell.ReadyAt() - } - } - } - - events := []time.Duration{ - ret.GCD.ReadyAt(), - nextReadyAt, - } - - if ret.HandOfReckoning != nil { - events = append(events, ret.HandOfReckoning.CD.ReadyAt()) - } - - CancelChaosBane(ret, sim) - ret.waitUntilNextEvent(sim, events, ret.castSequenceRotation) -} - -func (ret *RetributionPaladin) mainRotation(sim *core.Simulation) { - - // Setup - target := ret.Env.Encounter.TargetUnits[0] - - nextSwingAt := ret.AutoAttacks.NextAttackAt() - isExecutePhase := sim.IsExecutePhase20() - - nextPrimaryAbility := min(ret.CrusaderStrike.CD.ReadyAt(), ret.DivineStorm.CD.ReadyAt(), ret.SelectedJudgement.CD.ReadyAt()) - nextPrimaryAbilityDelta := nextPrimaryAbility - sim.CurrentTime - - if ret.HandOfReckoning != nil && ret.HandOfReckoning.IsReady(sim) { - ret.HandOfReckoning.Cast(sim, ret.CurrentTarget) - } - - if ret.GCD.IsReady(sim) { - switch { - case isExecutePhase && ret.HammerOfWrath.IsReady(sim) && ret.HoldLastAvengingWrathUntilExecution: - if ret.AvengingWrath.IsReady(sim) { - success := ret.AvengingWrath.Cast(sim, target) - if !success { - ret.WaitForMana(sim, ret.AvengingWrath.CurCast.Cost) - } - } - - success := ret.HammerOfWrath.Cast(sim, target) - if !success { - ret.WaitForMana(sim, ret.HammerOfWrath.CurCast.Cost) - } - case ret.SelectedJudgement.IsReady(sim): - success := ret.SelectedJudgement.Cast(sim, target) - if !success { - ret.WaitForMana(sim, ret.SelectedJudgement.CurCast.Cost) - } - case ret.HasLightswornBattlegear2Pc && ret.DivineStorm.IsReady(sim): - success := ret.DivineStorm.Cast(sim, target) - if !success { - ret.WaitForMana(sim, ret.DivineStorm.CurCast.Cost) - } - case ret.Env.GetNumTargets() > 1 && ret.Consecration.IsReady(sim): - success := ret.Consecration.Cast(sim, target) - if !success { - ret.WaitForMana(sim, ret.Consecration.CurCast.Cost) - } - case isExecutePhase && ret.HammerOfWrath.IsReady(sim): - success := ret.HammerOfWrath.Cast(sim, target) - if !success { - ret.WaitForMana(sim, ret.HammerOfWrath.CurCast.Cost) - } - case ret.DemonAndUndeadTargetCount >= ret.HolyWrathThreshold && ret.HolyWrath.IsReady(sim): - success := ret.HolyWrath.Cast(sim, target) - if !success { - ret.WaitForMana(sim, ret.HolyWrath.CurCast.Cost) - } - case ret.UseDivinePlea && ret.CurrentMana() < (ret.MaxMana()*ret.DivinePleaPercentage) && ret.DivinePlea.IsReady(sim): - ret.DivinePlea.Cast(sim, nil) - case ret.CrusaderStrike.IsReady(sim): - success := ret.CrusaderStrike.Cast(sim, target) - if !success { - ret.WaitForMana(sim, ret.CrusaderStrike.CurCast.Cost) - } - case ret.DivineStorm.IsReady(sim): - success := ret.DivineStorm.Cast(sim, target) - if !success { - ret.WaitForMana(sim, ret.DivineStorm.CurCast.Cost) - } - case (target.MobType == proto.MobType_MobTypeDemon || target.MobType == proto.MobType_MobTypeUndead) && - nextPrimaryAbilityDelta.Milliseconds() > int64(ret.ExoSlack) && ret.Exorcism.IsReady(sim) && ret.ArtOfWarInstantCast.IsActive(): - success := ret.Exorcism.Cast(sim, target) - if !success { - ret.WaitForMana(sim, ret.Exorcism.CurCast.Cost) - } - case nextPrimaryAbilityDelta.Milliseconds() > int64(ret.ConsSlack) && ret.Consecration.IsReady(sim) && ret.checkConsecrationClipping(sim): - success := ret.Consecration.Cast(sim, target) - if !success { - ret.WaitForMana(sim, ret.Consecration.CurCast.Cost) - } - case nextPrimaryAbilityDelta.Milliseconds() > int64(ret.ExoSlack) && ret.Exorcism.IsReady(sim) && ret.ArtOfWarInstantCast.IsActive(): - success := ret.Exorcism.Cast(sim, target) - if !success { - ret.WaitForMana(sim, ret.Exorcism.CurCast.Cost) - } - case ret.DemonAndUndeadTargetCount >= 1 && ret.HolyWrath.IsReady(sim): - // Holy Wrath isn't worth casting if it will reduce usages of CS/DS - if ret.CrusaderStrike.ReadyAt()-sim.CurrentTime < 500*time.Millisecond { - break - } - if ret.DivineStorm.ReadyAt()-sim.CurrentTime < 500*time.Millisecond { - break - } - success := ret.HolyWrath.Cast(sim, target) - if !success { - ret.WaitForMana(sim, ret.HolyWrath.CurCast.Cost) - } - } - } - - // All possible next events - events := []time.Duration{ - nextSwingAt, - ret.GCD.ReadyAt(), - ret.SelectedJudgement.CD.ReadyAt(), - ret.DivineStorm.CD.ReadyAt(), - ret.HammerOfWrath.CD.ReadyAt(), - ret.HolyWrath.CD.ReadyAt(), - ret.CrusaderStrike.CD.ReadyAt(), - ret.Consecration.CD.ReadyAt(), - ret.Exorcism.CD.ReadyAt(), - ret.DivinePlea.CD.ReadyAt(), - } - - if ret.HandOfReckoning != nil { - events = append(events, ret.HandOfReckoning.CD.ReadyAt()) - } - - CancelChaosBane(ret, sim) - ret.waitUntilNextEvent(sim, events, ret.mainRotation) -} - -func (ret *RetributionPaladin) checkConsecrationClipping(sim *core.Simulation) bool { - if ret.AvoidClippingConsecration { - return ret.Consecration.AOEDot().TickLength*4 <= sim.GetRemainingDuration() - } else { - // If we're not configured to check, always return success. - return true - } -} - -// Helper function for finding the next event -func (ret *RetributionPaladin) waitUntilNextEvent(sim *core.Simulation, events []time.Duration, rotationCallback func(*core.Simulation)) { - - // Find the minimum possible next event that is greater than the current time - nextEventAt := time.Duration(math.MaxInt64) // any event will happen before forever. - for _, elem := range events { - if elem > sim.CurrentTime && elem < nextEventAt { - nextEventAt = elem - } - } - // If the next action is the GCD, just return - if nextEventAt == ret.GCD.ReadyAt() { - if ret.CancelChaosBane && ret.HasActiveAura("Chaos Bane") { - ret.GetAura("Chaos Bane").Deactivate(sim) - } - return - } - - // Otherwise add a pending action for the next time - pa := &core.PendingAction{ - Priority: core.ActionPriorityLow, - OnAction: rotationCallback, - NextActionAt: nextEventAt, - } - - sim.AddPendingAction(pa) - - if ret.CancelChaosBane && ret.HasActiveAura("Chaos Bane") { - ret.GetAura("Chaos Bane").Deactivate(sim) - } -} - -func CancelChaosBane(ret *RetributionPaladin, sim *core.Simulation) { - if !ret.Paladin.CancelChaosBane { - return - } - if a := ret.Paladin.GetAura("Chaos Bane"); a != nil { - a.Deactivate(sim) - } -} diff --git a/sim/priest/healing/TestDisc.results b/sim/priest/healing/TestDisc.results index a57d5dc3b3..2e1c8bb972 100644 --- a/sim/priest/healing/TestDisc.results +++ b/sim/priest/healing/TestDisc.results @@ -343,7 +343,7 @@ dps_results: { dps_results: { key: "TestDisc-AllItems-Figurine-SapphireOwl-42413" value: { - tps: 19.00072 + tps: 18.9916 hps: 3650.23426 } } diff --git a/sim/priest/healing/TestHoly.results b/sim/priest/healing/TestHoly.results index 91517efd66..7de62a4da8 100644 --- a/sim/priest/healing/TestHoly.results +++ b/sim/priest/healing/TestHoly.results @@ -172,8 +172,8 @@ dps_results: { dps_results: { key: "TestHoly-AllItems-DarkmoonCard:Greatness-44255" value: { - tps: 36.25385 - hps: 4991.42137 + tps: 35.9717 + hps: 4983.05245 } } dps_results: { diff --git a/sim/priest/healing/healing_priest.go b/sim/priest/healing/healing_priest.go index 743f2e3231..1150ac7b73 100644 --- a/sim/priest/healing/healing_priest.go +++ b/sim/priest/healing/healing_priest.go @@ -1,7 +1,6 @@ package healing import ( - "github.com/wowsims/wotlk/sim/common" "github.com/wowsims/wotlk/sim/core" "github.com/wowsims/wotlk/sim/core/proto" "github.com/wowsims/wotlk/sim/priest" @@ -27,13 +26,7 @@ func RegisterHealingPriest() { type HealingPriest struct { *priest.Priest - rotation *proto.HealingPriest_Rotation - CustomRotation *common.CustomRotation - Options *proto.HealingPriest_Options - - // Spells to rotate through for cyclic rotation. - spellCycle []*core.Spell - nextCycleIndex int + Options *proto.HealingPriest_Options } func NewHealingPriest(character *core.Character, options *proto.Player) *HealingPriest { @@ -46,9 +39,8 @@ func NewHealingPriest(character *core.Character, options *proto.Player) *Healing basePriest := priest.New(character, selfBuffs, options.TalentsString) hpriest := &HealingPriest{ - Priest: basePriest, - rotation: healingOptions.Rotation, - Options: healingOptions.Options, + Priest: basePriest, + Options: healingOptions.Options, } hpriest.SelfBuffs.PowerInfusionTarget = &proto.UnitReference{} @@ -56,8 +48,6 @@ func NewHealingPriest(character *core.Character, options *proto.Player) *Healing hpriest.SelfBuffs.PowerInfusionTarget = hpriest.Options.PowerInfusionTarget } - hpriest.EnableResumeAfterManaWait(hpriest.tryUseGCD) - return hpriest } @@ -81,26 +71,8 @@ func (hpriest *HealingPriest) Initialize() { hpriest.ApplyRapture(hpriest.Options.RapturesPerMinute) hpriest.RegisterHymnOfHopeCD() - - if hpriest.rotation.Type == proto.HealingPriest_Rotation_Custom { - hpriest.CustomRotation = hpriest.makeCustomRotation() - } - - if hpriest.CustomRotation == nil { - hpriest.rotation.Type = proto.HealingPriest_Rotation_Cycle - hpriest.spellCycle = []*core.Spell{ - hpriest.GreaterHeal, - hpriest.FlashHeal, - hpriest.CircleOfHealing, - hpriest.BindingHeal, - hpriest.PrayerOfHealing, - hpriest.PrayerOfMending, - hpriest.PenanceHeal, - } - } } func (hpriest *HealingPriest) Reset(sim *core.Simulation) { hpriest.Priest.Reset(sim) - hpriest.nextCycleIndex = 0 } diff --git a/sim/priest/healing/rotation.go b/sim/priest/healing/rotation.go deleted file mode 100644 index 1169c21e71..0000000000 --- a/sim/priest/healing/rotation.go +++ /dev/null @@ -1,115 +0,0 @@ -package healing - -import ( - "github.com/wowsims/wotlk/sim/common" - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/core/proto" -) - -func (hpriest *HealingPriest) OnGCDReady(sim *core.Simulation) { - hpriest.tryUseGCD(sim) -} - -func (hpriest *HealingPriest) tryUseGCD(sim *core.Simulation) { - if hpriest.CustomRotation != nil { - hpriest.CustomRotation.Cast(sim) - } else { - spell := hpriest.chooseSpell(sim) - - if success := spell.Cast(sim, hpriest.CurrentTarget); !success { - hpriest.WaitForMana(sim, spell.CurCast.Cost) - } - } -} - -func (hpriest *HealingPriest) chooseSpell(sim *core.Simulation) *core.Spell { - if !hpriest.Renew.CurHot().IsActive() { - return hpriest.Renew - } else if hpriest.PowerWordShield.CanCast(sim, hpriest.CurrentTarget) { - return hpriest.PowerWordShield - } else { - for !hpriest.spellCycle[hpriest.nextCycleIndex].IsReady(sim) { - hpriest.nextCycleIndex = (hpriest.nextCycleIndex + 1) % len(hpriest.spellCycle) - } - spell := hpriest.spellCycle[hpriest.nextCycleIndex] - hpriest.nextCycleIndex = (hpriest.nextCycleIndex + 1) % len(hpriest.spellCycle) - return spell - } -} - -func (hpriest *HealingPriest) makeCustomRotation() *common.CustomRotation { - return common.NewCustomRotation(hpriest.rotation.CustomRotation, hpriest.GetCharacter(), map[int32]common.CustomSpell{ - int32(proto.HealingPriest_Rotation_GreaterHeal): { - Spell: hpriest.GreaterHeal, - }, - int32(proto.HealingPriest_Rotation_FlashHeal): { - Spell: hpriest.FlashHeal, - }, - int32(proto.HealingPriest_Rotation_Renew): { - Spell: hpriest.Renew, - Action: func(sim *core.Simulation, target *core.Unit) (bool, float64) { - for _, unit := range hpriest.Env.Raid.AllUnits { - renewHot := hpriest.Renew.Hot(unit) - if renewHot != nil && !renewHot.IsActive() { - success := hpriest.Renew.Cast(sim, unit) - return success, hpriest.Renew.CurCast.Cost - } - } - panic("No valid Renew target") - }, - Condition: func(sim *core.Simulation) bool { - for _, unit := range hpriest.Env.Raid.AllUnits { - renewHot := hpriest.Renew.Hot(unit) - if renewHot != nil && !renewHot.IsActive() { - return true - } - } - return false - }, - }, - int32(proto.HealingPriest_Rotation_PowerWordShield): { - Spell: hpriest.PowerWordShield, - Action: func(sim *core.Simulation, target *core.Unit) (bool, float64) { - for _, unit := range hpriest.Env.Raid.AllUnits { - if hpriest.PowerWordShield.CanCast(sim, unit) { - success := hpriest.PowerWordShield.Cast(sim, unit) - return success, hpriest.PowerWordShield.CurCast.Cost - } - } - panic("No valid PowerWordShield target") - }, - Condition: func(sim *core.Simulation) bool { - for _, unit := range hpriest.Env.Raid.AllUnits { - if hpriest.PowerWordShield.CanCast(sim, unit) { - return true - } - } - return false - }, - }, - int32(proto.HealingPriest_Rotation_CircleOfHealing): { - Spell: hpriest.CircleOfHealing, - Condition: func(sim *core.Simulation) bool { - return hpriest.CircleOfHealing.IsReady(sim) - }, - }, - int32(proto.HealingPriest_Rotation_PrayerOfHealing): { - Spell: hpriest.PrayerOfHealing, - }, - int32(proto.HealingPriest_Rotation_PrayerOfMending): { - Spell: hpriest.PrayerOfMending, - Condition: func(sim *core.Simulation) bool { - return hpriest.PrayerOfMending.IsReady(sim) - }, - }, - int32(proto.HealingPriest_Rotation_Penance): { - Spell: hpriest.PenanceHeal, - Condition: func(sim *core.Simulation) bool { - return hpriest.PenanceHeal.IsReady(sim) - }, - }, - int32(proto.HealingPriest_Rotation_BindingHeal): { - Spell: hpriest.BindingHeal, - }, - }) -} diff --git a/sim/priest/holy_fire.go b/sim/priest/holy_fire.go index 0490636cb6..5fbaeda9ac 100644 --- a/sim/priest/holy_fire.go +++ b/sim/priest/holy_fire.go @@ -7,8 +7,8 @@ import ( "github.com/wowsims/wotlk/sim/core/proto" ) -func (priest *Priest) RegisterHolyFireSpell(memeDream bool) { - hasGlyph := !memeDream && priest.HasMajorGlyph(proto.PriestMajorGlyph_GlyphOfSmite) +func (priest *Priest) RegisterHolyFireSpell() { + hasGlyph := priest.HasMajorGlyph(proto.PriestMajorGlyph_GlyphOfSmite) priest.HolyFire = priest.RegisterSpell(core.SpellConfig{ ActionID: core.ActionID{SpellID: 48135}, diff --git a/sim/priest/hymn_of_hope.go b/sim/priest/hymn_of_hope.go index 4b097acbea..f88c6ecafe 100644 --- a/sim/priest/hymn_of_hope.go +++ b/sim/priest/hymn_of_hope.go @@ -13,7 +13,6 @@ func (priest *Priest) RegisterHymnOfHopeCD() { manaMetrics := priest.NewManaMetrics(actionID) numTicks := 4 + core.TernaryInt32(priest.HasMajorGlyph(proto.PriestMajorGlyph_GlyphOfHymnOfHope), 1, 0) - channelTime := time.Duration(numTicks) * time.Second * 2 hymnOfHopeSpell := priest.RegisterSpell(core.SpellConfig{ ActionID: actionID, @@ -21,8 +20,7 @@ func (priest *Priest) RegisterHymnOfHopeCD() { Cast: core.CastConfig{ DefaultCast: core.Cast{ - GCD: core.GCDDefault, - ChannelTime: channelTime, + GCD: core.GCDDefault, }, CD: core.Cooldown{ Timer: priest.NewTimer(), @@ -31,9 +29,8 @@ func (priest *Priest) RegisterHymnOfHopeCD() { }, ApplyEffects: func(sim *core.Simulation, _ *core.Unit, spell *core.Spell) { - period := spell.CurCast.ChannelTime / time.Duration(numTicks) core.StartPeriodicAction(sim, core.PeriodicActionOptions{ - Period: period, + Period: time.Second * 2, NumTicks: int(numTicks), OnAction: func(sim *core.Simulation) { // This is 3%, but it increases the target's max mana by 20% for the duration diff --git a/sim/priest/mind_flay.go b/sim/priest/mind_flay.go index b96cbf8d94..d25ba8649d 100644 --- a/sim/priest/mind_flay.go +++ b/sim/priest/mind_flay.go @@ -71,7 +71,6 @@ func (priest *Priest) newMindFlaySpell(numTicksIdx int32) *core.Spell { mfReducTime = time.Millisecond * 170 } tickLength := time.Second - mfReducTime - channelTime := tickLength * time.Duration(numTicks) rolloverChance := float64(priest.Talents.PainAndSuffering) / 3.0 shadowFocus := 0.02 * float64(priest.Talents.ShadowFocus) @@ -92,21 +91,7 @@ func (priest *Priest) newMindFlaySpell(numTicksIdx int32) *core.Spell { }, Cast: core.CastConfig{ DefaultCast: core.Cast{ - GCD: core.GCDDefault, - ChannelTime: channelTime, - }, - ModifyCast: func(sim *core.Simulation, spell *core.Spell, cast *core.Cast) { - if spell.Unit.IsUsingAPL || priest.Latency == 0 { - return - } - // if our channel is longer than GCD it will have human latency to end it because you can't queue the next spell. - if float64(channelTime)*priest.CastSpeed > float64(core.GCDMin) { - variation := priest.Latency * (0.66 + sim.RandomFloat("spriest latency")*(1.33-0.66)) // should vary from 0.66 - 1.33 of given latency - cast.ChannelTime += time.Duration(variation / priest.CastSpeed * float64(time.Millisecond)) - if sim.Log != nil { - priest.Log(sim, "Latency: %.3f, Applied Latency: %.3f", priest.Latency, variation) - } - } + GCD: core.GCDDefault, }, }, BonusHitRating: float64(priest.Talents.ShadowFocus) * 1 * core.SpellHitRatingPerHitChance, @@ -154,18 +139,3 @@ func (priest *Priest) newMindFlaySpell(numTicksIdx int32) *core.Spell { }, }) } - -func (priest *Priest) MindFlayTickDuration() time.Duration { - return priest.ApplyCastSpeed(time.Second - core.TernaryDuration(priest.T10FourSetBonus, time.Millisecond*170, 0)) -} - -func (priest *Priest) AverageMindFlayLatencyDelay(numTicks int, gcd time.Duration) time.Duration { - wait := priest.ApplyCastSpeed(priest.MindFlay[numTicks].DefaultCast.ChannelTime) - if wait <= gcd || priest.Latency == 0 { - return 0 - } - - base := priest.Latency * 0.25 - variation := base + 0.5*base - return time.Duration(variation) * time.Millisecond -} diff --git a/sim/priest/mind_sear.go b/sim/priest/mind_sear.go index 4514daf3b3..fd48c35ca4 100644 --- a/sim/priest/mind_sear.go +++ b/sim/priest/mind_sear.go @@ -54,7 +54,6 @@ func (priest *Priest) newMindSearSpell(numTicksIdx int32) *core.Spell { flags |= core.SpellFlagAPL } - channelTime := time.Second * time.Duration(numTicks) miseryCoeff := priest.getMindSearMiseryCoefficient() mindSearTickSpell := priest.getMindSearTickSpell(numTicksIdx) @@ -67,8 +66,7 @@ func (priest *Priest) newMindSearSpell(numTicksIdx int32) *core.Spell { } config.Cast = core.CastConfig{ DefaultCast: core.Cast{ - GCD: core.GCDDefault, - ChannelTime: channelTime, + GCD: core.GCDDefault, }, } config.Dot = core.DotConfig{ diff --git a/sim/priest/penance.go b/sim/priest/penance.go index fb3eb199ae..a1b0432b6d 100644 --- a/sim/priest/penance.go +++ b/sim/priest/penance.go @@ -43,8 +43,7 @@ func (priest *Priest) makePenanceSpell(isHeal bool) *core.Spell { }, Cast: core.CastConfig{ DefaultCast: core.Cast{ - GCD: core.GCDDefault, - ChannelTime: time.Second * 2, + GCD: core.GCDDefault, }, CD: core.Cooldown{ Timer: priest.NewTimer(), diff --git a/sim/priest/priest.go b/sim/priest/priest.go index 0f78a7afae..5c851c955a 100644 --- a/sim/priest/priest.go +++ b/sim/priest/priest.go @@ -140,10 +140,8 @@ func (priest *Priest) Initialize() { priest.registerPowerInfusionCD() - if priest.IsUsingAPL { - priest.MindFlayAPL = priest.newMindFlaySpell(0) - priest.MindSearAPL = priest.newMindSearSpell(0) - } + priest.MindFlayAPL = priest.newMindFlaySpell(0) + priest.MindSearAPL = priest.newMindSearSpell(0) priest.MindFlay = []*core.Spell{ nil, // So we can use # of ticks as the index diff --git a/sim/priest/shadow/TestShadow.results b/sim/priest/shadow/TestShadow.results index fd4adab58a..a353b97a97 100644 --- a/sim/priest/shadow/TestShadow.results +++ b/sim/priest/shadow/TestShadow.results @@ -798,8 +798,8 @@ dps_results: { dps_results: { key: "TestShadow-AllItems-Zabra'sRaiment" value: { - dps: 6508.31094 - tps: 6310.96351 + dps: 6507.98519 + tps: 6310.63776 } } dps_results: { diff --git a/sim/priest/shadow/rotation.go b/sim/priest/shadow/rotation.go deleted file mode 100644 index 064af2ef3b..0000000000 --- a/sim/priest/shadow/rotation.go +++ /dev/null @@ -1,1173 +0,0 @@ -package shadow - -import ( - //"fmt" - "math" - "time" - - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/core/proto" -) - -const ( - mbIdx int = iota - dpIdx - vtIdx - swdIdx - mfIdx - swpIdx -) - -func (spriest *ShadowPriest) OnGCDReady(sim *core.Simulation) { - spriest.tryUseGCD(sim) -} - -func (spriest *ShadowPriest) OnManaTick(sim *core.Simulation) { - if spriest.FinishedWaitingForManaAndGCDReady(sim) { - spriest.tryUseGCD(sim) - } -} -func (spriest *ShadowPriest) tryUseGCD(sim *core.Simulation) { - if spriest.IsUsingAPL { - return - } - - // grab all of the shadow priest spell CDs remaining durations to use in the dps calculation - spriest.VTCastTime = spriest.ApplyCastSpeed(time.Millisecond * 1500) - spriest.AllCDs = []time.Duration{ - max(0, spriest.MindBlast.TimeToReady(sim)), - max(0, spriest.DevouringPlague.CurDot().RemainingDuration(sim)), - max(0, spriest.VampiricTouch.CurDot().RemainingDuration(sim)-spriest.VTCastTime), - max(0, spriest.ShadowWordDeath.TimeToReady(sim)), - 0, - } - - var spell *core.Spell - var waitTime time.Duration - target := spriest.CurrentTarget - - switch spriest.rotation.RotationType { - case proto.ShadowPriest_Rotation_Ideal: - spell, waitTime = spriest.chooseSpellIdeal(sim) - case proto.ShadowPriest_Rotation_Basic: - spell = spriest.chooseSpellBasicOrClipping(sim, false) - case proto.ShadowPriest_Rotation_Clipping: - spell = spriest.chooseSpellBasicOrClipping(sim, true) - case proto.ShadowPriest_Rotation_AoE: - spell, target = spriest.chooseSpellAOE(sim) - default: - spell, waitTime = spriest.chooseSpellIdeal(sim) - } - - if spell != nil { - if spell == spriest.MindFlay[3] && spriest.InnerFocus != nil && spriest.InnerFocus.IsReady(sim) { - spriest.InnerFocus.Cast(sim, nil) - } - - if success := spell.Cast(sim, target); !success { - spriest.WaitForMana(sim, spell.CurCast.Cost) - } - } else if waitTime != 0 { - spriest.WaitUntil(sim, sim.CurrentTime+waitTime) - } else { - spriest.WaitUntil(sim, sim.CurrentTime+time.Millisecond*500) - } -} - -func (spriest *ShadowPriest) chooseSpellAOE(sim *core.Simulation) (*core.Spell, *core.Unit) { - if len(sim.Encounter.Targets) >= 4 { - return spriest.MindSear[5], spriest.CurrentTarget - } - - for _, t := range sim.Encounter.TargetUnits { - if spriest.ShadowWordPain.Dot(t).IsActive() && spriest.ShadowWordPain.Dot(t).RemainingDuration(sim).Seconds() < 3 { - return spriest.MindFlay[2], t - } - } - - for _, t := range sim.Encounter.TargetUnits { - if !spriest.VampiricTouch.Dot(t).IsActive() && sim.GetRemainingDuration().Seconds() > 5 { - return spriest.VampiricTouch, t - } - } - - for _, t := range sim.Encounter.TargetUnits { - if !spriest.ShadowWordPain.Dot(t).IsActive() && sim.GetRemainingDuration().Seconds() > 12 && spriest.DevouringPlague.Dot(sim.Encounter.TargetUnits[0]).IsActive() { - return spriest.ShadowWordPain, t - } - if spriest.ShadowWordPain.Dot(t).IsActive() && spriest.ShadowWordPain.Dot(t).RemainingDuration(sim).Seconds() < 3 { - return spriest.MindFlay[2], t - } - } - - spell, _ := spriest.chooseSpellIdeal(sim) - return spell, spriest.CurrentTarget -} - -func (spriest *ShadowPriest) chooseSpellBasicOrClipping(sim *core.Simulation, isClipping bool) *core.Spell { - if spriest.DevouringPlague.CurDot().RemainingDuration(sim) <= 0 { - return spriest.DevouringPlague - } else if spriest.Talents.VampiricTouch && spriest.VampiricTouch.CurDot().RemainingDuration(sim) <= spriest.VTCastTime { - return spriest.VampiricTouch - } else if !spriest.ShadowWordPain.CurDot().IsActive() && spriest.ShadowWeavingAura.GetStacks() >= 5 { - return spriest.ShadowWordPain - } else if spriest.MindBlast.TimeToReady(sim) == 0 { - return spriest.MindBlast - } else if spriest.ShadowWordDeath.TimeToReady(sim) == 0 { - return spriest.ShadowWordDeath - } else { - var numTicks int - gcd := spriest.SpellGCD() - tickLength := spriest.MindFlayTickDuration() - if isClipping { - numTicks = spriest.ClippingMindflayRotation(sim, gcd, tickLength) - } else { - //numTicks = spriest.BasicMindflayRotation(sim, gcd, tickLength) - numTicks = 3 - } - return spriest.MindFlay[numTicks] - } -} - -// Returns (spellToCast, waitTime). waitTime should be nonzero only if spellToCast is nil. -func (spriest *ShadowPriest) chooseSpellIdeal(sim *core.Simulation) (*core.Spell, time.Duration) { - // TODO: probably do something different instead of making it global? - // some global variables used throughout the code - var currentWait time.Duration - var mbDamage float64 - var dpDamage float64 - var vtDamage float64 - var swdDamage float64 - var mfDamage float64 - var overwriteDPS float64 - - var currDotTickSpeed float64 - - //if sim.CurrentTime == 0 && spriest.rotation.PrecastVt { - //spriest.SpendMana(sim, spriest.VampiricTouch.DefaultCast.Cost, spriest.VampiricTouch.ResourceMetrics) - //spriest.VampiricTouch.SkipCastAndApplyEffects(sim, spriest.CurrentTarget) - //} - - // initialize function specific variables - var swStacks float64 - var numswptickstime float64 - var cdDpso float64 - var cdDps float64 - var chosenMfs int - var num_DP_ticks float64 - var num_VT_ticks float64 - var wait1 time.Duration - var wait2 time.Duration - var wait time.Duration - var wait3 time.Duration - - // initialize helpful variables for calculations later - gcd := spriest.SpellGCD() - tickLength := spriest.MindFlayTickDuration() - - dotTickSpeed := float64(spriest.ApplyCastSpeed(time.Second * 3)) - remain_fight := float64(sim.GetRemainingDuration()) - castMf2 := 0 // if SW stacks = 3, and we want to get SWP up at 5 stacks exactly, then we want to hard code a MF2 - bestIdx := -1 - - // How much time until lust is used? - timeUntilBLStarts := float64(spriest.BLUsedAt) - sim.CurrentTime.Seconds() - if timeUntilBLStarts < 0 { - timeUntilBLStarts = 0 - } - // How many VT ticks before lust is used? - numVTbeforeBL := math.Floor(timeUntilBLStarts / (dotTickSpeed * 1e-9)) - if numVTbeforeBL < 0 { - numVTbeforeBL = 0 - } - - swStacks = float64(spriest.ShadowWeavingAura.GetStacks()) - - // Reduce number of DP/VT ticks based on remaining duration - num_DP_ticks = min(float64(spriest.DevouringPlague.CurDot().NumberOfTicks), math.Floor(remain_fight/dotTickSpeed)) - num_VT_ticks = min(float64(spriest.VampiricTouch.CurDot().NumberOfTicks), math.Floor(remain_fight/dotTickSpeed)) - - // Spell damage numbers that are updated before each cast in order to determine the most optimal next cast based on dps over a finite window - // This is needed throughout the code to determine the optimal spell(s) to cast next - // MB dmg - mbDamage = 0 - impDamage := 0 - if spriest.options.UseMindBlast { - if spriest.T8FourSetBonus { //include benefit of 240 haste rating for 4 seconds. This isnt perfect because 1.6 dps per haste is an average and varies throughout the fight - impDamage = 1.6 * 240 * 4 - } - mbDamage = spriest.MindBlast.ExpectedInitialDamage(sim, spriest.CurrentTarget) + float64(impDamage) - } - - // DP dmg - dpTickDamage := spriest.DevouringPlague.ExpectedTickDamage(sim, spriest.CurrentTarget) - dpInit := dpTickDamage * spriest.DpInitMultiplier - dpDot := dpTickDamage * num_DP_ticks - dpDamage = dpInit + dpDot - - if sim.Log != nil { - //spriest.Log(sim, "dpTickDamage [%d]", dpTickDamage) - //spriest.Log(sim, "dpInit [%d]", dpInit) - //spriest.Log(sim, "dpDamage[%d]", dpDamage) - } - - // Determine number of DP ticks before BL. If there is at least 1 then it's worth using - numDPbeforeBL := math.Floor(timeUntilBLStarts / (dotTickSpeed * 1e-9)) - if numDPbeforeBL < 0 { - numDPbeforeBL = 0 - } - if (timeUntilBLStarts > gcd.Seconds() && numDPbeforeBL < 1 && sim.CurrentTime.Seconds() < float64(spriest.BLUsedAt)) || (timeUntilBLStarts <= gcd.Seconds() && timeUntilBLStarts > 0.01) { - dpDamage = 0 - } - - vtDamage = spriest.VampiricTouch.ExpectedTickDamage(sim, spriest.CurrentTarget) * num_VT_ticks - - // If there is at least 2 VT ticks then it's worth using - if timeUntilBLStarts > gcd.Seconds() && numVTbeforeBL < 2 && sim.CurrentTime.Seconds() < float64(spriest.BLUsedAt) { - vtDamage = 0 - } - - // SWD dmg - swdDamage = 0 - if spriest.options.UseShadowWordDeath { - swdDamage = spriest.ShadowWordDeath.ExpectedInitialDamage(sim, spriest.CurrentTarget) - } - - mfDamage = spriest.MindFlay[3].ExpectedTickDamage(sim, spriest.CurrentTarget) * 3 - swpTickDamage := spriest.ShadowWordPain.ExpectedTickDamage(sim, spriest.CurrentTarget) - - //if spriest.rotation.RotationType == 4 { - // msDamage = spriest.MindSear[5].ExpectedDamage(sim, spriest.CurrentTarget) - // } - castSwpNow := 0 // if SW stacks = 3, and we want to get SWP up immediately becaues fight length is low enough, then this flag gets set to 1 - if spriest.rotation.RotationType != 4 { - // this should be cleaned up, but essentially we want to cast SWP either 3rd or 5th in the rotation which is fight length dependent - - if swStacks > 2 && swStacks < 5 && !spriest.ShadowWordPain.CurDot().IsActive() { - addedDmg := mbDamage*0.12 + mfDamage*0.22*2/3 + swpTickDamage*2*gcd.Seconds()/3 - numswptickstime = addedDmg / (swpTickDamage * 0.06) * 3 //if the fight lenght is < numswptickstime then use swp 3rd.. if > then use at weaving = 5 - // - if remain_fight*math.Pow(10, -9) < numswptickstime { - castSwpNow = 1 - } else { - castMf2 = 1 - } - } - } - - var currDPS float64 - var nextTickWait time.Duration - var currDPS2 float64 - var overwriteDPS2 float64 - - if spriest.DevouringPlague.CurDot().IsActive() { - currDotTickSpeed = spriest.DevouringPlague.CurDot().TickPeriod().Seconds() - nextTickWait = spriest.DevouringPlague.CurDot().TimeUntilNextTick(sim) - - dpDotCurr := spriest.DevouringPlague.ExpectedTickDamageFromCurrentSnapshot(sim, spriest.CurrentTarget) - dpInitCurr := dpDotCurr * spriest.DpInitMultiplier - - cdDamage := mbDamage - if spriest.T10FourSetBonus || cdDamage == 0 { - cdDamage = mfDamage / 3 * 2 - } - - dotTickSpeednew := 3 * spriest.CastSpeed - currDPS = (dpInitCurr + dpDotCurr*8 + cdDamage) / (currDotTickSpeed * 8) - //overwriteDPS = (dpInitCurr + dpInit + dpDotCurr*1 + dpDot) / (dotTickSpeednew*8 + currDotTickSpeed*1) - overwriteDPS = (dpInit + dpDot) / (dotTickSpeednew * 8) - - if blAura := spriest.GetActiveAuraWithTag(core.BloodlustAuraTag); blAura != nil { - blRemainingDur := blAura.RemainingDuration(sim) - if blRemainingDur < time.Second*2 && blRemainingDur > time.Millisecond*100 { - dpRemainTicks := 8 - float64(spriest.DevouringPlague.CurDot().NumTicksRemaining(sim)) - overwriteDPS2 = dpInitCurr + dpRemainTicks*dpDotCurr*(1-spriest.CastSpeed) - currDPS2 = cdDamage - - if sim.Log != nil { - spriest.Log(sim, "currDPS2[%d]", currDPS2) - spriest.Log(sim, "overwriteDPS2[%d]", overwriteDPS2) - spriest.Log(sim, "dpRemainTicks[%d]", dpRemainTicks) - } - } - } - } - - // Make an array of DPCT per spell that will be used to find the optimal spell to cast - spellDPCT := []float64{ - // MB dps - mbDamage / (gcd + spriest.AllCDs[mbIdx]).Seconds(), - // DP dps - dpDamage / (gcd + spriest.AllCDs[dpIdx]).Seconds(), - // VT dps - vtDamage / (gcd + spriest.AllCDs[vtIdx]).Seconds(), - // SWD dps - swdDamage / (gcd + spriest.AllCDs[swdIdx]).Seconds(), - // MF dps 3 ticks - mfDamage / (tickLength * 3).Seconds(), - } - - //if sim.Log != nil { - //spriest.Log(sim, "mbDamage[%d]", mbDamage) - //spriest.Log(sim, "mb time[%d]", spriest.AllCDs[mbIdx]) - //spriest.Log(sim, "mftime[%d]", float64((tickLength * 3).Seconds())) - //spriest.Log(sim, "gcd[%d]", gcd.Seconds()) - //spriest.Log(sim, "CastSpeedMultiplier[%d]", spriest.PseudoStats.CastSpeedMultiplier) - //spriest.Log(sim, "critChance[%d]", critChance) - //} - - // Find the maximum DPCT spell - bestDmg := 0.0 - for i, v := range spellDPCT { - if sim.Log != nil { - spriest.Log(sim, "\tspellDPCT[%d]: %01.f", i, v) - spriest.Log(sim, "\tcdDiffs[%d]: %0.1f", i, spriest.AllCDs[i].Seconds()) - } - if v > bestDmg { - bestIdx = i - bestDmg = v - } - } - // Find the minimum CD ability to make sure that shouldnt be cast first - nextCD := core.NeverExpires - nextIdx := -1 - for i, v := range spriest.AllCDs[1 : len(spriest.AllCDs)-1] { - // if sim.Log != nil { - // spriest.Log(sim, "\tspriest.AllCDs[%d]: %01.f", i, v) - // spriest.Log(sim, "\tcdDiffs[%d]: %0.1f", i, cdDiffs[i].Seconds()) - //} - if v < nextCD { - nextCD = v - nextIdx = i + 1 - } - } - waitmin := nextCD - - // Now it's possible that the wait time for the chosen spell is long, if that's the case, then it might be better to investigate the dps over a 2 spell window to see if casting something else will benefit - if bestIdx < mfIdx { - currentWait = spriest.AllCDs[bestIdx] - } - - if spriest.AllCDs[mbIdx] < gcd && bestIdx == mfIdx && spriest.AllCDs[swdIdx] == 0 { - totalDps__poss := (mbDamage + swdDamage) / (gcd + gcd).Seconds() - totalDps__poss3 := (mbDamage + mfDamage*2/3) / (2*tickLength + gcd).Seconds() - - if totalDps__poss > totalDps__poss3 { - bestIdx = swdIdx - currentWait = spriest.AllCDs[bestIdx] - } - } - - if nextIdx != mfIdx && bestIdx != mfIdx && bestIdx != swpIdx && currentWait > waitmin && currentWait.Seconds() < 3 { // right now 3 might not be correct number, but we can study this to optimize - - if bestIdx == vtIdx { - cdDpso = vtDamage / (gcd + currentWait).Seconds() - } else if bestIdx == mbIdx { - cdDpso = mbDamage / (gcd + currentWait).Seconds() - } else if bestIdx == swdIdx { - cdDpso = swdDamage / (gcd + currentWait).Seconds() - } else if bestIdx == dpIdx { - cdDpso = dpDamage / (gcd + currentWait).Seconds() - } - - if nextIdx == vtIdx { - cdDps = vtDamage / (gcd + waitmin).Seconds() - } else if nextIdx == mbIdx { - cdDps = mbDamage / (gcd + waitmin).Seconds() - } else if nextIdx == swdIdx { - cdDps = swdDamage / (gcd + waitmin).Seconds() - } else if nextIdx == dpIdx { - cdDps = dpDamage / (gcd + waitmin).Seconds() - } - - residualWait := currentWait - gcd - if residualWait < 0 { - residualWait = 0 - } - totalDps__poss0 := (cdDpso * (currentWait + gcd).Seconds()) / (gcd + currentWait).Seconds() - totalDps__poss1 := (cdDpso*(currentWait+gcd).Seconds() + cdDps*(waitmin+gcd).Seconds()) / (waitmin + gcd + gcd + residualWait).Seconds() - - totalDps__poss2 := float64(0) - totalDps__poss3 := float64(0) - - residualMF := currentWait - 2*tickLength - if residualMF < 0 { - residualMF = 0 - } - totalDps__poss2 = (cdDpso*(currentWait+gcd).Seconds() + mfDamage*2/3) / (2*tickLength + gcd + residualMF).Seconds() - residualMF = currentWait - 3*tickLength - if residualMF < 0 { - residualMF = 0 - } - totalDps__poss3 = (cdDpso*(currentWait+gcd).Seconds() + mfDamage) / (3*tickLength + gcd + residualMF).Seconds() - - //if sim.Log != nil { - //spriest.Log(sim, "nextIdx[%d]", nextIdx) - //spriest.Log(sim, "bestIdx[%d]", bestIdx) - //spriest.Log(sim, "currentWait[%d]", currentWait.Seconds()) - //spriest.Log(sim, "total_dps__poss0[%d]", totalDps__poss0) - //spriest.Log(sim, "total_dps__poss1[%d]", totalDps__poss1) - //spriest.Log(sim, "total_dps__poss2[%d]", totalDps__poss2) - //spriest.Log(sim, "total_dps__poss3[%d]", totalDps__poss3) - //} - - // TODO looks fishy, repeated bestIdx = mfIdx - if (totalDps__poss1 > totalDps__poss0) || (totalDps__poss2 > totalDps__poss0) || (totalDps__poss3 > totalDps__poss0) { - if totalDps__poss1 > totalDps__poss0 && totalDps__poss1 > totalDps__poss2 && totalDps__poss1 > totalDps__poss3 { - bestIdx = nextIdx // if choosing the minimum wait time spell first is highest dps, then change the index and current wait - currentWait = waitmin - } else if totalDps__poss2 > totalDps__poss0 && totalDps__poss2 > totalDps__poss1 && totalDps__poss2 > totalDps__poss3 { - //bestIdx = bestIdx // if choosing the minimum wait time spell first is highest dps, then change the index and current wait - //currentWait = currentWait - bestIdx = mfIdx - } else if totalDps__poss3 > totalDps__poss0 && totalDps__poss3 > totalDps__poss1 && totalDps__poss3 > totalDps__poss2 { - //bestIdx = bestIdx // if choosing the minimum wait time spell first is highest dps, then change the index and current wait - //currentWait = currentWait - bestIdx = mfIdx - } else { - bestIdx = mfIdx - } - } - - } - - // If VT isnt chosen, and reapplying DP is more dps, then overwrite it next - if overwriteDPS-currDPS > 1000 && bestIdx != vtIdx { - bestIdx = dpIdx - currentWait = nextTickWait - } else { - overwriteDPS = 0 - } - - // Now it's possible that the wait time is > 1 gcd and is the minimum wait time. this is unlikely in wrath given how good MF is, but still might be worth to check - // if chosen wait time is > 0.3*GCD (this was optimized in private sim, but might want to reoptimize with procs/ect) then check if it's more dps to add a mf sequence - if bestIdx != mfIdx && currentWait.Seconds() > 0.3*gcd.Seconds() { - - if bestIdx == vtIdx { - cdDpso = vtDamage - } else if bestIdx == mbIdx { - cdDpso = mbDamage - } else if bestIdx == swdIdx { - cdDpso = swdDamage - } else if bestIdx == dpIdx { - cdDpso = dpDamage - } - - addedgcd := max(gcd, time.Duration(2)*tickLength) - addedgcdtime := addedgcd - time.Duration(2)*tickLength - - deltaMf1 := currentWait - gcd - if deltaMf1 < 0 { - deltaMf1 = 0 - } - deltaMf2 := currentWait - (tickLength*2 + addedgcdtime) - if deltaMf2 < 0 { - deltaMf2 = 0 - } - deltaMf3 := currentWait - tickLength*3 - if deltaMf3 < 0 { - deltaMf3 = 0 - } - - dpsPossibleshort := []float64{ - (cdDpso) / (gcd + currentWait).Seconds(), - (cdDpso + mfDamage/3) / (deltaMf1 + gcd + gcd).Seconds(), - (cdDpso + mfDamage/3*2) / (deltaMf2 + tickLength*2 + addedgcdtime + gcd).Seconds(), - (cdDpso + mfDamage) / (deltaMf3 + tickLength*3 + gcd).Seconds(), - } - - // Find the highest possible dps and its index - highestPossibleIdx := 0 - highestPossibleDmg := 0.0 - for i, v := range dpsPossibleshort { - if v >= highestPossibleDmg { - //if sim.Log != nil { - // spriest.Log(sim, "\thighestPossibleDmg[%d]: %01.f", i, v) - //} - highestPossibleIdx = i - highestPossibleDmg = v - } - } - mfAddIdx := highestPossibleIdx - - if mfAddIdx == 0 { - chosenMfs = 0 - } else if mfAddIdx == 1 { - chosenMfs = 1 - } else if mfAddIdx == 2 { - chosenMfs = 2 - } else if mfAddIdx == 3 { - chosenMfs = 3 - } - if chosenMfs > 0 { - if spriest.AllCDs[mbIdx].Seconds() < currentWait.Seconds() && spriest.AllCDs[mbIdx].Seconds() == 0 && (mfAddIdx == 2 && spellDPCT[mbIdx] > spellDPCT[mfIdx]/3*2) || (mfAddIdx == 3 && spellDPCT[mbIdx] > spellDPCT[mfIdx]) { - bestIdx = mbIdx - currentWait = spriest.AllCDs[mbIdx] - } else if tickLength*3 <= gcd { - bestIdx = mfIdx // TODO looks fishy, repeated bestIdx = mfIdx - } else { - bestIdx = mfIdx - } - } - } - - if bestIdx == vtIdx && spriest.AllCDs[mbIdx].Seconds() < currentWait.Seconds() && currentWait.Seconds() > 0.4 && spriest.options.UseMindBlast { - bestIdx = mbIdx - currentWait = spriest.AllCDs[mbIdx] - } - - // if current spell is SWD and mf2 is less than GCD, and is more dps than SWD then use instead - if bestIdx == swdIdx && tickLength*2 <= gcd { - if spellDPCT[swdIdx] < spellDPCT[mfIdx]*2/3 { - bestIdx = mfIdx - } - } - - // if MF1 is chosen, and SWD is off CD and isn't 0 dmg, then use SWD unless mf2 is < gcd - if chosenMfs == 1 && spriest.AllCDs[swdIdx] == 0 && swdDamage != 0 { - if tickLength*2 <= gcd { - bestIdx = mfIdx - } else { - bestIdx = swdIdx - currentWait = 0 - } - } - - if (overwriteDPS-currDPS > 1000 && (currentWait < gcd/2 || float64(currentWait) >= currDotTickSpeed*0.9)) && bestIdx != vtIdx { - bestIdx = dpIdx - currentWait = 0 - } - - if overwriteDPS-currDPS > 1000 && currentWait <= gcd && currentWait >= gcd/2 && spriest.AllCDs[swdIdx] == 0 { - if tickLength*2 <= gcd { - bestIdx = mfIdx - } else { - bestIdx = swdIdx - currentWait = 0 - } - } - - // if MF2 is chosen in order to get to 5 weaving stacks, then make sure that VT/DP are already up first - if castMf2 > 0 { - if !spriest.DevouringPlague.CurDot().IsActive() && swStacks >= 4 && dpDamage != 0 { - bestIdx = dpIdx - } else if !spriest.VampiricTouch.CurDot().IsActive() && swStacks >= 4 && spriest.DevouringPlague.CurDot().IsActive() && vtDamage != 0 { - bestIdx = vtIdx - } else { - bestIdx = mfIdx - } - } - // if at 5 SW stacks and SWP is not up, then cast unless VT/DP are down - if swStacks == 5 && !spriest.ShadowWordPain.CurDot().IsActive() { - if !spriest.DevouringPlague.CurDot().IsActive() && swStacks >= 4 && dpDamage != 0 { - bestIdx = dpIdx - } else if !spriest.VampiricTouch.CurDot().IsActive() && swStacks >= 4 && spriest.DevouringPlague.CurDot().IsActive() && vtDamage != 0 { - bestIdx = vtIdx - } else { - bestIdx = swpIdx - } - } - // cast SWP 3rd for short fights - if castSwpNow > 0 { - bestIdx = swpIdx - } - // Snap shot BL on DP - if overwriteDPS2-currDPS2 > 2500 && bestIdx != vtIdx { //Seems to be a dps loss to overwrite a DP to snap shot - bestIdx = dpIdx - currentWait = 0 - } - - //if timeUntilBLStarts < float64((time.Duration(3)*tickLength).Seconds()) && timeUntilBLStarts > 0.2 && bestIdx != swpIdx { - // bestIdx = mfIdx - // castMf2 = 1 - //} - // If BL is almost up and VT is not active, then use VT - if timeUntilBLStarts <= gcd.Seconds() && !spriest.VampiricTouch.CurDot().IsActive() && timeUntilBLStarts > 0 { - bestIdx = vtIdx - } - // If BL is up in <0.3 seconds and greater than 10ms, then wait for it to be active - if timeUntilBLStarts <= 0.3 && timeUntilBLStarts > 0.01 { - bestIdx = dpIdx - currentWait = time.Millisecond * time.Duration(math.Round(timeUntilBLStarts*1010)) - } - - //if sim.Log != nil { - //spriest.Log(sim, "spriest.BLUsedAt %d", currentWait) - //spriest.Log(sim, "dpDamage %d", dpDamage) - //spriest.Log(sim, "currentWait %d", currentWait) - //} - if spriest.PrevTicks == 4 { - castMf2 = 1 - bestIdx = mfIdx - spriest.PrevTicks = 0 - } - - if castMf2 == 1 && spriest.AllCDs[mbIdx].Seconds() == 0 && spriest.options.UseMindBlast { - return spriest.MindBlast, 0 - } - - if remain_fight*math.Pow(10, -9) < 2*float64(gcd.Seconds()) && !spriest.options.UseMindBlast { - bestIdx = dpIdx - } - - if currentWait <= gcd/6 && currentWait > 0 && bestIdx != swpIdx && bestIdx != mfIdx { - return nil, currentWait - } - - if currentWait >= gcd/6 && bestIdx != swpIdx && bestIdx != mfIdx { - bestIdx = mfIdx - } - - if bestIdx == mbIdx { - return spriest.MindBlast, 0 - } else if bestIdx == dpIdx { - return spriest.DevouringPlague, 0 - } else if bestIdx == vtIdx { - return spriest.VampiricTouch, 0 - } else if bestIdx == swdIdx { - return spriest.ShadowWordDeath, 0 - } else if bestIdx == swpIdx { - return spriest.ShadowWordPain, 0 // once swp is cast need a way for talents to refresh the duration - } else if bestIdx == mfIdx { - var numTicks int - - if chosenMfs == 1 { - numTicks = 1 // determiend above that it's more dps to add MF1, need if it's not better to enter ideal rotation instead - } else if (castMf2 == 1 && spriest.DevouringPlague.CurDot().IsActive() && spriest.VampiricTouch.CurDot().IsActive()) || (timeUntilBLStarts < (time.Duration(3)*tickLength).Seconds() && timeUntilBLStarts > 0.2) { - if float64(spriest.MindFlayTickDuration().Seconds()*3) < float64(gcd.Seconds()*1.3) { - numTicks = 3 - } else { - numTicks = 2 - } - } else { - numTicks = spriest.IdealMindflayRotation(sim, gcd, tickLength, currentWait, mfDamage, mbDamage, dpDamage, vtDamage, swdDamage, overwriteDPS) //enter the mf optimizaiton routine to optimze mf clips and for next optimal spell - } - - if numTicks == 3 && spriest.ShadowWordPain.CurDot().IsActive() && spriest.ShadowWordPain.CurDot().RemainingDuration(sim).Seconds() < tickLength.Seconds()*12 && float64(tickLength.Seconds()*3) >= gcd.Seconds() { - numTicks = 2 - } - - if numTicks == 0 { - // Means we'd rather wait for next CD (swp, vt, etc) than start a MF cast. - nextCD := core.NeverExpires - for _, v := range spriest.AllCDs[1 : len(spriest.AllCDs)-1] { - if v < nextCD { - nextCD = v - } - } - return nil, nextCD - } else if numTicks == 2 && spriest.AllCDs[mbIdx].Seconds() == 0 && spriest.options.UseMindBlast { - return spriest.MindBlast, 0 - } else { - //numTicks = 3 - if spriest.rotation.RotationType == 4 && len(sim.Encounter.Targets) >= 3 { - return spriest.MindSear[numTicks], 0 - } else { - return spriest.MindFlay[numTicks], 0 - } - } - } else { - mbcd := spriest.MindBlast.TimeToReady(sim) - swdcd := spriest.ShadowWordDeath.TimeToReady(sim) - vtidx := spriest.VampiricTouch.CurDot().RemainingDuration(sim) - spriest.VTCastTime - swpidx := spriest.ShadowWordPain.CurDot().RemainingDuration(sim) - dpidx := spriest.DevouringPlague.CurDot().RemainingDuration(sim) - wait1 = min(mbcd, swdcd) - wait2 = min(dpidx, wait1) - wait3 = min(vtidx, swpidx) - wait = min(wait3, wait2) - if wait <= 0 { - wait = time.Millisecond * 500 - } - return nil, wait - } -} - -// Returns the number of MF ticks to use, or 0 to wait for next CD. -func (spriest *ShadowPriest) BasicMindflayRotation(_ *core.Simulation, gcd time.Duration, _ time.Duration) int { - // just do MF3, never clipping - nextCD := core.NeverExpires - for _, v := range spriest.AllCDs { - if v < nextCD { - nextCD = v - } - } - // But don't start a MF if we can't get a single tick off. - if nextCD < gcd { - return 0 - } else { - return 3 - } -} - -// Returns the number of MF ticks to use, or 0 to wait for next CD. -func (spriest *ShadowPriest) IdealMindflayRotation(sim *core.Simulation, gcd time.Duration, tickLength time.Duration, - currentWait time.Duration, mfDamage, mbDamage, dpDamage, vtDamage, swdDamage, overwriteDPS float64) int { - nextCD := core.NeverExpires - nextIdx := -1 - - newCDs := []time.Duration{ - max(0, spriest.AllCDs[1]), - max(0, spriest.AllCDs[2]), - } - - if mbDamage != 0 { - newCDs = []time.Duration{ - max(0, spriest.AllCDs[0]), - max(0, spriest.AllCDs[1]), - max(0, spriest.AllCDs[2]), - } - } - - for i, v := range newCDs { - if v < nextCD { - nextCD = v - nextIdx = i - } - } - - if currentWait != 0 { - nextCD = currentWait - } - - var numTicks int - numTicks_Base := 0.0 - numTicks_floored := 0.0 - if nextCD < gcd/2 { - numTicks = 0 - } else { - numTicks_Base = nextCD.Seconds() / tickLength.Seconds() - numTicks_floored = math.Floor(nextCD.Seconds() / tickLength.Seconds()) - numTicks = int(numTicks_Base) - } - - AlmostAnotherTick := numTicks_Base - numTicks_floored - - if AlmostAnotherTick >= 0.25 { - numTicks += 1 - } - - mfTickDamage := mfDamage * 0.3333 - - if tickLength.Seconds() < gcd.Seconds()/2.9 { - numTicks = 3 - return numTicks - } - - if sim.Log != nil { - //spriest.Log(sim, "AlmostAnotherTick %d", AlmostAnotherTick) - //spriest.Log(sim, "numTicks %d", numTicks) - //spriest.Log(sim, "tickLength %d", tickLength.Seconds()) - //spriest.Log(sim, "nextCD %d", nextCD.Seconds()) - //spriest.Log(sim, "numTicks_Base %d", numTicks_Base) - //spriest.Log(sim, "numTicks_floored %d", numTicks_floored) - } - - if numTicks < 100 && overwriteDPS == 0 { // if the code entered this loop because mf is the higest dps spell, and the number of ticks that can fit in the remaining cd time is < 1, then just cast a mf3 as it essentially fits perfectly - // TODO: Should spriest latency be added to the second option here? - - mfTime := max(gcd, time.Duration(numTicks)*tickLength) - if numTicks == 0 { - mfTime = max(gcd, time.Duration(numTicks)*tickLength) - } - - if sim.Log != nil { - //spriest.Log(sim, "mfTime %d", mfTime.Seconds()) - //spriest.Log(sim, "spriest.AllCDs %d", spriest.AllCDs[0].Seconds()) - //spriest.Log(sim, "mf3Time %d", float64(time.Duration(3*tickLength).Seconds())) - } - // Amount of gap time after casting mind flay, but before each CD is available. - - cdDiffs := []time.Duration{ - max(0, spriest.AllCDs[0]-mfTime), - max(0, spriest.AllCDs[1]-mfTime), - max(0, spriest.AllCDs[2]-mfTime), - max(0, spriest.AllCDs[3]-mfTime), - 0, - } - - mfspdmg := 0.0 - if numTicks != 0 { - mfspdmg = mfTickDamage * float64(numTicks) / (time.Duration(numTicks) * tickLength).Seconds() - } else if numTicks > 3 { - mfspdmg = mfTickDamage * float64(3) / (time.Duration(3) * tickLength).Seconds() - } - if sim.Log != nil { - //spriest.Log(sim, "mfspdmg %d", mfspdmg) - } - spellDamages := []float64{ - // MB dps - mbDamage / (gcd + cdDiffs[mbIdx]).Seconds(), - // DP dps - dpDamage / (gcd + cdDiffs[dpIdx]).Seconds(), - // VT dps - vtDamage / (gcd + cdDiffs[vtIdx]).Seconds(), - // SWD dps - swdDamage / (gcd + cdDiffs[swdIdx]).Seconds(), - - mfspdmg, - } - - bestIdx := 0 - bestDmg := 0.0 - for i, v := range spellDamages { - if sim.Log != nil { - //spriest.Log(sim, "\tspellDamages[%d]: %01.f", i, v) - } - if v > bestDmg { - bestIdx = i - bestDmg = v - } - } - - //if numTicks < 1 && bestIdx == 4 { - // numTicks = 3 - //return numTicks - //} - - if sim.Log != nil { - //spriest.Log(sim, "bestIdx %d", bestIdx) - //spriest.Log(sim, "nextIdx %d", nextIdx) - //spriest.Log(sim, "spellDamages[bestIdx] %d", spellDamages[bestIdx]) - //spriest.Log(sim, "spellDamages[nextIdx] %d", spellDamages[nextIdx]) - //spriest.Log(sim, "numTicks %d", numTicks) - } - - if bestIdx != nextIdx && spellDamages[nextIdx] < spellDamages[bestIdx] && bestIdx != 4 { - numTicks_Base = spriest.AllCDs[bestIdx].Seconds() / tickLength.Seconds() - numTicks_floored = math.Floor(spriest.AllCDs[bestIdx].Seconds() / tickLength.Seconds()) - numTicks = int(numTicks_Base) - if sim.Log != nil { - //spriest.Log(sim, "numTicks2 %d", numTicks) - } - AlmostAnotherTick := numTicks_Base - numTicks_floored - - if AlmostAnotherTick >= 0.2 { - numTicks += 1 - } - - mfTime = max(gcd, time.Duration(numTicks)*tickLength) - if numTicks > 3 && numTicks < 5 { - addedgcd := max(gcd, time.Duration(2)*tickLength) - addedgcdtime := addedgcd - time.Duration(2)*tickLength - mfTime = max(gcd, time.Duration(numTicks)*tickLength+2*addedgcdtime) - } - deltaTime := spriest.AllCDs[bestIdx] - mfTime - cdDiffs = []time.Duration{ - max(0, spriest.AllCDs[0]-mfTime), - max(0, spriest.AllCDs[1]-mfTime), - max(0, spriest.AllCDs[2]-mfTime), - max(0, spriest.AllCDs[3]-mfTime), - 0, - } - if deltaTime.Seconds() < -1 { - numTicks -= 1 - cdDiffs[bestIdx] += tickLength - } - } - - if numTicks < 0 { - numTicks = 0 - } - - chosenWait := cdDiffs[bestIdx] - - //if sim.Log != nil { - //spriest.Log(sim, "numTicks %d", numTicks) - //spriest.Log(sim, "mfTime %d", mfTime.Seconds()) - //spriest.Log(sim, "chosenWait %d", chosenWait.Seconds()) - //} - - var newInd int - if chosenWait > gcd { - check_CDs := cdDiffs - check_CDs[bestIdx] = time.Second * 15 - // need to find a way to sort the cdDiffs and find the next highest dps cast with lower wait time - for i, v := range check_CDs { - if v < nextCD { - //nextCDc = v - newInd = i - } - } - } - skipNext := 0 - var totalWaitCurr float64 - var numTicksAvail float64 - var remainTime1 float64 - var remainTime2 float64 - var remainTime3 float64 - var addTime1 float64 - var addTime2 float64 - var addTime3 float64 - - if chosenWait.Seconds() > gcd.Seconds() && bestIdx != newInd && newInd > -1 { - - tick_var := float64(numTicks) - if numTicks == 1 { - totalWaitCurr = chosenWait.Seconds() - tick_var*gcd.Seconds() - } else { - totalWaitCurr = chosenWait.Seconds() - tick_var*tickLength.Seconds() - } - - if totalWaitCurr-gcd.Seconds() <= gcd.Seconds() { - if totalWaitCurr > tickLength.Seconds() { - numTicksAvail = math.Floor((totalWaitCurr - gcd.Seconds()) / tickLength.Seconds()) - } else { - numTicksAvail = math.Floor((totalWaitCurr - gcd.Seconds()) / gcd.Seconds()) - } - } else { - numTicksAvail = math.Floor((totalWaitCurr - gcd.Seconds()) / tickLength.Seconds()) - } - - if numTicksAvail < 0 { - numTicksAvail = 0 - } - - // TODO looks fishy, remainTime1 and remainTime2 are equal - remainTime1 = totalWaitCurr - tickLength.Seconds()*numTicksAvail - gcd.Seconds() - remainTime2 = totalWaitCurr - 1*tickLength.Seconds()*numTicksAvail - gcd.Seconds() - remainTime3 = totalWaitCurr - 2*tickLength.Seconds()*numTicksAvail - gcd.Seconds() - - if remainTime1 > 0 { - addTime1 = remainTime1 - } else { - addTime1 = 0 - } - - if remainTime2 > 0 { - addTime2 = remainTime2 - } else { - addTime2 = 0 - } - - if remainTime3 > 0 { - addTime3 = remainTime3 - } else { - addTime3 = 0 - } - - dpsPossible0 := []float64{ - 0, - 0, - 0, - } - - cd_dpsb := spellDamages[bestIdx] - cd_dpsn := spellDamages[newInd] - - dpsPossible0[0] = (numTicksAvail*mfTickDamage + cd_dpsb*gcd.Seconds() + cd_dpsn*gcd.Seconds()) / (numTicksAvail*tickLength.Seconds() + 2*gcd.Seconds() + addTime1) - dpsPossible0[1] = (tick_var*mfTickDamage + cd_dpsb*(cdDiffs[bestIdx].Seconds()+gcd.Seconds()) + cd_dpsn*(cdDiffs[newInd].Seconds())) / (tick_var*tickLength.Seconds() + (cdDiffs[bestIdx].Seconds() + gcd.Seconds()) + (cdDiffs[newInd].Seconds() + addTime2)) - dpsPossible0[2] = ((tick_var+1)*mfTickDamage + cd_dpsb*(cdDiffs[len(cdDiffs)-1-1].Seconds()+gcd.Seconds()) + cd_dpsn*(cdDiffs[len(cdDiffs)-1].Seconds()-tickLength.Seconds())) / ((tick_var+1)*tickLength.Seconds() + (cdDiffs[bestIdx].Seconds() + gcd.Seconds()) + (cdDiffs[newInd].Seconds() + addTime3)) - - highestPossibleDmg := 0.0 - highestPossibleIdx := -1 - // TODO looks fishy, this branch is never taken - if highestPossibleIdx == 0 { - for i, v := range dpsPossible0 { - - if v >= highestPossibleDmg { - highestPossibleIdx = i - highestPossibleDmg = v - } - } - } - if highestPossibleIdx > 0 { - numTicks = highestPossibleIdx + 1 - } else { - numTicks = int(numTicksAvail) - skipNext = 1 - } - } - - if sim.Log != nil { - //spriest.Log(sim, "numTicks3 %d", numTicks) - } - - if numTicks > 3 { - if (spriest.AllCDs[bestIdx] - time.Duration(numTicks-1)*tickLength - gcd) >= 0 { - //if (spriest.AllCDs[3]-time.Duration(numTicks-1)*tickLength <= 0) || (spriest.AllCDs[0]-time.Duration(numTicks-1)*tickLength <= 0) { \\might need to readd this for later phases - if spriest.AllCDs[3]-time.Duration(numTicks-1)*tickLength <= 0 { - numTicks = 3 - return numTicks - } - } - } - - if skipNext == 0 { - finalMFStart := math.Mod(float64(numTicks), 3) // Base ticks before adding additional - dpsPossible := []float64{ - bestDmg, // dps with no tick and just wait - 0, - 0, - 0, - } - dpsDuration := (chosenWait + gcd).Seconds() - - highestPossibleIdx := 0 - // TODO: Modified this slightly to expand time window, but it still doesn't change dps for any tests. - // Probably can remove this entirely (and then also the if highestPossibleIdx == 0 right after) - if (finalMFStart == 2) && (chosenWait <= tickLength && chosenWait > (tickLength-time.Millisecond*15)) { - highestPossibleIdx = 1 // if the wait time is equal to an extra mf tick, and there are already 2 ticks, then just add 1 - } - - if highestPossibleIdx == 0 { - switch finalMFStart { - case 0: - // this means that the extra ticks will be relative to starting a new mf cast entirely - dpsPossible[1] = (bestDmg*dpsDuration + mfDamage*1/3) / (gcd.Seconds() + gcd.Seconds()) // new damage for 1 extra tick - dpsPossible[2] = (bestDmg*dpsDuration + mfDamage*2/3) / (2*tickLength.Seconds() + gcd.Seconds()) // new damage for 2 extra tick - dpsPossible[3] = (bestDmg*dpsDuration + mfDamage) / (3*tickLength.Seconds() + gcd.Seconds()) // new damage for 3 extra tick - - case 1: - total_check_time := 2 * tickLength - - if total_check_time < gcd { - newDuration := (gcd + gcd).Seconds() - dpsPossible[1] = (bestDmg*dpsDuration + (mfDamage * 1 / 3 * (finalMFStart + 1))) / newDuration - } else { - newDuration := ((total_check_time - gcd) + gcd).Seconds() - dpsPossible[1] = (bestDmg*dpsDuration + (mfDamage * 1 / 3 * (finalMFStart + 1))) / newDuration - } - // % check add 2 - total_check_time2 := 2 * tickLength.Seconds() - if total_check_time2 < gcd.Seconds() { - dpsPossible[2] = (bestDmg*dpsDuration + (mfDamage * 1 / 3 * (finalMFStart + 2))) / (gcd.Seconds() + gcd.Seconds()) - } else { - dpsPossible[2] = (bestDmg*dpsDuration + (mfDamage * 1 / 3 * (finalMFStart + 2))) / (total_check_time2 + gcd.Seconds()) - } - case 2: - // % check add 1 - total_check_time := tickLength - newDuration := (total_check_time + gcd).Seconds() - dpsPossible[1] = (bestDmg*dpsDuration + mfDamage*1/3) / newDuration - - default: - dpsPossible[1] = (bestDmg*dpsDuration + mfDamage*1/3) / (gcd.Seconds() + gcd.Seconds()) - if tickLength*2 > gcd { - dpsPossible[2] = (bestDmg*dpsDuration + mfDamage*2/3) / (2*tickLength.Seconds() + gcd.Seconds()) - } else { - dpsPossible[2] = (bestDmg*dpsDuration + mfDamage*2/3) / (gcd.Seconds() + gcd.Seconds()) - } - dpsPossible[3] = (bestDmg*dpsDuration + mfDamage) / (3*tickLength.Seconds() + gcd.Seconds()) - } - } - - // Find the highest possible dps and its index - // highestPossibleIdx := 0 - highestPossibleDmg := 0.0 - if highestPossibleIdx == 0 { - for i, v := range dpsPossible { - if sim.Log != nil { - //spriest.Log(sim, "\tdpsPossible[%d]: %01.f", i, v) - } - if v >= highestPossibleDmg { - highestPossibleIdx = i - highestPossibleDmg = v - } - } - } - - numTicks += highestPossibleIdx - if sim.Log != nil { - //spriest.Log(sim, "numTicks4 %d", numTicks) - } - // if sim.Log != nil { - // spriest.Log(sim, "final_ticks %d", numTicks) - // } - if numTicks == 1 && tickLength*3 <= time.Duration(float64(gcd)*1.05) { - numTicks += 2 - } - if numTicks == 1 && tickLength*2 <= gcd { - numTicks += 1 - } - // Now that the number of optimal ticks has been determined to optimize dps - // Now optimize mf2s and mf3s - - //if numTicks == 0 { - //return numTicks - //} - - if numTicks == 1 { - numTicks = 1 - } else if numTicks == 2 || numTicks == 4 { - if numTicks == 4 { - spriest.PrevTicks = 4 - } - - if numTicks == 4 { - if sim.Log != nil { - spriest.Log(sim, "numTicks[%d]", numTicks) - spriest.Log(sim, "bestIdx %d", bestIdx) - spriest.Log(sim, "nextCD %d", nextCD.Seconds()) - spriest.Log(sim, "tickLength %d", tickLength.Seconds()) - spriest.Log(sim, "chosenWait %d", chosenWait.Seconds()) - } - } - - numTicks = 2 - - } else if numTicks == 0 { - numTicks = 2 - } else { - numTicks = 3 - } - } - } else { - numTicks = int(nextCD / tickLength) - if nextCD-max(gcd, time.Duration(2)*tickLength) < 0 && numTicks != 0 { - numTicks -= 1 - } - // if sim.Log != nil { - // spriest.Log(sim, "c_ticks %d", numTicks) - // spriest.Log(sim, "nextCD %d", nextCD) - // spriest.Log(sim, "tickLength %d", tickLength) - // } - if numTicks == 0 { - // if sim.Log != nil { - // spriest.Log(sim, "zero ticks %d", numTicks) - // } - numTicks = 2 - } - if numTicks >= 3 { - numTicks = 3 - } - } - if sim.Log != nil { - //spriest.Log(sim, "c_ticks %d", numTicks) - //spriest.Log(sim, "nextCD %d", nextCD) - //spriest.Log(sim, "tickLength %d", tickLength) - } - if numTicks >= 3 { - numTicks = 3 - } - - return numTicks -} - -func (spriest *ShadowPriest) ClippingMindflayRotation(_ *core.Simulation, gcd time.Duration, tickLength time.Duration) int { - nextCD := core.NeverExpires - for _, v := range spriest.AllCDs[1 : len(spriest.AllCDs)-1] { - if v < nextCD { - nextCD = v - } - } - - // if sim.Log != nil { - // spriest.Log(sim, " NextCD: %0.2f", nextCD.Seconds()) - // } - - // This means a CD is coming up before we could cast a single MF - if nextCD < gcd { - return 0 - } - - // How many ticks we have time for. - numTicks := int((nextCD - time.Duration(spriest.Latency)) / tickLength) - if numTicks == 1 { - return 1 - } else if numTicks == 2 || numTicks == 4 { - return 2 - } else { - return 3 - } -} diff --git a/sim/priest/shadow/shadow_priest.go b/sim/priest/shadow/shadow_priest.go index 0562a657f1..36a2ae9c6e 100644 --- a/sim/priest/shadow/shadow_priest.go +++ b/sim/priest/shadow/shadow_priest.go @@ -1,8 +1,6 @@ package shadow import ( - "time" - "github.com/wowsims/wotlk/sim/common/wotlk" "github.com/wowsims/wotlk/sim/core" "github.com/wowsims/wotlk/sim/core/proto" @@ -37,9 +35,8 @@ func NewShadowPriest(character *core.Character, options *proto.Player) *ShadowPr basePriest := priest.New(character, selfBuffs, options.TalentsString) basePriest.Latency = float64(basePriest.ChannelClipDelay.Milliseconds()) spriest := &ShadowPriest{ - Priest: basePriest, - rotation: shadowOptions.Rotation, - options: shadowOptions.Options, + Priest: basePriest, + options: shadowOptions.Options, } spriest.SelfBuffs.PowerInfusionTarget = &proto.UnitReference{} @@ -47,25 +44,14 @@ func NewShadowPriest(character *core.Character, options *proto.Player) *ShadowPr spriest.SelfBuffs.PowerInfusionTarget = shadowOptions.Options.PowerInfusionTarget } - spriest.EnableResumeAfterManaWait(spriest.tryUseGCD) - spriest.CanRolloverSWP = spriest.Talents.MindFlay && spriest.Talents.PainAndSuffering > 0 wotlk.ConstructValkyrPets(&spriest.Character) return spriest } type ShadowPriest struct { - PrevTicks float64 - *priest.Priest - rotation *proto.ShadowPriest_Rotation - options *proto.ShadowPriest_Options - - VTCastTime time.Duration - AllCDs []time.Duration - BLUsedAt time.Duration - - CanRolloverSWP bool + options *proto.ShadowPriest_Options } func (spriest *ShadowPriest) GetPriest() *priest.Priest { @@ -74,33 +60,8 @@ func (spriest *ShadowPriest) GetPriest() *priest.Priest { func (spriest *ShadowPriest) Initialize() { spriest.Priest.Initialize() - - if !spriest.IsUsingAPL && spriest.rotation.PrecastType > 0 { - precastSpell := spriest.VampiricTouch - if spriest.rotation.PrecastType == 2 { - precastSpell = spriest.MindBlast - } - - // Do this post-finalize so cast speed is updated with new stats - spriest.Env.RegisterPostFinalizeEffect(func() { - precastSpellAt := -spriest.ApplyCastSpeedForSpell(precastSpell.DefaultCast.CastTime, precastSpell) - - spriest.RegisterPrepullAction(precastSpellAt, func(sim *core.Simulation) { - precastSpell.Cast(sim, spriest.CurrentTarget) - }) - }) - } } func (spriest *ShadowPriest) Reset(sim *core.Simulation) { spriest.Priest.Reset(sim) - - // Save info related to blood lust timing - spriest.BLUsedAt = 0 - if bloodlustMCD := spriest.GetMajorCooldownIgnoreTag(core.BloodlustActionID); bloodlustMCD != nil { - timings := bloodlustMCD.GetTimings() - if len(timings) > 0 { - spriest.BLUsedAt = timings[0] - } - } } diff --git a/sim/priest/shadowfiend.go b/sim/priest/shadowfiend.go index be5fea8825..dcbb95f5a7 100644 --- a/sim/priest/shadowfiend.go +++ b/sim/priest/shadowfiend.go @@ -41,12 +41,4 @@ func (priest *Priest) registerShadowfiendSpell() { priest.ShadowfiendAura.Activate(sim) }, }) - - if !priest.IsUsingAPL { - priest.AddMajorCooldown(core.MajorCooldown{ - Spell: priest.Shadowfiend, - Priority: 1, - Type: core.CooldownTypeMana, - }) - } } diff --git a/sim/priest/smite.go b/sim/priest/smite.go index 0cc95b84ca..ac9d8264e0 100644 --- a/sim/priest/smite.go +++ b/sim/priest/smite.go @@ -6,7 +6,7 @@ import ( "github.com/wowsims/wotlk/sim/core" ) -func (priest *Priest) RegisterSmiteSpell(memeDream bool) { +func (priest *Priest) RegisterSmiteSpell() { priest.Smite = priest.RegisterSpell(core.SpellConfig{ ActionID: core.ActionID{SpellID: 48123}, SpellSchool: core.SpellSchoolHoly, @@ -23,10 +23,8 @@ func (priest *Priest) RegisterSmiteSpell(memeDream bool) { }, }, - BonusCritRating: float64(priest.Talents.HolySpecialization) * 1 * core.CritRatingPerCritChance, - DamageMultiplier: 1 * - (1 + 0.05*float64(priest.Talents.SearingLight)) * - core.TernaryFloat64(memeDream, 1.2, 1), + BonusCritRating: float64(priest.Talents.HolySpecialization) * 1 * core.CritRatingPerCritChance, + DamageMultiplier: 1 + 0.05*float64(priest.Talents.SearingLight), CritMultiplier: priest.DefaultSpellCritMultiplier(), ThreatMultiplier: 1 - []float64{0, .07, .14, .20}[priest.Talents.SilentResolve], diff --git a/sim/priest/smite/TestSmite.results b/sim/priest/smite/TestSmite.results index c37dd30657..110aae8059 100644 --- a/sim/priest/smite/TestSmite.results +++ b/sim/priest/smite/TestSmite.results @@ -46,739 +46,739 @@ character_stats_results: { dps_results: { key: "TestSmite-AllItems-AbsolutionRegalia" value: { - dps: 1995.65978 - tps: 1685.19061 + dps: 1995.47614 + tps: 1685.05564 } } dps_results: { key: "TestSmite-AllItems-Althor'sAbacus-50359" value: { - dps: 2894.04696 - tps: 2431.07532 + dps: 2893.83018 + tps: 2430.91688 } } dps_results: { key: "TestSmite-AllItems-Althor'sAbacus-50366" value: { - dps: 2907.685 - tps: 2442.39619 + dps: 2907.46733 + tps: 2442.2371 } } dps_results: { key: "TestSmite-AllItems-AustereEarthsiegeDiamond" value: { - dps: 2844.67304 - tps: 2388.45874 + dps: 2844.46107 + tps: 2388.30346 } } dps_results: { key: "TestSmite-AllItems-Bandit'sInsignia-40371" value: { - dps: 2783.08293 - tps: 2338.96466 + dps: 2782.87337 + tps: 2338.81139 } } dps_results: { key: "TestSmite-AllItems-BaubleofTrueBlood-50354" value: { - dps: 2784.21341 - tps: 2340.78415 + dps: 2783.94305 + tps: 2340.58703 hps: 90.33849 } } dps_results: { key: "TestSmite-AllItems-BaubleofTrueBlood-50726" value: { - dps: 2784.21341 - tps: 2340.78415 + dps: 2783.94305 + tps: 2340.58703 hps: 90.33849 } } dps_results: { key: "TestSmite-AllItems-BeamingEarthsiegeDiamond" value: { - dps: 2896.6066 - tps: 2430.4724 + dps: 2896.39463 + tps: 2430.31712 } } dps_results: { key: "TestSmite-AllItems-BlessedRegaliaofUndeadCleansing" value: { - dps: 2214.0364 - tps: 1868.07834 + dps: 2213.89453 + tps: 1867.97361 } } dps_results: { key: "TestSmite-AllItems-BracingEarthsiegeDiamond" value: { - dps: 2859.94481 - tps: 2353.70915 + dps: 2859.73182 + tps: 2353.55626 } } dps_results: { key: "TestSmite-AllItems-ChaoticSkyflareDiamond" value: { - dps: 2874.02992 - tps: 2411.10571 + dps: 2873.81795 + tps: 2410.95042 } } dps_results: { key: "TestSmite-AllItems-CorpseTongueCoin-50349" value: { - dps: 2783.08293 - tps: 2338.96466 + dps: 2782.87337 + tps: 2338.81139 } } dps_results: { key: "TestSmite-AllItems-CorpseTongueCoin-50352" value: { - dps: 2783.08293 - tps: 2338.96466 + dps: 2782.87337 + tps: 2338.81139 } } dps_results: { key: "TestSmite-AllItems-CorrodedSkeletonKey-50356" value: { - dps: 2783.08293 - tps: 2338.96466 + dps: 2782.87337 + tps: 2338.81139 hps: 64 } } dps_results: { key: "TestSmite-AllItems-CrimsonAcolyte'sRaiment" value: { - dps: 3656.43315 - tps: 3094.38378 + dps: 3656.275 + tps: 3094.26738 } } dps_results: { key: "TestSmite-AllItems-CrimsonAcolyte'sRegalia" value: { - dps: 3403.97761 - tps: 2858.95096 + dps: 3403.63853 + tps: 2858.7041 } } dps_results: { key: "TestSmite-AllItems-DarkmoonCard:Berserker!-42989" value: { - dps: 2809.61022 - tps: 2358.63454 + dps: 2809.40067 + tps: 2358.48127 } } dps_results: { key: "TestSmite-AllItems-DarkmoonCard:Death-42990" value: { - dps: 2856.17338 - tps: 2406.6212 + dps: 2855.92826 + tps: 2406.4309 } } dps_results: { key: "TestSmite-AllItems-DarkmoonCard:Greatness-44255" value: { - dps: 2988.88506 - tps: 2512.16435 + dps: 2988.6755 + tps: 2512.01108 } } dps_results: { key: "TestSmite-AllItems-Death'sChoice-47464" value: { - dps: 2783.08293 - tps: 2338.96466 + dps: 2782.87337 + tps: 2338.81139 } } dps_results: { key: "TestSmite-AllItems-DeathKnight'sAnguish-38212" value: { - dps: 2792.70508 - tps: 2346.01678 + dps: 2792.49553 + tps: 2345.86351 } } dps_results: { key: "TestSmite-AllItems-Deathbringer'sWill-50362" value: { - dps: 2783.08293 - tps: 2338.96466 + dps: 2782.87337 + tps: 2338.81139 } } dps_results: { key: "TestSmite-AllItems-Deathbringer'sWill-50363" value: { - dps: 2783.08293 - tps: 2338.96466 + dps: 2782.87337 + tps: 2338.81139 } } dps_results: { key: "TestSmite-AllItems-Defender'sCode-40257" value: { - dps: 2783.08293 - tps: 2338.96466 + dps: 2782.87337 + tps: 2338.81139 } } dps_results: { key: "TestSmite-AllItems-DestructiveSkyflareDiamond" value: { - dps: 2848.80173 - tps: 2390.98808 + dps: 2848.58975 + tps: 2390.83279 } } dps_results: { key: "TestSmite-AllItems-DislodgedForeignObject-50348" value: { - dps: 2892.00829 - tps: 2422.7308 + dps: 2891.88465 + tps: 2422.64278 } } dps_results: { key: "TestSmite-AllItems-DislodgedForeignObject-50353" value: { - dps: 2878.27734 - tps: 2413.69279 + dps: 2878.07976 + tps: 2413.54911 } } dps_results: { key: "TestSmite-AllItems-EffulgentSkyflareDiamond" value: { - dps: 2844.67304 - tps: 2388.45874 + dps: 2844.46107 + tps: 2388.30346 } } dps_results: { key: "TestSmite-AllItems-EmberSkyflareDiamond" value: { - dps: 2901.60191 - tps: 2436.99942 + dps: 2901.38893 + tps: 2436.84342 } } dps_results: { key: "TestSmite-AllItems-EnigmaticSkyflareDiamond" value: { - dps: 2846.44341 - tps: 2389.0365 + dps: 2846.23143 + tps: 2388.88121 } } dps_results: { key: "TestSmite-AllItems-EnigmaticStarflareDiamond" value: { - dps: 2846.03224 - tps: 2389.54878 + dps: 2845.82027 + tps: 2389.3935 } } dps_results: { key: "TestSmite-AllItems-EphemeralSnowflake-50260" value: { - dps: 2775.36116 - tps: 2330.40091 + dps: 2775.20299 + tps: 2330.28527 } } dps_results: { key: "TestSmite-AllItems-EssenceofGossamer-37220" value: { - dps: 2783.08293 - tps: 2338.96466 + dps: 2782.87337 + tps: 2338.81139 } } dps_results: { key: "TestSmite-AllItems-EternalEarthsiegeDiamond" value: { - dps: 2844.67304 - tps: 2388.45874 + dps: 2844.46107 + tps: 2388.30346 } } dps_results: { key: "TestSmite-AllItems-ExtractofNecromanticPower-40373" value: { - dps: 2847.15813 - tps: 2398.41544 + dps: 2846.94857 + tps: 2398.26217 } } dps_results: { key: "TestSmite-AllItems-EyeoftheBroodmother-45308" value: { - dps: 2886.63813 - tps: 2423.12085 + dps: 2886.44236 + tps: 2422.97869 } } dps_results: { key: "TestSmite-AllItems-Figurine-SapphireOwl-42413" value: { - dps: 2927.69669 - tps: 2463.26545 + dps: 2927.48714 + tps: 2463.11218 } } dps_results: { key: "TestSmite-AllItems-ForethoughtTalisman-40258" value: { - dps: 2851.89303 - tps: 2396.08356 + dps: 2851.67899 + tps: 2395.92708 } } dps_results: { key: "TestSmite-AllItems-ForgeEmber-37660" value: { - dps: 2851.36407 - tps: 2394.13159 + dps: 2851.15451 + tps: 2393.97832 } } dps_results: { key: "TestSmite-AllItems-ForlornSkyflareDiamond" value: { - dps: 2859.94481 - tps: 2401.12839 + dps: 2859.73182 + tps: 2400.97239 } } dps_results: { key: "TestSmite-AllItems-ForlornStarflareDiamond" value: { - dps: 2856.89045 - tps: 2398.59446 + dps: 2856.67767 + tps: 2398.4386 } } dps_results: { key: "TestSmite-AllItems-FuryoftheFiveFlights-40431" value: { - dps: 2783.08293 - tps: 2338.96466 + dps: 2782.87337 + tps: 2338.81139 } } dps_results: { key: "TestSmite-AllItems-FuturesightRune-38763" value: { - dps: 2865.78098 - tps: 2408.01177 + dps: 2865.56665 + tps: 2407.85508 } } dps_results: { key: "TestSmite-AllItems-GarbofFaith" value: { - dps: 2622.90525 - tps: 2209.44725 + dps: 2622.70384 + tps: 2209.29954 } } dps_results: { key: "TestSmite-AllItems-Gladiator'sInvestiture" value: { - dps: 3097.07074 - tps: 2621.61262 + dps: 3096.91139 + tps: 2621.49536 } } dps_results: { key: "TestSmite-AllItems-Gladiator'sRaiment" value: { - dps: 2778.12313 - tps: 2340.70258 + dps: 2777.84271 + tps: 2340.49807 } } dps_results: { key: "TestSmite-AllItems-GlowingTwilightScale-54573" value: { - dps: 2900.86598 - tps: 2436.73575 + dps: 2900.64875 + tps: 2436.57699 } } dps_results: { key: "TestSmite-AllItems-GlowingTwilightScale-54589" value: { - dps: 2916.36375 - tps: 2449.60037 + dps: 2916.14552 + tps: 2449.44089 } } dps_results: { key: "TestSmite-AllItems-GnomishLightningGenerator-41121" value: { - dps: 2850.05052 - tps: 2398.02263 + dps: 2850.13779 + tps: 2398.08766 } } dps_results: { key: "TestSmite-AllItems-Heartpierce-49982" value: { - dps: 2901.60191 - tps: 2436.99942 + dps: 2901.38893 + tps: 2436.84342 } } dps_results: { key: "TestSmite-AllItems-Heartpierce-50641" value: { - dps: 2901.60191 - tps: 2436.99942 + dps: 2901.38893 + tps: 2436.84342 } } dps_results: { key: "TestSmite-AllItems-ImpassiveSkyflareDiamond" value: { - dps: 2846.44341 - tps: 2389.0365 + dps: 2846.23143 + tps: 2388.88121 } } dps_results: { key: "TestSmite-AllItems-ImpassiveStarflareDiamond" value: { - dps: 2846.03224 - tps: 2389.54878 + dps: 2845.82027 + tps: 2389.3935 } } dps_results: { key: "TestSmite-AllItems-IncisorFragment-37723" value: { - dps: 2783.08293 - tps: 2338.96466 + dps: 2782.87337 + tps: 2338.81139 } } dps_results: { key: "TestSmite-AllItems-InsightfulEarthsiegeDiamond" value: { - dps: 2985.93267 - tps: 2511.63616 + dps: 2985.7207 + tps: 2511.48088 } } dps_results: { key: "TestSmite-AllItems-InvigoratingEarthsiegeDiamond" value: { - dps: 2844.67304 - tps: 2388.45874 + dps: 2844.46107 + tps: 2388.30346 } } dps_results: { key: "TestSmite-AllItems-LastWord-50179" value: { - dps: 2901.60191 - tps: 2436.99942 + dps: 2901.38893 + tps: 2436.84342 } } dps_results: { key: "TestSmite-AllItems-LastWord-50708" value: { - dps: 2901.60191 - tps: 2436.99942 + dps: 2901.38893 + tps: 2436.84342 } } dps_results: { key: "TestSmite-AllItems-Lavanthor'sTalisman-37872" value: { - dps: 2783.08293 - tps: 2338.96466 + dps: 2782.87337 + tps: 2338.81139 } } dps_results: { key: "TestSmite-AllItems-MajesticDragonFigurine-40430" value: { - dps: 2955.91562 - tps: 2482.50483 + dps: 2955.70512 + tps: 2482.3508 } } dps_results: { key: "TestSmite-AllItems-MeteoriteWhetstone-37390" value: { - dps: 2799.28132 - tps: 2351.15048 + dps: 2799.07176 + tps: 2350.99721 } } dps_results: { key: "TestSmite-AllItems-NevermeltingIceCrystal-50259" value: { - dps: 2863.61187 - tps: 2405.67062 + dps: 2863.27632 + tps: 2405.42676 } } dps_results: { key: "TestSmite-AllItems-Nibelung-49992" value: { - dps: 2901.60191 - tps: 2436.99942 + dps: 2901.38893 + tps: 2436.84342 } } dps_results: { key: "TestSmite-AllItems-Nibelung-50648" value: { - dps: 2901.60191 - tps: 2436.99942 + dps: 2901.38893 + tps: 2436.84342 } } dps_results: { key: "TestSmite-AllItems-OfferingofSacrifice-37638" value: { - dps: 2783.08293 - tps: 2338.96466 + dps: 2782.87337 + tps: 2338.81139 } } dps_results: { key: "TestSmite-AllItems-PersistentEarthshatterDiamond" value: { - dps: 2844.67304 - tps: 2388.45874 + dps: 2844.46107 + tps: 2388.30346 } } dps_results: { key: "TestSmite-AllItems-PersistentEarthsiegeDiamond" value: { - dps: 2844.67304 - tps: 2388.45874 + dps: 2844.46107 + tps: 2388.30346 } } dps_results: { key: "TestSmite-AllItems-PetrifiedScarab-21685" value: { - dps: 2783.08293 - tps: 2338.96466 + dps: 2782.87337 + tps: 2338.81139 } } dps_results: { key: "TestSmite-AllItems-PetrifiedTwilightScale-54571" value: { - dps: 2783.08293 - tps: 2338.96466 + dps: 2782.87337 + tps: 2338.81139 } } dps_results: { key: "TestSmite-AllItems-PetrifiedTwilightScale-54591" value: { - dps: 2783.08293 - tps: 2338.96466 + dps: 2782.87337 + tps: 2338.81139 } } dps_results: { key: "TestSmite-AllItems-PowerfulEarthshatterDiamond" value: { - dps: 2844.67304 - tps: 2388.45874 + dps: 2844.46107 + tps: 2388.30346 } } dps_results: { key: "TestSmite-AllItems-PowerfulEarthsiegeDiamond" value: { - dps: 2844.67304 - tps: 2388.45874 + dps: 2844.46107 + tps: 2388.30346 } } dps_results: { key: "TestSmite-AllItems-PurifiedShardoftheGods" value: { - dps: 2783.08293 - tps: 2338.96466 + dps: 2782.87337 + tps: 2338.81139 } } dps_results: { key: "TestSmite-AllItems-RegaliaofFaith" value: { - dps: 2639.07517 - tps: 2233.62531 + dps: 2638.93021 + tps: 2233.51836 } } dps_results: { key: "TestSmite-AllItems-ReignoftheDead-47316" value: { - dps: 2965.6255 - tps: 2506.39096 + dps: 2965.40989 + tps: 2506.23335 } } dps_results: { key: "TestSmite-AllItems-ReignoftheDead-47477" value: { - dps: 2988.30259 - tps: 2527.17565 + dps: 2988.08626 + tps: 2527.01752 } } dps_results: { key: "TestSmite-AllItems-RelentlessEarthsiegeDiamond" value: { - dps: 2872.02031 - tps: 2410.33656 + dps: 2871.80834 + tps: 2410.18128 } } dps_results: { key: "TestSmite-AllItems-RevitalizingSkyflareDiamond" value: { - dps: 2869.30107 - tps: 2408.39573 + dps: 2869.0891 + tps: 2408.24045 } } dps_results: { key: "TestSmite-AllItems-RuneofRepulsion-40372" value: { - dps: 2783.08293 - tps: 2338.96466 + dps: 2782.87337 + tps: 2338.81139 } } dps_results: { key: "TestSmite-AllItems-SanctificationGarb" value: { - dps: 2766.23464 - tps: 2331.88086 + dps: 2766.03738 + tps: 2331.73868 } } dps_results: { key: "TestSmite-AllItems-SanctificationRegalia" value: { - dps: 2799.71504 - tps: 2362.65649 + dps: 2799.56623 + tps: 2362.54679 } } dps_results: { key: "TestSmite-AllItems-SealofthePantheon-36993" value: { - dps: 2783.08293 - tps: 2338.96466 + dps: 2782.87337 + tps: 2338.81139 } } dps_results: { key: "TestSmite-AllItems-ShinyShardoftheGods" value: { - dps: 2783.08293 - tps: 2338.96466 + dps: 2782.87337 + tps: 2338.81139 } } dps_results: { key: "TestSmite-AllItems-Sindragosa'sFlawlessFang-50361" value: { - dps: 2783.08293 - tps: 2338.96466 + dps: 2782.87337 + tps: 2338.81139 } } dps_results: { key: "TestSmite-AllItems-SliverofPureIce-50339" value: { - dps: 3004.25046 - tps: 2532.71111 + dps: 3004.03453 + tps: 2532.55327 } } dps_results: { key: "TestSmite-AllItems-SliverofPureIce-50346" value: { - dps: 3024.45542 - tps: 2551.52189 + dps: 3024.23868 + tps: 2551.36347 } } dps_results: { key: "TestSmite-AllItems-SoulPreserver-37111" value: { - dps: 2829.57624 - tps: 2377.55851 + dps: 2829.36365 + tps: 2377.40307 } } dps_results: { key: "TestSmite-AllItems-SouloftheDead-40382" value: { - dps: 2942.10685 - tps: 2478.39753 + dps: 2941.89729 + tps: 2478.24426 } } dps_results: { key: "TestSmite-AllItems-SparkofLife-37657" value: { - dps: 2879.02312 - tps: 2419.68116 + dps: 2878.81356 + tps: 2419.52789 } } dps_results: { key: "TestSmite-AllItems-SphereofRedDragon'sBlood-37166" value: { - dps: 2809.43043 - tps: 2361.09267 + dps: 2809.22087 + tps: 2360.9394 } } dps_results: { key: "TestSmite-AllItems-SwiftSkyflareDiamond" value: { - dps: 2844.67304 - tps: 2388.45874 + dps: 2844.46107 + tps: 2388.30346 } } dps_results: { key: "TestSmite-AllItems-SwiftStarflareDiamond" value: { - dps: 2844.67304 - tps: 2388.45874 + dps: 2844.46107 + tps: 2388.30346 } } dps_results: { key: "TestSmite-AllItems-SwiftWindfireDiamond" value: { - dps: 2844.67304 - tps: 2388.45874 + dps: 2844.46107 + tps: 2388.30346 } } dps_results: { key: "TestSmite-AllItems-TalismanofTrollDivinity-37734" value: { - dps: 2857.32763 - tps: 2399.73234 + dps: 2857.11717 + tps: 2399.57842 } } dps_results: { key: "TestSmite-AllItems-TearsoftheVanquished-47215" value: { - dps: 2918.1954 - tps: 2453.9325 + dps: 2917.98584 + tps: 2453.77923 } } dps_results: { key: "TestSmite-AllItems-TheGeneral'sHeart-45507" value: { - dps: 2783.08293 - tps: 2338.96466 + dps: 2782.87337 + tps: 2338.81139 } } dps_results: { key: "TestSmite-AllItems-ThunderingSkyflareDiamond" value: { - dps: 2844.67304 - tps: 2388.45874 + dps: 2844.46107 + tps: 2388.30346 } } dps_results: { key: "TestSmite-AllItems-TinyAbominationinaJar-50351" value: { - dps: 2809.43043 - tps: 2361.09267 + dps: 2809.22087 + tps: 2360.9394 } } dps_results: { key: "TestSmite-AllItems-TinyAbominationinaJar-50706" value: { - dps: 2809.43043 - tps: 2361.09267 + dps: 2809.22087 + tps: 2360.9394 } } dps_results: { key: "TestSmite-AllItems-TirelessSkyflareDiamond" value: { - dps: 2859.94481 - tps: 2401.12839 + dps: 2859.73182 + tps: 2400.97239 } } dps_results: { key: "TestSmite-AllItems-TirelessStarflareDiamond" value: { - dps: 2856.89045 - tps: 2398.59446 + dps: 2856.67767 + tps: 2398.4386 } } dps_results: { key: "TestSmite-AllItems-TomeofArcanePhenomena-36972" value: { - dps: 2822.59725 - tps: 2369.91019 + dps: 2822.4374 + tps: 2369.79338 } } dps_results: { key: "TestSmite-AllItems-TrenchantEarthshatterDiamond" value: { - dps: 2856.89045 - tps: 2398.59446 + dps: 2856.67767 + tps: 2398.4386 } } dps_results: { key: "TestSmite-AllItems-TrenchantEarthsiegeDiamond" value: { - dps: 2859.94481 - tps: 2401.12839 + dps: 2859.73182 + tps: 2400.97239 } } dps_results: { key: "TestSmite-AllItems-Val'anyr,HammerofAncientKings-46017" value: { - dps: 2971.98183 - tps: 2487.99516 + dps: 2971.76409 + tps: 2487.83574 } } dps_results: { @@ -791,50 +791,50 @@ dps_results: { dps_results: { key: "TestSmite-AllItems-WingedTalisman-37844" value: { - dps: 2835.27316 - tps: 2382.3622 + dps: 2835.04964 + tps: 2382.19892 } } dps_results: { key: "TestSmite-AllItems-Zabra'sRaiment" value: { - dps: 2815.72712 - tps: 2378.09865 + dps: 2815.57936 + tps: 2377.9897 } } dps_results: { key: "TestSmite-AllItems-Zabra'sRegalia" value: { - dps: 2931.27671 - tps: 2466.27309 + dps: 2931.07129 + tps: 2466.1225 } } dps_results: { key: "TestSmite-Average-Default" value: { - dps: 2892.01638 - tps: 2428.52981 + dps: 2892.02467 + tps: 2428.5357 } } dps_results: { key: "TestSmite-Settings-Undead-p1-Basic-default-FullBuffs-LongMultiTarget" value: { - dps: 2901.60191 - tps: 3015.73285 + dps: 2901.38893 + tps: 3015.57684 } } dps_results: { key: "TestSmite-Settings-Undead-p1-Basic-default-FullBuffs-LongSingleTarget" value: { - dps: 2901.60191 - tps: 2436.99942 + dps: 2901.38893 + tps: 2436.84342 } } dps_results: { key: "TestSmite-Settings-Undead-p1-Basic-default-FullBuffs-ShortSingleTarget" value: { - dps: 4836.07031 - tps: 4107.85388 + dps: 4835.0054 + tps: 4107.07385 } } dps_results: { @@ -855,13 +855,13 @@ dps_results: { key: "TestSmite-Settings-Undead-p1-Basic-default-NoBuffs-ShortSingleTarget" value: { dps: 2520.9093 - tps: 2134.74022 + tps: 2126.72097 } } dps_results: { key: "TestSmite-SwitchInFrontOfTarget-Default" value: { - dps: 2901.60191 - tps: 2436.99942 + dps: 2901.38893 + tps: 2436.84342 } } diff --git a/sim/priest/smite/rotation.go b/sim/priest/smite/rotation.go deleted file mode 100644 index b37fcca221..0000000000 --- a/sim/priest/smite/rotation.go +++ /dev/null @@ -1,91 +0,0 @@ -package smite - -import ( - "github.com/wowsims/wotlk/sim/core" -) - -func (spriest *SmitePriest) OnGCDReady(sim *core.Simulation) { - spriest.tryUseGCD(sim) -} - -func (spriest *SmitePriest) tryUseGCD(sim *core.Simulation) { - var spell *core.Spell - - if spriest.rotation.MemeDream { - spell = spriest.chooseSpellMemeDream(sim) - } else { - spell = spriest.chooseSpell(sim) - } - - if spell == nil { - // nil means wait for HF. - spriest.WaitUntil(sim, spriest.HolyFire.ReadyAt()) - return - } - - if success := spell.Cast(sim, spriest.CurrentTarget); !success { - spriest.WaitForMana(sim, spell.CurCast.Cost) - } -} - -func (spriest *SmitePriest) chooseSpell(sim *core.Simulation) *core.Spell { - if spriest.holyFireDotWillBeUp(sim) { - if spriest.InnerFocus != nil && spriest.InnerFocus.IsReady(sim) { - spriest.InnerFocus.Cast(sim, nil) - } - - // Make sure we spam smite while dot is active. - return spriest.Smite - } else if spriest.rotation.UseDevouringPlague && !spriest.DevouringPlague.CurDot().IsActive() { - return spriest.DevouringPlague - } else if !spriest.ShadowWordPain.CurDot().IsActive() { - return spriest.ShadowWordPain - } else if spriest.HolyFire.IsReady(sim) { - return spriest.HolyFire - } else if spriest.HolyFire.TimeToReady(sim) <= spriest.allowedHFDelay { - return nil - } else if spriest.ImprovedSpiritTap.IsActive() { - return spriest.Smite - } else if spriest.Penance != nil && spriest.Penance.IsReady(sim) { - return spriest.Penance - } else if spriest.rotation.UseShadowWordDeath && spriest.ShadowWordDeath.IsReady(sim) { - return spriest.ShadowWordDeath - } else if spriest.rotation.UseMindBlast && spriest.MindBlast.IsReady(sim) { - return spriest.MindBlast - } else if spriest.Talents.MindFlay { - mfTickLength := spriest.MindFlayTickDuration() - hfTimeToReady := spriest.HolyFire.TimeToReady(sim) - numTicks := min(3, int(hfTimeToReady/mfTickLength+1)) - return spriest.MindFlay[numTicks] - } else { - return spriest.Smite - } -} - -func (spriest *SmitePriest) chooseSpellMemeDream(sim *core.Simulation) *core.Spell { - if spriest.rotation.UseDevouringPlague && !spriest.DevouringPlague.CurDot().IsActive() { - return spriest.DevouringPlague - } else if !spriest.ShadowWordPain.CurDot().IsActive() { - return spriest.ShadowWordPain - } else if spriest.HolyFire.IsReady(sim) { - return spriest.HolyFire - } else if spriest.HolyFire.TimeToReady(sim) <= spriest.allowedHFDelay { - return nil - } else { - if spriest.InnerFocus != nil && spriest.InnerFocus.IsReady(sim) { - spriest.InnerFocus.Cast(sim, nil) - } - - return spriest.Smite - } -} - -// Returns whether a Smite cast starting now would complete while Holy Fire is active. -func (spriest *SmitePriest) holyFireDotWillBeUp(sim *core.Simulation) bool { - if !spriest.HolyFire.CurDot().IsActive() { - return false - } - - smiteCastTime := spriest.ApplyCastSpeedForSpell(spriest.Smite.DefaultCast.CastTime, spriest.Smite) - return smiteCastTime <= spriest.HolyFire.CurDot().RemainingDuration(sim) -} diff --git a/sim/priest/smite/smite_priest.go b/sim/priest/smite/smite_priest.go index ea967c83bb..1c11d6c834 100644 --- a/sim/priest/smite/smite_priest.go +++ b/sim/priest/smite/smite_priest.go @@ -1,8 +1,6 @@ package smite import ( - "time" - "github.com/wowsims/wotlk/sim/core" "github.com/wowsims/wotlk/sim/core/proto" "github.com/wowsims/wotlk/sim/priest" @@ -35,10 +33,7 @@ func NewSmitePriest(character *core.Character, options *proto.Player) *SmitePrie basePriest := priest.New(character, selfBuffs, options.TalentsString) spriest := &SmitePriest{ - Priest: basePriest, - rotation: smiteOptions.Rotation, - - allowedHFDelay: time.Millisecond * time.Duration(smiteOptions.Rotation.AllowedHolyFireDelayMs), + Priest: basePriest, } spriest.SelfBuffs.PowerInfusionTarget = &proto.UnitReference{} @@ -46,17 +41,11 @@ func NewSmitePriest(character *core.Character, options *proto.Player) *SmitePrie spriest.SelfBuffs.PowerInfusionTarget = smiteOptions.Options.PowerInfusionTarget } - spriest.EnableResumeAfterManaWait(spriest.tryUseGCD) - return spriest } type SmitePriest struct { *priest.Priest - - rotation *proto.SmitePriest_Rotation - - allowedHFDelay time.Duration } func (spriest *SmitePriest) GetPriest() *priest.Priest { @@ -66,8 +55,8 @@ func (spriest *SmitePriest) GetPriest() *priest.Priest { func (spriest *SmitePriest) Initialize() { spriest.Priest.Initialize() - spriest.RegisterHolyFireSpell(spriest.rotation.MemeDream) - spriest.RegisterSmiteSpell(spriest.rotation.MemeDream) + spriest.RegisterHolyFireSpell() + spriest.RegisterSmiteSpell() spriest.RegisterPenanceSpell() spriest.RegisterHymnOfHopeCD() } diff --git a/sim/priest/talents.go b/sim/priest/talents.go index 3b4cae890b..3a4aeee251 100644 --- a/sim/priest/talents.go +++ b/sim/priest/talents.go @@ -397,9 +397,7 @@ func (priest *Priest) applyMisery() { priest.VampiricTouch.RelatedAuras = append(priest.VampiricTouch.RelatedAuras, miseryAuras) } if priest.MindFlay[1] != nil { - if priest.IsUsingAPL { - priest.MindFlayAPL.RelatedAuras = append(priest.MindFlayAPL.RelatedAuras, miseryAuras) - } + priest.MindFlayAPL.RelatedAuras = append(priest.MindFlayAPL.RelatedAuras, miseryAuras) priest.MindFlay[1].RelatedAuras = append(priest.MindFlay[1].RelatedAuras, miseryAuras) priest.MindFlay[2].RelatedAuras = append(priest.MindFlay[2].RelatedAuras, miseryAuras) priest.MindFlay[3].RelatedAuras = append(priest.MindFlay[3].RelatedAuras, miseryAuras) From 37e1b78c1ec31c461dabfc2dd339bc00169ab00b Mon Sep 17 00:00:00 2001 From: James Tanner Date: Thu, 4 Jan 2024 21:19:12 -0800 Subject: [PATCH 09/28] Commit before fixing rogue tests --- sim/rogue/feint.go | 13 - sim/rogue/rogue.go | 53 +--- sim/rogue/rogue_test.go | 36 +-- sim/rogue/rotation.go | 77 ----- sim/rogue/rotation_assassination.go | 374 ----------------------- sim/rogue/rotation_combat.go | 454 ---------------------------- sim/rogue/rotation_generic.go | 430 -------------------------- sim/rogue/rotation_multi.go | 405 ------------------------- sim/rogue/rotation_subtlety.go | 340 --------------------- sim/rogue/talents.go | 12 - sim/rogue/tricks_of_the_trade.go | 16 - sim/rogue/vanish.go | 30 +- 12 files changed, 18 insertions(+), 2222 deletions(-) delete mode 100644 sim/rogue/rotation.go delete mode 100644 sim/rogue/rotation_assassination.go delete mode 100644 sim/rogue/rotation_combat.go delete mode 100644 sim/rogue/rotation_generic.go delete mode 100644 sim/rogue/rotation_multi.go delete mode 100644 sim/rogue/rotation_subtlety.go diff --git a/sim/rogue/feint.go b/sim/rogue/feint.go index 459902376c..363328ebb3 100644 --- a/sim/rogue/feint.go +++ b/sim/rogue/feint.go @@ -36,17 +36,4 @@ func (rogue *Rogue) registerFeintSpell() { spell.CalcAndDealOutcome(sim, target, spell.OutcomeMeleeSpecialHit) }, }) - // Feint - if rogue.Rotation.UseFeint { - rogue.AddMajorCooldown(core.MajorCooldown{ - Spell: rogue.Feint, - Priority: core.CooldownPriorityDefault, - Type: core.CooldownTypeDPS, - //don't feint if you're gonna waste energy by using the gcd - ShouldActivate: func(sim *core.Simulation, character *core.Character) bool { - thresh := 55.0 //55 simmed best with standard settings for now 3/12/2023, will refine with the rotational refinements. 55 was definitely best for combat, didn't make a difference for muti - return rogue.CurrentEnergy() <= thresh - }, - }) - } } diff --git a/sim/rogue/rogue.go b/sim/rogue/rogue.go index f41e5375ba..5804c9374e 100644 --- a/sim/rogue/rogue.go +++ b/sim/rogue/rogue.go @@ -1,7 +1,6 @@ package rogue import ( - "math" "time" "github.com/wowsims/wotlk/sim/core" @@ -39,21 +38,14 @@ const RogueBleedTag = "RogueBleed" type Rogue struct { core.Character - Talents *proto.RogueTalents - Options *proto.Rogue_Options - Rotation *proto.Rogue_Rotation - - rotation rotation + Talents *proto.RogueTalents + Options *proto.Rogue_Options bleedCategory *core.ExclusiveCategory sliceAndDiceDurations [6]time.Duration exposeArmorDurations [6]time.Duration - allMCDsDisabled bool - - maxEnergy float64 - Backstab *core.Spell BladeFlurry *core.Spell DeadlyPoison *core.Spell @@ -185,13 +177,6 @@ func (rogue *Rogue) Initialize() { rogue.registerVanishSpell() rogue.finishingMoveEffectApplier = rogue.makeFinishingMoveEffectApplier() - - if !rogue.IsUsingAPL && rogue.Rotation.TricksOfTheTradeFrequency != proto.Rogue_Rotation_Never && !rogue.HasSetBonus(Tier10, 2) { - rogue.RegisterPrepullAction(-10*time.Second, func(sim *core.Simulation) { - rogue.TricksOfTheTrade.Cast(sim, nil) - rogue.UpdateMajorCooldowns() - }) - } } func (rogue *Rogue) ApplyEnergyTickMultiplier(multiplier float64) { @@ -202,30 +187,6 @@ func (rogue *Rogue) Reset(sim *core.Simulation) { for _, mcd := range rogue.GetMajorCooldowns() { mcd.Disable() } - rogue.allMCDsDisabled = true - - if !rogue.IsUsingAPL { - // Stealth triggered effects (Overkill and Master of Subtlety) pre-pull activation - if rogue.Rotation.OpenWithGarrote || rogue.Rotation.OpenWithPremeditation { - rogue.AutoAttacks.CancelAutoSwing(sim) - rogue.StealthAura.Activate(sim) - } else { - if rogue.Options.StartingOverkillDuration > 0 { - if rogue.Talents.Overkill { - duration := time.Second * time.Duration(math.Min(float64(rogue.Options.StartingOverkillDuration), 20)) - rogue.OverkillAura.Activate(sim) - rogue.OverkillAura.UpdateExpires(duration) - } - if rogue.Talents.MasterOfSubtlety > 0 { - duration := time.Second * time.Duration(math.Min(float64(rogue.Options.StartingOverkillDuration), 6)) - rogue.MasterOfSubtletyAura.Activate(sim) - rogue.MasterOfSubtletyAura.UpdateExpires(duration) - } - } - } - } - - rogue.setupRotation(sim) } func (rogue *Rogue) MeleeCritMultiplier(applyLethality bool) float64 { @@ -248,13 +209,13 @@ func NewRogue(character *core.Character, options *proto.Player) *Rogue { Character: *character, Talents: &proto.RogueTalents{}, Options: rogueOptions.Options, - Rotation: rogueOptions.Rotation, } core.FillTalentsProto(rogue.Talents.ProtoReflect(), options.TalentsString, TalentTreeSizes) // Passive rogue threat reduction: https://wotlk.wowhead.com/spell=21184/rogue-passive-dnd rogue.PseudoStats.ThreatMultiplier *= 0.71 rogue.PseudoStats.CanParry = true + maxEnergy := 100.0 if rogue.Talents.Vigor { maxEnergy += 10 @@ -265,8 +226,7 @@ func NewRogue(character *core.Character, options *proto.Player) *Rogue { if rogue.HasSetBonus(Arena, 4) { maxEnergy += 10 } - rogue.maxEnergy = maxEnergy - rogue.EnableEnergyBar(maxEnergy, rogue.OnEnergyGain) + rogue.EnableEnergyBar(maxEnergy) rogue.ApplyEnergyTickMultiplier([]float64{0, 0.08, 0.16, 0.25}[rogue.Talents.Vitality]) rogue.EnableAutoAttacks(rogue, core.AutoAttackOptions{ @@ -303,11 +263,6 @@ func (rogue *Rogue) BreakStealth(sim *core.Simulation) { } } -// Can the rogue fulfil the weapon equipped requirement for Mutilate? -func (rogue *Rogue) CanMutilate() bool { - return rogue.Talents.Mutilate && rogue.HasDagger(core.MainHand) && rogue.HasDagger(core.OffHand) -} - // Does the rogue have a dagger equipped in the specified hand (main or offhand)? func (rogue *Rogue) HasDagger(hand core.Hand) bool { if hand == core.MainHand { diff --git a/sim/rogue/rogue_test.go b/sim/rogue/rogue_test.go index 2edf03bf44..9fdd9220c1 100644 --- a/sim/rogue/rogue_test.go +++ b/sim/rogue/rogue_test.go @@ -238,79 +238,67 @@ var SubtletyGlyphs = &proto.Glyphs{ var PlayerOptionsCombatDI = &proto.Player_Rogue{ Rogue: &proto.Rogue{ - Options: DeadlyInstant, - Rotation: &proto.Rogue_Rotation{}, + Options: DeadlyInstant, }, } var PlayerOptionsCombatDD = &proto.Player_Rogue{ Rogue: &proto.Rogue{ - Options: DeadlyDeadly, - Rotation: &proto.Rogue_Rotation{}, + Options: DeadlyDeadly, }, } var PlayerOptionsCombatID = &proto.Player_Rogue{ Rogue: &proto.Rogue{ - Options: InstantDeadly, - Rotation: &proto.Rogue_Rotation{}, + Options: InstantDeadly, }, } var PlayerOptionsCombatII = &proto.Player_Rogue{ Rogue: &proto.Rogue{ - Options: InstantInstant, - Rotation: &proto.Rogue_Rotation{}, + Options: InstantInstant, }, } var PlayerOptionsNoLethality = &proto.Player_Rogue{ Rogue: &proto.Rogue{ - Options: DeadlyInstant, - Rotation: &proto.Rogue_Rotation{}, + Options: DeadlyInstant, }, } var PlayerOptionsNoPotW = &proto.Player_Rogue{ Rogue: &proto.Rogue{ - Options: DeadlyInstant, - Rotation: &proto.Rogue_Rotation{}, + Options: DeadlyInstant, }, } var PlayerOptionsNoLethalityNoPotW = &proto.Player_Rogue{ Rogue: &proto.Rogue{ - Options: DeadlyInstant, - Rotation: &proto.Rogue_Rotation{}, + Options: DeadlyInstant, }, } var PlayerOptionsAssassinationDI = &proto.Player_Rogue{ Rogue: &proto.Rogue{ - Options: DeadlyInstant, - Rotation: &proto.Rogue_Rotation{}, + Options: DeadlyInstant, }, } var PlayerOptionsAssassinationDD = &proto.Player_Rogue{ Rogue: &proto.Rogue{ - Options: DeadlyDeadly, - Rotation: &proto.Rogue_Rotation{}, + Options: DeadlyDeadly, }, } var PlayerOptionsAssassinationID = &proto.Player_Rogue{ Rogue: &proto.Rogue{ - Options: InstantDeadly, - Rotation: &proto.Rogue_Rotation{}, + Options: InstantDeadly, }, } var PlayerOptionsAssassinationII = &proto.Player_Rogue{ Rogue: &proto.Rogue{ - Options: InstantInstant, - Rotation: &proto.Rogue_Rotation{}, + Options: InstantInstant, }, } var PlayerOptionsSubtletyID = &proto.Player_Rogue{ Rogue: &proto.Rogue{ - Options: InstantDeadly, - Rotation: &proto.Rogue_Rotation{}, + Options: InstantDeadly, }, } diff --git a/sim/rogue/rotation.go b/sim/rogue/rotation.go deleted file mode 100644 index 95190e3799..0000000000 --- a/sim/rogue/rotation.go +++ /dev/null @@ -1,77 +0,0 @@ -package rogue - -import ( - "github.com/wowsims/wotlk/sim/core" -) - -type rotation interface { - setup(sim *core.Simulation, rogue *Rogue) - run(sim *core.Simulation, rogue *Rogue) -} - -type PriorityAction int32 - -const ( - Skip PriorityAction = iota - Build - Cast - Wait - Once -) - -type prio struct { - check func(sim *core.Simulation, rogue *Rogue) PriorityAction - cast func(sim *core.Simulation, rogue *Rogue) bool - cost float64 -} - -func (rogue *Rogue) OnEnergyGain(sim *core.Simulation) { - if rogue.IsUsingAPL { - return - } - - if sim.CurrentTime < 0 { - return - } - - rogue.TryUseCooldowns(sim) - - if !rogue.GCD.IsReady(sim) { - return - } - - rogue.rotation.run(sim, rogue) -} - -func (rogue *Rogue) OnGCDReady(sim *core.Simulation) { - if rogue.IsUsingAPL { - return - } - rogue.TryUseCooldowns(sim) - - if rogue.IsWaitingForEnergy() { - rogue.DoNothing() - return - } - - rogue.rotation.run(sim, rogue) -} - -func (rogue *Rogue) setupRotation(sim *core.Simulation) { - if rogue.IsUsingAPL { - return - } - switch { - case rogue.Env.GetNumTargets() >= 3: - rogue.rotation = &rotation_multi{} // rotation multi will soon be removed - case rogue.CanMutilate(): - rogue.rotation = &rotation_assassination{} - case rogue.Talents.CombatPotency > 0: - rogue.rotation = &rotation_combat{} - case rogue.Talents.HonorAmongThieves > 0: - rogue.rotation = &rotation_subtlety{} - default: - rogue.rotation = &rotation_generic{} - } - rogue.rotation.setup(sim, rogue) -} diff --git a/sim/rogue/rotation_assassination.go b/sim/rogue/rotation_assassination.go deleted file mode 100644 index a4a98bc23d..0000000000 --- a/sim/rogue/rotation_assassination.go +++ /dev/null @@ -1,374 +0,0 @@ -package rogue - -import ( - "log" - "slices" - "time" - - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/core/proto" -) - -type rotation_assassination struct { - prios []prio -} - -func (x *rotation_assassination) setup(sim *core.Simulation, rogue *Rogue) { - rogue.bleedCategory = rogue.CurrentTarget.GetExclusiveEffectCategory(core.BleedEffectCategory) - - x.prios = x.prios[:0] - - mutiCost := rogue.Mutilate.DefaultCast.Cost - rupCost := rogue.Rupture.DefaultCast.Cost - envCost := rogue.Envenom.DefaultCast.Cost - - // estimate of energy per second while nothing is cast - energyPerSecond := func() float64 { - if rogue.Talents.FocusedAttacks == 0 { - return 10 * rogue.EnergyTickMultiplier - } - - getCritChance := func(spell *core.Spell) float64 { - at := rogue.AttackTables[rogue.CurrentTarget.UnitIndex] - - critCap := 1.0 - at.BaseGlanceChance - if miss := at.BaseMissChance + 0.19 - spell.PhysicalHitChance(at); miss > 0 { - critCap -= miss - } - if dodge := at.BaseDodgeChance - spell.ExpertisePercentage() - rogue.PseudoStats.DodgeReduction; dodge > 0 { - critCap -= dodge - } - - critChance := spell.PhysicalCritChance(at) - if critChance > critCap { - critChance = critCap - } - return critChance - } - - critsPerSecond := getCritChance(rogue.AutoAttacks.MHAuto())/rogue.AutoAttacks.MainhandSwingSpeed().Seconds() + - getCritChance(rogue.AutoAttacks.OHAuto())/rogue.AutoAttacks.OffhandSwingSpeed().Seconds() - procChance := []float64{0, 0.33, 0.66, 1}[rogue.Talents.FocusedAttacks] - - return 10*rogue.EnergyTickMultiplier + critsPerSecond*procChance*2 - } - - // Garrote - if rogue.Rotation.OpenWithGarrote && !rogue.PseudoStats.InFrontOfTarget && rogue.IsStealthed() { - x.prios = append(x.prios, prio{ - func(sim *core.Simulation, rogue *Rogue) PriorityAction { - if rogue.CurrentEnergy() > rogue.Garrote.DefaultCast.Cost && rogue.IsStealthed() { - return Once - } - return Wait - }, - func(sim *core.Simulation, rogue *Rogue) bool { - return rogue.Garrote.Cast(sim, rogue.CurrentTarget) - }, - rogue.Garrote.DefaultCast.Cost, - }) - } - - // Slice And Dice - x.prios = append(x.prios, prio{ - func(sim *core.Simulation, rogue *Rogue) PriorityAction { - if rogue.SliceAndDiceAura.IsActive() { - return Skip - } - if rogue.ComboPoints() > 0 && rogue.CurrentEnergy() > rogue.SliceAndDice.DefaultCast.Cost { - return Cast - } - if rogue.ComboPoints() < 1 && rogue.CurrentEnergy() > mutiCost { - return Build - } - return Wait - }, - func(sim *core.Simulation, rogue *Rogue) bool { - return rogue.SliceAndDice.Cast(sim, rogue.CurrentTarget) - }, - rogue.SliceAndDice.DefaultCast.Cost, - }) - - // Hunger while planning - if rogue.Talents.HungerForBlood { - x.prios = append(x.prios, prio{ - func(sim *core.Simulation, rogue *Rogue) PriorityAction { - - prioExpose := rogue.Rotation.ExposeArmorFrequency == proto.Rogue_Rotation_Once || - rogue.Rotation.ExposeArmorFrequency == proto.Rogue_Rotation_Maintain - if prioExpose && !rogue.ExposeArmorAuras.Get(rogue.CurrentTarget).IsActive() { - return Skip - } - - if rogue.HungerForBloodAura.IsActive() { - return Skip - } - - if !x.targetHasBleed(sim, rogue) { - return Skip - } - - if x.targetHasBleed(sim, rogue) && rogue.CurrentEnergy() > rogue.HungerForBlood.DefaultCast.Cost { - return Cast - } - return Wait - }, - func(sim *core.Simulation, rogue *Rogue) bool { - return rogue.HungerForBlood.Cast(sim, rogue.CurrentTarget) - }, - rogue.HungerForBlood.DefaultCast.Cost, - }) - } - - // Expose armor - if rogue.Rotation.ExposeArmorFrequency == proto.Rogue_Rotation_Once || rogue.Rotation.ExposeArmorFrequency == proto.Rogue_Rotation_Maintain { - hasCastExpose := false - x.prios = append(x.prios, prio{ - func(sim *core.Simulation, rogue *Rogue) PriorityAction { - if hasCastExpose && rogue.Rotation.ExposeArmorFrequency == proto.Rogue_Rotation_Once { - return Skip - } - timeLeft := rogue.ExposeArmorAuras.Get(rogue.CurrentTarget).RemainingDuration(sim) - minPoints := max(1, min(rogue.Rotation.MinimumComboPointsExposeArmor, 5)) - if rogue.Rotation.ExposeArmorFrequency != proto.Rogue_Rotation_Once { - minPoints = 1 - } - if timeLeft <= 0 { - if rogue.ComboPoints() < minPoints { - if rogue.CurrentEnergy() >= mutiCost { - return Build - } else { - return Wait - } - } else { - if rogue.CurrentEnergy() >= rogue.ExposeArmor.DefaultCast.Cost { - return Cast - } else { - return Wait - } - } - } else { - energyGained := energyPerSecond() * timeLeft.Seconds() - cpGenerated := energyGained / mutiCost - currentCp := float64(rogue.ComboPoints()) - if currentCp+cpGenerated > 5 { - return Skip - } else { - if currentCp < 5 { - if rogue.CurrentEnergy() >= mutiCost { - return Build - } - } - return Wait - } - } - }, - func(sim *core.Simulation, rogue *Rogue) bool { - casted := rogue.ExposeArmor.Cast(sim, rogue.CurrentTarget) - if casted { - hasCastExpose = true - } - return casted - }, - rogue.ExposeArmor.DefaultCast.Cost, - }) - } - - // Rupture for Bleed - if rogue.Rotation.RuptureForBleed { - x.prios = append(x.prios, prio{ - func(sim *core.Simulation, rogue *Rogue) PriorityAction { - if x.targetHasBleed(sim, rogue) { - return Skip - } - if rogue.HungerForBloodAura.IsActive() { - return Skip - } - if rogue.ComboPoints() > 0 && rogue.CurrentEnergy() >= rupCost { - return Cast - } - if rogue.ComboPoints() < 1 && rogue.CurrentEnergy() >= mutiCost { - return Build - } - return Wait - }, - func(sim *core.Simulation, rogue *Rogue) bool { - return rogue.Rupture.Cast(sim, rogue.CurrentTarget) - }, - rupCost, - }) - } - - // Hunger for Blood - if rogue.Talents.HungerForBlood { - x.prios = append(x.prios, prio{ - func(sim *core.Simulation, rogue *Rogue) PriorityAction { - if rogue.HungerForBloodAura.IsActive() { - return Skip - } - - if !x.targetHasBleed(sim, rogue) { - return Skip - } - - if x.targetHasBleed(sim, rogue) && rogue.CurrentEnergy() >= rogue.HungerForBlood.DefaultCast.Cost { - return Cast - } - return Wait - }, - func(s *core.Simulation, r *Rogue) bool { - return rogue.HungerForBlood.Cast(sim, rogue.CurrentTarget) - }, - rogue.HungerForBlood.DefaultCast.Cost, - }) - } - - // Enable CDs - x.prios = append(x.prios, prio{ - func(sim *core.Simulation, rogue *Rogue) PriorityAction { - for _, mcd := range rogue.GetMajorCooldowns() { - if mcd.Spell != rogue.ColdBlood { - mcd.Enable() - } - } - return Once - }, - func(s *core.Simulation, r *Rogue) bool { - return true - }, - 0, - }) - - // Rupture - x.prios = append(x.prios, prio{ - func(sim *core.Simulation, rogue *Rogue) PriorityAction { - cp, e := rogue.ComboPoints(), rogue.CurrentEnergy() - - if rogue.Rotation.AssassinationFinisherPriority == proto.Rogue_Rotation_EnvenomRupture { - if rogue.Rupture.CurDot().IsActive() || sim.GetRemainingDuration() < rogue.RuptureDuration(4) { - return Skip - } - if !rogue.EnvenomAura.IsActive() || cp < 4 || rogue.Talents.Ruthlessness < 3 { - return Skip - } - - // use Rupture if you can re-cast Envenom with minimal delay, hoping for a Ruthlessness proc ;) - avail := e + rogue.EnvenomAura.RemainingDuration(sim).Seconds()*energyPerSecond() - cost := rupCost + mutiCost + envCost - if avail >= cost { - return Cast - } - return Skip - - } else { - if rogue.Rupture.CurDot().IsActive() || sim.GetRemainingDuration() < time.Second*18 { - return Skip - } - if cp >= 4 && e >= rupCost { - return Cast - } - if cp < 4 && e >= mutiCost { - return Build - } - return Wait - } - }, - func(sim *core.Simulation, rogue *Rogue) bool { - return rogue.Rupture.Cast(sim, rogue.CurrentTarget) - }, - rupCost, - }) - - // Envenom - x.prios = append(x.prios, prio{ - func(sim *core.Simulation, rogue *Rogue) PriorityAction { - e, cp := rogue.CurrentEnergy(), rogue.ComboPoints() - - // end of combat handling - possibly use low CP Envenoms instead of doing nothing - if dur := sim.GetRemainingDuration(); dur <= 10*time.Second { - avail := e + dur.Seconds()*energyPerSecond() - - if cp == 3 && avail < mutiCost+envCost && e >= envCost { - return Cast - } - - if cp >= 1 && avail < mutiCost && e >= envCost { - return Cast - } - } - - if cp >= 4 { - eps := energyPerSecond() - - if rogue.EnvenomAura.IsActive() { - // don't clip Envenom, unless you'd energy cap - if e < rogue.maxEnergy-eps && sim.GetRemainingDuration() >= rogue.EnvenomDuration(5) { - return Wait - } - return Cast - } - - // pool, so two Mutilate casts fit into the next uptime; this is a very minor DPS gain, and primarily for lower gear levels - cost := envCost + mutiCost + mutiCost - if cp == 5 && rogue.Talents.RelentlessStrikes == 5 { - cost -= 25 - } - avail := e + rogue.EnvenomDuration(cp).Seconds()*eps - if avail < cost { - return Wait - } - return Cast - } - - if e >= mutiCost { - return Build - } - return Wait - }, - func(sim *core.Simulation, rogue *Rogue) bool { - if rogue.ColdBlood.IsReady(sim) && rogue.ComboPoints() == 5 { - rogue.ColdBlood.Cast(sim, rogue.CurrentTarget) - } - return rogue.Envenom.Cast(sim, rogue.CurrentTarget) - }, - envCost, - }) -} - -func (x *rotation_assassination) run(sim *core.Simulation, rogue *Rogue) { - for i := 0; i < len(x.prios); i++ { - switch p := x.prios[i]; p.check(sim, rogue) { - case Skip: - continue - case Build: - if !rogue.Mutilate.Cast(sim, rogue.CurrentTarget) { - rogue.WaitForEnergy(sim, rogue.Mutilate.DefaultCast.Cost) - return - } - case Cast: - if !p.cast(sim, rogue) { - rogue.WaitForEnergy(sim, p.cost) - return - } - case Once: - if !p.cast(sim, rogue) { - rogue.WaitForEnergy(sim, p.cost) - return - } - x.prios = slices.Delete(x.prios, i, i+1) - i-- - case Wait: - rogue.DoNothing() - return - } - - if !rogue.GCD.IsReady(sim) { - return - } - } - log.Panic("skipped all prios") -} - -func (x *rotation_assassination) targetHasBleed(_ *core.Simulation, rogue *Rogue) bool { - return rogue.bleedCategory.AnyActive() || rogue.CurrentTarget.HasActiveAuraWithTag(RogueBleedTag) || rogue.Options.AssumeBleedActive -} diff --git a/sim/rogue/rotation_combat.go b/sim/rogue/rotation_combat.go deleted file mode 100644 index a38113ba66..0000000000 --- a/sim/rogue/rotation_combat.go +++ /dev/null @@ -1,454 +0,0 @@ -package rogue - -import ( - "log" - "slices" - "time" - - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/core/proto" -) - -type rotation_combat struct { - prios []prio - - builder *core.Spell -} - -func (x *rotation_combat) setup(_ *core.Simulation, rogue *Rogue) { - x.prios = x.prios[:0] - - x.builder = rogue.SinisterStrike - if rogue.Rotation.CombatBuilder == proto.Rogue_Rotation_Backstab && rogue.HasDagger(core.MainHand) && !rogue.PseudoStats.InFrontOfTarget { - x.builder = rogue.Backstab - } - if rogue.Talents.Hemorrhage && rogue.Rotation.CombatBuilder == proto.Rogue_Rotation_HemorrhageCombat { - x.builder = rogue.Hemorrhage - } - - bldCost := x.builder.DefaultCast.Cost - sndCost := rogue.SliceAndDice.DefaultCast.Cost - rupCost := rogue.Rupture.DefaultCast.Cost - evisCost := rogue.Eviscerate.DefaultCast.Cost - - baseEps := 10 * rogue.EnergyTickMultiplier - maxPool := rogue.maxEnergy - 3*float64(rogue.Talents.CombatPotency) - - ruthCp := 0.2 * float64(rogue.Talents.Ruthlessness) - - // estimate of energy per second while nothing is cast - energyPerSecond := func() float64 { - if rogue.Talents.CombatPotency == 0 { - return 10 * rogue.EnergyTickMultiplier - } - - spell := rogue.AutoAttacks.OHAuto() - at := rogue.AttackTables[rogue.CurrentTarget.UnitIndex] - - landChance := 1.0 - if miss := at.BaseMissChance + 0.19 - spell.PhysicalHitChance(at); miss > 0 { - landChance -= miss - } - if dodge := at.BaseDodgeChance - spell.ExpertisePercentage() - spell.Unit.PseudoStats.DodgeReduction; dodge > 0 { - landChance -= dodge - } - - landsPerSecond := landChance / rogue.AutoAttacks.OffhandSwingSpeed().Seconds() - - return 10*rogue.EnergyTickMultiplier + landsPerSecond*0.2*float64(rogue.Talents.CombatPotency)*3 - } - - // Glyph of Backstab support - var bonusDuration float64 - rupRemaining := func(sim *core.Simulation) time.Duration { - if dot := rogue.Rupture.CurDot(); dot.IsActive() { - return dot.RemainingDuration(sim) - } - return 0 - } - - if x.builder == rogue.Backstab && rogue.HasMajorGlyph(proto.RogueMajorGlyph_GlyphOfBackstab) { - bonusDuration = 6 - rupRemaining = func(sim *core.Simulation) time.Duration { - if dot := rogue.Rupture.CurDot(); dot.IsActive() { - dur := dot.RemainingDuration(sim) - dur += dot.TickLength * time.Duration(dot.MaxStacks+3-dot.NumberOfTicks) - return dur - } - return 0 - } - } - - // Garrote - if rogue.Rotation.OpenWithGarrote && !rogue.PseudoStats.InFrontOfTarget && rogue.IsStealthed() { - x.prios = append(x.prios, prio{ - func(sim *core.Simulation, rogue *Rogue) PriorityAction { - if rogue.CurrentEnergy() > rogue.Garrote.DefaultCast.Cost && rogue.IsStealthed() { - return Once - } - return Wait - }, - func(sim *core.Simulation, rogue *Rogue) bool { - return rogue.Garrote.Cast(sim, rogue.CurrentTarget) - }, - rogue.Garrote.DefaultCast.Cost, - }) - } - - // Slice And Dice - x.prios = append(x.prios, prio{ - func(sim *core.Simulation, rogue *Rogue) PriorityAction { - cp, e := rogue.ComboPoints(), rogue.CurrentEnergy() - - if sndDur := rogue.SliceAndDiceAura.RemainingDuration(sim); sndDur > 0 { - if cp == 5 { // pool for snd if pooling for rupture fails - rupDur := rupRemaining(sim) - if e+rupDur.Seconds()*energyPerSecond() > maxPool { - if e+sndDur.Seconds()*energyPerSecond() <= maxPool { - return Wait - } - } - return Skip - } - - if cp >= 1 { // don't build if it reduces uptime - if e+sndDur.Seconds()*energyPerSecond() < sndCost+bldCost || sndDur < time.Second { - return Wait - } - } - return Skip - } - - // end of fight - heuristically, 2s of snd beat a 3 CP eviscerate for DPE, and 3s are close to a 5 CP one. - if cp >= 3 && sim.GetRemainingDuration() < time.Duration(2000+600*cp)*time.Millisecond { - return Skip - } - - if cp >= 1 && e >= sndCost { - return Cast - } - if cp < 1 && e >= bldCost { - return Build - } - return Wait - }, - func(sim *core.Simulation, rogue *Rogue) bool { - return rogue.SliceAndDice.Cast(sim, rogue.CurrentTarget) - }, - sndCost, - }) - - // Expose armor - update this as well - if rogue.Rotation.ExposeArmorFrequency == proto.Rogue_Rotation_Once || rogue.Rotation.ExposeArmorFrequency == proto.Rogue_Rotation_Maintain { - hasCastExpose := false - x.prios = append(x.prios, prio{ - func(sim *core.Simulation, rogue *Rogue) PriorityAction { - if hasCastExpose && rogue.Rotation.ExposeArmorFrequency == proto.Rogue_Rotation_Once { - return Skip - } - timeLeft := rogue.ExposeArmorAuras.Get(rogue.CurrentTarget).RemainingDuration(sim) - minPoints := max(1, min(rogue.Rotation.MinimumComboPointsExposeArmor, 5)) - if rogue.Rotation.ExposeArmorFrequency != proto.Rogue_Rotation_Once { - minPoints = 1 - } - if timeLeft <= 0 { - if rogue.ComboPoints() < minPoints { - if rogue.CurrentEnergy() >= bldCost { - return Build - } else { - return Wait - } - } else { - if rogue.CurrentEnergy() >= rogue.ExposeArmor.DefaultCast.Cost { - return Cast - } else { - return Wait - } - } - } else { - energyGained := energyPerSecond() * timeLeft.Seconds() - cpGenerated := energyGained / bldCost - currentCp := float64(rogue.ComboPoints()) - if currentCp+cpGenerated > 5 { - return Skip - } else { - if currentCp < 5 { - if rogue.CurrentEnergy() >= bldCost { - return Build - } - } - return Wait - } - } - }, - func(sim *core.Simulation, rogue *Rogue) bool { - casted := rogue.ExposeArmor.Cast(sim, rogue.CurrentTarget) - if casted { - hasCastExpose = true - } - return casted - }, - rogue.ExposeArmor.DefaultCast.Cost, - }) - } - - // Enable CDs - x.prios = append(x.prios, prio{ - func(sim *core.Simulation, rogue *Rogue) PriorityAction { - for _, mcd := range rogue.GetMajorCooldowns() { - mcd.Enable() - } - return Once - }, - func(s *core.Simulation, r *Rogue) bool { - return true - }, - 0, - }) - - if rogue.Rotation.CombatFinisherPriority == proto.Rogue_Rotation_EviscerateRupture { - // this is the pre-3.3.3 "rupture-less" rotation, essentially - x.prios = append(x.prios, prio{ - func(sim *core.Simulation, rogue *Rogue) PriorityAction { - e, cp := rogue.CurrentEnergy(), rogue.ComboPoints() - - if dur := sim.GetRemainingDuration(); dur <= 10*time.Second { - // end of fight handling - build towards a 3+ cp eviscerate, or just sinister strike - switch cp { - case 5: - if e >= evisCost { - return Cast - } - return Wait - default: - if e+dur.Seconds()*energyPerSecond() >= bldCost+evisCost { - return Build - } - if cp >= 3 && e >= evisCost { - return Cast - } - if cp < 3 && e >= bldCost { - return Build - } - } - return Wait - } - - if cp >= 5 { - sndDur := rogue.SliceAndDiceAura.RemainingDuration(sim) - // correcting with ruthCp seems to be a loss, so we just use bldCost directly - if e+sndDur.Seconds()*energyPerSecond() >= evisCost+bldCost+sndCost { - return Cast - } - return Wait - } - return Build - }, - func(sim *core.Simulation, rogue *Rogue) bool { - return rogue.Eviscerate.Cast(sim, rogue.CurrentTarget) - }, - evisCost, - }) - - return - } - - const ruptureMinDuration = time.Second * 10 // heuristically, 4-5 rupture ticks are better DPE than eviscerate - - // seconds a 5 cp rupture can be delayed to match a 4 cp rupture's dps. for rup4to5 and rup3to4, this delay is < 2s, - // which also means that clipping 3 or 4 cp ruptures is usually a dps loss - rup4to5 := (rogue.RuptureDuration(4).Seconds() + bonusDuration) * (1 - rogue.RuptureDamage(4)/rogue.RuptureDamage(5)) - rup3to4 := (rogue.RuptureDuration(3).Seconds() + bonusDuration) * (1 - rogue.RuptureDamage(3)/rogue.RuptureDamage(4)) - - // Rupture - x.prios = append(x.prios, prio{ - func(sim *core.Simulation, rogue *Rogue) PriorityAction { - cp, e := rogue.ComboPoints(), rogue.CurrentEnergy() - - if sim.GetRemainingDuration() < ruptureMinDuration { - return Skip - } - - rupDot := rogue.Rupture.CurDot() - if !rupDot.IsActive() { - if cp == 5 && e >= rupCost { - return Cast - } - if cp == 4 && e+rup4to5*energyPerSecond() < bldCost+rupCost { - return Cast - } - if cp == 3 && e+rup3to4*energyPerSecond() < bldCost+rupCost { - return Cast - } - if e >= bldCost { - return Build - } - return Wait - } - - // there's ample time to rebuild, simply skip - dur := rupRemaining(sim).Seconds() - if e+dur*baseEps > maxPool { - return Skip - } - - if cp == 5 { - if e+dur*energyPerSecond() > maxPool { - return Skip // can't pool any longer, maybe we can fit in Eviscerate - } - return Wait - } - if cp == 4 && e+(dur+rup4to5)*energyPerSecond() < bldCost+rupCost { - return Wait - } - if cp == 3 && e+(dur+rup3to4)*energyPerSecond() < bldCost+rupCost { - return Wait - } - if e >= bldCost { - return Build - } - return Wait - }, - func(sim *core.Simulation, rogue *Rogue) bool { - return rogue.Rupture.Cast(sim, rogue.CurrentTarget) - }, - rupCost, - }) - - bldPerCp := 1.0 - if x.builder == rogue.SinisterStrike && rogue.HasMajorGlyph(proto.RogueMajorGlyph_GlyphOfSinisterStrike) { - attackTable := rogue.AttackTables[rogue.CurrentTarget.UnitIndex] - crit := rogue.SinisterStrike.PhysicalCritChance(attackTable) - bldPerCp = 1 / (1 + crit*(0.5+0.2*float64(rogue.Talents.SealFate))) - } - if x.builder == rogue.Backstab && rogue.Talents.SealFate > 0 { - attackTable := rogue.AttackTables[rogue.CurrentTarget.UnitIndex] - crit := rogue.Backstab.PhysicalCritChance(attackTable) - bldPerCp = 1 / (1 + crit*(0.2*float64(rogue.Talents.SealFate))) - } - - // Eviscerate - x.prios = append(x.prios, prio{ - func(sim *core.Simulation, rogue *Rogue) PriorityAction { - e, cp := rogue.CurrentEnergy(), rogue.ComboPoints() - - if dur := sim.GetRemainingDuration(); dur <= ruptureMinDuration { - // end of fight handling - build towards a 3+ cp eviscerate, or just sinister strike - switch cp { - case 5: - if e >= evisCost { - return Cast - } - return Wait - default: - if e+dur.Seconds()*energyPerSecond() >= bldCost+evisCost { - return Build - } - if cp >= 3 && e >= evisCost { - return Cast - } - if cp < 3 && e >= bldCost { - return Build - } - } - return Wait - } - - // we only get here if there's ample time left on rupture, or rupture pooling failed: in these cases, we - // can try to fill in a 5 cp eviscerate, if it's not too disruptive. lower cp eviscerates aren't worth it, - // since sinister spam isn't all that much worse - if cp <= 4 { - return Build - } - - cost := evisCost + (4-ruthCp)*bldCost*bldPerCp + rupCost - - rupDur := rupRemaining(sim) - sndDur := rogue.SliceAndDiceAura.RemainingDuration(sim) - if sndDur < rupDur { - cost += sndCost + (1-ruthCp)*bldCost*bldPerCp - } - - if avail := e + rupDur.Seconds()*energyPerSecond(); avail >= cost { - return Cast - } - - // we'd lose a CP here, so we just wait... - if e <= maxPool { - return Wait - } - - // ... and if that doesn't work, allow to clip snd - if sndDur < rogue.sliceAndDiceDurations[2]-rogue.sliceAndDiceDurations[1] { - rogue.SliceAndDice.Cast(sim, rogue.CurrentTarget) - return Wait - } - - return Build - }, - func(sim *core.Simulation, rogue *Rogue) bool { - return rogue.Eviscerate.Cast(sim, rogue.CurrentTarget) - }, - evisCost, - }) -} - -func (x *rotation_combat) run(sim *core.Simulation, rogue *Rogue) { - for i := 0; i < len(x.prios); i++ { - switch p := x.prios[i]; p.check(sim, rogue) { - case Skip: - continue - case Build: - //Handle Ghostly Strike. This is badly copy-pasted code, and is not considered in a regular raid setting. - if rogue.Talents.GhostlyStrike && rogue.Rotation.UseGhostlyStrike && rogue.GhostlyStrike.IsReady(sim) { - x.builder = rogue.GhostlyStrike - - if !x.builder.Cast(sim, rogue.CurrentTarget) { - rogue.WaitForEnergy(sim, x.builder.DefaultCast.Cost) - - x.builder = rogue.SinisterStrike - if rogue.Rotation.CombatBuilder == proto.Rogue_Rotation_Backstab && rogue.HasDagger(core.MainHand) && !rogue.PseudoStats.InFrontOfTarget { - x.builder = rogue.Backstab - } - if rogue.Talents.Hemorrhage && rogue.Rotation.CombatBuilder == proto.Rogue_Rotation_HemorrhageCombat { - x.builder = rogue.Hemorrhage - } - - return - } - - x.builder = rogue.SinisterStrike - if rogue.Rotation.CombatBuilder == proto.Rogue_Rotation_Backstab && rogue.HasDagger(core.MainHand) && !rogue.PseudoStats.InFrontOfTarget { - x.builder = rogue.Backstab - } - if rogue.Talents.Hemorrhage && rogue.Rotation.CombatBuilder == proto.Rogue_Rotation_HemorrhageCombat { - x.builder = rogue.Hemorrhage - } - //Done with Ghostly Strike - } else if !x.builder.Cast(sim, rogue.CurrentTarget) { - rogue.WaitForEnergy(sim, x.builder.DefaultCast.Cost) - return - } - case Cast: - if !p.cast(sim, rogue) { - rogue.WaitForEnergy(sim, p.cost) - return - } - case Once: - if !p.cast(sim, rogue) { - rogue.WaitForEnergy(sim, p.cost) - return - } - x.prios = slices.Delete(x.prios, i, i+1) - i-- - case Wait: - rogue.DoNothing() - return - } - - if !rogue.GCD.IsReady(sim) { - return - } - } - log.Panic("skipped all prios") -} diff --git a/sim/rogue/rotation_generic.go b/sim/rogue/rotation_generic.go deleted file mode 100644 index a3ad5da4f7..0000000000 --- a/sim/rogue/rotation_generic.go +++ /dev/null @@ -1,430 +0,0 @@ -package rogue - -import ( - "log" - "slices" - "time" - - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/core/proto" -) - -type rotation_generic struct { - prios []prio - - builder *core.Spell -} - -func (x *rotation_generic) setup(_ *core.Simulation, rogue *Rogue) { - x.prios = x.prios[:0] - - x.builder = rogue.SinisterStrike - if rogue.HasDagger(core.MainHand) && !rogue.PseudoStats.InFrontOfTarget { - x.builder = rogue.Backstab - } - if rogue.CanMutilate() { - x.builder = rogue.Mutilate - } - if rogue.Talents.Hemorrhage { - x.builder = rogue.Hemorrhage - } - - bldCost := x.builder.DefaultCast.Cost - sndCost := rogue.SliceAndDice.DefaultCast.Cost - rupCost := rogue.Rupture.DefaultCast.Cost - - baseEps := 10 * rogue.EnergyTickMultiplier - maxPool := rogue.maxEnergy - 3*float64(rogue.Talents.CombatPotency) - 2*float64(rogue.Talents.FocusedAttacks)/3.0 - - ruthCp := 0.2 * float64(rogue.Talents.Ruthlessness) - rsPerCp := float64(rogue.Talents.RelentlessStrikes) - - // estimate of energy per second while nothing is cast - energyPerSecond := func() float64 { - var eps float64 - if rogue.Talents.CombatPotency > 0 { - spell := rogue.AutoAttacks.OHAuto() - at := rogue.AttackTables[rogue.CurrentTarget.UnitIndex] - - landChance := 1.0 - if miss := at.BaseMissChance + 0.19 - spell.PhysicalHitChance(at); miss > 0 { - landChance -= miss - } - if dodge := at.BaseDodgeChance - spell.ExpertisePercentage() - spell.Unit.PseudoStats.DodgeReduction; dodge > 0 { - landChance -= dodge - } - - landsPerSecond := landChance / rogue.AutoAttacks.OffhandSwingSpeed().Seconds() - - eps += landsPerSecond * 0.2 * float64(rogue.Talents.CombatPotency) * 3 - } - if rogue.Talents.FocusedAttacks > 0 { - getCritChance := func(spell *core.Spell) float64 { - at := rogue.AttackTables[rogue.CurrentTarget.UnitIndex] - - critCap := 1.0 - at.BaseGlanceChance - if miss := at.BaseMissChance + 0.19 - spell.PhysicalHitChance(at); miss > 0 { - critCap -= miss - } - if dodge := at.BaseDodgeChance - spell.ExpertisePercentage() - rogue.PseudoStats.DodgeReduction; dodge > 0 { - critCap -= dodge - } - - critChance := spell.PhysicalCritChance(at) - if critChance > critCap { - critChance = critCap - } - return critChance - } - - critsPerSecond := getCritChance(rogue.AutoAttacks.MHAuto())/rogue.AutoAttacks.MainhandSwingSpeed().Seconds() + - getCritChance(rogue.AutoAttacks.OHAuto())/rogue.AutoAttacks.OffhandSwingSpeed().Seconds() - procChance := []float64{0, 0.33, 0.66, 1}[rogue.Talents.FocusedAttacks] - - eps += critsPerSecond * procChance * 2 - } - return 10*rogue.EnergyTickMultiplier + eps - } - - // Glyph of Backstab support - var bonusDuration float64 - rupRemaining := func(sim *core.Simulation) time.Duration { - if dot := rogue.Rupture.CurDot(); dot.IsActive() { - return dot.RemainingDuration(sim) - } - return 0 - } - - if x.builder == rogue.Backstab && rogue.HasMajorGlyph(proto.RogueMajorGlyph_GlyphOfBackstab) { - bonusDuration = 6 - rupRemaining = func(sim *core.Simulation) time.Duration { - if dot := rogue.Rupture.CurDot(); dot.IsActive() { - dur := dot.RemainingDuration(sim) - dur += dot.TickLength * time.Duration(dot.MaxStacks+3-dot.NumberOfTicks) - return dur - } - return 0 - } - } - - // Garrote - if rogue.Rotation.OpenWithGarrote && !rogue.PseudoStats.InFrontOfTarget { - x.prios = append(x.prios, prio{ - func(sim *core.Simulation, rogue *Rogue) PriorityAction { - if rogue.CurrentEnergy() > rogue.Garrote.DefaultCast.Cost { - return Once - } - return Wait - }, - func(sim *core.Simulation, rogue *Rogue) bool { - return rogue.Garrote.Cast(sim, rogue.CurrentTarget) - }, - rogue.Garrote.DefaultCast.Cost, - }) - } - - // Slice And Dice - x.prios = append(x.prios, prio{ - func(sim *core.Simulation, rogue *Rogue) PriorityAction { - cp, e := rogue.ComboPoints(), rogue.CurrentEnergy() - - if sndDur := rogue.SliceAndDiceAura.RemainingDuration(sim); sndDur > 0 { - if cp == 5 { // pool for snd if pooling for rupture fails - rupDur := rupRemaining(sim) - if e+rupDur.Seconds()*energyPerSecond() > maxPool { - if e+sndDur.Seconds()*energyPerSecond() <= maxPool { - return Wait - } - } - return Skip - } - - if cp >= 1 { // don't build if it reduces uptime - if e+sndDur.Seconds()*energyPerSecond() < sndCost+bldCost || sndDur < time.Second { - return Wait - } - } - return Skip - } - - // end of fight - heuristically, 2s of snd beat a 3 CP eviscerate for DPE, and 3s are close to a 5 CP one. - if cp >= 3 && sim.GetRemainingDuration() < time.Duration(2000+600*cp)*time.Millisecond { - return Skip - } - - if cp >= 1 && e >= sndCost { - return Cast - } - if cp < 1 && e >= bldCost { - return Build - } - return Wait - }, - func(sim *core.Simulation, rogue *Rogue) bool { - return rogue.SliceAndDice.Cast(sim, rogue.CurrentTarget) - }, - sndCost, - }) - - // Expose armor - update this as well - if rogue.Rotation.ExposeArmorFrequency == proto.Rogue_Rotation_Once || rogue.Rotation.ExposeArmorFrequency == proto.Rogue_Rotation_Maintain { - hasCastExpose := false - x.prios = append(x.prios, prio{ - func(sim *core.Simulation, rogue *Rogue) PriorityAction { - if hasCastExpose && rogue.Rotation.ExposeArmorFrequency == proto.Rogue_Rotation_Once { - return Skip - } - timeLeft := rogue.ExposeArmorAuras.Get(rogue.CurrentTarget).RemainingDuration(sim) - minPoints := max(1, min(rogue.Rotation.MinimumComboPointsExposeArmor, 5)) - if rogue.Rotation.ExposeArmorFrequency != proto.Rogue_Rotation_Once { - minPoints = 1 - } - if timeLeft <= 0 { - if rogue.ComboPoints() < minPoints { - if rogue.CurrentEnergy() >= bldCost { - return Build - } else { - return Wait - } - } else { - if rogue.CurrentEnergy() >= rogue.ExposeArmor.DefaultCast.Cost { - return Cast - } else { - return Wait - } - } - } else { - energyGained := energyPerSecond() * timeLeft.Seconds() - cpGenerated := energyGained / bldCost - currentCp := float64(rogue.ComboPoints()) - if currentCp+cpGenerated > 5 { - return Skip - } else { - if currentCp < 5 { - if rogue.CurrentEnergy() >= bldCost { - return Build - } - } - return Wait - } - } - }, - func(sim *core.Simulation, rogue *Rogue) bool { - casted := rogue.ExposeArmor.Cast(sim, rogue.CurrentTarget) - if casted { - hasCastExpose = true - } - return casted - }, - rogue.ExposeArmor.DefaultCast.Cost, - }) - } - - // Enable CDs - x.prios = append(x.prios, prio{ - func(sim *core.Simulation, rogue *Rogue) PriorityAction { - for _, mcd := range rogue.GetMajorCooldowns() { - mcd.Enable() - } - return Once - }, - func(s *core.Simulation, r *Rogue) bool { - return true - }, - 0, - }) - - const ruptureMinDuration = time.Second * 10 // heuristically, 4-5 rupture ticks are better DPE than eviscerate - - // seconds a 5 cp rupture can be delayed to match a 4 cp rupture's dps. for rup4to5 and rup3to4, this delay is < 2s, - // which also means that clipping 3 or 4 cp ruptures is usually a dps loss - rup4to5 := (rogue.RuptureDuration(4).Seconds() + bonusDuration) * (1 - rogue.RuptureDamage(4)/rogue.RuptureDamage(5)) - rup3to4 := (rogue.RuptureDuration(3).Seconds() + bonusDuration) * (1 - rogue.RuptureDamage(3)/rogue.RuptureDamage(4)) - - // Rupture - x.prios = append(x.prios, prio{ - func(sim *core.Simulation, rogue *Rogue) PriorityAction { - cp, e := rogue.ComboPoints(), rogue.CurrentEnergy() - - if sim.GetRemainingDuration() < ruptureMinDuration { - return Skip - } - - rupDot := rogue.Rupture.CurDot() - if !rupDot.IsActive() { - if cp == 5 && e >= rupCost { - return Cast - } - if cp == 4 && e+rup4to5*energyPerSecond() < bldCost+rupCost { - return Cast - } - if cp == 3 && e+rup3to4*energyPerSecond() < bldCost+rupCost { - return Cast - } - if e >= bldCost { - return Build - } - return Wait - } - - // there's ample time to rebuild, simply skip - dur := rupRemaining(sim).Seconds() - if e+dur*baseEps > maxPool { - return Skip - } - - if cp == 5 { - if e+dur*energyPerSecond() > maxPool { - return Skip // can't pool any longer, maybe we can fit in Eviscerate - } - return Wait - } - if cp == 4 && e+(dur+rup4to5)*energyPerSecond() < bldCost+rupCost { - return Wait - } - if cp == 3 && e+(dur+rup3to4)*energyPerSecond() < bldCost+rupCost { - return Wait - } - if e >= bldCost { - return Build - } - return Wait - }, - func(sim *core.Simulation, rogue *Rogue) bool { - return rogue.Rupture.Cast(sim, rogue.CurrentTarget) - }, - rupCost, - }) - - bldPerCp := 1.0 - if x.builder == rogue.SinisterStrike { - attackTable := rogue.AttackTables[rogue.CurrentTarget.UnitIndex] - crit := rogue.SinisterStrike.PhysicalCritChance(attackTable) - var extraChance float64 - if rogue.HasMajorGlyph(proto.RogueMajorGlyph_GlyphOfSinisterStrike) { - extraChance = 0.5 - } - bldPerCp = 1 / (1 + crit*(extraChance+0.2*float64(rogue.Talents.SealFate))) - } - if x.builder == rogue.Backstab { - attackTable := rogue.AttackTables[rogue.CurrentTarget.UnitIndex] - crit := rogue.Backstab.PhysicalCritChance(attackTable) - bldPerCp = 1 / (1 + crit*(0.2*float64(rogue.Talents.SealFate))) - } - if x.builder == rogue.Hemorrhage { - attackTable := rogue.AttackTables[rogue.CurrentTarget.UnitIndex] - crit := rogue.Hemorrhage.PhysicalCritChance(attackTable) - bldPerCp = 1 / (1 + crit*(0.2*float64(rogue.Talents.SealFate))) - } - if x.builder == rogue.Mutilate { - attackTable := rogue.AttackTables[rogue.CurrentTarget.UnitIndex] - critMH := rogue.MutilateMH.PhysicalCritChance(attackTable) - critOH := rogue.MutilateOH.PhysicalCritChance(attackTable) - crit := 1 - (1-critMH)*(1-critOH) - bldPerCp = 1 / (2 + crit*(0.2*float64(rogue.Talents.SealFate))) - } - - // direct damage finisher (Eviscerate/Envenom) - finisher := rogue.Eviscerate - if rogue.Talents.MasterPoisoner > 0 { - finisher = rogue.Envenom - } - finisherCost := finisher.DefaultCast.Cost - x.prios = append(x.prios, prio{ - func(sim *core.Simulation, rogue *Rogue) PriorityAction { - e, cp := rogue.CurrentEnergy(), rogue.ComboPoints() - - if dur := sim.GetRemainingDuration(); dur <= ruptureMinDuration { - // end of fight handling - build towards a 3+ cp finisher, or just spam the builder - switch cp { - case 5: - if e >= finisherCost { - return Cast - } - return Wait - default: - if e+dur.Seconds()*energyPerSecond() >= bldCost+finisherCost { - return Build - } - if cp >= 3 && e >= finisherCost { - return Cast - } - if cp < 3 && e >= bldCost { - return Build - } - } - return Wait - } - - // we only get here if there's ample time left on rupture, or rupture pooling failed: in these cases, we - // can try to fill in a 5 cp finisher, if it's not too disruptive. lower cp finishers aren't worth it, - // since builder spam isn't all that much worse - if cp <= 4 { - return Build - } - - cost := finisherCost - 5*rsPerCp + (4-ruthCp)*bldCost*bldPerCp + rupCost - - rupDur := rupRemaining(sim) - sndDur := rogue.SliceAndDiceAura.RemainingDuration(sim) - if sndDur < rupDur { - cost += sndCost - 1*rsPerCp + (1-ruthCp)*bldCost*bldPerCp - } - - if avail := e + rupDur.Seconds()*energyPerSecond(); avail >= cost { - return Cast - } - - // we'd lose a CP here, so we just wait... - if e <= maxPool { - return Wait - } - - // ... and if that doesn't work, allow to clip snd - if sndDur < rogue.sliceAndDiceDurations[2]-rogue.sliceAndDiceDurations[1] { - rogue.SliceAndDice.Cast(sim, rogue.CurrentTarget) - return Wait - } - - return Build - }, - func(sim *core.Simulation, rogue *Rogue) bool { - return finisher.Cast(sim, rogue.CurrentTarget) - }, - finisherCost, - }) -} - -func (x *rotation_generic) run(sim *core.Simulation, rogue *Rogue) { - for i := 0; i < len(x.prios); i++ { - switch p := x.prios[i]; p.check(sim, rogue) { - case Skip: - continue - case Build: - if !x.builder.Cast(sim, rogue.CurrentTarget) { - rogue.WaitForEnergy(sim, x.builder.DefaultCast.Cost) - return - } - case Cast: - if !p.cast(sim, rogue) { - rogue.WaitForEnergy(sim, p.cost) - return - } - case Once: - if !p.cast(sim, rogue) { - rogue.WaitForEnergy(sim, p.cost) - return - } - x.prios = slices.Delete(x.prios, i, i+1) - i-- - case Wait: - rogue.DoNothing() - return - } - - if !rogue.GCD.IsReady(sim) { - return - } - } - log.Panic("skipped all prios") -} diff --git a/sim/rogue/rotation_multi.go b/sim/rogue/rotation_multi.go deleted file mode 100644 index b9000428f8..0000000000 --- a/sim/rogue/rotation_multi.go +++ /dev/null @@ -1,405 +0,0 @@ -package rogue - -import ( - "math" - "time" - - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/core/proto" -) - -type rogueRotationItem struct { - ExpiresAt time.Duration - MinimumBuildDuration time.Duration - MaximumBuildDuration time.Duration - PrioIndex int -} - -type roguePriorityItem struct { - Aura *core.Aura - CastCount int32 - EnergyCost float64 - PoolAmount float64 - GetDuration func(*Rogue, int32) time.Duration - GetSpell func(*Rogue, int32) *core.Spell - IsFiller bool - MaximumComboPoints int32 - MaxCasts int32 - MinimumComboPoints int32 -} - -type shouldCastRotationItemResult int32 - -const ( - ShouldNotCast shouldCastRotationItemResult = iota - ShouldBuild - ShouldCast - ShouldWait -) - -type rotation_multi struct { - priorityItems []roguePriorityItem - rotationItems []rogueRotationItem - - builder *core.Spell - builderPoints int32 -} - -func (x *rotation_multi) setup(sim *core.Simulation, rogue *Rogue) { - x.builder = rogue.SinisterStrike - x.builderPoints = 1 - - if rogue.CanMutilate() { - x.builder = rogue.Mutilate - x.builderPoints = 2 - } - - if rogue.Talents.Hemorrhage { - x.builder = rogue.Hemorrhage - x.builderPoints = 1 - } - - if rogue.Talents.SlaughterFromTheShadows > 0 && !rogue.Rotation.HemoWithDagger && !rogue.PseudoStats.InFrontOfTarget && rogue.HasDagger(core.MainHand) { - x.builder = rogue.Backstab - x.builderPoints = 1 - } - - // Slice and Dice - x.priorityItems = x.priorityItems[:0] - - sliceAndDice := roguePriorityItem{ - MinimumComboPoints: 1, - MaximumComboPoints: 5, - Aura: rogue.SliceAndDiceAura, - EnergyCost: rogue.SliceAndDice.DefaultCast.Cost, - GetDuration: func(rogue *Rogue, cp int32) time.Duration { - return rogue.sliceAndDiceDurations[cp] - }, - GetSpell: func(rogue *Rogue, cp int32) *core.Spell { - return rogue.SliceAndDice - }, - } - if rogue.Rotation.MultiTargetSliceFrequency != proto.Rogue_Rotation_Never { - sliceAndDice.MinimumComboPoints = max(1, rogue.Rotation.MinimumComboPointsMultiTargetSlice) - if rogue.Rotation.MultiTargetSliceFrequency == proto.Rogue_Rotation_Once { - sliceAndDice.MaxCasts = 1 - } - x.priorityItems = append(x.priorityItems, sliceAndDice) - } - - // Expose Armor - if rogue.Rotation.ExposeArmorFrequency == proto.Rogue_Rotation_Maintain || - rogue.Rotation.ExposeArmorFrequency == proto.Rogue_Rotation_Once { - minPoints := int32(1) - maxCasts := int32(0) - if rogue.Rotation.ExposeArmorFrequency == proto.Rogue_Rotation_Once { - minPoints = rogue.Rotation.MinimumComboPointsExposeArmor - maxCasts = 1 - } - x.priorityItems = append(x.priorityItems, roguePriorityItem{ - MaxCasts: maxCasts, - MaximumComboPoints: 5, - MinimumComboPoints: minPoints, - Aura: rogue.ExposeArmorAuras.Get(rogue.CurrentTarget), - EnergyCost: rogue.ExposeArmor.DefaultCast.Cost, - GetDuration: func(rogue *Rogue, cp int32) time.Duration { - return rogue.exposeArmorDurations[cp] - }, - GetSpell: func(rogue *Rogue, cp int32) *core.Spell { - return rogue.ExposeArmor - }, - }) - } - - // Hunger for Blood - if rogue.Talents.HungerForBlood { - x.priorityItems = append(x.priorityItems, roguePriorityItem{ - MaximumComboPoints: 0, - Aura: rogue.HungerForBloodAura, - EnergyCost: rogue.HungerForBlood.DefaultCast.Cost, - GetDuration: func(rogue *Rogue, cp int32) time.Duration { - return rogue.HungerForBloodAura.Duration - }, - GetSpell: func(rogue *Rogue, cp int32) *core.Spell { - return rogue.HungerForBlood - }, - }) - } - - // Dummy priority to enable CDs - x.priorityItems = append(x.priorityItems, roguePriorityItem{ - MaxCasts: 1, - MaximumComboPoints: 0, - GetDuration: func(rogue *Rogue, cp int32) time.Duration { - return 0 - }, - GetSpell: func(rogue *Rogue, cp int32) *core.Spell { - if rogue.allMCDsDisabled { - for _, mcd := range rogue.GetMajorCooldowns() { - mcd.Enable() - } - rogue.allMCDsDisabled = false - } - return nil - }, - }) - - x.priorityItems = append(x.priorityItems, roguePriorityItem{ - MaximumComboPoints: 0, - EnergyCost: rogue.FanOfKnives.DefaultCast.Cost, - GetSpell: func(rogue *Rogue, i int32) *core.Spell { - return rogue.FanOfKnives - }, - }) - x.rotationItems = x.planRotation(sim, rogue) -} - -func (x *rotation_multi) run(sim *core.Simulation, rogue *Rogue) { - if len(x.rotationItems) < 1 { - panic("Rotation is empty") - } - eps := x.getExpectedEnergyPerSecond(rogue) - shouldCast := x.shouldCastNextRotationItem(sim, rogue, eps) - item := x.rotationItems[0] - prio := x.priorityItems[item.PrioIndex] - - switch shouldCast { - case ShouldNotCast: - x.rotationItems = x.rotationItems[1:] - x.run(sim, rogue) - case ShouldBuild: - spell := x.builder - if spell == nil || spell.Cast(sim, rogue.CurrentTarget) { - if rogue.GCD.IsReady(sim) { - x.run(sim, rogue) - } - } else { - panic("Unexpected builder cast failure") - } - case ShouldCast: - spell := prio.GetSpell(rogue, rogue.ComboPoints()) - if spell == nil || spell.Cast(sim, rogue.CurrentTarget) { - x.priorityItems[item.PrioIndex].CastCount += 1 - x.rotationItems = x.planRotation(sim, rogue) - if rogue.GCD.IsReady(sim) { - x.run(sim, rogue) - } - } else { - panic("Unexpected cast failure") - } - case ShouldWait: - desiredEnergy := 100.0 - if rogue.ComboPoints() == 5 { - desiredEnergy = prio.EnergyCost - } else { - if rogue.CurrentEnergy() < prio.EnergyCost && rogue.ComboPoints() >= prio.MinimumComboPoints { - desiredEnergy = prio.EnergyCost - } else if rogue.ComboPoints() < 5 { - desiredEnergy = x.builder.DefaultCast.Cost - } - } - cdAvailableTime := time.Second * 10 - if sim.CurrentTime > cdAvailableTime { - cdAvailableTime = core.NeverExpires - } - nextExpiration := cdAvailableTime - for _, otherItem := range x.rotationItems { - if otherItem.ExpiresAt < nextExpiration { - nextExpiration = otherItem.ExpiresAt - } - } - neededEnergy := desiredEnergy - rogue.CurrentEnergy() - energyAvailableTime := time.Second*time.Duration(neededEnergy/eps) + 1*time.Second - energyAt := sim.CurrentTime + energyAvailableTime - if energyAt < nextExpiration { - rogue.WaitForEnergy(sim, desiredEnergy) - } else if nextExpiration > sim.CurrentTime { - rogue.WaitUntil(sim, nextExpiration) - } else { - rogue.DoNothing() - } - } -} - -func (x *rotation_multi) energyToBuild(points int32) float64 { - costPerBuilder := x.builder.DefaultCast.Cost - - buildersNeeded := math.Ceil(float64(points) / float64(x.builderPoints)) - return buildersNeeded * costPerBuilder -} - -func (x *rotation_multi) timeToBuild(points int32, builderPoints int32, eps float64, finisherCost float64) time.Duration { - energyNeeded := x.energyToBuild(points) + finisherCost - secondsNeeded := energyNeeded / eps - globalsNeeded := math.Ceil(float64(points)/float64(builderPoints)) + 1 - // Return greater of the time it takes to use the globals and the time it takes to build the energy - return max(time.Second*time.Duration(secondsNeeded), time.Second*time.Duration(globalsNeeded)) -} - -func (x *rotation_multi) shouldCastNextRotationItem(sim *core.Simulation, rogue *Rogue, eps float64) shouldCastRotationItemResult { - if len(x.rotationItems) == 0 { - panic("Empty rotation") - } - currentEnergy := rogue.CurrentEnergy() - comboPoints := rogue.ComboPoints() - currentTime := sim.CurrentTime - item := x.rotationItems[0] - prio := x.priorityItems[item.PrioIndex] - tte := item.ExpiresAt - currentTime - clippingThreshold := time.Second * 2 - timeUntilNextGCD := rogue.GCD.TimeToReady(sim) - - // Check to see if a higher prio item will expire - if len(x.rotationItems) >= 2 { - timeElapsed := time.Second * 1 - for _, nextItem := range x.rotationItems[1:] { - if nextItem.ExpiresAt <= currentTime+timeElapsed { - return ShouldNotCast - } - timeElapsed += nextItem.MinimumBuildDuration - } - } - - // Expires before next GCD - if tte <= timeUntilNextGCD { - if comboPoints >= prio.MinimumComboPoints && currentEnergy >= (prio.EnergyCost+prio.PoolAmount) { - return ShouldCast - } else if comboPoints < prio.MinimumComboPoints && currentEnergy >= x.builder.DefaultCast.Cost { - return ShouldBuild - } else { - return ShouldWait - } - } - if comboPoints >= prio.MaximumComboPoints { // Don't need CP - // Cast - if tte <= clippingThreshold && currentEnergy >= (prio.EnergyCost+prio.PoolAmount) { - return ShouldCast - } - // Pool energy - if tte <= clippingThreshold && currentEnergy < (prio.EnergyCost+prio.PoolAmount) { - return ShouldWait - } - // We have time to squeeze in another spell - if tte > item.MinimumBuildDuration { - // Find the first lower prio item that can be cast and use it - for lpi, lowerPrio := range x.priorityItems[item.PrioIndex+1:] { - if comboPoints > lowerPrio.MinimumComboPoints && currentEnergy > lowerPrio.EnergyCost && lowerPrio.MaxCasts == 0 { - x.rotationItems = append([]rogueRotationItem{ - {ExpiresAt: currentTime, PrioIndex: lpi + item.PrioIndex + 1}, - }, x.rotationItems...) - return ShouldCast - } - } - } - // Overcap CP with builder - if x.timeToBuild(1, x.builderPoints, eps, prio.EnergyCost+prio.PoolAmount) <= tte && currentEnergy >= x.builder.DefaultCast.Cost { - return ShouldBuild - } - } else if comboPoints < prio.MinimumComboPoints { // Need CP - if currentEnergy >= x.builder.DefaultCast.Cost { - return ShouldBuild - } else { - return ShouldWait - } - } else { // Between MinimumComboPoints and MaximumComboPoints - if currentEnergy >= prio.EnergyCost+prio.PoolAmount && tte <= timeUntilNextGCD { - return ShouldCast - } - ttb := x.timeToBuild(1, 2, eps, prio.EnergyCost+prio.PoolAmount-currentEnergy) - if currentEnergy >= x.builder.DefaultCast.Cost && tte > ttb { - return ShouldBuild - } - } - return ShouldWait -} - -func (x *rotation_multi) getExpectedEnergyPerSecond(rogue *Rogue) float64 { - const finishersPerSecond = 1.0 / 6 - const averageComboPointsSpendOnFinisher = 4.0 - bonusEnergyPerSecond := float64(rogue.Talents.CombatPotency) * 3 * 0.2 * 1.0 / (rogue.AutoAttacks.OH().SwingSpeed / 1.4) - bonusEnergyPerSecond += float64(rogue.Talents.FocusedAttacks) - bonusEnergyPerSecond += float64(rogue.Talents.RelentlessStrikes) * 0.04 * 25 * finishersPerSecond * averageComboPointsSpendOnFinisher - return (core.EnergyPerTick*rogue.EnergyTickMultiplier)/core.EnergyTickDuration.Seconds() + bonusEnergyPerSecond -} - -func (x *rotation_multi) planRotation(sim *core.Simulation, rogue *Rogue) []rogueRotationItem { - var rotationItems []rogueRotationItem - eps := x.getExpectedEnergyPerSecond(rogue) - for pi, prio := range x.priorityItems { - if prio.MaxCasts > 0 && prio.CastCount >= prio.MaxCasts { - continue - } - maxCP := prio.MaximumComboPoints - for maxCP > 0 && prio.GetDuration(rogue, maxCP)+sim.CurrentTime > sim.Duration { - maxCP-- - } - var expiresAt time.Duration - if prio.Aura != nil { - expiresAt = prio.Aura.ExpiresAt() - } else if prio.MaxCasts == 1 { - expiresAt = sim.CurrentTime // TODO looks fishy, repeated expiresAt = sim.CurrentTime - } else { - expiresAt = sim.CurrentTime - } - minimumBuildDuration := x.timeToBuild(prio.MinimumComboPoints, x.builderPoints, eps, prio.EnergyCost) - maximumBuildDuration := x.timeToBuild(maxCP, x.builderPoints, eps, prio.EnergyCost) - rotationItems = append(rotationItems, rogueRotationItem{ - ExpiresAt: expiresAt, - MaximumBuildDuration: maximumBuildDuration, - MinimumBuildDuration: minimumBuildDuration, - PrioIndex: pi, - }) - } - - currentTime := sim.CurrentTime - comboPoints := rogue.ComboPoints() - currentEnergy := rogue.CurrentEnergy() - - var prioStack []rogueRotationItem - for _, item := range rotationItems { - if item.ExpiresAt >= sim.Duration { - continue - } - prio := x.priorityItems[item.PrioIndex] - maxBuildAt := item.ExpiresAt - item.MaximumBuildDuration - if prio.Aura == nil { - timeValueOfResources := time.Duration((float64(comboPoints)*x.builder.DefaultCast.Cost/float64(x.builderPoints) + currentEnergy) / eps) - maxBuildAt = currentTime - item.MaximumBuildDuration - timeValueOfResources - } - if currentTime < maxBuildAt { - // Put it on the to cast stack - prioStack = append(prioStack, item) - if prio.MinimumComboPoints > 0 { - comboPoints = 0 - } - currentTime += item.MaximumBuildDuration - } else { - cpUsed := max(0, prio.MinimumComboPoints-comboPoints) - energyUsed := max(0, prio.EnergyCost-currentEnergy) - minBuildTime := x.timeToBuild(cpUsed, x.builderPoints, eps, energyUsed) - if currentTime+minBuildTime <= item.ExpiresAt || !prio.IsFiller { - prioStack = append(prioStack, item) - currentTime = max(item.ExpiresAt, currentTime+minBuildTime) - currentEnergy = 0 - if prio.MinimumComboPoints > 0 { - comboPoints = 0 - } - } else if len(prioStack) < 1 || (prio.Aura != nil && !prio.Aura.IsActive() && !prio.IsFiller) || prio.MaxCasts == 1 { - // Plan to cast it as soon as possible - prioStack = append(prioStack, item) - currentTime += item.MinimumBuildDuration - currentEnergy = 0 - if prio.MinimumComboPoints > 0 { - comboPoints = 0 - } - } - } - } - - // Reverse - for i, j := 0, len(prioStack)-1; i < j; i, j = i+1, j-1 { - prioStack[i], prioStack[j] = prioStack[j], prioStack[i] - } - - return prioStack -} diff --git a/sim/rogue/rotation_subtlety.go b/sim/rogue/rotation_subtlety.go deleted file mode 100644 index d1d5a51224..0000000000 --- a/sim/rogue/rotation_subtlety.go +++ /dev/null @@ -1,340 +0,0 @@ -package rogue - -import ( - "log" - "slices" - "time" - - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/core/proto" -) - -type rotation_subtlety struct { - prios []prio - - builder *core.Spell -} - -func (x *rotation_subtlety) setup(sim *core.Simulation, rogue *Rogue) { - x.setSubtletyBuilder(sim, rogue) - - x.prios = x.prios[:0] - - secondsPerComboPoint := func() float64 { - honorAmongThievesChance := []float64{0, 0.33, 0.66, 1.0}[rogue.Talents.HonorAmongThieves] - return 1 + 1/(float64(rogue.Options.HonorOfThievesCritRate+100)/100*honorAmongThievesChance) - } - - comboPointsPerSecond := func() float64 { - return 1 / secondsPerComboPoint() - } - - energyPerSecond := func() float64 { - return 10 * rogue.EnergyTickMultiplier - } - - if rogue.Rotation.OpenWithPremeditation && rogue.Talents.Premeditation && rogue.IsStealthed() { - x.prios = append(x.prios, prio{ - func(s *core.Simulation, r *Rogue) PriorityAction { - if rogue.Premeditation.CanCast(s, r.CurrentTarget) { - return Once - } - return Wait - }, - func(s *core.Simulation, r *Rogue) bool { - return r.Premeditation.Cast(s, r.CurrentTarget) - }, - rogue.Premeditation.DefaultCast.Cost, - }) - } - - if rogue.Rotation.OpenWithShadowstep && rogue.Talents.Shadowstep { - x.prios = append(x.prios, prio{ - func(s *core.Simulation, r *Rogue) PriorityAction { - if rogue.CurrentEnergy() > rogue.Shadowstep.DefaultCast.Cost { - return Once - } - return Wait - }, - func(s *core.Simulation, r *Rogue) bool { - return rogue.Shadowstep.Cast(sim, rogue.CurrentTarget) - }, - rogue.Shadowstep.DefaultCast.Cost, - }) - } - - // Garrote - if rogue.Rotation.OpenWithGarrote && !rogue.PseudoStats.InFrontOfTarget && rogue.IsStealthed() { - x.prios = append(x.prios, prio{ - func(sim *core.Simulation, rogue *Rogue) PriorityAction { - if rogue.CurrentEnergy() > rogue.Garrote.DefaultCast.Cost && rogue.IsStealthed() { - return Once - } - return Wait - }, - func(sim *core.Simulation, rogue *Rogue) bool { - return rogue.Garrote.Cast(sim, rogue.CurrentTarget) - }, - rogue.Garrote.DefaultCast.Cost, - }) - } - - // Slice and Dice - x.prios = append(x.prios, prio{ - func(sim *core.Simulation, rogue *Rogue) PriorityAction { - if rogue.SliceAndDiceAura.IsActive() { - return Skip - } - // end of combat handling - prefer Eviscerate over a mostly wasted SnD - if rogue.ComboPoints() >= 2 && rogue.sliceAndDiceDurations[rogue.ComboPoints()] >= 2*sim.GetRemainingDuration() { - return Skip - } - if rogue.ComboPoints() >= 1 && rogue.CurrentEnergy() > rogue.SliceAndDice.DefaultCast.Cost { - return Cast - } - if rogue.ComboPoints() < 1 && rogue.CurrentEnergy() > x.builder.DefaultCast.Cost && comboPointsPerSecond() >= 0.7 { - return Wait - } - if rogue.ComboPoints() < 1 && rogue.CurrentEnergy() > x.builder.DefaultCast.Cost { - return Build - } - return Wait - }, - func(sim *core.Simulation, rogue *Rogue) bool { - return rogue.SliceAndDice.Cast(sim, rogue.CurrentTarget) - }, - rogue.SliceAndDice.DefaultCast.Cost, - }) - - // Expose armor - if rogue.Rotation.ExposeArmorFrequency == proto.Rogue_Rotation_Once || rogue.Rotation.ExposeArmorFrequency == proto.Rogue_Rotation_Maintain { - hasCastExpose := false - x.prios = append(x.prios, prio{ - func(sim *core.Simulation, rogue *Rogue) PriorityAction { - if hasCastExpose && rogue.Rotation.ExposeArmorFrequency == proto.Rogue_Rotation_Once { - return Skip - } - timeLeft := rogue.ExposeArmorAuras.Get(rogue.CurrentTarget).RemainingDuration(sim) - minPoints := max(1, min(rogue.Rotation.MinimumComboPointsExposeArmor, 5)) - if rogue.Rotation.ExposeArmorFrequency != proto.Rogue_Rotation_Once { - minPoints = 1 - } - if timeLeft <= 0 { - if rogue.ComboPoints() < minPoints { - if rogue.CurrentEnergy() >= x.builder.DefaultCast.Cost && comboPointsPerSecond() < 1 { - return Build - } else { - return Wait - } - } else { - if rogue.CurrentEnergy() >= rogue.ExposeArmor.DefaultCast.Cost { - return Cast - } else { - return Wait - } - } - } else { - energyGained := energyPerSecond() * timeLeft.Seconds() - comboGained := comboPointsPerSecond() * timeLeft.Seconds() - cpGenerated := energyGained/x.builder.DefaultCast.Cost + comboGained - currentCP := float64(rogue.ComboPoints()) - if currentCP+cpGenerated > 5 { - return Skip - } else { - if currentCP < 5 { - if rogue.CurrentEnergy() >= x.builder.DefaultCast.Cost { - return Build - } - } - return Wait - } - } - }, - func(sim *core.Simulation, rogue *Rogue) bool { - casted := rogue.ExposeArmor.Cast(sim, rogue.CurrentTarget) - if casted { - hasCastExpose = true - } - return casted - }, - rogue.ExposeArmor.DefaultCast.Cost, - }) - } - - // Enable CDS - x.prios = append(x.prios, prio{ - func(sim *core.Simulation, rogue *Rogue) PriorityAction { - for _, mcd := range rogue.GetMajorCooldowns() { - mcd.Enable() - } - return Once - }, - func(_ *core.Simulation, _ *Rogue) bool { - return true - }, - 0, - }) - - //Shadowstep - if rogue.Talents.Shadowstep { - x.prios = append(x.prios, prio{ - func(sim *core.Simulation, rogue *Rogue) PriorityAction { - if rogue.Shadowstep.IsReady(sim) { - // Can we cast Rupture now? - if !rogue.Rupture.CurDot().IsActive() && rogue.ComboPoints() >= 5 && rogue.CurrentEnergy() >= rogue.Rupture.DefaultCast.Cost+rogue.Shadowstep.DefaultCast.Cost { - return Cast - } else { - return Skip - } - } - return Skip - }, - func(sim *core.Simulation, rogue *Rogue) bool { - return rogue.Shadowstep.Cast(sim, rogue.CurrentTarget) - }, - rogue.Shadowstep.DefaultCast.Cost, - }) - } - - const ruptureMinDuration = time.Second * 8 // heuristically, 3-4 Rupture ticks are better DPE than Eviscerate or Envenom - - // Rupture - x.prios = append(x.prios, prio{ - func(sim *core.Simulation, rogue *Rogue) PriorityAction { - if rogue.Rupture.CurDot().IsActive() || sim.GetRemainingDuration() < ruptureMinDuration { - return Skip - } - if rogue.ComboPoints() >= 5 && rogue.CurrentEnergy() >= rogue.Rupture.DefaultCast.Cost { - return Cast - } - // don't explicitly wait here, to shorten downtime - if rogue.ComboPoints() < 5 && rogue.CurrentEnergy() >= x.builder.DefaultCast.Cost+rogue.Rupture.DefaultCast.Cost { - return Build - } - return Wait - }, - func(sim *core.Simulation, rogue *Rogue) bool { - return rogue.Rupture.Cast(sim, rogue.CurrentTarget) - }, - rogue.Rupture.DefaultCast.Cost, - }) - - //Envenom - if rogue.Rotation.SubtletyFinisherPriority == proto.Rogue_Rotation_SubtletyEnvenom { - x.prios = append(x.prios, prio{ - func(sim *core.Simulation, rogue *Rogue) PriorityAction { - if !rogue.DeadlyPoison.CurDot().Aura.IsActive() { - return Skip - } - if rogue.EnvenomAura.IsActive() { - return Skip - } - if rogue.ComboPoints() >= 5 && rogue.CurrentEnergy() >= rogue.Envenom.DefaultCast.Cost { - return Cast - } - if rogue.ComboPoints() < 5 && rogue.CurrentEnergy() >= x.builder.DefaultCast.Cost+rogue.Envenom.DefaultCast.Cost { - return Build - } - return Wait - }, - func(sim *core.Simulation, rogue *Rogue) bool { - return rogue.Envenom.Cast(sim, rogue.CurrentTarget) - }, - rogue.Envenom.DefaultCast.Cost, - }) - } - - // Eviscerate - x.prios = append(x.prios, prio{ - func(sim *core.Simulation, rogue *Rogue) PriorityAction { - // end of combat handling - prefer Eviscerate over Builder, heuristically - if sim.GetRemainingDuration().Seconds() < secondsPerComboPoint() && rogue.ComboPoints() >= 2 && rogue.CurrentEnergy() >= rogue.Eviscerate.DefaultCast.Cost { - return Cast - } - if rogue.ComboPoints() >= 5 && rogue.CurrentEnergy() >= rogue.Eviscerate.DefaultCast.Cost { - return Cast - } - if rogue.ComboPoints() < 5 && rogue.CurrentEnergy() >= x.builder.DefaultCast.Cost+rogue.Eviscerate.DefaultCast.Cost { - return Build - } - return Wait - }, - func(sim *core.Simulation, rogue *Rogue) bool { - return rogue.Eviscerate.Cast(sim, rogue.CurrentTarget) - }, - rogue.Eviscerate.DefaultCast.Cost, - }) -} - -func (x *rotation_subtlety) run(sim *core.Simulation, rogue *Rogue) { - for i := 0; i < len(x.prios); i++ { - switch p := x.prios[i]; p.check(sim, rogue) { - case Skip: - continue - case Build: - if rogue.ComboPoints() == 4 && rogue.CurrentEnergy() <= rogue.maxEnergy-10 { - // just wait for HaT proc - if it happens, a finisher will follow and often cost effectively 0 energy, - // so we add another GCD worth of energy headroom - rogue.DoNothing() - return - } - - x.setSubtletyBuilder(sim, rogue) - if !x.builder.Cast(sim, rogue.CurrentTarget) { - rogue.WaitForEnergy(sim, x.builder.DefaultCast.Cost) - return - } - case Cast: - if !p.cast(sim, rogue) { - rogue.WaitForEnergy(sim, p.cost) - return - } - case Once: - if !p.cast(sim, rogue) { - rogue.WaitForEnergy(sim, p.cost) - return - } - x.prios = slices.Delete(x.prios, i, i+1) - i-- - case Wait: - rogue.DoNothing() - return - } - - if !rogue.GCD.IsReady(sim) { - return - } - } - log.Panic("skipped all prios") -} - -func (x *rotation_subtlety) setSubtletyBuilder(sim *core.Simulation, rogue *Rogue) { - // Garrote - if !rogue.Garrote.CurDot().Aura.IsActive() && rogue.IsStealthed() && !rogue.PseudoStats.InFrontOfTarget { - x.builder = rogue.Garrote - return - } - // Ambush - if rogue.IsStealthed() && !rogue.PseudoStats.InFrontOfTarget && rogue.HasDagger(core.MainHand) { - x.builder = rogue.Ambush - return - } - // Backstab - if rogue.Rotation.SubtletyBuilder == proto.Rogue_Rotation_BackstabSub && !rogue.PseudoStats.InFrontOfTarget && rogue.HasDagger(core.MainHand) { - x.builder = rogue.Backstab - return - } - // Ghostly Strike -- should only be considered when glyphed - if rogue.Talents.GhostlyStrike && rogue.Rotation.UseGhostlyStrike && rogue.GhostlyStrike.IsReady(sim) { - x.builder = rogue.GhostlyStrike - return - } - // Hemorrhage - if rogue.Talents.Hemorrhage { - x.builder = rogue.Hemorrhage - return - } - - // Sinister Strike - x.builder = rogue.SinisterStrike -} diff --git a/sim/rogue/talents.go b/sim/rogue/talents.go index e45f63e03e..d2bf6b5479 100644 --- a/sim/rogue/talents.go +++ b/sim/rogue/talents.go @@ -510,12 +510,6 @@ func (rogue *Rogue) registerBladeFlurryCD() { Type: core.CooldownTypeDPS, Priority: core.CooldownPriorityDefault, ShouldActivate: func(sim *core.Simulation, character *core.Character) bool { - - if rogue.Rotation.MultiTargetSliceFrequency == proto.Rogue_Rotation_Never { - // Well let's just cast BF now, no need to optimize around slices that will never be cast - return true - } - if sim.GetRemainingDuration() > cooldownDur+dur { // We'll have enough time to cast another BF, so use it immediately to make sure we get the 2nd one. return true @@ -543,16 +537,10 @@ func (rogue *Rogue) registerAdrenalineRushCD() { OnGain: func(aura *core.Aura, sim *core.Simulation) { rogue.ResetEnergyTick(sim) rogue.ApplyEnergyTickMultiplier(1.0) - if r, ok := rogue.rotation.(*rotation_multi); ok { - r.planRotation(sim, rogue) - } }, OnExpire: func(aura *core.Aura, sim *core.Simulation) { rogue.ResetEnergyTick(sim) rogue.ApplyEnergyTickMultiplier(-1.0) - if r, ok := rogue.rotation.(*rotation_multi); ok { - r.planRotation(sim, rogue) - } }, }) diff --git a/sim/rogue/tricks_of_the_trade.go b/sim/rogue/tricks_of_the_trade.go index 60c87bb983..13116fc0b2 100644 --- a/sim/rogue/tricks_of_the_trade.go +++ b/sim/rogue/tricks_of_the_trade.go @@ -72,20 +72,4 @@ func (rogue *Rogue) registerTricksOfTheTradeSpell() { } }, }) - - if rogue.Rotation.TricksOfTheTradeFrequency != proto.Rogue_Rotation_Never { - // TODO: Support Rogue_Rotation_Once - rogue.AddMajorCooldown(core.MajorCooldown{ - Spell: rogue.TricksOfTheTrade, - Priority: core.CooldownPriorityBloodlust, - Type: core.CooldownTypeDPS, - ShouldActivate: func(sim *core.Simulation, character *core.Character) bool { - if hasShadowblades { - return rogue.CurrentEnergy() <= rogue.maxEnergy-15-rogue.EnergyTickMultiplier*10 - } else { - return true - } - }, - }) - } } diff --git a/sim/rogue/vanish.go b/sim/rogue/vanish.go index a3cc28cfbf..c22f370cbb 100644 --- a/sim/rogue/vanish.go +++ b/sim/rogue/vanish.go @@ -27,38 +27,12 @@ func (rogue *Rogue) registerVanishSpell() { rogue.AutoAttacks.CancelAutoSwing(sim) // Apply stealth rogue.StealthAura.Activate(sim) - - if !rogue.IsUsingAPL { - // Master of Subtlety - if rogue.Talents.MasterOfSubtlety > 0 { - _, premedCPs := checkPremediation(sim, rogue) - _, garroteCPs := checkGarrote(sim, rogue) - - if premedCPs > 0 && rogue.ComboPoints()+premedCPs+garroteCPs <= 5 { - rogue.Premeditation.Cast(sim, target) - } - - if garroteCPs > 0 { - rogue.Garrote.Cast(sim, target) - } - } - - // Break the Stealth effect automatically after a dely with an auto swing - pa := &core.PendingAction{ - NextActionAt: sim.CurrentTime + time.Second * time.Duration(rogue.Options.VanishBreakTime), - Priority: core.ActionPriorityAuto, - } - pa.OnAction = func(sim *core.Simulation) { - rogue.BreakStealth(sim) - rogue.AutoAttacks.EnableAutoSwing(sim) - } - } }, }) rogue.AddMajorCooldown(core.MajorCooldown{ - Spell: rogue.Vanish, - Type: core.CooldownTypeDPS, + Spell: rogue.Vanish, + Type: core.CooldownTypeDPS, Priority: core.CooldownPriorityDrums, ShouldActivate: func(s *core.Simulation, c *core.Character) bool { From c097de661132a1a9947b1c39ba3430a98cc5a057 Mon Sep 17 00:00:00 2001 From: James Tanner Date: Thu, 4 Jan 2024 21:32:32 -0800 Subject: [PATCH 10/28] Finish rogue --- sim/core/debuffs.go | 21 +- sim/mage/TestArcane.results | 4 +- sim/mage/TestFire.results | 8 +- sim/mage/TestFrost.results | 416 +++++------ .../retribution/TestRetribution.results | 664 +++++++++--------- sim/priest/healing/TestDisc.results | 2 +- sim/priest/healing/TestHoly.results | 4 +- sim/priest/shadow/TestShadow.results | 4 +- sim/priest/smite/TestSmite.results | 454 ++++++------ sim/rogue/TestCombat.results | 192 ++--- 10 files changed, 877 insertions(+), 892 deletions(-) diff --git a/sim/core/debuffs.go b/sim/core/debuffs.go index 7242de9ea7..ee7223233e 100644 --- a/sim/core/debuffs.go +++ b/sim/core/debuffs.go @@ -191,24 +191,9 @@ func applyDebuffEffects(target *Unit, targetIdx int, debuffs *proto.Debuffs, rai } func ScheduledMajorArmorAura(aura *Aura, options PeriodicActionOptions, raid *proto.Raid) { - // Individual rogue sim rotation option messes with these debuff options, - // so it has to be handled separately. - allRogues := RaidPlayersWithClass(raid, proto.Class_ClassRogue) - singleExposeDelay := len(allRogues) == 1 && - allRogues[0].Spec.(*proto.Player_Rogue).Rogue.Rotation.ExposeArmorFrequency == proto.Rogue_Rotation_Once - - if singleExposeDelay { - target := aura.Unit - exposeArmorAura := ExposeArmorAura(target, false) - exposeArmorAura.ApplyOnExpire(func(_ *Aura, sim *Simulation) { - aura.Duration = NeverExpires - StartPeriodicAction(sim, options) - }) - } else { - aura.OnReset = func(aura *Aura, sim *Simulation) { - aura.Duration = NeverExpires - StartPeriodicAction(sim, options) - } + aura.OnReset = func(aura *Aura, sim *Simulation) { + aura.Duration = NeverExpires + StartPeriodicAction(sim, options) } } diff --git a/sim/mage/TestArcane.results b/sim/mage/TestArcane.results index 5f0cf2c0be..4a70f5b230 100644 --- a/sim/mage/TestArcane.results +++ b/sim/mage/TestArcane.results @@ -252,8 +252,8 @@ dps_results: { dps_results: { key: "TestArcane-AllItems-EphemeralSnowflake-50260" value: { - dps: 10727.16841 - tps: 6570.11619 + dps: 10738.79708 + tps: 6577.6561 } } dps_results: { diff --git a/sim/mage/TestFire.results b/sim/mage/TestFire.results index b939817bf9..d26760097b 100644 --- a/sim/mage/TestFire.results +++ b/sim/mage/TestFire.results @@ -770,8 +770,8 @@ dps_results: { dps_results: { key: "TestFire-Settings-Troll-p3_fire_alliance-Fire-fire-FullBuffs-LongMultiTarget" value: { - dps: 38064.82304 - tps: 32963.64697 + dps: 38085.36222 + tps: 32980.78258 } } dps_results: { @@ -791,8 +791,8 @@ dps_results: { dps_results: { key: "TestFire-Settings-Troll-p3_fire_alliance-Fire-fire-NoBuffs-LongMultiTarget" value: { - dps: 22173.53497 - tps: 20541.48297 + dps: 22222.81509 + tps: 20575.92958 } } dps_results: { diff --git a/sim/mage/TestFrost.results b/sim/mage/TestFrost.results index cc1f38bac4..dc582270eb 100644 --- a/sim/mage/TestFrost.results +++ b/sim/mage/TestFrost.results @@ -46,277 +46,277 @@ character_stats_results: { dps_results: { key: "TestFrost-AllItems-Althor'sAbacus-50359" value: { - dps: 7933.66277 - tps: 6459.8041 + dps: 7928.24208 + tps: 6453.45112 } } dps_results: { key: "TestFrost-AllItems-Althor'sAbacus-50366" value: { - dps: 7968.21694 - tps: 6488.27328 + dps: 7962.77382 + tps: 6481.89515 } } dps_results: { key: "TestFrost-AllItems-AustereEarthsiegeDiamond" value: { - dps: 7765.31653 - tps: 6324.30567 + dps: 7760.1538 + tps: 6318.09095 } } dps_results: { key: "TestFrost-AllItems-Bandit'sInsignia-40371" value: { - dps: 7652.51748 - tps: 6228.1685 + dps: 7647.27929 + tps: 6222.02013 } } dps_results: { key: "TestFrost-AllItems-BaubleofTrueBlood-50354" value: { - dps: 7652.00052 - tps: 6227.57151 - hps: 92.573 + dps: 7646.41564 + tps: 6221.07535 + hps: 92.57675 } } dps_results: { key: "TestFrost-AllItems-BaubleofTrueBlood-50726" value: { - dps: 7652.00052 - tps: 6227.57151 - hps: 92.573 + dps: 7646.41564 + tps: 6221.07535 + hps: 92.57675 } } dps_results: { key: "TestFrost-AllItems-BeamingEarthsiegeDiamond" value: { - dps: 7783.7779 - tps: 6341.22794 + dps: 7782.85819 + tps: 6339.33425 } } dps_results: { key: "TestFrost-AllItems-BlessedRegaliaofUndeadCleansing" value: { - dps: 6024.87702 - tps: 4845.65031 + dps: 6005.44274 + tps: 4826.77708 } } dps_results: { key: "TestFrost-AllItems-Bloodmage'sRegalia" value: { - dps: 8140.05763 - tps: 6685.8876 + dps: 8143.08775 + tps: 6688.26693 } } dps_results: { key: "TestFrost-AllItems-BracingEarthsiegeDiamond" value: { - dps: 7803.91273 - tps: 6229.21586 + dps: 7798.72055 + tps: 6223.09271 } } dps_results: { key: "TestFrost-AllItems-ChaoticSkyflareDiamond" value: { - dps: 8004.42685 - tps: 6540.31281 + dps: 8003.40047 + tps: 6538.31272 } } dps_results: { key: "TestFrost-AllItems-CorpseTongueCoin-50349" value: { - dps: 7652.51748 - tps: 6228.1685 + dps: 7647.27929 + tps: 6222.02013 } } dps_results: { key: "TestFrost-AllItems-CorpseTongueCoin-50352" value: { - dps: 7652.51748 - tps: 6228.1685 + dps: 7647.27929 + tps: 6222.02013 } } dps_results: { key: "TestFrost-AllItems-CorrodedSkeletonKey-50356" value: { - dps: 7652.51748 - tps: 6228.1685 + dps: 7647.27929 + tps: 6222.02013 hps: 64 } } dps_results: { key: "TestFrost-AllItems-DarkmoonCard:Berserker!-42989" value: { - dps: 7727.10393 - tps: 6294.20537 + dps: 7721.01592 + tps: 6287.16324 } } dps_results: { key: "TestFrost-AllItems-DarkmoonCard:Death-42990" value: { - dps: 7734.47564 - tps: 6306.31917 + dps: 7731.37855 + tps: 6303.73706 } } dps_results: { key: "TestFrost-AllItems-DarkmoonCard:Greatness-44255" value: { - dps: 7690.85322 - tps: 6274.32423 + dps: 7684.58603 + tps: 6266.86577 } } dps_results: { key: "TestFrost-AllItems-Death'sChoice-47464" value: { - dps: 7652.51748 - tps: 6228.1685 + dps: 7647.27929 + tps: 6222.02013 } } dps_results: { key: "TestFrost-AllItems-DeathKnight'sAnguish-38212" value: { - dps: 7685.02105 - tps: 6253.78087 + dps: 7678.84495 + tps: 6246.81867 } } dps_results: { key: "TestFrost-AllItems-Deathbringer'sWill-50362" value: { - dps: 7652.51748 - tps: 6228.1685 + dps: 7647.27929 + tps: 6222.02013 } } dps_results: { key: "TestFrost-AllItems-Deathbringer'sWill-50363" value: { - dps: 7652.51748 - tps: 6228.1685 + dps: 7647.27929 + tps: 6222.02013 } } dps_results: { key: "TestFrost-AllItems-Defender'sCode-40257" value: { - dps: 7652.51748 - tps: 6228.1685 + dps: 7647.27929 + tps: 6222.02013 } } dps_results: { key: "TestFrost-AllItems-DestructiveSkyflareDiamond" value: { - dps: 7784.47384 - tps: 6342.56315 + dps: 7783.55414 + tps: 6340.66928 } } dps_results: { key: "TestFrost-AllItems-DislodgedForeignObject-50348" value: { - dps: 8384.30782 - tps: 6875.40602 + dps: 8381.41843 + tps: 6873.3235 } } dps_results: { key: "TestFrost-AllItems-DislodgedForeignObject-50353" value: { - dps: 8289.8124 - tps: 6783.32805 + dps: 8297.80523 + tps: 6789.83899 } } dps_results: { key: "TestFrost-AllItems-EffulgentSkyflareDiamond" value: { - dps: 7765.31653 - tps: 6324.30567 + dps: 7760.1538 + tps: 6318.09095 } } dps_results: { key: "TestFrost-AllItems-EmberSkyflareDiamond" value: { - dps: 7813.94105 - tps: 6365.39795 + dps: 7812.27004 + tps: 6362.69935 } } dps_results: { key: "TestFrost-AllItems-EnigmaticSkyflareDiamond" value: { - dps: 7783.81326 - tps: 6341.9621 + dps: 7782.89356 + tps: 6340.06823 } } dps_results: { key: "TestFrost-AllItems-EnigmaticStarflareDiamond" value: { - dps: 7778.77525 - tps: 6337.46563 + dps: 7777.85554 + tps: 6335.57176 } } dps_results: { key: "TestFrost-AllItems-EphemeralSnowflake-50260" value: { - dps: 7755.40406 - tps: 6315.42295 + dps: 7759.64948 + tps: 6319.89085 } } dps_results: { key: "TestFrost-AllItems-EssenceofGossamer-37220" value: { - dps: 7652.51748 - tps: 6228.1685 + dps: 7647.27929 + tps: 6222.02013 } } dps_results: { key: "TestFrost-AllItems-EternalEarthsiegeDiamond" value: { - dps: 7765.31653 - tps: 6324.30567 + dps: 7760.1538 + tps: 6318.09095 } } dps_results: { key: "TestFrost-AllItems-ExtractofNecromanticPower-40373" value: { - dps: 7727.1541 - tps: 6295.38387 + dps: 7723.41199 + tps: 6291.61522 } } dps_results: { key: "TestFrost-AllItems-EyeoftheBroodmother-45308" value: { - dps: 7913.07517 - tps: 6459.71001 + dps: 7906.80366 + tps: 6452.50593 } } dps_results: { key: "TestFrost-AllItems-Figurine-SapphireOwl-42413" value: { - dps: 7673.31368 - tps: 6245.89566 + dps: 7668.23295 + tps: 6239.78194 } } dps_results: { key: "TestFrost-AllItems-ForethoughtTalisman-40258" value: { - dps: 7826.85897 - tps: 6371.80846 + dps: 7821.50761 + tps: 6365.5332 } } dps_results: { key: "TestFrost-AllItems-ForgeEmber-37660" value: { - dps: 7831.62918 - tps: 6382.78835 + dps: 7824.55194 + tps: 6374.99683 } } dps_results: { key: "TestFrost-AllItems-ForlornSkyflareDiamond" value: { - dps: 7803.91273 - tps: 6356.04504 + dps: 7798.72055 + tps: 6349.7974 } } dps_results: { key: "TestFrost-AllItems-ForlornStarflareDiamond" value: { - dps: 7796.19349 - tps: 6349.69717 + dps: 7791.0072 + tps: 6343.45611 } } dps_results: { @@ -329,15 +329,15 @@ dps_results: { dps_results: { key: "TestFrost-AllItems-FuryoftheFiveFlights-40431" value: { - dps: 7652.51748 - tps: 6228.1685 + dps: 7647.27929 + tps: 6222.02013 } } dps_results: { key: "TestFrost-AllItems-FuturesightRune-38763" value: { - dps: 7750.19737 - tps: 6307.40657 + dps: 7744.89597 + tps: 6301.18733 } } dps_results: { @@ -350,85 +350,85 @@ dps_results: { dps_results: { key: "TestFrost-AllItems-GlowingTwilightScale-54573" value: { - dps: 7950.93986 - tps: 6474.03869 + dps: 7945.50795 + tps: 6467.67314 } } dps_results: { key: "TestFrost-AllItems-GlowingTwilightScale-54589" value: { - dps: 7990.20596 - tps: 6506.39003 + dps: 7984.74857 + tps: 6499.9959 } } dps_results: { key: "TestFrost-AllItems-GnomishLightningGenerator-41121" value: { - dps: 7712.63873 - tps: 6291.8092 + dps: 7726.20314 + tps: 6306.13936 } } dps_results: { key: "TestFrost-AllItems-Heartpierce-49982" value: { - dps: 8004.42685 - tps: 6540.31281 + dps: 8003.40047 + tps: 6538.31272 } } dps_results: { key: "TestFrost-AllItems-Heartpierce-50641" value: { - dps: 8004.42685 - tps: 6540.31281 + dps: 8003.40047 + tps: 6538.31272 } } dps_results: { key: "TestFrost-AllItems-IllustrationoftheDragonSoul-40432" value: { - dps: 7936.00618 - tps: 6480.54928 + dps: 7930.51116 + tps: 6474.17485 } } dps_results: { key: "TestFrost-AllItems-ImpassiveSkyflareDiamond" value: { - dps: 7783.81326 - tps: 6341.9621 + dps: 7782.89356 + tps: 6340.06823 } } dps_results: { key: "TestFrost-AllItems-ImpassiveStarflareDiamond" value: { - dps: 7778.77525 - tps: 6337.46563 + dps: 7777.85554 + tps: 6335.57176 } } dps_results: { key: "TestFrost-AllItems-IncisorFragment-37723" value: { - dps: 7652.51748 - tps: 6228.1685 + dps: 7647.27929 + tps: 6222.02013 } } dps_results: { key: "TestFrost-AllItems-InsightfulEarthsiegeDiamond" value: { - dps: 7774.27285 - tps: 6336.45718 + dps: 7772.45693 + tps: 6333.79039 } } dps_results: { key: "TestFrost-AllItems-InvigoratingEarthsiegeDiamond" value: { - dps: 7765.31653 - tps: 6324.30567 + dps: 7760.1538 + tps: 6318.09095 } } dps_results: { key: "TestFrost-AllItems-Khadgar'sRegalia" value: { - dps: 6575.79129 - tps: 5306.49837 + dps: 6580.00377 + tps: 5309.1505 } } dps_results: { @@ -441,239 +441,239 @@ dps_results: { dps_results: { key: "TestFrost-AllItems-Lavanthor'sTalisman-37872" value: { - dps: 7652.51748 - tps: 6228.1685 + dps: 7647.27929 + tps: 6222.02013 } } dps_results: { key: "TestFrost-AllItems-MajesticDragonFigurine-40430" value: { - dps: 7652.83765 - tps: 6225.62283 + dps: 7647.59946 + tps: 6219.47581 } } dps_results: { key: "TestFrost-AllItems-MeteoriteWhetstone-37390" value: { - dps: 7698.15546 - tps: 6263.90226 + dps: 7691.79354 + tps: 6256.75774 } } dps_results: { key: "TestFrost-AllItems-NevermeltingIceCrystal-50259" value: { - dps: 7848.80614 - tps: 6384.95591 + dps: 7847.31458 + tps: 6384.09669 } } dps_results: { key: "TestFrost-AllItems-Nibelung-49992" value: { - dps: 8004.42685 - tps: 6540.31281 + dps: 8003.40047 + tps: 6538.31272 } } dps_results: { key: "TestFrost-AllItems-Nibelung-50648" value: { - dps: 8004.42685 - tps: 6540.31281 + dps: 8003.40047 + tps: 6538.31272 } } dps_results: { key: "TestFrost-AllItems-OfferingofSacrifice-37638" value: { - dps: 7652.51748 - tps: 6228.1685 + dps: 7647.27929 + tps: 6222.02013 } } dps_results: { key: "TestFrost-AllItems-PersistentEarthshatterDiamond" value: { - dps: 7765.31653 - tps: 6324.30567 + dps: 7760.1538 + tps: 6318.09095 } } dps_results: { key: "TestFrost-AllItems-PersistentEarthsiegeDiamond" value: { - dps: 7765.31653 - tps: 6324.30567 + dps: 7760.1538 + tps: 6318.09095 } } dps_results: { key: "TestFrost-AllItems-PetrifiedScarab-21685" value: { - dps: 7651.50716 - tps: 6227.25922 + dps: 7646.26897 + tps: 6221.11085 } } dps_results: { key: "TestFrost-AllItems-PetrifiedTwilightScale-54571" value: { - dps: 7652.51748 - tps: 6228.1685 + dps: 7647.27929 + tps: 6222.02013 } } dps_results: { key: "TestFrost-AllItems-PetrifiedTwilightScale-54591" value: { - dps: 7652.51748 - tps: 6228.1685 + dps: 7647.27929 + tps: 6222.02013 } } dps_results: { key: "TestFrost-AllItems-PowerfulEarthshatterDiamond" value: { - dps: 7765.31653 - tps: 6324.30567 + dps: 7760.1538 + tps: 6318.09095 } } dps_results: { key: "TestFrost-AllItems-PowerfulEarthsiegeDiamond" value: { - dps: 7765.31653 - tps: 6324.30567 + dps: 7760.1538 + tps: 6318.09095 } } dps_results: { key: "TestFrost-AllItems-PurifiedShardoftheGods" value: { - dps: 7652.51748 - tps: 6228.1685 + dps: 7647.27929 + tps: 6222.02013 } } dps_results: { key: "TestFrost-AllItems-ReignoftheDead-47316" value: { - dps: 7998.48484 - tps: 6538.10806 + dps: 7998.96913 + tps: 6538.92968 } } dps_results: { key: "TestFrost-AllItems-ReignoftheDead-47477" value: { - dps: 8047.7877 - tps: 6582.45344 + dps: 8048.33749 + tps: 6583.34161 } } dps_results: { key: "TestFrost-AllItems-RelentlessEarthsiegeDiamond" value: { - dps: 7984.09185 - tps: 6521.00509 + dps: 7978.38291 + tps: 6514.28941 } } dps_results: { key: "TestFrost-AllItems-RevitalizingSkyflareDiamond" value: { - dps: 7765.2869 - tps: 6323.1634 + dps: 7760.12417 + tps: 6316.94905 } } dps_results: { key: "TestFrost-AllItems-RuneofRepulsion-40372" value: { - dps: 7652.51748 - tps: 6228.1685 + dps: 7647.27929 + tps: 6222.02013 } } dps_results: { key: "TestFrost-AllItems-SealofthePantheon-36993" value: { - dps: 7652.51748 - tps: 6228.1685 + dps: 7647.27929 + tps: 6222.02013 } } dps_results: { key: "TestFrost-AllItems-ShinyShardoftheGods" value: { - dps: 7652.51748 - tps: 6228.1685 + dps: 7647.27929 + tps: 6222.02013 } } dps_results: { key: "TestFrost-AllItems-Sindragosa'sFlawlessFang-50361" value: { - dps: 7652.51748 - tps: 6228.1685 + dps: 7647.27929 + tps: 6222.02013 } } dps_results: { key: "TestFrost-AllItems-SliverofPureIce-50339" value: { - dps: 7900.7323 - tps: 6435.45003 + dps: 7895.33302 + tps: 6429.12257 } } dps_results: { key: "TestFrost-AllItems-SliverofPureIce-50346" value: { - dps: 7932.14518 - tps: 6461.58463 + dps: 7926.72551 + tps: 6455.23432 } } dps_results: { key: "TestFrost-AllItems-SoulPreserver-37111" value: { - dps: 7770.31579 - tps: 6325.22253 + dps: 7765.00113 + tps: 6318.98842 } } dps_results: { key: "TestFrost-AllItems-SouloftheDead-40382" value: { - dps: 7725.7366 - tps: 6296.32776 + dps: 7719.6486 + tps: 6289.29418 } } dps_results: { key: "TestFrost-AllItems-SparkofLife-37657" value: { - dps: 7757.64893 - tps: 6327.51453 + dps: 7755.89541 + tps: 6324.01321 } } dps_results: { key: "TestFrost-AllItems-SphereofRedDragon'sBlood-37166" value: { - dps: 7696.99765 - tps: 6273.70353 + dps: 7706.01629 + tps: 6281.8047 } } dps_results: { key: "TestFrost-AllItems-SwiftSkyflareDiamond" value: { - dps: 7765.31653 - tps: 6324.30567 + dps: 7760.1538 + tps: 6318.09095 } } dps_results: { key: "TestFrost-AllItems-SwiftStarflareDiamond" value: { - dps: 7765.31653 - tps: 6324.30567 + dps: 7760.1538 + tps: 6318.09095 } } dps_results: { key: "TestFrost-AllItems-SwiftWindfireDiamond" value: { - dps: 7765.31653 - tps: 6324.30567 + dps: 7760.1538 + tps: 6318.09095 } } dps_results: { key: "TestFrost-AllItems-TalismanofTrollDivinity-37734" value: { - dps: 7652.81744 - tps: 6226.83399 + dps: 7647.57925 + tps: 6220.68724 } } dps_results: { key: "TestFrost-AllItems-TearsoftheVanquished-47215" value: { - dps: 7691.42109 - tps: 6261.64718 + dps: 7686.34035 + tps: 6255.4996 } } dps_results: { @@ -686,106 +686,106 @@ dps_results: { dps_results: { key: "TestFrost-AllItems-TheGeneral'sHeart-45507" value: { - dps: 7652.51748 - tps: 6228.1685 + dps: 7647.27929 + tps: 6222.02013 } } dps_results: { key: "TestFrost-AllItems-TheTwinBladesofAzzinoth" value: { - dps: 6372.08189 - tps: 5180.43316 + dps: 6369.89154 + tps: 5180.72909 } } dps_results: { key: "TestFrost-AllItems-ThunderingSkyflareDiamond" value: { - dps: 7765.31653 - tps: 6324.30567 + dps: 7760.1538 + tps: 6318.09095 } } dps_results: { key: "TestFrost-AllItems-TinyAbominationinaJar-50351" value: { - dps: 7696.99765 - tps: 6273.70353 + dps: 7706.01629 + tps: 6281.8047 } } dps_results: { key: "TestFrost-AllItems-TinyAbominationinaJar-50706" value: { - dps: 7696.99765 - tps: 6273.70353 + dps: 7706.01629 + tps: 6281.8047 } } dps_results: { key: "TestFrost-AllItems-TirelessSkyflareDiamond" value: { - dps: 7803.91273 - tps: 6356.04504 + dps: 7798.72055 + tps: 6349.7974 } } dps_results: { key: "TestFrost-AllItems-TirelessStarflareDiamond" value: { - dps: 7796.19349 - tps: 6349.69717 + dps: 7791.0072 + tps: 6343.45611 } } dps_results: { key: "TestFrost-AllItems-TomeofArcanePhenomena-36972" value: { - dps: 7779.60815 - tps: 6327.85299 + dps: 7784.88807 + tps: 6332.07288 } } dps_results: { key: "TestFrost-AllItems-TrenchantEarthshatterDiamond" value: { - dps: 7796.19349 - tps: 6349.69717 + dps: 7791.0072 + tps: 6343.45611 } } dps_results: { key: "TestFrost-AllItems-TrenchantEarthsiegeDiamond" value: { - dps: 7803.91273 - tps: 6356.04504 + dps: 7798.72055 + tps: 6349.7974 } } dps_results: { key: "TestFrost-AllItems-WingedTalisman-37844" value: { - dps: 7755.11162 - tps: 6320.25051 + dps: 7749.91677 + tps: 6314.13796 } } dps_results: { key: "TestFrost-Average-Default" value: { - dps: 8088.78057 - tps: 6620.05808 + dps: 8088.27706 + tps: 6619.63625 } } dps_results: { key: "TestFrost-Settings-Troll-p3_frost_alliance-Frost-frost-FullBuffs-LongMultiTarget" value: { - dps: 8004.42685 - tps: 6818.27786 + dps: 8003.40047 + tps: 6815.93838 } } dps_results: { key: "TestFrost-Settings-Troll-p3_frost_alliance-Frost-frost-FullBuffs-LongSingleTarget" value: { - dps: 8004.42685 - tps: 6540.31281 + dps: 8003.40047 + tps: 6538.31272 } } dps_results: { key: "TestFrost-Settings-Troll-p3_frost_alliance-Frost-frost-FullBuffs-ShortSingleTarget" value: { - dps: 10047.18185 - tps: 8250.71555 + dps: 10069.72226 + tps: 8272.31852 } } dps_results: { @@ -848,7 +848,7 @@ dps_results: { dps_results: { key: "TestFrost-SwitchInFrontOfTarget-Default" value: { - dps: 8004.42685 - tps: 6540.31281 + dps: 8003.40047 + tps: 6538.31272 } } diff --git a/sim/paladin/retribution/TestRetribution.results b/sim/paladin/retribution/TestRetribution.results index 80ffc5e518..f2a5eba241 100644 --- a/sim/paladin/retribution/TestRetribution.results +++ b/sim/paladin/retribution/TestRetribution.results @@ -46,8 +46,8 @@ character_stats_results: { dps_results: { key: "TestRetribution-AllItems-AegisBattlegear" value: { - dps: 6268.37146 - tps: 6353.83098 + dps: 6267.52464 + tps: 6352.98416 dtps: 9.92959 } } @@ -62,48 +62,48 @@ dps_results: { dps_results: { key: "TestRetribution-AllItems-Althor'sAbacus-50359" value: { - dps: 6465.57257 - tps: 6551.05699 + dps: 6465.71452 + tps: 6551.19894 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-Althor'sAbacus-50366" value: { - dps: 6471.12751 - tps: 6556.61193 + dps: 6471.26908 + tps: 6556.75349 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-AshtongueTalismanofZeal-32489" value: { - dps: 6468.86887 - tps: 6554.34976 + dps: 6469.44227 + tps: 6554.92317 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-AustereEarthsiegeDiamond" value: { - dps: 6530.15775 - tps: 6615.64217 + dps: 6530.10682 + tps: 6615.59123 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-Bandit'sInsignia-40371" value: { - dps: 6628.55546 - tps: 6713.89718 + dps: 6628.55432 + tps: 6713.89603 dtps: 10.03858 } } dps_results: { key: "TestRetribution-AllItems-BaubleofTrueBlood-50354" value: { - dps: 6420.11322 - tps: 6505.59764 + dps: 6420.2583 + tps: 6505.74271 dtps: 9.48456 hps: 94.7032 } @@ -111,8 +111,8 @@ dps_results: { dps_results: { key: "TestRetribution-AllItems-BaubleofTrueBlood-50726" value: { - dps: 6420.11322 - tps: 6505.59764 + dps: 6420.2583 + tps: 6505.74271 dtps: 9.48456 hps: 94.7032 } @@ -120,96 +120,96 @@ dps_results: { dps_results: { key: "TestRetribution-AllItems-BeamingEarthsiegeDiamond" value: { - dps: 6544.91075 - tps: 6630.33528 + dps: 6545.05403 + tps: 6630.47856 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-Beast-tamer'sShoulders-30892" value: { - dps: 6398.97549 - tps: 6484.17274 + dps: 6399.15708 + tps: 6484.35433 dtps: 9.23882 } } dps_results: { key: "TestRetribution-AllItems-BlessedBattlegearofUndeadSlaying" value: { - dps: 5408.7184 - tps: 5491.96468 + dps: 5408.57284 + tps: 5491.81912 dtps: 9.23882 } } dps_results: { key: "TestRetribution-AllItems-BlessedGarboftheUndeadSlayer" value: { - dps: 5352.69147 - tps: 5435.99401 + dps: 5352.64254 + tps: 5435.94508 dtps: 9.23882 } } dps_results: { key: "TestRetribution-AllItems-BlessedRegaliaofUndeadCleansing" value: { - dps: 5184.95794 - tps: 5268.18041 + dps: 5184.81786 + tps: 5268.04033 dtps: 9.23882 } } dps_results: { key: "TestRetribution-AllItems-BracingEarthsiegeDiamond" value: { - dps: 6536.35928 - tps: 6491.11652 + dps: 6536.30717 + tps: 6491.06544 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-Bryntroll,theBoneArbiter-50415" value: { - dps: 6999.49261 - tps: 7084.97703 + dps: 6999.6297 + tps: 7085.11412 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-Bryntroll,theBoneArbiter-50709" value: { - dps: 7031.30525 - tps: 7116.78967 + dps: 7031.44182 + tps: 7116.92623 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-ChaoticSkyflareDiamond" value: { - dps: 6663.47166 - tps: 6748.95608 + dps: 6663.61419 + tps: 6749.09861 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-CorpseTongueCoin-50349" value: { - dps: 6420.37555 - tps: 6505.85997 + dps: 6420.52064 + tps: 6506.00506 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-CorpseTongueCoin-50352" value: { - dps: 6420.37555 - tps: 6505.85997 + dps: 6420.52064 + tps: 6506.00506 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-CorrodedSkeletonKey-50356" value: { - dps: 6420.37555 - tps: 6505.85997 + dps: 6420.52064 + tps: 6506.00506 dtps: 9.92959 hps: 64 } @@ -217,216 +217,216 @@ dps_results: { dps_results: { key: "TestRetribution-AllItems-DarkmoonCard:Berserker!-42989" value: { - dps: 6518.45383 - tps: 6603.93825 + dps: 6518.42139 + tps: 6603.90581 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-DarkmoonCard:Death-42990" value: { - dps: 6568.11706 - tps: 6653.46885 + dps: 6568.56742 + tps: 6653.91921 dtps: 9.77043 } } dps_results: { key: "TestRetribution-AllItems-DarkmoonCard:Greatness-44255" value: { - dps: 6420.37555 - tps: 6505.33665 + dps: 6420.52064 + tps: 6505.48174 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-Death'sChoice-47464" value: { - dps: 7001.45475 - tps: 7086.93917 + dps: 7001.57473 + tps: 7087.05915 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-DeathKnight'sAnguish-38212" value: { - dps: 6484.37787 - tps: 6569.86229 + dps: 6484.24836 + tps: 6569.73278 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-Deathbringer'sWill-50362" value: { - dps: 6754.79378 - tps: 6840.44585 + dps: 6755.26996 + tps: 6840.92204 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-Deathbringer'sWill-50363" value: { - dps: 6801.15779 - tps: 6886.7823 + dps: 6800.03362 + tps: 6885.65813 dtps: 10.29273 } } dps_results: { key: "TestRetribution-AllItems-Defender'sCode-40257" value: { - dps: 6420.37555 - tps: 6505.85997 + dps: 6420.52064 + tps: 6506.00506 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-DestructiveSkyflareDiamond" value: { - dps: 6547.8397 - tps: 6633.32412 + dps: 6547.98298 + tps: 6633.4674 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-DislodgedForeignObject-50348" value: { - dps: 6640.22126 - tps: 6726.41689 + dps: 6641.1179 + tps: 6727.31352 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-DislodgedForeignObject-50353" value: { - dps: 6607.8895 - tps: 6693.70378 + dps: 6609.03015 + tps: 6694.84443 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-EffulgentSkyflareDiamond" value: { - dps: 6530.15775 - tps: 6615.64217 + dps: 6530.10682 + tps: 6615.59123 dtps: 9.731 } } dps_results: { key: "TestRetribution-AllItems-EmberSkyflareDiamond" value: { - dps: 6536.35928 - tps: 6621.8142 + dps: 6536.30717 + tps: 6621.76208 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-EnigmaticSkyflareDiamond" value: { - dps: 6544.91075 - tps: 6630.39516 + dps: 6545.05403 + tps: 6630.53844 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-EnigmaticStarflareDiamond" value: { - dps: 6541.49838 - tps: 6626.98279 + dps: 6541.64166 + tps: 6627.12607 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-EphemeralSnowflake-50260" value: { - dps: 6540.37893 - tps: 6626.39435 + dps: 6540.15806 + tps: 6626.17348 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-EssenceofGossamer-37220" value: { - dps: 6420.37555 - tps: 6505.85997 + dps: 6420.52064 + tps: 6506.00506 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-EternalEarthsiegeDiamond" value: { - dps: 6530.15775 - tps: 6615.64217 + dps: 6530.10682 + tps: 6615.59123 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-ExtractofNecromanticPower-40373" value: { - dps: 6576.99883 - tps: 6662.50294 + dps: 6577.62612 + tps: 6663.13023 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-EyeoftheBroodmother-45308" value: { - dps: 6541.10959 - tps: 6626.59401 + dps: 6541.07166 + tps: 6626.55608 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-Figurine-SapphireOwl-42413" value: { - dps: 6420.37555 - tps: 6505.7242 + dps: 6420.52064 + tps: 6505.86929 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-ForethoughtTalisman-40258" value: { - dps: 6448.40275 - tps: 6533.88717 + dps: 6448.5459 + tps: 6534.03031 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-ForgeEmber-37660" value: { - dps: 6500.39038 - tps: 6585.8748 + dps: 6500.35794 + tps: 6585.84236 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-ForlornSkyflareDiamond" value: { - dps: 6536.35928 - tps: 6621.8437 + dps: 6536.30717 + tps: 6621.79159 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-ForlornStarflareDiamond" value: { - dps: 6535.11898 - tps: 6620.6034 + dps: 6535.0671 + tps: 6620.55151 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-FuriousGladiator'sLibramofFortitude-42853" value: { - dps: 6682.2126 - tps: 6767.69702 + dps: 6682.35485 + tps: 6767.83927 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-FuturesightRune-38763" value: { - dps: 6436.03038 - tps: 6521.5148 + dps: 6436.17439 + tps: 6521.65881 dtps: 9.92959 } } @@ -441,80 +441,80 @@ dps_results: { dps_results: { key: "TestRetribution-AllItems-GlowingTwilightScale-54573" value: { - dps: 6468.35004 - tps: 6553.83446 + dps: 6468.4918 + tps: 6553.97622 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-GlowingTwilightScale-54589" value: { - dps: 6474.66247 - tps: 6560.14689 + dps: 6474.80379 + tps: 6560.28821 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-GnomishLightningGenerator-41121" value: { - dps: 6540.91693 - tps: 6626.22985 + dps: 6541.36776 + tps: 6626.68068 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-HatefulGladiator'sLibramofFortitude-42851" value: { - dps: 6651.70785 - tps: 6737.19227 + dps: 6651.85055 + tps: 6737.33497 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-IllustrationoftheDragonSoul-40432" value: { - dps: 6431.2686 - tps: 6516.75301 + dps: 6431.41229 + tps: 6516.89671 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-ImpassiveSkyflareDiamond" value: { - dps: 6544.91075 - tps: 6630.39516 + dps: 6545.05403 + tps: 6630.53844 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-ImpassiveStarflareDiamond" value: { - dps: 6541.49838 - tps: 6626.98279 + dps: 6541.64166 + tps: 6627.12607 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-IncisorFragment-37723" value: { - dps: 6584.63506 - tps: 6670.11948 + dps: 6584.77153 + tps: 6670.25595 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-InsightfulEarthsiegeDiamond" value: { - dps: 6530.15775 - tps: 6617.24615 + dps: 6530.10682 + tps: 6617.19522 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-InvigoratingEarthsiegeDiamond" value: { - dps: 6562.45389 - tps: 6647.93831 + dps: 6562.40098 + tps: 6647.8854 dtps: 9.92959 hps: 12.10749 } @@ -522,72 +522,72 @@ dps_results: { dps_results: { key: "TestRetribution-AllItems-LastWord-50179" value: { - dps: 6861.95405 - tps: 6947.43847 + dps: 6862.09336 + tps: 6947.57778 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-LastWord-50708" value: { - dps: 6891.5707 - tps: 6977.05512 + dps: 6891.70956 + tps: 6977.19398 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-Lavanthor'sTalisman-37872" value: { - dps: 6420.37555 - tps: 6505.85997 + dps: 6420.52064 + tps: 6506.00506 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-LibramofFuriousBlows-37574" value: { - dps: 6594.19122 - tps: 6679.67564 + dps: 6594.26071 + tps: 6679.74513 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-LibramofObstruction-40707" value: { - dps: 6569.76696 - tps: 6655.25138 + dps: 6569.9109 + tps: 6655.39532 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-LibramofReciprocation-40706" value: { - dps: 6569.76696 - tps: 6655.25138 + dps: 6569.9109 + tps: 6655.39532 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-LibramofThreeTruths-50455" value: { - dps: 6988.96862 - tps: 7074.45304 + dps: 6989.10988 + tps: 7074.5943 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-LibramofValiance-47661" value: { - dps: 6956.365 - tps: 7041.84942 + dps: 6956.32355 + tps: 7041.80797 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-LibramoftheSacredShield-45145" value: { - dps: 6569.76696 - tps: 6655.25138 + dps: 6569.9109 + tps: 6655.39532 dtps: 9.92959 } } @@ -602,8 +602,8 @@ dps_results: { dps_results: { key: "TestRetribution-AllItems-LightswornBattlegear" value: { - dps: 7650.81686 - tps: 7738.32677 + dps: 7652.37702 + tps: 7739.88693 dtps: 9.92959 } } @@ -618,104 +618,104 @@ dps_results: { dps_results: { key: "TestRetribution-AllItems-MajesticDragonFigurine-40430" value: { - dps: 6420.37555 - tps: 6505.85997 + dps: 6420.52064 + tps: 6506.00506 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-MeteoriteWhetstone-37390" value: { - dps: 6553.90912 - tps: 6639.78002 + dps: 6554.05506 + tps: 6639.92597 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-NevermeltingIceCrystal-50259" value: { - dps: 6479.55694 - tps: 6565.04136 + dps: 6479.3976 + tps: 6564.88202 dtps: 10.29273 } } dps_results: { key: "TestRetribution-AllItems-OfferingofSacrifice-37638" value: { - dps: 6420.37555 - tps: 6505.85997 + dps: 6420.52064 + tps: 6506.00506 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-PersistentEarthshatterDiamond" value: { - dps: 6556.35971 - tps: 6641.84413 + dps: 6556.3074 + tps: 6641.79181 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-PersistentEarthsiegeDiamond" value: { - dps: 6562.52488 - tps: 6648.0093 + dps: 6562.47224 + tps: 6647.95666 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-PetrifiedScarab-21685" value: { - dps: 6420.37555 - tps: 6505.85997 + dps: 6420.52064 + tps: 6506.00506 dtps: 8.19524 } } dps_results: { key: "TestRetribution-AllItems-PetrifiedTwilightScale-54571" value: { - dps: 6420.37555 - tps: 6505.85997 + dps: 6420.52064 + tps: 6506.00506 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-PetrifiedTwilightScale-54591" value: { - dps: 6420.37555 - tps: 6505.85997 + dps: 6420.52064 + tps: 6506.00506 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-PowerfulEarthshatterDiamond" value: { - dps: 6530.15775 - tps: 6615.64217 + dps: 6530.10682 + tps: 6615.59123 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-PowerfulEarthsiegeDiamond" value: { - dps: 6530.15775 - tps: 6615.64217 + dps: 6530.10682 + tps: 6615.59123 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-PurifiedShardoftheGods" value: { - dps: 6420.37555 - tps: 6505.85997 + dps: 6420.52064 + tps: 6506.00506 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-RedemptionBattlegear" value: { - dps: 5847.28087 - tps: 5936.60002 + dps: 5847.91647 + tps: 5937.23562 dtps: 9.23882 } } @@ -730,136 +730,136 @@ dps_results: { dps_results: { key: "TestRetribution-AllItems-ReignoftheDead-47316" value: { - dps: 6683.04766 - tps: 6768.56404 + dps: 6682.32469 + tps: 6767.84107 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-ReignoftheDead-47477" value: { - dps: 6716.19926 - tps: 6801.71564 + dps: 6715.46847 + tps: 6800.98485 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-RelentlessEarthsiegeDiamond" value: { - dps: 6663.47166 - tps: 6748.95608 + dps: 6663.61419 + tps: 6749.09861 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-RelentlessGladiator'sLibramofFortitude-42854" value: { - dps: 6704.07703 - tps: 6789.56145 + dps: 6704.21895 + tps: 6789.70337 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-RevitalizingSkyflareDiamond" value: { - dps: 6530.15775 - tps: 6615.08129 + dps: 6530.10682 + tps: 6615.03035 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-RuneofRepulsion-40372" value: { - dps: 6420.37555 - tps: 6505.85997 + dps: 6420.52064 + tps: 6506.00506 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-SavageGladiator'sLibramofFortitude-42611" value: { - dps: 6642.43152 - tps: 6727.91594 + dps: 6642.57436 + tps: 6728.05878 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-SealofthePantheon-36993" value: { - dps: 6420.37555 - tps: 6505.85997 + dps: 6420.52064 + tps: 6506.00506 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-Shadowmourne-49623" value: { - dps: 7904.17373 - tps: 7989.49917 + dps: 7904.00969 + tps: 7989.33513 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-ShinyShardoftheGods" value: { - dps: 6420.37555 - tps: 6505.85997 + dps: 6420.52064 + tps: 6506.00506 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-Sindragosa'sFlawlessFang-50361" value: { - dps: 6420.37555 - tps: 6505.85997 + dps: 6420.52064 + tps: 6506.00506 dtps: 6.55074 } } dps_results: { key: "TestRetribution-AllItems-SliverofPureIce-50339" value: { - dps: 6460.27012 - tps: 6546.31676 + dps: 6460.41245 + tps: 6546.45908 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-SliverofPureIce-50346" value: { - dps: 6465.32007 - tps: 6551.36671 + dps: 6465.46204 + tps: 6551.50868 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-SoulPreserver-37111" value: { - dps: 6439.31285 - tps: 6524.79727 + dps: 6439.45662 + tps: 6524.94104 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-SouloftheDead-40382" value: { - dps: 6511.50012 - tps: 6598.69608 + dps: 6511.46767 + tps: 6598.66364 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-SparkofLife-37657" value: { - dps: 6506.70356 - tps: 6588.86818 + dps: 6505.76336 + tps: 6587.92798 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-SphereofRedDragon'sBlood-37166" value: { - dps: 6560.29702 - tps: 6645.6894 + dps: 6560.42813 + tps: 6645.82051 dtps: 9.92959 } } @@ -874,48 +874,48 @@ dps_results: { dps_results: { key: "TestRetribution-AllItems-SwiftSkyflareDiamond" value: { - dps: 6562.52488 - tps: 6648.0093 + dps: 6562.47224 + tps: 6647.95666 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-SwiftStarflareDiamond" value: { - dps: 6556.35971 - tps: 6641.84413 + dps: 6556.3074 + tps: 6641.79181 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-SwiftWindfireDiamond" value: { - dps: 6545.57067 - tps: 6631.05509 + dps: 6545.51892 + tps: 6631.00334 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-TalismanofTrollDivinity-37734" value: { - dps: 6420.37555 - tps: 6505.85997 + dps: 6420.52064 + tps: 6506.00506 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-TearsoftheVanquished-47215" value: { - dps: 6420.37555 - tps: 6505.39119 + dps: 6420.52064 + tps: 6505.53628 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-TheGeneral'sHeart-45507" value: { - dps: 6420.37555 - tps: 6505.85997 + dps: 6420.52064 + tps: 6506.00506 dtps: 9.92959 } } @@ -930,72 +930,72 @@ dps_results: { dps_results: { key: "TestRetribution-AllItems-ThunderingSkyflareDiamond" value: { - dps: 6578.68896 - tps: 6664.31897 + dps: 6578.78508 + tps: 6664.4151 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-TinyAbominationinaJar-50351" value: { - dps: 7023.73776 - tps: 7109.97541 + dps: 7024.62707 + tps: 7110.86472 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-TinyAbominationinaJar-50706" value: { - dps: 7123.31213 - tps: 7209.60107 + dps: 7123.34647 + tps: 7209.63541 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-TirelessSkyflareDiamond" value: { - dps: 6536.35928 - tps: 6621.8437 + dps: 6536.30717 + tps: 6621.79159 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-TirelessStarflareDiamond" value: { - dps: 6535.11898 - tps: 6620.6034 + dps: 6535.0671 + tps: 6620.55151 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-TomeofArcanePhenomena-36972" value: { - dps: 6535.26623 - tps: 6620.91519 + dps: 6536.78528 + tps: 6622.43424 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-TomeoftheLightbringer-32368" value: { - dps: 6569.76696 - tps: 6655.25138 + dps: 6569.9109 + tps: 6655.39532 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-TrenchantEarthshatterDiamond" value: { - dps: 6535.11898 - tps: 6620.6034 + dps: 6535.0671 + tps: 6620.55151 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-TrenchantEarthsiegeDiamond" value: { - dps: 6536.35928 - tps: 6621.8437 + dps: 6536.30717 + tps: 6621.79159 dtps: 9.92959 } } @@ -1018,64 +1018,64 @@ dps_results: { dps_results: { key: "TestRetribution-AllItems-UndeadSlayer'sBlessedArmor" value: { - dps: 5397.45216 - tps: 5481.00412 + dps: 5397.40235 + tps: 5480.95432 dtps: 9.23882 } } dps_results: { key: "TestRetribution-AllItems-Val'anyr,HammerofAncientKings-46017" value: { - dps: 5145.39682 - tps: 5230.26174 + dps: 5145.63201 + tps: 5230.49693 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-WingedTalisman-37844" value: { - dps: 6439.86531 - tps: 6525.34973 + dps: 6440.00643 + tps: 6525.49085 dtps: 9.92959 } } dps_results: { key: "TestRetribution-AllItems-WrathfulGladiator'sLibramofFortitude-51478" value: { - dps: 6729.06495 - tps: 6814.54937 + dps: 6729.2065 + tps: 6814.69091 dtps: 9.92959 } } dps_results: { key: "TestRetribution-Average-Default" value: { - dps: 6668.56873 - tps: 6753.17123 + dps: 6668.69511 + tps: 6753.29762 dtps: 13.59845 } } dps_results: { key: "TestRetribution-Settings-BloodElf-p1-Retribution Paladin SOC-default-FullBuffs-LongMultiTarget" value: { - dps: 18965.91539 - tps: 20678.01503 + dps: 18965.75625 + tps: 20677.85589 dtps: 10.57482 } } dps_results: { key: "TestRetribution-Settings-BloodElf-p1-Retribution Paladin SOC-default-FullBuffs-LongSingleTarget" value: { - dps: 5477.99131 - tps: 5563.62785 + dps: 5477.65446 + tps: 5563.291 dtps: 11.82069 } } dps_results: { key: "TestRetribution-Settings-BloodElf-p1-Retribution Paladin SOC-default-FullBuffs-ShortSingleTarget" value: { - dps: 6192.80238 - tps: 6287.44359 + dps: 6191.11812 + tps: 6281.82806 dtps: 59.10347 } } @@ -1103,24 +1103,24 @@ dps_results: { dps_results: { key: "TestRetribution-Settings-BloodElf-p1-Retribution Paladin SOR-default-FullBuffs-LongMultiTarget" value: { - dps: 16956.30594 - tps: 18668.0915 + dps: 16956.62716 + tps: 18668.41273 dtps: 10.33353 } } dps_results: { key: "TestRetribution-Settings-BloodElf-p1-Retribution Paladin SOR-default-FullBuffs-LongSingleTarget" value: { - dps: 5849.18097 - tps: 5934.73392 + dps: 5849.24722 + tps: 5934.80017 dtps: 11.82069 } } dps_results: { key: "TestRetribution-Settings-BloodElf-p1-Retribution Paladin SOR-default-FullBuffs-ShortSingleTarget" value: { - dps: 6634.80579 - tps: 6729.31363 + dps: 6635.13703 + tps: 6725.70508 dtps: 59.10347 } } @@ -1148,24 +1148,24 @@ dps_results: { dps_results: { key: "TestRetribution-Settings-BloodElf-p1-Retribution Paladin SOV 2 Target Swapping-default-FullBuffs-LongMultiTarget" value: { - dps: 18993.19487 - tps: 20701.35603 + dps: 18992.27977 + tps: 20700.44093 dtps: 8.80605 } } dps_results: { key: "TestRetribution-Settings-BloodElf-p1-Retribution Paladin SOV 2 Target Swapping-default-FullBuffs-LongSingleTarget" value: { - dps: 6663.47166 - tps: 6748.95608 + dps: 6663.61419 + tps: 6749.09861 dtps: 9.92959 } } dps_results: { key: "TestRetribution-Settings-BloodElf-p1-Retribution Paladin SOV 2 Target Swapping-default-FullBuffs-ShortSingleTarget" value: { - dps: 7381.2945 - tps: 7473.81754 + dps: 7382.00712 + tps: 7472.77717 dtps: 49.64794 } } @@ -1193,24 +1193,24 @@ dps_results: { dps_results: { key: "TestRetribution-Settings-BloodElf-p1-Retribution Paladin SOV-default-FullBuffs-LongMultiTarget" value: { - dps: 18993.19487 - tps: 20701.35603 + dps: 18992.27977 + tps: 20700.44093 dtps: 8.80605 } } dps_results: { key: "TestRetribution-Settings-BloodElf-p1-Retribution Paladin SOV-default-FullBuffs-LongSingleTarget" value: { - dps: 6663.47166 - tps: 6748.95608 + dps: 6663.61419 + tps: 6749.09861 dtps: 9.92959 } } dps_results: { key: "TestRetribution-Settings-BloodElf-p1-Retribution Paladin SOV-default-FullBuffs-ShortSingleTarget" value: { - dps: 7381.2945 - tps: 7473.81754 + dps: 7382.00712 + tps: 7472.77717 dtps: 49.64794 } } @@ -1238,24 +1238,24 @@ dps_results: { dps_results: { key: "TestRetribution-Settings-Draenei-p1-Retribution Paladin SOC-default-FullBuffs-LongMultiTarget" value: { - dps: 19088.7306 - tps: 20780.43386 + dps: 19088.57134 + tps: 20780.2746 dtps: 10.14629 } } dps_results: { key: "TestRetribution-Settings-Draenei-p1-Retribution Paladin SOC-default-FullBuffs-LongSingleTarget" value: { - dps: 5488.69007 - tps: 5573.32505 + dps: 5488.35294 + tps: 5572.98793 dtps: 11.82069 } } dps_results: { key: "TestRetribution-Settings-Draenei-p1-Retribution Paladin SOC-default-FullBuffs-ShortSingleTarget" value: { - dps: 6196.77971 - tps: 6291.46684 + dps: 6195.09407 + tps: 6285.8247 dtps: 59.10347 } } @@ -1283,24 +1283,24 @@ dps_results: { dps_results: { key: "TestRetribution-Settings-Draenei-p1-Retribution Paladin SOR-default-FullBuffs-LongMultiTarget" value: { - dps: 17080.08349 - tps: 18772.80641 + dps: 17080.40494 + tps: 18773.12786 dtps: 9.95262 } } dps_results: { key: "TestRetribution-Settings-Draenei-p1-Retribution Paladin SOR-default-FullBuffs-LongSingleTarget" value: { - dps: 5863.30716 - tps: 5947.85146 + dps: 5863.37349 + tps: 5947.91779 dtps: 11.82069 } } dps_results: { key: "TestRetribution-Settings-Draenei-p1-Retribution Paladin SOR-default-FullBuffs-ShortSingleTarget" value: { - dps: 6647.36735 - tps: 6741.92039 + dps: 6647.69899 + tps: 6738.28782 dtps: 59.10347 } } @@ -1328,24 +1328,24 @@ dps_results: { dps_results: { key: "TestRetribution-Settings-Draenei-p1-Retribution Paladin SOV 2 Target Swapping-default-FullBuffs-LongMultiTarget" value: { - dps: 19119.70694 - tps: 20805.09347 + dps: 19118.75828 + tps: 20804.14482 dtps: 8.48862 } } dps_results: { key: "TestRetribution-Settings-Draenei-p1-Retribution Paladin SOV 2 Target Swapping-default-FullBuffs-LongSingleTarget" value: { - dps: 6676.72376 - tps: 6761.15752 + dps: 6676.86616 + tps: 6761.29993 dtps: 9.92959 } } dps_results: { key: "TestRetribution-Settings-Draenei-p1-Retribution Paladin SOV 2 Target Swapping-default-FullBuffs-ShortSingleTarget" value: { - dps: 7390.6795 - tps: 7483.24301 + dps: 7391.39147 + tps: 7482.18276 dtps: 49.64794 } } @@ -1373,24 +1373,24 @@ dps_results: { dps_results: { key: "TestRetribution-Settings-Draenei-p1-Retribution Paladin SOV-default-FullBuffs-LongMultiTarget" value: { - dps: 19119.70694 - tps: 20805.09347 + dps: 19118.75828 + tps: 20804.14482 dtps: 8.48862 } } dps_results: { key: "TestRetribution-Settings-Draenei-p1-Retribution Paladin SOV-default-FullBuffs-LongSingleTarget" value: { - dps: 6676.72376 - tps: 6761.15752 + dps: 6676.86616 + tps: 6761.29993 dtps: 9.92959 } } dps_results: { key: "TestRetribution-Settings-Draenei-p1-Retribution Paladin SOV-default-FullBuffs-ShortSingleTarget" value: { - dps: 7390.6795 - tps: 7483.24301 + dps: 7391.39147 + tps: 7482.18276 dtps: 49.64794 } } @@ -1418,24 +1418,24 @@ dps_results: { dps_results: { key: "TestRetribution-Settings-Dwarf-p1-Retribution Paladin SOC-default-FullBuffs-LongMultiTarget" value: { - dps: 19001.07213 - tps: 20693.66744 + dps: 19000.91274 + tps: 20693.50805 dtps: 10.14629 } } dps_results: { key: "TestRetribution-Settings-Dwarf-p1-Retribution Paladin SOC-default-FullBuffs-LongSingleTarget" value: { - dps: 5483.6814 - tps: 5568.37492 + dps: 5483.34399 + tps: 5568.03751 dtps: 11.82069 } } dps_results: { key: "TestRetribution-Settings-Dwarf-p1-Retribution Paladin SOC-default-FullBuffs-ShortSingleTarget" value: { - dps: 6192.92007 - tps: 6287.62251 + dps: 6191.23305 + tps: 6281.97057 dtps: 59.10347 } } @@ -1463,24 +1463,24 @@ dps_results: { dps_results: { key: "TestRetribution-Settings-Dwarf-p1-Retribution Paladin SOR-default-FullBuffs-LongMultiTarget" value: { - dps: 16988.83779 - tps: 18680.83618 + dps: 16989.15945 + tps: 18681.15785 dtps: 9.95262 } } dps_results: { key: "TestRetribution-Settings-Dwarf-p1-Retribution Paladin SOR-default-FullBuffs-LongSingleTarget" value: { - dps: 5860.18948 - tps: 5944.76826 + dps: 5860.25589 + tps: 5944.83467 dtps: 11.82069 } } dps_results: { key: "TestRetribution-Settings-Dwarf-p1-Retribution Paladin SOR-default-FullBuffs-ShortSingleTarget" value: { - dps: 6643.44831 - tps: 6738.01641 + dps: 6643.78035 + tps: 6734.3761 dtps: 59.10347 } } @@ -1508,24 +1508,24 @@ dps_results: { dps_results: { key: "TestRetribution-Settings-Dwarf-p1-Retribution Paladin SOV 2 Target Swapping-default-FullBuffs-LongMultiTarget" value: { - dps: 19035.16533 - tps: 20720.23806 + dps: 19034.21526 + tps: 20719.28799 dtps: 8.48862 } } dps_results: { key: "TestRetribution-Settings-Dwarf-p1-Retribution Paladin SOV 2 Target Swapping-default-FullBuffs-LongSingleTarget" value: { - dps: 6674.98513 - tps: 6759.41251 + dps: 6675.1274 + tps: 6759.55479 dtps: 9.92959 } } dps_results: { key: "TestRetribution-Settings-Dwarf-p1-Retribution Paladin SOV 2 Target Swapping-default-FullBuffs-ShortSingleTarget" value: { - dps: 7389.18398 - tps: 7481.76099 + dps: 7389.89531 + tps: 7480.69367 dtps: 49.64794 } } @@ -1553,24 +1553,24 @@ dps_results: { dps_results: { key: "TestRetribution-Settings-Dwarf-p1-Retribution Paladin SOV-default-FullBuffs-LongMultiTarget" value: { - dps: 19035.16533 - tps: 20720.23806 + dps: 19034.21526 + tps: 20719.28799 dtps: 8.48862 } } dps_results: { key: "TestRetribution-Settings-Dwarf-p1-Retribution Paladin SOV-default-FullBuffs-LongSingleTarget" value: { - dps: 6674.98513 - tps: 6759.41251 + dps: 6675.1274 + tps: 6759.55479 dtps: 9.92959 } } dps_results: { key: "TestRetribution-Settings-Dwarf-p1-Retribution Paladin SOV-default-FullBuffs-ShortSingleTarget" value: { - dps: 7389.18398 - tps: 7481.76099 + dps: 7389.89531 + tps: 7480.69367 dtps: 49.64794 } } @@ -1598,24 +1598,24 @@ dps_results: { dps_results: { key: "TestRetribution-Settings-Human-p1-Retribution Paladin SOC-default-FullBuffs-LongMultiTarget" value: { - dps: 18979.81052 - tps: 20672.24611 + dps: 18979.65129 + tps: 20672.08688 dtps: 10.14629 } } dps_results: { key: "TestRetribution-Settings-Human-p1-Retribution Paladin SOC-default-FullBuffs-LongSingleTarget" value: { - dps: 5480.23 - tps: 5564.91574 + dps: 5479.89294 + tps: 5564.57868 dtps: 11.82069 } } dps_results: { key: "TestRetribution-Settings-Human-p1-Retribution Paladin SOC-default-FullBuffs-ShortSingleTarget" value: { - dps: 6191.78073 - tps: 6286.46786 + dps: 6190.09544 + tps: 6280.82607 dtps: 59.10347 } } @@ -1643,24 +1643,24 @@ dps_results: { dps_results: { key: "TestRetribution-Settings-Human-p1-Retribution Paladin SOR-default-FullBuffs-LongMultiTarget" value: { - dps: 16969.61369 - tps: 18661.45781 + dps: 16969.93508 + tps: 18661.7792 dtps: 9.95262 } } dps_results: { key: "TestRetribution-Settings-Human-p1-Retribution Paladin SOR-default-FullBuffs-LongSingleTarget" value: { - dps: 5853.43767 - tps: 5938.00926 + dps: 5853.50398 + tps: 5938.07557 dtps: 11.82069 } } dps_results: { key: "TestRetribution-Settings-Human-p1-Retribution Paladin SOR-default-FullBuffs-ShortSingleTarget" value: { - dps: 6637.28889 - tps: 6731.84193 + dps: 6637.62044 + tps: 6728.20926 dtps: 59.10347 } } @@ -1688,24 +1688,24 @@ dps_results: { dps_results: { key: "TestRetribution-Settings-Human-p1-Retribution Paladin SOV 2 Target Swapping-default-FullBuffs-LongMultiTarget" value: { - dps: 19008.65557 - tps: 20693.6027 + dps: 19007.73945 + tps: 20692.68658 dtps: 8.48862 } } dps_results: { key: "TestRetribution-Settings-Human-p1-Retribution Paladin SOV 2 Target Swapping-default-FullBuffs-LongSingleTarget" value: { - dps: 6666.72119 - tps: 6751.1424 + dps: 6666.86363 + tps: 6751.28483 dtps: 9.92959 } } dps_results: { key: "TestRetribution-Settings-Human-p1-Retribution Paladin SOV 2 Target Swapping-default-FullBuffs-ShortSingleTarget" value: { - dps: 7383.00254 - tps: 7475.56606 + dps: 7383.71468 + tps: 7474.50596 dtps: 49.64794 } } @@ -1733,24 +1733,24 @@ dps_results: { dps_results: { key: "TestRetribution-Settings-Human-p1-Retribution Paladin SOV-default-FullBuffs-LongMultiTarget" value: { - dps: 19008.65557 - tps: 20693.6027 + dps: 19007.73945 + tps: 20692.68658 dtps: 8.48862 } } dps_results: { key: "TestRetribution-Settings-Human-p1-Retribution Paladin SOV-default-FullBuffs-LongSingleTarget" value: { - dps: 6666.72119 - tps: 6751.1424 + dps: 6666.86363 + tps: 6751.28483 dtps: 9.92959 } } dps_results: { key: "TestRetribution-Settings-Human-p1-Retribution Paladin SOV-default-FullBuffs-ShortSingleTarget" value: { - dps: 7383.00254 - tps: 7475.56606 + dps: 7383.71468 + tps: 7474.50596 dtps: 49.64794 } } @@ -1778,8 +1778,8 @@ dps_results: { dps_results: { key: "TestRetribution-SwitchInFrontOfTarget-Default" value: { - dps: 6317.40296 - tps: 6402.77929 + dps: 6317.26995 + tps: 6402.64627 dtps: 9.92959 } } diff --git a/sim/priest/healing/TestDisc.results b/sim/priest/healing/TestDisc.results index 2e1c8bb972..a57d5dc3b3 100644 --- a/sim/priest/healing/TestDisc.results +++ b/sim/priest/healing/TestDisc.results @@ -343,7 +343,7 @@ dps_results: { dps_results: { key: "TestDisc-AllItems-Figurine-SapphireOwl-42413" value: { - tps: 18.9916 + tps: 19.00072 hps: 3650.23426 } } diff --git a/sim/priest/healing/TestHoly.results b/sim/priest/healing/TestHoly.results index 7de62a4da8..91517efd66 100644 --- a/sim/priest/healing/TestHoly.results +++ b/sim/priest/healing/TestHoly.results @@ -172,8 +172,8 @@ dps_results: { dps_results: { key: "TestHoly-AllItems-DarkmoonCard:Greatness-44255" value: { - tps: 35.9717 - hps: 4983.05245 + tps: 36.25385 + hps: 4991.42137 } } dps_results: { diff --git a/sim/priest/shadow/TestShadow.results b/sim/priest/shadow/TestShadow.results index a353b97a97..fd4adab58a 100644 --- a/sim/priest/shadow/TestShadow.results +++ b/sim/priest/shadow/TestShadow.results @@ -798,8 +798,8 @@ dps_results: { dps_results: { key: "TestShadow-AllItems-Zabra'sRaiment" value: { - dps: 6507.98519 - tps: 6310.63776 + dps: 6508.31094 + tps: 6310.96351 } } dps_results: { diff --git a/sim/priest/smite/TestSmite.results b/sim/priest/smite/TestSmite.results index 110aae8059..c37dd30657 100644 --- a/sim/priest/smite/TestSmite.results +++ b/sim/priest/smite/TestSmite.results @@ -46,739 +46,739 @@ character_stats_results: { dps_results: { key: "TestSmite-AllItems-AbsolutionRegalia" value: { - dps: 1995.47614 - tps: 1685.05564 + dps: 1995.65978 + tps: 1685.19061 } } dps_results: { key: "TestSmite-AllItems-Althor'sAbacus-50359" value: { - dps: 2893.83018 - tps: 2430.91688 + dps: 2894.04696 + tps: 2431.07532 } } dps_results: { key: "TestSmite-AllItems-Althor'sAbacus-50366" value: { - dps: 2907.46733 - tps: 2442.2371 + dps: 2907.685 + tps: 2442.39619 } } dps_results: { key: "TestSmite-AllItems-AustereEarthsiegeDiamond" value: { - dps: 2844.46107 - tps: 2388.30346 + dps: 2844.67304 + tps: 2388.45874 } } dps_results: { key: "TestSmite-AllItems-Bandit'sInsignia-40371" value: { - dps: 2782.87337 - tps: 2338.81139 + dps: 2783.08293 + tps: 2338.96466 } } dps_results: { key: "TestSmite-AllItems-BaubleofTrueBlood-50354" value: { - dps: 2783.94305 - tps: 2340.58703 + dps: 2784.21341 + tps: 2340.78415 hps: 90.33849 } } dps_results: { key: "TestSmite-AllItems-BaubleofTrueBlood-50726" value: { - dps: 2783.94305 - tps: 2340.58703 + dps: 2784.21341 + tps: 2340.78415 hps: 90.33849 } } dps_results: { key: "TestSmite-AllItems-BeamingEarthsiegeDiamond" value: { - dps: 2896.39463 - tps: 2430.31712 + dps: 2896.6066 + tps: 2430.4724 } } dps_results: { key: "TestSmite-AllItems-BlessedRegaliaofUndeadCleansing" value: { - dps: 2213.89453 - tps: 1867.97361 + dps: 2214.0364 + tps: 1868.07834 } } dps_results: { key: "TestSmite-AllItems-BracingEarthsiegeDiamond" value: { - dps: 2859.73182 - tps: 2353.55626 + dps: 2859.94481 + tps: 2353.70915 } } dps_results: { key: "TestSmite-AllItems-ChaoticSkyflareDiamond" value: { - dps: 2873.81795 - tps: 2410.95042 + dps: 2874.02992 + tps: 2411.10571 } } dps_results: { key: "TestSmite-AllItems-CorpseTongueCoin-50349" value: { - dps: 2782.87337 - tps: 2338.81139 + dps: 2783.08293 + tps: 2338.96466 } } dps_results: { key: "TestSmite-AllItems-CorpseTongueCoin-50352" value: { - dps: 2782.87337 - tps: 2338.81139 + dps: 2783.08293 + tps: 2338.96466 } } dps_results: { key: "TestSmite-AllItems-CorrodedSkeletonKey-50356" value: { - dps: 2782.87337 - tps: 2338.81139 + dps: 2783.08293 + tps: 2338.96466 hps: 64 } } dps_results: { key: "TestSmite-AllItems-CrimsonAcolyte'sRaiment" value: { - dps: 3656.275 - tps: 3094.26738 + dps: 3656.43315 + tps: 3094.38378 } } dps_results: { key: "TestSmite-AllItems-CrimsonAcolyte'sRegalia" value: { - dps: 3403.63853 - tps: 2858.7041 + dps: 3403.97761 + tps: 2858.95096 } } dps_results: { key: "TestSmite-AllItems-DarkmoonCard:Berserker!-42989" value: { - dps: 2809.40067 - tps: 2358.48127 + dps: 2809.61022 + tps: 2358.63454 } } dps_results: { key: "TestSmite-AllItems-DarkmoonCard:Death-42990" value: { - dps: 2855.92826 - tps: 2406.4309 + dps: 2856.17338 + tps: 2406.6212 } } dps_results: { key: "TestSmite-AllItems-DarkmoonCard:Greatness-44255" value: { - dps: 2988.6755 - tps: 2512.01108 + dps: 2988.88506 + tps: 2512.16435 } } dps_results: { key: "TestSmite-AllItems-Death'sChoice-47464" value: { - dps: 2782.87337 - tps: 2338.81139 + dps: 2783.08293 + tps: 2338.96466 } } dps_results: { key: "TestSmite-AllItems-DeathKnight'sAnguish-38212" value: { - dps: 2792.49553 - tps: 2345.86351 + dps: 2792.70508 + tps: 2346.01678 } } dps_results: { key: "TestSmite-AllItems-Deathbringer'sWill-50362" value: { - dps: 2782.87337 - tps: 2338.81139 + dps: 2783.08293 + tps: 2338.96466 } } dps_results: { key: "TestSmite-AllItems-Deathbringer'sWill-50363" value: { - dps: 2782.87337 - tps: 2338.81139 + dps: 2783.08293 + tps: 2338.96466 } } dps_results: { key: "TestSmite-AllItems-Defender'sCode-40257" value: { - dps: 2782.87337 - tps: 2338.81139 + dps: 2783.08293 + tps: 2338.96466 } } dps_results: { key: "TestSmite-AllItems-DestructiveSkyflareDiamond" value: { - dps: 2848.58975 - tps: 2390.83279 + dps: 2848.80173 + tps: 2390.98808 } } dps_results: { key: "TestSmite-AllItems-DislodgedForeignObject-50348" value: { - dps: 2891.88465 - tps: 2422.64278 + dps: 2892.00829 + tps: 2422.7308 } } dps_results: { key: "TestSmite-AllItems-DislodgedForeignObject-50353" value: { - dps: 2878.07976 - tps: 2413.54911 + dps: 2878.27734 + tps: 2413.69279 } } dps_results: { key: "TestSmite-AllItems-EffulgentSkyflareDiamond" value: { - dps: 2844.46107 - tps: 2388.30346 + dps: 2844.67304 + tps: 2388.45874 } } dps_results: { key: "TestSmite-AllItems-EmberSkyflareDiamond" value: { - dps: 2901.38893 - tps: 2436.84342 + dps: 2901.60191 + tps: 2436.99942 } } dps_results: { key: "TestSmite-AllItems-EnigmaticSkyflareDiamond" value: { - dps: 2846.23143 - tps: 2388.88121 + dps: 2846.44341 + tps: 2389.0365 } } dps_results: { key: "TestSmite-AllItems-EnigmaticStarflareDiamond" value: { - dps: 2845.82027 - tps: 2389.3935 + dps: 2846.03224 + tps: 2389.54878 } } dps_results: { key: "TestSmite-AllItems-EphemeralSnowflake-50260" value: { - dps: 2775.20299 - tps: 2330.28527 + dps: 2775.36116 + tps: 2330.40091 } } dps_results: { key: "TestSmite-AllItems-EssenceofGossamer-37220" value: { - dps: 2782.87337 - tps: 2338.81139 + dps: 2783.08293 + tps: 2338.96466 } } dps_results: { key: "TestSmite-AllItems-EternalEarthsiegeDiamond" value: { - dps: 2844.46107 - tps: 2388.30346 + dps: 2844.67304 + tps: 2388.45874 } } dps_results: { key: "TestSmite-AllItems-ExtractofNecromanticPower-40373" value: { - dps: 2846.94857 - tps: 2398.26217 + dps: 2847.15813 + tps: 2398.41544 } } dps_results: { key: "TestSmite-AllItems-EyeoftheBroodmother-45308" value: { - dps: 2886.44236 - tps: 2422.97869 + dps: 2886.63813 + tps: 2423.12085 } } dps_results: { key: "TestSmite-AllItems-Figurine-SapphireOwl-42413" value: { - dps: 2927.48714 - tps: 2463.11218 + dps: 2927.69669 + tps: 2463.26545 } } dps_results: { key: "TestSmite-AllItems-ForethoughtTalisman-40258" value: { - dps: 2851.67899 - tps: 2395.92708 + dps: 2851.89303 + tps: 2396.08356 } } dps_results: { key: "TestSmite-AllItems-ForgeEmber-37660" value: { - dps: 2851.15451 - tps: 2393.97832 + dps: 2851.36407 + tps: 2394.13159 } } dps_results: { key: "TestSmite-AllItems-ForlornSkyflareDiamond" value: { - dps: 2859.73182 - tps: 2400.97239 + dps: 2859.94481 + tps: 2401.12839 } } dps_results: { key: "TestSmite-AllItems-ForlornStarflareDiamond" value: { - dps: 2856.67767 - tps: 2398.4386 + dps: 2856.89045 + tps: 2398.59446 } } dps_results: { key: "TestSmite-AllItems-FuryoftheFiveFlights-40431" value: { - dps: 2782.87337 - tps: 2338.81139 + dps: 2783.08293 + tps: 2338.96466 } } dps_results: { key: "TestSmite-AllItems-FuturesightRune-38763" value: { - dps: 2865.56665 - tps: 2407.85508 + dps: 2865.78098 + tps: 2408.01177 } } dps_results: { key: "TestSmite-AllItems-GarbofFaith" value: { - dps: 2622.70384 - tps: 2209.29954 + dps: 2622.90525 + tps: 2209.44725 } } dps_results: { key: "TestSmite-AllItems-Gladiator'sInvestiture" value: { - dps: 3096.91139 - tps: 2621.49536 + dps: 3097.07074 + tps: 2621.61262 } } dps_results: { key: "TestSmite-AllItems-Gladiator'sRaiment" value: { - dps: 2777.84271 - tps: 2340.49807 + dps: 2778.12313 + tps: 2340.70258 } } dps_results: { key: "TestSmite-AllItems-GlowingTwilightScale-54573" value: { - dps: 2900.64875 - tps: 2436.57699 + dps: 2900.86598 + tps: 2436.73575 } } dps_results: { key: "TestSmite-AllItems-GlowingTwilightScale-54589" value: { - dps: 2916.14552 - tps: 2449.44089 + dps: 2916.36375 + tps: 2449.60037 } } dps_results: { key: "TestSmite-AllItems-GnomishLightningGenerator-41121" value: { - dps: 2850.13779 - tps: 2398.08766 + dps: 2850.05052 + tps: 2398.02263 } } dps_results: { key: "TestSmite-AllItems-Heartpierce-49982" value: { - dps: 2901.38893 - tps: 2436.84342 + dps: 2901.60191 + tps: 2436.99942 } } dps_results: { key: "TestSmite-AllItems-Heartpierce-50641" value: { - dps: 2901.38893 - tps: 2436.84342 + dps: 2901.60191 + tps: 2436.99942 } } dps_results: { key: "TestSmite-AllItems-ImpassiveSkyflareDiamond" value: { - dps: 2846.23143 - tps: 2388.88121 + dps: 2846.44341 + tps: 2389.0365 } } dps_results: { key: "TestSmite-AllItems-ImpassiveStarflareDiamond" value: { - dps: 2845.82027 - tps: 2389.3935 + dps: 2846.03224 + tps: 2389.54878 } } dps_results: { key: "TestSmite-AllItems-IncisorFragment-37723" value: { - dps: 2782.87337 - tps: 2338.81139 + dps: 2783.08293 + tps: 2338.96466 } } dps_results: { key: "TestSmite-AllItems-InsightfulEarthsiegeDiamond" value: { - dps: 2985.7207 - tps: 2511.48088 + dps: 2985.93267 + tps: 2511.63616 } } dps_results: { key: "TestSmite-AllItems-InvigoratingEarthsiegeDiamond" value: { - dps: 2844.46107 - tps: 2388.30346 + dps: 2844.67304 + tps: 2388.45874 } } dps_results: { key: "TestSmite-AllItems-LastWord-50179" value: { - dps: 2901.38893 - tps: 2436.84342 + dps: 2901.60191 + tps: 2436.99942 } } dps_results: { key: "TestSmite-AllItems-LastWord-50708" value: { - dps: 2901.38893 - tps: 2436.84342 + dps: 2901.60191 + tps: 2436.99942 } } dps_results: { key: "TestSmite-AllItems-Lavanthor'sTalisman-37872" value: { - dps: 2782.87337 - tps: 2338.81139 + dps: 2783.08293 + tps: 2338.96466 } } dps_results: { key: "TestSmite-AllItems-MajesticDragonFigurine-40430" value: { - dps: 2955.70512 - tps: 2482.3508 + dps: 2955.91562 + tps: 2482.50483 } } dps_results: { key: "TestSmite-AllItems-MeteoriteWhetstone-37390" value: { - dps: 2799.07176 - tps: 2350.99721 + dps: 2799.28132 + tps: 2351.15048 } } dps_results: { key: "TestSmite-AllItems-NevermeltingIceCrystal-50259" value: { - dps: 2863.27632 - tps: 2405.42676 + dps: 2863.61187 + tps: 2405.67062 } } dps_results: { key: "TestSmite-AllItems-Nibelung-49992" value: { - dps: 2901.38893 - tps: 2436.84342 + dps: 2901.60191 + tps: 2436.99942 } } dps_results: { key: "TestSmite-AllItems-Nibelung-50648" value: { - dps: 2901.38893 - tps: 2436.84342 + dps: 2901.60191 + tps: 2436.99942 } } dps_results: { key: "TestSmite-AllItems-OfferingofSacrifice-37638" value: { - dps: 2782.87337 - tps: 2338.81139 + dps: 2783.08293 + tps: 2338.96466 } } dps_results: { key: "TestSmite-AllItems-PersistentEarthshatterDiamond" value: { - dps: 2844.46107 - tps: 2388.30346 + dps: 2844.67304 + tps: 2388.45874 } } dps_results: { key: "TestSmite-AllItems-PersistentEarthsiegeDiamond" value: { - dps: 2844.46107 - tps: 2388.30346 + dps: 2844.67304 + tps: 2388.45874 } } dps_results: { key: "TestSmite-AllItems-PetrifiedScarab-21685" value: { - dps: 2782.87337 - tps: 2338.81139 + dps: 2783.08293 + tps: 2338.96466 } } dps_results: { key: "TestSmite-AllItems-PetrifiedTwilightScale-54571" value: { - dps: 2782.87337 - tps: 2338.81139 + dps: 2783.08293 + tps: 2338.96466 } } dps_results: { key: "TestSmite-AllItems-PetrifiedTwilightScale-54591" value: { - dps: 2782.87337 - tps: 2338.81139 + dps: 2783.08293 + tps: 2338.96466 } } dps_results: { key: "TestSmite-AllItems-PowerfulEarthshatterDiamond" value: { - dps: 2844.46107 - tps: 2388.30346 + dps: 2844.67304 + tps: 2388.45874 } } dps_results: { key: "TestSmite-AllItems-PowerfulEarthsiegeDiamond" value: { - dps: 2844.46107 - tps: 2388.30346 + dps: 2844.67304 + tps: 2388.45874 } } dps_results: { key: "TestSmite-AllItems-PurifiedShardoftheGods" value: { - dps: 2782.87337 - tps: 2338.81139 + dps: 2783.08293 + tps: 2338.96466 } } dps_results: { key: "TestSmite-AllItems-RegaliaofFaith" value: { - dps: 2638.93021 - tps: 2233.51836 + dps: 2639.07517 + tps: 2233.62531 } } dps_results: { key: "TestSmite-AllItems-ReignoftheDead-47316" value: { - dps: 2965.40989 - tps: 2506.23335 + dps: 2965.6255 + tps: 2506.39096 } } dps_results: { key: "TestSmite-AllItems-ReignoftheDead-47477" value: { - dps: 2988.08626 - tps: 2527.01752 + dps: 2988.30259 + tps: 2527.17565 } } dps_results: { key: "TestSmite-AllItems-RelentlessEarthsiegeDiamond" value: { - dps: 2871.80834 - tps: 2410.18128 + dps: 2872.02031 + tps: 2410.33656 } } dps_results: { key: "TestSmite-AllItems-RevitalizingSkyflareDiamond" value: { - dps: 2869.0891 - tps: 2408.24045 + dps: 2869.30107 + tps: 2408.39573 } } dps_results: { key: "TestSmite-AllItems-RuneofRepulsion-40372" value: { - dps: 2782.87337 - tps: 2338.81139 + dps: 2783.08293 + tps: 2338.96466 } } dps_results: { key: "TestSmite-AllItems-SanctificationGarb" value: { - dps: 2766.03738 - tps: 2331.73868 + dps: 2766.23464 + tps: 2331.88086 } } dps_results: { key: "TestSmite-AllItems-SanctificationRegalia" value: { - dps: 2799.56623 - tps: 2362.54679 + dps: 2799.71504 + tps: 2362.65649 } } dps_results: { key: "TestSmite-AllItems-SealofthePantheon-36993" value: { - dps: 2782.87337 - tps: 2338.81139 + dps: 2783.08293 + tps: 2338.96466 } } dps_results: { key: "TestSmite-AllItems-ShinyShardoftheGods" value: { - dps: 2782.87337 - tps: 2338.81139 + dps: 2783.08293 + tps: 2338.96466 } } dps_results: { key: "TestSmite-AllItems-Sindragosa'sFlawlessFang-50361" value: { - dps: 2782.87337 - tps: 2338.81139 + dps: 2783.08293 + tps: 2338.96466 } } dps_results: { key: "TestSmite-AllItems-SliverofPureIce-50339" value: { - dps: 3004.03453 - tps: 2532.55327 + dps: 3004.25046 + tps: 2532.71111 } } dps_results: { key: "TestSmite-AllItems-SliverofPureIce-50346" value: { - dps: 3024.23868 - tps: 2551.36347 + dps: 3024.45542 + tps: 2551.52189 } } dps_results: { key: "TestSmite-AllItems-SoulPreserver-37111" value: { - dps: 2829.36365 - tps: 2377.40307 + dps: 2829.57624 + tps: 2377.55851 } } dps_results: { key: "TestSmite-AllItems-SouloftheDead-40382" value: { - dps: 2941.89729 - tps: 2478.24426 + dps: 2942.10685 + tps: 2478.39753 } } dps_results: { key: "TestSmite-AllItems-SparkofLife-37657" value: { - dps: 2878.81356 - tps: 2419.52789 + dps: 2879.02312 + tps: 2419.68116 } } dps_results: { key: "TestSmite-AllItems-SphereofRedDragon'sBlood-37166" value: { - dps: 2809.22087 - tps: 2360.9394 + dps: 2809.43043 + tps: 2361.09267 } } dps_results: { key: "TestSmite-AllItems-SwiftSkyflareDiamond" value: { - dps: 2844.46107 - tps: 2388.30346 + dps: 2844.67304 + tps: 2388.45874 } } dps_results: { key: "TestSmite-AllItems-SwiftStarflareDiamond" value: { - dps: 2844.46107 - tps: 2388.30346 + dps: 2844.67304 + tps: 2388.45874 } } dps_results: { key: "TestSmite-AllItems-SwiftWindfireDiamond" value: { - dps: 2844.46107 - tps: 2388.30346 + dps: 2844.67304 + tps: 2388.45874 } } dps_results: { key: "TestSmite-AllItems-TalismanofTrollDivinity-37734" value: { - dps: 2857.11717 - tps: 2399.57842 + dps: 2857.32763 + tps: 2399.73234 } } dps_results: { key: "TestSmite-AllItems-TearsoftheVanquished-47215" value: { - dps: 2917.98584 - tps: 2453.77923 + dps: 2918.1954 + tps: 2453.9325 } } dps_results: { key: "TestSmite-AllItems-TheGeneral'sHeart-45507" value: { - dps: 2782.87337 - tps: 2338.81139 + dps: 2783.08293 + tps: 2338.96466 } } dps_results: { key: "TestSmite-AllItems-ThunderingSkyflareDiamond" value: { - dps: 2844.46107 - tps: 2388.30346 + dps: 2844.67304 + tps: 2388.45874 } } dps_results: { key: "TestSmite-AllItems-TinyAbominationinaJar-50351" value: { - dps: 2809.22087 - tps: 2360.9394 + dps: 2809.43043 + tps: 2361.09267 } } dps_results: { key: "TestSmite-AllItems-TinyAbominationinaJar-50706" value: { - dps: 2809.22087 - tps: 2360.9394 + dps: 2809.43043 + tps: 2361.09267 } } dps_results: { key: "TestSmite-AllItems-TirelessSkyflareDiamond" value: { - dps: 2859.73182 - tps: 2400.97239 + dps: 2859.94481 + tps: 2401.12839 } } dps_results: { key: "TestSmite-AllItems-TirelessStarflareDiamond" value: { - dps: 2856.67767 - tps: 2398.4386 + dps: 2856.89045 + tps: 2398.59446 } } dps_results: { key: "TestSmite-AllItems-TomeofArcanePhenomena-36972" value: { - dps: 2822.4374 - tps: 2369.79338 + dps: 2822.59725 + tps: 2369.91019 } } dps_results: { key: "TestSmite-AllItems-TrenchantEarthshatterDiamond" value: { - dps: 2856.67767 - tps: 2398.4386 + dps: 2856.89045 + tps: 2398.59446 } } dps_results: { key: "TestSmite-AllItems-TrenchantEarthsiegeDiamond" value: { - dps: 2859.73182 - tps: 2400.97239 + dps: 2859.94481 + tps: 2401.12839 } } dps_results: { key: "TestSmite-AllItems-Val'anyr,HammerofAncientKings-46017" value: { - dps: 2971.76409 - tps: 2487.83574 + dps: 2971.98183 + tps: 2487.99516 } } dps_results: { @@ -791,50 +791,50 @@ dps_results: { dps_results: { key: "TestSmite-AllItems-WingedTalisman-37844" value: { - dps: 2835.04964 - tps: 2382.19892 + dps: 2835.27316 + tps: 2382.3622 } } dps_results: { key: "TestSmite-AllItems-Zabra'sRaiment" value: { - dps: 2815.57936 - tps: 2377.9897 + dps: 2815.72712 + tps: 2378.09865 } } dps_results: { key: "TestSmite-AllItems-Zabra'sRegalia" value: { - dps: 2931.07129 - tps: 2466.1225 + dps: 2931.27671 + tps: 2466.27309 } } dps_results: { key: "TestSmite-Average-Default" value: { - dps: 2892.02467 - tps: 2428.5357 + dps: 2892.01638 + tps: 2428.52981 } } dps_results: { key: "TestSmite-Settings-Undead-p1-Basic-default-FullBuffs-LongMultiTarget" value: { - dps: 2901.38893 - tps: 3015.57684 + dps: 2901.60191 + tps: 3015.73285 } } dps_results: { key: "TestSmite-Settings-Undead-p1-Basic-default-FullBuffs-LongSingleTarget" value: { - dps: 2901.38893 - tps: 2436.84342 + dps: 2901.60191 + tps: 2436.99942 } } dps_results: { key: "TestSmite-Settings-Undead-p1-Basic-default-FullBuffs-ShortSingleTarget" value: { - dps: 4835.0054 - tps: 4107.07385 + dps: 4836.07031 + tps: 4107.85388 } } dps_results: { @@ -855,13 +855,13 @@ dps_results: { key: "TestSmite-Settings-Undead-p1-Basic-default-NoBuffs-ShortSingleTarget" value: { dps: 2520.9093 - tps: 2126.72097 + tps: 2134.74022 } } dps_results: { key: "TestSmite-SwitchInFrontOfTarget-Default" value: { - dps: 2901.38893 - tps: 2436.84342 + dps: 2901.60191 + tps: 2436.99942 } } diff --git a/sim/rogue/TestCombat.results b/sim/rogue/TestCombat.results index 094e9c81fc..78ab4bff78 100644 --- a/sim/rogue/TestCombat.results +++ b/sim/rogue/TestCombat.results @@ -981,43 +981,43 @@ dps_results: { dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Deadly-fan_aoe-FullBuffs-LongMultiTarget" value: { - dps: 21435.04268 - tps: 15218.8803 + dps: 21132.20952 + tps: 15003.86876 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Deadly-fan_aoe-FullBuffs-LongSingleTarget" value: { - dps: 3539.13966 - tps: 2512.78916 + dps: 3516.89637 + tps: 2496.99642 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Deadly-fan_aoe-FullBuffs-ShortSingleTarget" value: { - dps: 4297.57812 - tps: 3051.28047 + dps: 4109.75712 + tps: 2917.92755 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Deadly-fan_aoe-NoBuffs-LongMultiTarget" value: { - dps: 13206.06312 - tps: 9376.30481 + dps: 13003.58802 + tps: 9232.54749 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Deadly-fan_aoe-NoBuffs-LongSingleTarget" value: { - dps: 1785.96568 - tps: 1268.03563 + dps: 1778.52693 + tps: 1262.75412 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Deadly-fan_aoe-NoBuffs-ShortSingleTarget" value: { - dps: 1898.48085 - tps: 1347.9214 + dps: 1863.43428 + tps: 1323.03834 } } dps_results: { @@ -1149,43 +1149,43 @@ dps_results: { dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Instant-fan_aoe-FullBuffs-LongMultiTarget" value: { - dps: 23026.48078 - tps: 16348.80135 + dps: 22695.82072 + tps: 16114.03271 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Instant-fan_aoe-FullBuffs-LongSingleTarget" value: { - dps: 4633.5605 - tps: 3289.82796 + dps: 4601.62498 + tps: 3267.15373 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Instant-fan_aoe-FullBuffs-ShortSingleTarget" value: { - dps: 5540.589 - tps: 3933.81819 + dps: 5306.8537 + tps: 3767.86612 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Instant-fan_aoe-NoBuffs-LongMultiTarget" value: { - dps: 13454.08262 - tps: 9552.39866 + dps: 13260.84412 + tps: 9415.19933 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Instant-fan_aoe-NoBuffs-LongSingleTarget" value: { - dps: 2312.07404 - tps: 1641.57257 + dps: 2301.87343 + tps: 1634.33013 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Instant-fan_aoe-NoBuffs-ShortSingleTarget" value: { - dps: 2393.64181 - tps: 1699.48569 + dps: 2337.44435 + tps: 1659.58549 } } dps_results: { @@ -1317,43 +1317,43 @@ dps_results: { dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Deadly-fan_aoe-FullBuffs-LongMultiTarget" value: { - dps: 25576.22706 - tps: 18159.12122 + dps: 25256.98021 + tps: 17932.45595 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Deadly-fan_aoe-FullBuffs-LongSingleTarget" value: { - dps: 5051.3607 - tps: 3586.46609 + dps: 5018.34623 + tps: 3563.02583 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Deadly-fan_aoe-FullBuffs-ShortSingleTarget" value: { - dps: 6092.44116 - tps: 4325.63322 + dps: 5809.23206 + tps: 4124.55476 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Deadly-fan_aoe-NoBuffs-LongMultiTarget" value: { - dps: 15002.54589 - tps: 10651.80759 + dps: 14807.07114 + tps: 10513.02051 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Deadly-fan_aoe-NoBuffs-LongSingleTarget" value: { - dps: 2529.97284 - tps: 1796.28072 + dps: 2519.14739 + tps: 1788.59464 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Deadly-fan_aoe-NoBuffs-ShortSingleTarget" value: { - dps: 2644.86445 - tps: 1877.85376 + dps: 2588.00612 + tps: 1837.48434 } } dps_results: { @@ -1485,43 +1485,43 @@ dps_results: { dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Instant-fan_aoe-FullBuffs-LongMultiTarget" value: { - dps: 19109.11172 - tps: 13567.46932 + dps: 18824.30249 + tps: 13365.25477 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Instant-fan_aoe-FullBuffs-LongSingleTarget" value: { - dps: 4217.58491 - tps: 2994.48528 + dps: 4189.47287 + tps: 2974.52573 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Instant-fan_aoe-FullBuffs-ShortSingleTarget" value: { - dps: 5274.9979 - tps: 3745.24851 + dps: 5004.60982 + tps: 3553.27297 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Instant-fan_aoe-NoBuffs-LongMultiTarget" value: { - dps: 11025.5797 - tps: 7828.16159 + dps: 10831.81586 + tps: 7690.58926 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Instant-fan_aoe-NoBuffs-LongSingleTarget" value: { - dps: 1993.74101 - tps: 1415.55612 + dps: 1983.7099 + tps: 1408.43403 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Instant-fan_aoe-NoBuffs-ShortSingleTarget" value: { - dps: 2156.33219 - tps: 1530.99585 + dps: 2101.37058 + tps: 1491.97311 } } dps_results: { @@ -1653,43 +1653,43 @@ dps_results: { dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Deadly-fan_aoe-FullBuffs-LongMultiTarget" value: { - dps: 21615.92487 - tps: 15347.30666 + dps: 21290.63515 + tps: 15116.35096 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Deadly-fan_aoe-FullBuffs-LongSingleTarget" value: { - dps: 3565.29603 - tps: 2531.36018 + dps: 3540.60866 + tps: 2513.83215 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Deadly-fan_aoe-FullBuffs-ShortSingleTarget" value: { - dps: 4362.48163 - tps: 3097.36196 + dps: 4172.47671 + tps: 2962.45847 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Deadly-fan_aoe-NoBuffs-LongMultiTarget" value: { - dps: 13327.72899 - tps: 9462.68758 + dps: 13113.07646 + tps: 9310.28429 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Deadly-fan_aoe-NoBuffs-LongSingleTarget" value: { - dps: 1801.49013 - tps: 1279.05799 + dps: 1793.27032 + tps: 1273.22193 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Deadly-fan_aoe-NoBuffs-ShortSingleTarget" value: { - dps: 1933.6019 - tps: 1372.85735 + dps: 1900.39941 + tps: 1349.28358 } } dps_results: { @@ -1821,43 +1821,43 @@ dps_results: { dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Instant-fan_aoe-FullBuffs-LongMultiTarget" value: { - dps: 23204.3601 - tps: 16475.09567 + dps: 22855.23185 + tps: 16227.21462 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Instant-fan_aoe-FullBuffs-LongSingleTarget" value: { - dps: 4667.4418 - tps: 3313.88368 + dps: 4631.68558 + tps: 3288.49676 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Instant-fan_aoe-FullBuffs-ShortSingleTarget" value: { - dps: 5622.83334 - tps: 3992.21167 + dps: 5384.15189 + tps: 3822.74784 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Instant-fan_aoe-NoBuffs-LongMultiTarget" value: { - dps: 13586.68098 - tps: 9646.54349 + dps: 13404.07154 + tps: 9516.8908 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Instant-fan_aoe-NoBuffs-LongSingleTarget" value: { - dps: 2332.01436 - tps: 1655.7302 + dps: 2322.07483 + tps: 1648.67313 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Instant-fan_aoe-NoBuffs-ShortSingleTarget" value: { - dps: 2435.28497 - tps: 1729.05233 + dps: 2383.73941 + tps: 1692.45498 } } dps_results: { @@ -1989,43 +1989,43 @@ dps_results: { dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Deadly-fan_aoe-FullBuffs-LongMultiTarget" value: { - dps: 25775.50672 - tps: 18300.60977 + dps: 25439.18557 + tps: 18061.82176 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Deadly-fan_aoe-FullBuffs-LongSingleTarget" value: { - dps: 5087.70125 - tps: 3612.26789 + dps: 5052.03546 + tps: 3586.94518 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Deadly-fan_aoe-FullBuffs-ShortSingleTarget" value: { - dps: 6179.0402 - tps: 4387.11854 + dps: 5894.33138 + tps: 4184.97528 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Deadly-fan_aoe-NoBuffs-LongMultiTarget" value: { - dps: 15142.98192 - tps: 10751.51716 + dps: 14939.32565 + tps: 10606.92121 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Deadly-fan_aoe-NoBuffs-LongSingleTarget" value: { - dps: 2550.98882 - tps: 1811.20206 + dps: 2539.17634 + tps: 1802.8152 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Deadly-fan_aoe-NoBuffs-ShortSingleTarget" value: { - dps: 2689.5647 - tps: 1909.59093 + dps: 2635.71107 + tps: 1871.35486 } } dps_results: { @@ -2157,43 +2157,43 @@ dps_results: { dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Instant-fan_aoe-FullBuffs-LongMultiTarget" value: { - dps: 19281.73013 - tps: 13690.02839 + dps: 18971.67938 + tps: 13469.89236 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Instant-fan_aoe-FullBuffs-LongSingleTarget" value: { - dps: 4255.39217 - tps: 3021.32844 + dps: 4220.37505 + tps: 2996.46629 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Instant-fan_aoe-FullBuffs-ShortSingleTarget" value: { - dps: 5352.90194 - tps: 3800.56038 + dps: 5084.05186 + tps: 3609.67682 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Instant-fan_aoe-NoBuffs-LongMultiTarget" value: { - dps: 11144.86205 - tps: 7912.85206 + dps: 10943.42878 + tps: 7769.83444 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Instant-fan_aoe-NoBuffs-LongSingleTarget" value: { - dps: 2007.95517 - tps: 1425.64817 + dps: 1997.50981 + tps: 1418.23196 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Instant-fan_aoe-NoBuffs-ShortSingleTarget" value: { - dps: 2196.75486 - tps: 1559.69595 + dps: 2147.90528 + tps: 1525.01275 } } dps_results: { From f75c707da58a6e283082c25a941fea387267e007 Mon Sep 17 00:00:00 2001 From: James Tanner Date: Sat, 6 Jan 2024 10:05:08 -0800 Subject: [PATCH 11/28] Commit before making another fix in master --- sim/shaman/bloodlust.go | 13 +- sim/shaman/elemental/elemental.go | 30 +- sim/shaman/elemental/elemental_test.go | 4 +- sim/shaman/elemental/rotation.go | 311 --------------- sim/shaman/enhancement/enhancement.go | 84 ---- sim/shaman/enhancement/enhancement_test.go | 6 +- sim/shaman/enhancement/priority_rotation.go | 411 -------------------- sim/shaman/enhancement/rotation.go | 31 -- sim/shaman/fire_elemental_pet.go | 1 - sim/shaman/fire_elemental_totem.go | 39 +- sim/shaman/fire_totems.go | 59 +-- sim/shaman/restoration/restoration.go | 20 +- sim/shaman/restoration/rotation.go | 58 --- sim/shaman/shaman.go | 133 +------ sim/shaman/shamanistic_rage.go | 30 +- sim/shaman/totems.go | 41 -- ui/elemental_shaman/apls/advanced.apl.json | 1 - 17 files changed, 22 insertions(+), 1250 deletions(-) delete mode 100644 sim/shaman/elemental/rotation.go delete mode 100644 sim/shaman/enhancement/priority_rotation.go delete mode 100644 sim/shaman/enhancement/rotation.go delete mode 100644 sim/shaman/restoration/rotation.go diff --git a/sim/shaman/bloodlust.go b/sim/shaman/bloodlust.go index 3e63f43d90..73dcebdf2d 100644 --- a/sim/shaman/bloodlust.go +++ b/sim/shaman/bloodlust.go @@ -12,9 +12,6 @@ func (shaman *Shaman) BloodlustActionID() core.ActionID { } func (shaman *Shaman) registerBloodlustCD() { - if !shaman.SelfBuffs.Bloodlust && !shaman.IsUsingAPL { - return - } actionID := shaman.BloodlustActionID() blAuras := []*core.Aura{} @@ -24,7 +21,7 @@ func (shaman *Shaman) registerBloodlustCD() { } } - bloodlustSpell := shaman.RegisterSpell(core.SpellConfig{ + shaman.RegisterSpell(core.SpellConfig{ ActionID: actionID, Flags: core.SpellFlagAPL, @@ -72,12 +69,4 @@ func (shaman *Shaman) registerBloodlustCD() { } }, }) - - if !shaman.IsUsingAPL { - shaman.AddMajorCooldown(core.MajorCooldown{ - Spell: bloodlustSpell, - Priority: core.CooldownPriorityBloodlust, - Type: core.CooldownTypeDPS, - }) - } } diff --git a/sim/shaman/elemental/elemental.go b/sim/shaman/elemental/elemental.go index 3e734f02d6..aa4a5e1bfd 100644 --- a/sim/shaman/elemental/elemental.go +++ b/sim/shaman/elemental/elemental.go @@ -32,37 +32,16 @@ func NewElementalShaman(character *core.Character, options *proto.Player) *Eleme Shield: eleShamOptions.Options.Shield, } - if eleShamOptions.Rotation.Bloodlust != proto.ElementalShaman_Rotation_UnsetBloodlust { - selfBuffs.Bloodlust = eleShamOptions.Rotation.Bloodlust == proto.ElementalShaman_Rotation_UseBloodlust - } - totems := &proto.ShamanTotems{} if eleShamOptions.Options.Totems != nil { totems = eleShamOptions.Options.Totems totems.UseFireMcd = true // Control fire totems as MCD. } - var rotation Rotation - - switch eleShamOptions.Rotation.Type { - case proto.ElementalShaman_Rotation_Adaptive: - rotation = NewAdaptiveRotation(eleShamOptions.Rotation) - case proto.ElementalShaman_Rotation_Manual: - rotation = NewManualRotation(eleShamOptions.Rotation) - default: - rotation = NewAdaptiveRotation(eleShamOptions.Rotation) - } - - inRange := eleShamOptions.Rotation.InThunderstormRange - if eleShamOptions.Options.ThunderstormRange != proto.ElementalShaman_Options_UnsetTSRange { - inRange = eleShamOptions.Options.ThunderstormRange == proto.ElementalShaman_Options_TSInRange - } + inRange := eleShamOptions.Options.ThunderstormRange == proto.ElementalShaman_Options_TSInRange ele := &ElementalShaman{ - Shaman: shaman.NewShaman(character, options.TalentsString, totems, selfBuffs, inRange), - rotation: rotation, - has4pT6: character.HasSetBonus(shaman.ItemSetSkyshatterRegalia, 4), + Shaman: shaman.NewShaman(character, options.TalentsString, totems, selfBuffs, inRange), } - ele.EnableResumeAfterManaWait(ele.tryUseGCD) if mh := ele.GetMHWeapon(); mh != nil { ele.ApplyFlametongueImbueToItem(mh, false) @@ -90,10 +69,6 @@ func NewElementalShaman(character *core.Character, options *proto.Player) *Eleme type ElementalShaman struct { *shaman.Shaman - - rotation Rotation - - has4pT6 bool } func (eleShaman *ElementalShaman) GetShaman() *shaman.Shaman { @@ -102,5 +77,4 @@ func (eleShaman *ElementalShaman) GetShaman() *shaman.Shaman { func (eleShaman *ElementalShaman) Reset(sim *core.Simulation) { eleShaman.Shaman.Reset(sim) - eleShaman.rotation.Reset(eleShaman, sim) } diff --git a/sim/shaman/elemental/elemental_test.go b/sim/shaman/elemental/elemental_test.go index fe06b3efc2..5a20559d19 100644 --- a/sim/shaman/elemental/elemental_test.go +++ b/sim/shaman/elemental/elemental_test.go @@ -113,9 +113,8 @@ var PlayerOptionsAdaptive = &proto.Player_ElementalShaman{ Options: &proto.ElementalShaman_Options{ Shield: proto.ShamanShield_WaterShield, Bloodlust: true, - Totems: BasicTotems, + Totems: FireElementalBasicTotems, }, - Rotation: &proto.ElementalShaman_Rotation{}, }, } @@ -126,7 +125,6 @@ var PlayerOptionsAdaptiveFireElemental = &proto.Player_ElementalShaman{ Bloodlust: true, Totems: FireElementalBasicTotems, }, - Rotation: &proto.ElementalShaman_Rotation{}, }, } diff --git a/sim/shaman/elemental/rotation.go b/sim/shaman/elemental/rotation.go deleted file mode 100644 index 3847fdbd7e..0000000000 --- a/sim/shaman/elemental/rotation.go +++ /dev/null @@ -1,311 +0,0 @@ -package elemental - -import ( - "time" - - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/core/proto" -) - -// func (eleShaman *ElementalShaman) GetPresimOptions(_ proto.Player) *core.PresimOptions { -// return eleShaman.rotation.GetPresimOptions() -// } - -func (eleShaman *ElementalShaman) OnGCDReady(sim *core.Simulation) { - if eleShaman.IsUsingAPL { - return - } - - eleShaman.tryUseGCD(sim) -} - -func (eleShaman *ElementalShaman) tryUseGCD(sim *core.Simulation) { - if eleShaman.TryDropTotems(sim) { - return - } - - eleShaman.rotation.DoAction(eleShaman, sim) -} - -// Picks which attacks / abilities the Shaman does. -type Rotation interface { - // GetPresimOptions() *core.PresimOptions - - // Returns the action this rotation would like to take next. - DoAction(*ElementalShaman, *core.Simulation) - - // Returns this rotation to its initial state. Called before each Sim iteration. - Reset(*ElementalShaman, *core.Simulation) -} - -// ################################################################ -// -// ADAPTIVE -// -// ################################################################ -type AdaptiveRotation struct { - fnmm float64 - clmm float64 - lvbFSWait time.Duration -} - -func (rotation *AdaptiveRotation) DoAction(eleShaman *ElementalShaman, sim *core.Simulation) { - target := eleShaman.CurrentTarget - - shouldTS := false - cmp := eleShaman.CurrentManaPercent() - percent := sim.GetRemainingDurationPercent() - 0.1 - if eleShaman.Env.GetNumTargets() > 1 { - percent = 0.9 // single target we need less mana. - } - if cmp < percent { - shouldTS = true - } - if shouldTS && eleShaman.Thunderstorm.IsReady(sim) { - eleShaman.Thunderstorm.Cast(sim, target) - return - } - - fsTime := eleShaman.FlameShock.CurDot().RemainingDuration(sim) - lvTime := eleShaman.LavaBurst.CD.TimeToReady(sim) - lvCastTime := eleShaman.ApplyCastSpeed(eleShaman.LavaBurst.DefaultCast.CastTime) - if fsTime <= 0 && eleShaman.FlameShock.IsReady(sim) { - if !eleShaman.FlameShock.Cast(sim, target) { - eleShaman.WaitForMana(sim, eleShaman.FlameShock.CurCast.Cost) - } - return - } else if fsTime > lvCastTime { - if lvTime <= 0 { - if !eleShaman.LavaBurst.Cast(sim, target) { - eleShaman.WaitForMana(sim, eleShaman.LavaBurst.CurCast.Cost) - } - return - } else if lvTime <= rotation.lvbFSWait && fsTime > lvCastTime+lvTime { - // If we have enough time to wait lvbFSWait and still have FS up, we should just wait to cast LvB. - eleShaman.WaitUntil(sim, sim.CurrentTime+lvTime) - return - } - } - - fsCD := eleShaman.FlameShock.CD.TimeToReady(sim) - if fsCD > fsTime { - fsTime = fsCD - } - // If FS will be needed and is ready in < lvbFSWait time, delay. - if fsTime <= rotation.lvbFSWait { - eleShaman.WaitUntil(sim, sim.CurrentTime+fsTime) - return - } - - if cmp > rotation.clmm && eleShaman.ChainLightning.IsReady(sim) { - clTime := eleShaman.ApplyCastSpeed(eleShaman.ChainLightning.DefaultCast.CastTime) - // Only CL if cast time > 1 second than CL or there is more than 1 target. - if clTime > core.GCDMin || eleShaman.Env.GetNumTargets() > 1 { - if !eleShaman.ChainLightning.Cast(sim, target) { - eleShaman.WaitForMana(sim, eleShaman.ChainLightning.CurCast.Cost) - } - return - } - } else if cmp > rotation.fnmm && eleShaman.FireNova.IsReady(sim) { - if !eleShaman.FireNova.Cast(sim, target) { - eleShaman.WaitForMana(sim, eleShaman.FireNova.CurCast.Cost) - } - return - } - - if !eleShaman.LightningBolt.Cast(sim, target) { - if sim.Log != nil { - eleShaman.Log(sim, "Failed to cast LB, cost: %0.1f, current mana: %0.1f\n") - } - eleShaman.WaitForMana(sim, eleShaman.LightningBolt.CurCast.Cost) - } -} - -func (rotation *AdaptiveRotation) Reset(_ *ElementalShaman, sim *core.Simulation) { - rotation.fnmm = 1.0 - rotation.clmm = 1.0 - if len(sim.Encounter.Targets) > 4 { - // 5+ targets FN is better - rotation.fnmm = 0.33 - // Allow CL as long as you have decent mana (leaving most mana for FN) - rotation.clmm = 0.5 - } else if len(sim.Encounter.Targets) == 4 { - // 4 targets, enable both similar prio, prob looking at real AoE now (short fight) - rotation.clmm = 0.33 - rotation.fnmm = 0.33 - } else if len(sim.Encounter.Targets) == 3 { - // 3 targets, enable both, but prio CL (more efficient) - // Still trying to be very mana efficient as 3 targets - // is still often a "boss fight" and could be long. - rotation.clmm = 0.33 - rotation.fnmm = 0.66 - } else if len(sim.Encounter.Targets) == 2 { - // enable CL with 2 - rotation.clmm = 0.33 - } -} - -// func (rotation *AdaptiveRotation) GetPresimOptions() *core.PresimOptions { -// return &core.PresimOptions{ -// SetPresimPlayerOptions: func(player *proto.Player) { -// }, - -// OnPresimResult: func(presimResult proto.UnitMetrics, iterations int32, duration time.Duration) bool { -// return true -// }, -// } -// } - -func NewAdaptiveRotation(options *proto.ElementalShaman_Rotation) *AdaptiveRotation { - if options.LvbFsWaitMs == 0 { - options.LvbFsWaitMs = 175 - } - return &AdaptiveRotation{ - lvbFSWait: time.Duration(options.LvbFsWaitMs) * time.Millisecond, - } -} - -// ################################################################ -// -// MANUAL -// -// ################################################################ -type ManualRotation struct { - options *proto.ElementalShaman_Rotation -} - -func (rotation *ManualRotation) DoAction(eleShaman *ElementalShaman, sim *core.Simulation) { - target := eleShaman.CurrentTarget - lvbFSWait := time.Duration(rotation.options.LvbFsWaitMs) * time.Millisecond - shouldTS := false - cmp := eleShaman.CurrentManaPercent() - - // TODO: expose these percents to let user tweak - percent := sim.GetRemainingDurationPercent() - 0.1 - if eleShaman.Env.GetNumTargets() > 1 { - percent = 0.9 - } - if cmp < percent { - shouldTS = true - } - if shouldTS && rotation.options.UseThunderstorm && eleShaman.Thunderstorm.IsReady(sim) { - eleShaman.Thunderstorm.Cast(sim, target) - return - } - - fsRemain := eleShaman.FlameShock.CurDot().RemainingDuration(sim) - needFS := fsRemain <= 0 - // Only overwrite if lvb is ready right now. - if !needFS && rotation.options.OverwriteFlameshock && eleShaman.LavaBurst.CD.TimeToReady(sim) <= core.GCDDefault { - lvbTime := max(eleShaman.ApplyCastSpeed(eleShaman.LavaBurst.DefaultCast.CastTime), core.GCDMin) - if fsRemain < lvbTime { - needFS = true - } - } - - allowLvB := true - if rotation.options.AlwaysCritLvb { - lvbTime := max(eleShaman.ApplyCastSpeed(eleShaman.LavaBurst.DefaultCast.CastTime), core.GCDMin) - if fsRemain <= lvbTime { - allowLvB = false - } - } - - shouldCL := rotation.options.UseChainLightning && cmp > (rotation.options.ClMinManaPer/100) && eleShaman.ChainLightning.IsReady(sim) - clTime := eleShaman.ApplyCastSpeed(eleShaman.ChainLightning.DefaultCast.CastTime) - - // Never cast CL if single target and cast time <= 1 second - // This is effecively a waste of haste (that is probably temporary.) - if clTime <= time.Second && eleShaman.Env.GetNumTargets() == 1 { - shouldCL = false - } - lvbCD := eleShaman.LavaBurst.CD.TimeToReady(sim) - if shouldCL && rotation.options.UseClOnlyGap { - shouldCL = false - clCast := max(eleShaman.ApplyCastSpeed(eleShaman.ChainLightning.DefaultCast.CastTime), core.GCDMin) - // If LvB CD < CL cast time, we should use CL to pass the time until then. - // Or if FS is about to expire and we didn't cast LvB. - if fsRemain <= clCast || (lvbCD <= clCast) { - shouldCL = true - } - } - - fsCD := eleShaman.FlameShock.CD.TimeToReady(sim) - if fsCD > fsRemain { - fsRemain = fsCD - } - - // If FS will be needed and is ready in < lvbFSWait time, delay. - if fsRemain <= lvbFSWait && fsRemain > 0 { - eleShaman.WaitUntil(sim, sim.CurrentTime+fsRemain) - return - } - - // If LvB will be ready in < lvbFSWait time, delay - if lvbCD <= lvbFSWait && lvbCD > 0 { - eleShaman.WaitUntil(sim, sim.CurrentTime+lvbCD) - return - } - - if needFS && eleShaman.FlameShock.IsReady(sim) { - if !eleShaman.FlameShock.Cast(sim, target) { - eleShaman.WaitForMana(sim, eleShaman.FlameShock.CurCast.Cost) - } - return - } else if allowLvB && eleShaman.LavaBurst.IsReady(sim) { - if !eleShaman.LavaBurst.Cast(sim, target) { - eleShaman.WaitForMana(sim, eleShaman.LavaBurst.CurCast.Cost) - } - return - } else if shouldCL { - if !eleShaman.ChainLightning.Cast(sim, target) { - eleShaman.WaitForMana(sim, eleShaman.ChainLightning.CurCast.Cost) - } - return - } else if rotation.options.UseFireNova && cmp > (rotation.options.FnMinManaPer/100) && eleShaman.FireNova.IsReady(sim) { - if !eleShaman.FireNova.Cast(sim, target) { - eleShaman.WaitForMana(sim, eleShaman.FireNova.CurCast.Cost) - } - return - } - - if !eleShaman.LightningBolt.Cast(sim, target) { - if sim.Log != nil { - eleShaman.Log(sim, "Failed to cast LB, cost: %0.1f, current mana: %0.1f\n") - } - eleShaman.WaitForMana(sim, eleShaman.LightningBolt.CurCast.Cost) - } -} - -func (rotation *ManualRotation) Reset(_ *ElementalShaman, _ *core.Simulation) { -} - -// func (rotation *ManualRotation) GetPresimOptions() *core.PresimOptions { -// return &core.PresimOptions{ -// SetPresimPlayerOptions: func(player *proto.Player) { -// }, - -// OnPresimResult: func(presimResult proto.UnitMetrics, iterations int32, duration time.Duration) bool { -// return true -// }, -// } -// } - -func NewManualRotation(options *proto.ElementalShaman_Rotation) *ManualRotation { - return &ManualRotation{ - options: options, - } -} - -// A single action that an Agent can take. -type AgentAction interface { - GetActionID() core.ActionID - - // TODO: Maybe change this to 'ResourceCost' - // Amount of mana required to perform the action. - GetManaCost() float64 - - // Do the action. Returns whether the action was successful. An unsuccessful - // action indicates that the prerequisites, like resource cost, were not met. - Cast(sim *core.Simulation) bool -} diff --git a/sim/shaman/enhancement/enhancement.go b/sim/shaman/enhancement/enhancement.go index 00d3ef34e8..e1653492f2 100644 --- a/sim/shaman/enhancement/enhancement.go +++ b/sim/shaman/enhancement/enhancement.go @@ -3,7 +3,6 @@ package enhancement import ( "time" - "github.com/wowsims/wotlk/sim/common" "github.com/wowsims/wotlk/sim/core" "github.com/wowsims/wotlk/sim/core/proto" "github.com/wowsims/wotlk/sim/shaman" @@ -36,11 +35,6 @@ func NewEnhancementShaman(character *core.Character, options *proto.Player) *Enh ImbueOH: enhOptions.Options.ImbueOh, } - // Override with new rotation option bloodlust. - if enhOptions.Rotation.Bloodlust != proto.EnhancementShaman_Rotation_UnsetBloodlust { - selfBuffs.Bloodlust = enhOptions.Rotation.Bloodlust == proto.EnhancementShaman_Rotation_UseBloodlust - } - totems := &proto.ShamanTotems{} if enhOptions.Options.Totems != nil { totems = enhOptions.Options.Totems @@ -50,9 +44,6 @@ func NewEnhancementShaman(character *core.Character, options *proto.Player) *Enh Shaman: shaman.NewShaman(character, options.TalentsString, totems, selfBuffs, true), } - enh.EnableResumeAfterManaWait(enh.OnGCDReady) - enh.rotation = NewPriorityRotation(enh, enhOptions.Rotation) - // Enable Auto Attacks for this spec enh.EnableAutoAttacks(enh, core.AutoAttackOptions{ MainHand: enh.WeaponFromMainHand(enh.DefaultMeleeCritMultiplier()), @@ -64,12 +55,6 @@ func NewEnhancementShaman(character *core.Character, options *proto.Player) *Enh enh.ApplyFlametongueImbue(enh.getImbueProcMask(proto.ShamanImbue_FlametongueWeapon), false) enh.ApplyFlametongueImbue(enh.getImbueProcMask(proto.ShamanImbue_FlametongueWeaponDownrank), true) - if enhOptions.Rotation.LightningboltWeave { - enh.maelstromWeaponMinStack = enhOptions.Rotation.MaelstromweaponMinStack - } else { - enh.maelstromWeaponMinStack = 5 - } - if !enh.HasMHWeapon() { enh.SelfBuffs.ImbueMH = proto.ShamanImbue_NoImbue } @@ -83,8 +68,6 @@ func NewEnhancementShaman(character *core.Character, options *proto.Player) *Enh SpiritWolf2: enh.NewSpiritWolf(2), } - enh.ShamanisticRageManaThreshold = enhOptions.Rotation.ShamanisticRageManaThreshold - return enh } @@ -102,13 +85,8 @@ func (enh *EnhancementShaman) getImbueProcMask(imbue proto.ShamanImbue) core.Pro type EnhancementShaman struct { *shaman.Shaman - rotation Rotation - maelstromWeaponMinStack int32 - // for weaving Lava Burst or Lightning Bolt previousSwingAt time.Duration - - scheduler common.GCDScheduler } func (enh *EnhancementShaman) GetShaman() *shaman.Shaman { @@ -132,13 +110,6 @@ func (enh *EnhancementShaman) Initialize() { enh.ApplySyncType(proto.ShamanSyncType_Auto) }) } - enh.DelayDPSCooldowns(3 * time.Second) - - if !enh.IsUsingAPL { - enh.RegisterPrepullAction(-time.Second, func(sim *core.Simulation) { - enh.ItemSwap.SwapItems(sim, []proto.ItemSlot{proto.ItemSlot_ItemSlotMainHand, proto.ItemSlot_ItemSlotOffHand}) - }) - } } func (enh *EnhancementShaman) Reset(sim *core.Simulation) { @@ -183,58 +154,3 @@ func (enh *EnhancementShaman) ApplySyncType(syncType proto.ShamanSyncType) { enh.AutoAttacks.SetReplaceMHSwing(nil) } } - -func (enh *EnhancementShaman) CastLightningBoltWeave(sim *core.Simulation, reactionTime time.Duration) bool { - previousAttack := sim.CurrentTime - enh.previousSwingAt - reactionTime = core.TernaryDuration(previousAttack < reactionTime, reactionTime-previousAttack, 0) - - //calculate cast times for weaving - lbCastTime := enh.ApplyCastSpeed(enh.LightningBolt.DefaultCast.CastTime-(time.Millisecond*time.Duration(500*enh.MaelstromWeaponAura.GetStacks()))) + reactionTime - //calculate swing times for weaving - timeUntilSwing := enh.AutoAttacks.NextAttackAt() - sim.CurrentTime - - if lbCastTime < timeUntilSwing { - if reactionTime > 0 { - reactionTime += sim.CurrentTime - - enh.HardcastWaitUntil(sim, reactionTime, func(_ *core.Simulation, _ *core.Unit) { - enh.GCD.Reset() - enh.LightningBolt.Cast(sim, enh.CurrentTarget) - }) - - enh.WaitUntil(sim, reactionTime) - return true - } - return enh.LightningBolt.Cast(sim, enh.CurrentTarget) - } - - return false -} - -func (enh *EnhancementShaman) CastLavaBurstWeave(sim *core.Simulation, reactionTime time.Duration) bool { - previousAttack := sim.CurrentTime - enh.previousSwingAt - reactionTime = core.TernaryDuration(previousAttack < reactionTime, reactionTime-previousAttack, 0) - - //calculate cast times for weaving - lvbCastTime := enh.ApplyCastSpeed(enh.LavaBurst.DefaultCast.CastTime) + reactionTime - //calculate swing times for weaving - timeUntilSwing := enh.AutoAttacks.NextAttackAt() - sim.CurrentTime - - if lvbCastTime < timeUntilSwing { - if reactionTime > 0 { - reactionTime += sim.CurrentTime - - enh.HardcastWaitUntil(sim, reactionTime, func(_ *core.Simulation, _ *core.Unit) { - enh.GCD.Reset() - enh.LavaBurst.Cast(sim, enh.CurrentTarget) - }) - - enh.WaitUntil(sim, reactionTime) - return true - } - - return enh.LavaBurst.Cast(sim, enh.CurrentTarget) - } - - return false -} diff --git a/sim/shaman/enhancement/enhancement_test.go b/sim/shaman/enhancement/enhancement_test.go index 33d9f3dd8b..14da520aef 100644 --- a/sim/shaman/enhancement/enhancement_test.go +++ b/sim/shaman/enhancement/enhancement_test.go @@ -87,15 +87,13 @@ var StandardGlyphs = &proto.Glyphs{ var PlayerOptionsWFWF = &proto.Player_EnhancementShaman{ EnhancementShaman: &proto.EnhancementShaman{ - Options: enhShamWFWF, - Rotation: &proto.EnhancementShaman_Rotation{}, + Options: enhShamWFWF, }, } var PlayerOptionsFTFT = &proto.Player_EnhancementShaman{ EnhancementShaman: &proto.EnhancementShaman{ - Options: enhShamFTFT, - Rotation: &proto.EnhancementShaman_Rotation{}, + Options: enhShamFTFT, }, } diff --git a/sim/shaman/enhancement/priority_rotation.go b/sim/shaman/enhancement/priority_rotation.go deleted file mode 100644 index 8a1900dfba..0000000000 --- a/sim/shaman/enhancement/priority_rotation.go +++ /dev/null @@ -1,411 +0,0 @@ -package enhancement - -import ( - "time" - - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/core/proto" -) - -// Default Priority Order -const ( - LightningBolt = iota - StormstrikeApplyDebuff - WeaveLavaBurst - WeaveLightningBolt - MagmaTotem - Stormstrike - FlameShock - EarthShock - FrostShock - FireNova - DelayedWeave - LightningShield - DropAllTotems - LavaLash - NumberSpells // Used to get the max number of spells in the prio list, keep at bottoom -) - -type PriorityRotation struct { - options *proto.EnhancementShaman_Rotation - spellPriority []Spell -} - -type Cast func(sim *core.Simulation, target *core.Unit) bool -type Condition func(sim *core.Simulation, target *core.Unit) bool -type ReadyAt func() time.Duration - -// Holds all the spell info we need to make decisions -type Spell struct { - readyAt ReadyAt - cast Cast - // Must pass this check to cast or use readyAt, a special condition to be met - condition Condition -} - -func NewPriorityRotation(enh *EnhancementShaman, options *proto.EnhancementShaman_Rotation) *PriorityRotation { - rotation := &PriorityRotation{ - options: options, - } - - rotation.buildPriorityRotation(enh) - - return rotation -} - -func (rotation *PriorityRotation) buildPriorityRotation(enh *EnhancementShaman) { - stormstrikeApplyDebuff := Spell{ - condition: func(sim *core.Simulation, target *core.Unit) bool { - return !enh.StormstrikeDebuffAura(target).IsActive() - }, - cast: func(sim *core.Simulation, target *core.Unit) bool { - return enh.Stormstrike.IsReady(sim) && enh.Stormstrike.Cast(sim, target) - }, - readyAt: func() time.Duration { - return enh.Stormstrike.ReadyAt() - }, - } - - instantLightningBolt := Spell{ - condition: func(sim *core.Simulation, target *core.Unit) bool { - return enh.MaelstromWeaponAura.GetStacks() == 5 - }, - cast: func(sim *core.Simulation, target *core.Unit) bool { - return enh.LightningBolt.Cast(sim, enh.CurrentTarget) - }, - readyAt: func() time.Duration { - return 0 - }, - } - - chainLightning := Spell{ - condition: func(sim *core.Simulation, target *core.Unit) bool { - return enh.MaelstromWeaponAura.GetStacks() == 5 && enh.ChainLightning.IsReady(sim) - }, - cast: func(sim *core.Simulation, target *core.Unit) bool { - return enh.ChainLightning.Cast(sim, enh.CurrentTarget) - }, - readyAt: func() time.Duration { - return 0 - }, - } - - stormstrike := Spell{ - condition: func(sim *core.Simulation, target *core.Unit) bool { - //Checking if we learned the spell, ie untalented - return enh.Stormstrike != nil - }, - cast: func(sim *core.Simulation, target *core.Unit) bool { - //TODO add in SS delay so we don't lose flametongues, if Last attack = current time - return enh.Stormstrike.IsReady(sim) && enh.Stormstrike.Cast(sim, target) - }, - readyAt: func() time.Duration { - return enh.Stormstrike.ReadyAt() - }, - } - - weaveLightningBolt := Spell{ - condition: func(sim *core.Simulation, target *core.Unit) bool { - return rotation.options.LightningboltWeave && enh.MaelstromWeaponAura.GetStacks() >= rotation.options.MaelstromweaponMinStack && enh.CurrentMana() >= enh.LightningBolt.DefaultCast.Cost - }, - cast: func(sim *core.Simulation, target *core.Unit) bool { - reactionTime := time.Millisecond * time.Duration(rotation.options.AutoWeaveDelay) - return enh.CastLightningBoltWeave(sim, reactionTime) - }, - readyAt: func() time.Duration { - return 0 - }, - } - - weaveLavaBurst := Spell{ - condition: func(sim *core.Simulation, target *core.Unit) bool { - if enh.CurrentMana() < enh.LavaBurst.CurCast.Cost { - return false - } - - return rotation.options.LavaburstWeave && enh.MaelstromWeaponAura.GetStacks() >= rotation.options.MaelstromweaponMinStack - }, - cast: func(sim *core.Simulation, target *core.Unit) bool { - reactionTime := time.Millisecond * time.Duration(rotation.options.AutoWeaveDelay) - return rotation.options.LavaburstWeave && enh.LavaBurst.IsReady(sim) && enh.CastLavaBurstWeave(sim, reactionTime) - }, - readyAt: func() time.Duration { - return 0 - }, - } - - flameShock := Spell{ - condition: func(sim *core.Simulation, target *core.Unit) bool { - fsDot := enh.FlameShock.Dot(target) - return rotation.options.WeaveFlameShock && fsDot.RemainingDuration(sim) <= time.Duration(rotation.options.FlameShockClipTicks)*fsDot.TickLength - }, - cast: func(sim *core.Simulation, target *core.Unit) bool { - return enh.FlameShock.IsReady(sim) && enh.FlameShock.Cast(sim, target) - }, - readyAt: func() time.Duration { - return enh.FlameShock.ReadyAt() - }, - } - - earthShock := Spell{ - condition: func(sim *core.Simulation, target *core.Unit) bool { - return rotation.options.PrimaryShock == proto.EnhancementShaman_Rotation_Earth - }, - cast: func(sim *core.Simulation, target *core.Unit) bool { - return enh.EarthShock.IsReady(sim) && enh.EarthShock.Cast(sim, target) - }, - readyAt: func() time.Duration { - return enh.EarthShock.ReadyAt() - }, - } - - frostShock := Spell{ - condition: func(sim *core.Simulation, target *core.Unit) bool { - return rotation.options.PrimaryShock == proto.EnhancementShaman_Rotation_Frost - }, - cast: func(sim *core.Simulation, target *core.Unit) bool { - return enh.FrostShock.IsReady(sim) && enh.FrostShock.Cast(sim, target) - }, - readyAt: func() time.Duration { - return enh.EarthShock.ReadyAt() - }, - } - - lightningShield := Spell{ - condition: func(sim *core.Simulation, target *core.Unit) bool { - return enh.LightningShield != nil && !enh.LightningShieldAura.IsActive() - }, - cast: func(sim *core.Simulation, _ *core.Unit) bool { - return enh.LightningShield.Cast(sim, nil) - }, - readyAt: func() time.Duration { - return 0 - }, - } - - fireNova := Spell{ - condition: func(sim *core.Simulation, target *core.Unit) bool { - if enh.Totems.Fire == proto.FireTotem_NoFireTotem { - return false - } - - return enh.NextTotemDrops[2] > sim.CurrentTime && enh.CurrentMana() > rotation.options.FirenovaManaThreshold - }, - cast: func(sim *core.Simulation, target *core.Unit) bool { - return enh.FireNova.IsReady(sim) && enh.FireNova.Cast(sim, target) - }, - readyAt: func() time.Duration { - return enh.FireNova.ReadyAt() - }, - } - - lavaLash := Spell{ - condition: func(sim *core.Simulation, target *core.Unit) bool { - //Checking if we learned the spell, ie untalented - return enh.LavaLash != nil && enh.AutoAttacks.IsDualWielding - }, - cast: func(sim *core.Simulation, target *core.Unit) bool { - //TODO add in LL delay so we don't lose flametongues, if Last attack = current time - return enh.LavaLash.IsReady(sim) && enh.LavaLash.Cast(sim, target) - }, - readyAt: func() time.Duration { - return enh.LavaLash.ReadyAt() - }, - } - - magmaTotem := Spell{ - condition: func(sim *core.Simulation, target *core.Unit) bool { - //TODO : rework totems to make them easier to work with. - return enh.Totems.Fire == proto.FireTotem_MagmaTotem && enh.NextTotemDrops[2] <= sim.CurrentTime - }, - cast: func(sim *core.Simulation, target *core.Unit) bool { - return enh.MagmaTotem.Cast(sim, target) - }, - readyAt: func() time.Duration { - return 0 - }, - } - - dropAllTotems := Spell{ - condition: func(sim *core.Simulation, target *core.Unit) bool { - return true - }, - cast: func(sim *core.Simulation, target *core.Unit) bool { - // TODO : totems need to be dropped all at once. - return enh.TryDropTotems(sim) - }, - readyAt: func() time.Duration { - return 0 - }, - } - - delayedWeave := Spell{ - condition: func(sim *core.Simulation, target *core.Unit) bool { - if enh.CurrentMana() < enh.LightningBolt.DefaultCast.Cost { - return false - } - - return rotation.options.LightningboltWeave && rotation.options.DelayGcdWeave > 0 && enh.MaelstromWeaponAura.GetStacks() >= rotation.options.MaelstromweaponMinStack - }, - cast: func(sim *core.Simulation, target *core.Unit) bool { - timeUntilSwing := enh.AutoAttacks.NextAttackAt() - sim.CurrentTime - if timeUntilSwing <= time.Millisecond*time.Duration(rotation.options.DelayGcdWeave) && timeUntilSwing != 0 { - delay := enh.AutoAttacks.NextAttackAt() + time.Millisecond*100 - if delay < sim.CurrentTime { - return false - } - - enh.HardcastWaitUntil(sim, delay, func(_ *core.Simulation, _ *core.Unit) { - enh.GCD.Reset() - enh.CastLightningBoltWeave(sim, 0) - }) - - enh.WaitUntil(sim, delay) - return true - } - - return false - }, - readyAt: func() time.Duration { - return 0 - }, - } - - //Normal Priority Rotation - var spellPriority []Spell - if rotation.options.RotationType == proto.EnhancementShaman_Rotation_Priority { - spellPriority = make([]Spell, NumberSpells) - spellPriority[StormstrikeApplyDebuff] = stormstrikeApplyDebuff - spellPriority[LightningBolt] = instantLightningBolt - spellPriority[Stormstrike] = stormstrike - spellPriority[FlameShock] = flameShock - spellPriority[EarthShock] = earthShock - spellPriority[LightningShield] = lightningShield - spellPriority[FireNova] = fireNova - spellPriority[LavaLash] = lavaLash - spellPriority[WeaveLightningBolt] = weaveLightningBolt - spellPriority[FrostShock] = frostShock - spellPriority[WeaveLavaBurst] = weaveLavaBurst - spellPriority[MagmaTotem] = magmaTotem - spellPriority[DropAllTotems] = dropAllTotems - spellPriority[DelayedWeave] = delayedWeave - } - - //Custom Priority Rotation - if rotation.options.RotationType == proto.EnhancementShaman_Rotation_Custom && rotation.options.CustomRotation != nil { - spellPriority := make([]Spell, 0, len(rotation.options.CustomRotation.Spells)) - - // Turn weaving off, will enable them if they have been added. - rotation.options.LightningboltWeave = false - rotation.options.LavaburstWeave = false - rotation.options.WeaveFlameShock = false - rotation.options.PrimaryShock = proto.EnhancementShaman_Rotation_None - for _, customSpellProto := range rotation.options.CustomRotation.Spells { - switch customSpellProto.Spell { - case int32(proto.EnhancementShaman_Rotation_StormstrikeDebuffMissing): - spellPriority = append(spellPriority, stormstrikeApplyDebuff) - case int32(proto.EnhancementShaman_Rotation_LightningBolt): - spellPriority = append(spellPriority, instantLightningBolt) - case int32(proto.EnhancementShaman_Rotation_ChainLightning): - spellPriority = append(spellPriority, chainLightning) - case int32(proto.EnhancementShaman_Rotation_LightningBoltWeave): - rotation.options.LightningboltWeave = true - spellPriority = append(spellPriority, weaveLightningBolt) - case int32(proto.EnhancementShaman_Rotation_LightningBoltDelayedWeave): - rotation.options.LightningboltWeave = true - spellPriority = append(spellPriority, delayedWeave) - case int32(proto.EnhancementShaman_Rotation_Stormstrike): - spellPriority = append(spellPriority, stormstrike) - case int32(proto.EnhancementShaman_Rotation_FlameShock): - rotation.options.WeaveFlameShock = true - spellPriority = append(spellPriority, flameShock) - case int32(proto.EnhancementShaman_Rotation_FireNova): - spellPriority = append(spellPriority, fireNova) - case int32(proto.EnhancementShaman_Rotation_LavaLash): - spellPriority = append(spellPriority, lavaLash) - case int32(proto.EnhancementShaman_Rotation_EarthShock): - if rotation.options.PrimaryShock == proto.EnhancementShaman_Rotation_None { - rotation.options.PrimaryShock = proto.EnhancementShaman_Rotation_Earth - spellPriority = append(spellPriority, earthShock) - } - case int32(proto.EnhancementShaman_Rotation_LightningShield): - spellPriority = append(spellPriority, lightningShield) - case int32(proto.EnhancementShaman_Rotation_FrostShock): - if rotation.options.PrimaryShock == proto.EnhancementShaman_Rotation_None { - rotation.options.PrimaryShock = proto.EnhancementShaman_Rotation_Frost - spellPriority = append(spellPriority, frostShock) - } - case int32(proto.EnhancementShaman_Rotation_LavaBurst): - rotation.options.LavaburstWeave = true - spellPriority = append(spellPriority, weaveLavaBurst) - case int32(proto.EnhancementShaman_Rotation_MagmaTotem): - spellPriority = append(spellPriority, magmaTotem) - } - } - - rotation.spellPriority = spellPriority - return - } - - rotation.spellPriority = spellPriority -} - -func (rotation *PriorityRotation) DoAction(enh *EnhancementShaman, sim *core.Simulation) { - target := enh.CurrentTarget - - cheapestSpell := enh.LightningBolt.CurCast.Cost - if enh.LavaLash != nil { - cheapestSpell = enh.LavaLash.CurCast.Cost - } - - // Incase the array is empty - if len(rotation.spellPriority) == 0 { - enh.DoNothing() - } - - //Mana guard, our cheapest spell. - if enh.CurrentMana() < cheapestSpell { - // Lets top off lightning shield stacks before waiting for mana. - if enh.LightningShield != nil && enh.LightningShieldAura.GetStacks() < 3 { - enh.LightningShield.Cast(sim, nil) - } - enh.WaitForMana(sim, cheapestSpell) - return - } - - // We could choose to not wait for auto attacks if we don't have any MW stacks, - // this would reduce the amount of DoAction calls by a little bit; might not be a issue though. - upcomingCD := enh.AutoAttacks.NextAttackAt() - var cast Cast - for _, spell := range rotation.spellPriority { - if !spell.condition(sim, target) { - continue - } - - if spell.cast(sim, target) { - return - } - - readyAt := spell.readyAt() - if readyAt > sim.CurrentTime && (upcomingCD > readyAt || upcomingCD < sim.CurrentTime) { - upcomingCD = readyAt - cast = spell.cast - } - } - - //Lets wait on a upcoming CD or AutoAttack - enh.WaitUntil(sim, upcomingCD) - - //Incase the next auto is our best CD then there are no spells to cast. - if cast != nil { - //We have a upcoming CD and we know what to cast lets just do that. - enh.HardcastWaitUntil(sim, upcomingCD, func(sim *core.Simulation, target *core.Unit) { - enh.GCD.Reset() - cast(sim, target) - }) - } -} - -func (rotation *PriorityRotation) Reset(_ *EnhancementShaman, _ *core.Simulation) { - -} diff --git a/sim/shaman/enhancement/rotation.go b/sim/shaman/enhancement/rotation.go deleted file mode 100644 index 53476c86d5..0000000000 --- a/sim/shaman/enhancement/rotation.go +++ /dev/null @@ -1,31 +0,0 @@ -package enhancement - -import ( - "github.com/wowsims/wotlk/sim/core" -) - -func (enh *EnhancementShaman) OnAutoAttack(sim *core.Simulation, _ *core.Spell) { - enh.previousSwingAt = sim.CurrentTime -} - -func (enh *EnhancementShaman) OnGCDReady(sim *core.Simulation) { - // TODO move this into the rotation, also this uses waitForMana if it was unable to cast the totem - // that will need to be pulled out so we are not waiting for a magma totem mana cost - enh.rotation.DoAction(enh, sim) -} - -type Rotation interface { - DoAction(*EnhancementShaman, *core.Simulation) - Reset(*EnhancementShaman, *core.Simulation) -} - -// CUSTOM ROTATION (advanced) (also WIP). -// -// TODO: figure out how to do this (probably too complicated to copy hunters) -type AgentAction interface { - GetActionID() core.ActionID - - GetManaCost() float64 - - Cast(sim *core.Simulation) bool -} diff --git a/sim/shaman/fire_elemental_pet.go b/sim/shaman/fire_elemental_pet.go index 255277e8df..879a5e56dc 100644 --- a/sim/shaman/fire_elemental_pet.go +++ b/sim/shaman/fire_elemental_pet.go @@ -99,7 +99,6 @@ func (fireElemental *FireElemental) ExecuteCustomRotation(sim *core.Simulation) fireNovaCasts := fireElemental.FireNova.SpellMetrics[0].Casts if fireBlastCasts == maxFireBlastCasts && fireNovaCasts == maxFireNovaCasts { - fireElemental.DoNothing() return } diff --git a/sim/shaman/fire_elemental_totem.go b/sim/shaman/fire_elemental_totem.go index fe82987ad5..cebf9fed61 100644 --- a/sim/shaman/fire_elemental_totem.go +++ b/sim/shaman/fire_elemental_totem.go @@ -10,7 +10,7 @@ import ( const fireTotemDuration time.Duration = time.Second * 120 func (shaman *Shaman) registerFireElementalTotem() { - if !shaman.Totems.UseFireElemental && !shaman.IsUsingAPL { + if !shaman.Totems.UseFireElemental { return } @@ -55,50 +55,13 @@ func (shaman *Shaman) registerFireElementalTotem() { shaman.FireElemental.EnableWithTimeout(sim, shaman.FireElemental, fireTotemDuration) - //TODO handle more then one swap if the fight is greater then 5 mins, for now will just do the one. - if !shaman.IsUsingAPL && shaman.FireElementalTotem.SpellMetrics[target.Index].Casts == 1 { - shaman.ItemSwap.SwapItems(sim, []proto.ItemSlot{proto.ItemSlot_ItemSlotMainHand, proto.ItemSlot_ItemSlotOffHand}) - } - // Add a dummy aura to show in metrics fireElementalAura.Activate(sim) }, }) - //Enh has 1.5seconds GCD also, so just going to wait the normal 1.5 instead of using the dynamic Spell GCD - var castWindow = 1550 * time.Millisecond - - enhTier10Aura := shaman.GetAura("Maelstrom Power") - shaman.AddMajorCooldown(core.MajorCooldown{ Spell: shaman.FireElementalTotem, Type: core.CooldownTypeUnknown, - ShouldActivate: func(sim *core.Simulation, character *core.Character) bool { - success := false - if enhTier10Aura != nil && shaman.Totems.EnhTierTenBonus && shaman.fireElementalSnapShot != nil { - if enhTier10Aura.IsActive() { - success = shaman.fireElementalSnapShot.CanSnapShot(sim, castWindow) - } else if sim.CurrentTime+fireTotemDuration > sim.Encounter.Duration { - success = true - } - } else if sim.CurrentTime > 1*time.Second && shaman.fireElementalSnapShot == nil { - success = true - } else if sim.Encounter.Duration <= 120*time.Second && sim.CurrentTime >= 10*time.Second { - success = true - } else if sim.Encounter.Duration > 120*time.Second && sim.CurrentTime >= 20*time.Second { - success = true - } else if shaman.fireElementalSnapShot != nil { - success = shaman.fireElementalSnapShot.CanSnapShot(sim, castWindow) - } - - if success && shaman.fireElementalSnapShot != nil { - shaman.castFireElemental = true - shaman.fireElementalSnapShot.ActivateMajorCooldowns(sim) - shaman.fireElementalSnapShot.ResetProcTrackers() - shaman.castFireElemental = false - } - - return success - }, }) } diff --git a/sim/shaman/fire_totems.go b/sim/shaman/fire_totems.go index 43f88bd94e..689a92328b 100644 --- a/sim/shaman/fire_totems.go +++ b/sim/shaman/fire_totems.go @@ -4,23 +4,9 @@ import ( "time" "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/core/proto" ) func (shaman *Shaman) registerSearingTotemSpell() { - var extraCastCondition core.CanCastCondition - if !shaman.IsUsingAPL && shaman.Totems.Fire == proto.FireTotem_SearingTotem && shaman.Totems.UseFireMcd { - extraCastCondition = func(sim *core.Simulation, target *core.Unit) bool { - if shaman.Totems.Fire != proto.FireTotem_SearingTotem { - return false - } - if shaman.SearingTotem.Dot(shaman.CurrentTarget).IsActive() || shaman.FireElemental.IsEnabled() || shaman.FireElementalTotem.IsReady(sim) { - return false - } - return true - } - } - shaman.SearingTotem = shaman.RegisterSpell(core.SpellConfig{ ActionID: core.ActionID{SpellID: 58704}, SpellSchool: core.SpellSchoolFire, @@ -38,7 +24,6 @@ func (shaman *Shaman) registerSearingTotemSpell() { GCD: time.Second, }, }, - ExtraCastCondition: extraCastCondition, BonusHitRating: float64(shaman.Talents.ElementalPrecision) * core.SpellHitRatingPerHitChance, DamageMultiplier: 1 + float64(shaman.Talents.CallOfFlame)*0.05, @@ -66,37 +51,13 @@ func (shaman *Shaman) registerSearingTotemSpell() { shaman.MagmaTotem.AOEDot().Cancel(sim) shaman.FireElemental.Disable(sim) spell.Dot(sim.GetTargetUnit(0)).Apply(sim) - if !shaman.Totems.UseFireMcd { - // +1 needed because of rounding issues with totem tick time. - shaman.NextTotemDrops[FireTotem] = sim.CurrentTime + time.Second*60 + 1 - } + // +1 needed because of rounding issues with totem tick time. + shaman.NextTotemDrops[FireTotem] = sim.CurrentTime + time.Second*60 + 1 }, }) - - if extraCastCondition == nil { - return - } - shaman.AddMajorCooldown(core.MajorCooldown{ - Spell: shaman.SearingTotem, - Priority: core.CooldownPriorityDefault, // TODO needs to be altered due to snap shotting. - Type: core.CooldownTypeDPS, - }) } func (shaman *Shaman) registerMagmaTotemSpell() { - var extraCastCondition core.CanCastCondition - if !shaman.IsUsingAPL && shaman.Totems.Fire == proto.FireTotem_MagmaTotem && shaman.Totems.UseFireMcd { - extraCastCondition = func(sim *core.Simulation, target *core.Unit) bool { - if shaman.Totems.Fire != proto.FireTotem_MagmaTotem { - return false - } - if shaman.MagmaTotem.AOEDot().IsActive() || shaman.FireElemental.IsEnabled() || shaman.FireElementalTotem.IsReady(sim) { - return false - } - return true - } - } - shaman.MagmaTotem = shaman.RegisterSpell(core.SpellConfig{ ActionID: core.ActionID{SpellID: 58734}, SpellSchool: core.SpellSchoolFire, @@ -114,7 +75,6 @@ func (shaman *Shaman) registerMagmaTotemSpell() { GCD: time.Second, }, }, - ExtraCastCondition: extraCastCondition, BonusHitRating: float64(shaman.Talents.ElementalPrecision) * core.SpellHitRatingPerHitChance, DamageMultiplier: 1 + float64(shaman.Talents.CallOfFlame)*0.05, @@ -141,19 +101,8 @@ func (shaman *Shaman) registerMagmaTotemSpell() { shaman.SearingTotem.Dot(shaman.CurrentTarget).Cancel(sim) shaman.FireElemental.Disable(sim) spell.AOEDot().Apply(sim) - if !shaman.Totems.UseFireMcd { - // +1 needed because of rounding issues with totem tick time. - shaman.NextTotemDrops[FireTotem] = sim.CurrentTime + time.Second*20 + 1 - } + // +1 needed because of rounding issues with totem tick time. + shaman.NextTotemDrops[FireTotem] = sim.CurrentTime + time.Second*20 + 1 }, }) - - if extraCastCondition == nil { - return - } - shaman.AddMajorCooldown(core.MajorCooldown{ - Spell: shaman.MagmaTotem, - Priority: core.CooldownPriorityDefault, // TODO needs to be altered due to snap shotting. - Type: core.CooldownTypeDPS, - }) } diff --git a/sim/shaman/restoration/restoration.go b/sim/shaman/restoration/restoration.go index 880f4c0d29..a4a2d0b706 100644 --- a/sim/shaman/restoration/restoration.go +++ b/sim/shaman/restoration/restoration.go @@ -1,8 +1,6 @@ package restoration import ( - "time" - "github.com/wowsims/wotlk/sim/core" "github.com/wowsims/wotlk/sim/core/proto" "github.com/wowsims/wotlk/sim/shaman" @@ -33,26 +31,15 @@ func NewRestorationShaman(character *core.Character, options *proto.Player) *Res Shield: restoShamOptions.Options.Shield, } - if restoShamOptions.Rotation.Bloodlust != proto.RestorationShaman_Rotation_UnsetBloodlust { - selfBuffs.Bloodlust = restoShamOptions.Rotation.Bloodlust == proto.RestorationShaman_Rotation_UseBloodlust - } - totems := &proto.ShamanTotems{} if restoShamOptions.Options.Totems != nil { totems = restoShamOptions.Options.Totems } resto := &RestorationShaman{ - Shaman: shaman.NewShaman(character, options.TalentsString, totems, selfBuffs, false), - rotation: restoShamOptions.Rotation, + Shaman: shaman.NewShaman(character, options.TalentsString, totems, selfBuffs, false), } - // can only use earth shield if specc'd - resto.rotation.UseEarthShield = resto.rotation.UseEarthShield && resto.Talents.EarthShield - resto.earthShieldPPM = restoShamOptions.Options.EarthShieldPPM - - resto.EnableResumeAfterManaWait(resto.tryUseGCD) - if resto.HasMHWeapon() { resto.ApplyEarthlivingImbueToItem(resto.GetMHWeapon()) } @@ -65,10 +52,6 @@ func NewRestorationShaman(character *core.Character, options *proto.Player) *Res type RestorationShaman struct { *shaman.Shaman - - rotation *proto.RestorationShaman_Rotation - earthShieldPPM int32 - lastEarthShieldProc time.Duration } func (resto *RestorationShaman) GetShaman() *shaman.Shaman { @@ -77,7 +60,6 @@ func (resto *RestorationShaman) GetShaman() *shaman.Shaman { func (resto *RestorationShaman) Reset(sim *core.Simulation) { resto.Shaman.Reset(sim) - resto.lastEarthShieldProc = -core.NeverExpires } func (resto *RestorationShaman) GetMainTarget() *core.Unit { // TODO: make this just grab first player that isn't self. diff --git a/sim/shaman/restoration/rotation.go b/sim/shaman/restoration/rotation.go deleted file mode 100644 index 08a0c52d54..0000000000 --- a/sim/shaman/restoration/rotation.go +++ /dev/null @@ -1,58 +0,0 @@ -package restoration - -import ( - "time" - - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/core/proto" -) - -func (resto *RestorationShaman) OnGCDReady(sim *core.Simulation) { - resto.tryUseGCD(sim) -} - -func (resto *RestorationShaman) tryUseGCD(sim *core.Simulation) { - - // TODO: This could actually just be made as a PA that runs and triggers the shield instead of part of the rotation here. - es := resto.EarthShield.Hot(resto.CurrentTarget) - if es.IsActive() && resto.earthShieldPPM > 0 { - procTime := time.Duration(60.0 / float64(resto.earthShieldPPM) * float64(time.Second)) - lastProc := resto.lastEarthShieldProc - if lastProc+procTime < sim.CurrentTime { - es.OnSpellHitTaken(es.Aura, sim, nil, &core.SpellResult{Outcome: core.OutcomeHit, Target: resto.CurrentTarget}) - resto.lastEarthShieldProc = sim.CurrentTime - } - } - - if resto.TryDropTotems(sim) { - return - } - - var spell *core.Spell - switch resto.rotation.PrimaryHeal { - case proto.ShamanHealSpell_AutoHeal: - if len(resto.Party.Players) > 3 { - spell = resto.ChainHeal - } else { - // TODO: lots of things to consider here... - spell = resto.LesserHealingWave - } - case proto.ShamanHealSpell_LesserHealingWave: - spell = resto.LesserHealingWave - case proto.ShamanHealSpell_HealingWave: - panic("healing wave not implemented yet") - spell = resto.HealingWave - case proto.ShamanHealSpell_ChainHeal: - spell = resto.ChainHeal - } - - if resto.rotation.UseEarthShield && !es.IsActive() { - spell = resto.EarthShield - } else if resto.rotation.UseRiptide && !resto.Riptide.Hot(resto.CurrentTarget).IsActive() && resto.Riptide.IsReady(sim) { - spell = resto.Riptide - } - - if !spell.Cast(sim, resto.CurrentTarget) { - resto.WaitForMana(sim, spell.CurCast.Cost) - } -} diff --git a/sim/shaman/shaman.go b/sim/shaman/shaman.go index 79f21578ba..a895f3acc3 100644 --- a/sim/shaman/shaman.go +++ b/sim/shaman/shaman.go @@ -80,8 +80,6 @@ type Shaman struct { thunderstormInRange bool // flag if thunderstorm will be in range. - ShamanisticRageManaThreshold float64 //% of mana to use sham. rage at - Talents *proto.ShamanTalents SelfBuffs SelfBuffs @@ -116,10 +114,8 @@ type Shaman struct { FeralSpirit *core.Spell SpiritWolves *SpiritWolves - castFireElemental bool - FireElemental *FireElemental - FireElementalTotem *core.Spell - fireElementalSnapShot *core.SnapshotManager + FireElemental *FireElemental + FireElementalTotem *core.Spell MagmaTotem *core.Spell ManaSpringTotem *core.Spell @@ -227,8 +223,6 @@ func (shaman *Shaman) AddPartyBuffs(partyBuffs *proto.PartyBuffs) { } func (shaman *Shaman) Initialize() { - enableSnapshot := shaman.Totems.BonusSpellpower == 0 - shaman.registerChainLightningSpell() shaman.registerFeralSpirit() shaman.registerFireElementalTotem() @@ -256,19 +250,6 @@ func (shaman *Shaman) Initialize() { shaman.registerCallOfTheElements() shaman.registerBloodlustCD() - - if shaman.Totems.UseFireElemental && enableSnapshot { - shaman.fireElementalSnapShot = core.NewSnapshotManager(shaman.GetCharacter()) - shaman.setupProcTrackers() - } - - // Healing stream totem applies a HoT (aura) and so needs to be handled as a pre-pull action - // instead of during init/reset. - if !shaman.IsUsingAPL && shaman.Totems.Water == proto.WaterTotem_HealingStreamTotem { - shaman.RegisterPrepullAction(0, func(sim *core.Simulation) { - shaman.HealingStreamTotem.Cast(sim, &shaman.Unit) - }) - } } func (shaman *Shaman) RegisterHealingSpells() { @@ -301,11 +282,6 @@ func (shaman *Shaman) RegisterHealingSpells() { } func (shaman *Shaman) Reset(sim *core.Simulation) { - if shaman.Totems.UseFireElemental { - shaman.setupFireElementalCooldowns() - shaman.castFireElemental = false - } - // Check to see if we are casting a totem to set its expire time. for i := range shaman.NextTotemDrops { shaman.NextTotemDrops[i] = core.NeverExpires @@ -344,111 +320,6 @@ func (shaman *Shaman) Reset(sim *core.Simulation) { shaman.FlameShock.CD.Reset() } -func (shaman *Shaman) setupProcTrackers() { - snapshotManager := shaman.fireElementalSnapShot - - snapshotManager.AddProc(40212, "Potion of Wild Magic", true) - snapshotManager.AddProc(33697, "Blood Fury", true) - snapshotManager.AddProc(59620, "Berserking MH Proc", false) - snapshotManager.AddProc(59620, "Berserking OH Proc", false) - - //AP Ring Procs - snapshotManager.AddProc(44308, "Signet of Edward the Odd Proc", false) - snapshotManager.AddProc(50401, "Ashen Band of Unmatched Vengeance Proc", false) - snapshotManager.AddProc(50402, "Ashen Band of Endless Vengeance Proc", false) - snapshotManager.AddProc(52571, "Ashen Band of Unmatched Might Proc", false) - snapshotManager.AddProc(52572, "Ashen Band of Endless Might Proc", false) - - //SP Trinket Procs - snapshotManager.AddProc(40255, "Dying Curse Proc", false) - snapshotManager.AddProc(40682, "Sundial of the Exiled Proc", false) - snapshotManager.AddProc(37660, "Forge Ember Proc", false) - snapshotManager.AddProc(45518, "Flare of the Heavens Proc", false) - snapshotManager.AddProc(54572, "Charred Twilight Scale Proc", false) - snapshotManager.AddProc(54588, "Charred Twilight Scale H Proc", false) - snapshotManager.AddProc(47213, "Abyssal Rune Proc", false) - snapshotManager.AddProc(45490, "Pandora's Plea Proc", false) - snapshotManager.AddProc(50348, "Dislodged Foreign Object H", false) - snapshotManager.AddProc(50353, "Dislodged Foreign Object", false) - snapshotManager.AddProc(50360, "Phylactery of the Nameless Lich Proc", false) - snapshotManager.AddProc(50365, "Phylactery of the Nameless Lich H Proc", false) - snapshotManager.AddProc(50345, "Muradin's Spyglass H Proc", false) - snapshotManager.AddProc(50340, "Muradin's Spyglass Proc", false) - - // SP Ring Procs - snapshotManager.AddProc(50398, "Ashen Band of Endless Destruction", false) - - //AP Trinket Procs - snapshotManager.AddProc(40684, "Mirror of Truth Proc", false) - snapshotManager.AddProc(45522, "Blood of the Old God Proc", false) - snapshotManager.AddProc(40767, "Sonic Booster Proc", false) - snapshotManager.AddProc(44914, "Anvil of Titans Proc", false) - snapshotManager.AddProc(45286, "Pyrite Infuser Proc", false) - snapshotManager.AddProc(47214, "Banner of Victory Proc", false) - snapshotManager.AddProc(49074, "Coren's Chromium Coaster Proc", false) - snapshotManager.AddProc(50342, "Whispering Fanged Skull Proc", false) - snapshotManager.AddProc(50343, "Whispering Fanged Skull H Proc", false) - snapshotManager.AddProc(54569, "Sharpened Twilight Scale Proc", false) - snapshotManager.AddProc(54590, "Sharpened Twilight Scale H Proc", false) - snapshotManager.AddProc(47115, "Deaths Verdict Agility Proc", false) - snapshotManager.AddProc(47131, "Deaths Verdict H Agility Proc", false) - snapshotManager.AddProc(47303, "Deaths Choice Agility Proc", false) - snapshotManager.AddProc(47464, "Deaths Choice H Agility Proc", false) - snapshotManager.AddProc(71492, "Deathbringer's Will Strength Proc", false) - snapshotManager.AddProc(71561, "Deathbringer's Will H Strength Proc", false) - snapshotManager.AddProc(71492, "Deathbringer's Will Agility Proc", false) - snapshotManager.AddProc(71561, "Deathbringer's Will H Agility Proc", false) - snapshotManager.AddProc(71492, "Deathbringer's Will AP Proc", false) - snapshotManager.AddProc(71561, "Deathbringer's Will H AP Proc", false) - - // Tier Bonus - snapshotManager.AddProc(70831, "Maelstrom Power", false) -} - -func (shaman *Shaman) setupFireElementalCooldowns() { - if shaman.fireElementalSnapShot == nil { - return - } - - shaman.fireElementalSnapShot.ClearMajorCooldowns() - - // blood fury (orc) - shaman.fireElementalCooldownSync(core.ActionID{SpellID: 33697}, false) - - // potion of Wild Magic - shaman.fireElementalCooldownSync(core.ActionID{ItemID: 40212}, true) - - //active sp trinkets - shaman.fireElementalCooldownSync(core.ActionID{ItemID: 37873}, false) - shaman.fireElementalCooldownSync(core.ActionID{ItemID: 45148}, false) - shaman.fireElementalCooldownSync(core.ActionID{ItemID: 48724}, false) - shaman.fireElementalCooldownSync(core.ActionID{ItemID: 50357}, false) - - // active ap trinkets - shaman.fireElementalCooldownSync(core.ActionID{ItemID: 35937}, false) - shaman.fireElementalCooldownSync(core.ActionID{ItemID: 36871}, false) - shaman.fireElementalCooldownSync(core.ActionID{ItemID: 37166}, false) - shaman.fireElementalCooldownSync(core.ActionID{ItemID: 37556}, false) - shaman.fireElementalCooldownSync(core.ActionID{ItemID: 37557}, false) - shaman.fireElementalCooldownSync(core.ActionID{ItemID: 38080}, false) - shaman.fireElementalCooldownSync(core.ActionID{ItemID: 38081}, false) - shaman.fireElementalCooldownSync(core.ActionID{ItemID: 38761}, false) - shaman.fireElementalCooldownSync(core.ActionID{ItemID: 39257}, false) - shaman.fireElementalCooldownSync(core.ActionID{ItemID: 45263}, false) - shaman.fireElementalCooldownSync(core.ActionID{ItemID: 46086}, false) - shaman.fireElementalCooldownSync(core.ActionID{ItemID: 47734}, false) -} - -func (shaman *Shaman) fireElementalCooldownSync(actionID core.ActionID, isPotion bool) { - if majorCd := shaman.Character.GetMajorCooldown(actionID); majorCd != nil { - majorCd.ShouldActivate = func(sim *core.Simulation, character *core.Character) bool { - return shaman.castFireElemental || (shaman.FireElementalTotem.CD.TimeToReady(sim) > majorCd.Spell.CD.Duration && !isPotion) || shaman.FireElementalTotem.CD.ReadyAt() > shaman.Env.Encounter.Duration - } - - shaman.fireElementalSnapShot.AddMajorCooldown(majorCd) - } -} - func (shaman *Shaman) ElementalCritMultiplier(secondary float64) float64 { critBonus := 0.2*float64(shaman.Talents.ElementalFury) + secondary return shaman.SpellCritMultiplier(1, critBonus) diff --git a/sim/shaman/shamanistic_rage.go b/sim/shaman/shamanistic_rage.go index 42fcde55ef..d62b95fe91 100644 --- a/sim/shaman/shamanistic_rage.go +++ b/sim/shaman/shamanistic_rage.go @@ -12,10 +12,7 @@ func (shaman *Shaman) registerShamanisticRageCD() { return } - t10Bonus := false - if shaman.HasSetBonus(ItemSetFrostWitchBattlegear, 2) { - t10Bonus = true - } + t10Bonus := shaman.HasSetBonus(ItemSetFrostWitchBattlegear, 2) actionID := core.ActionID{SpellID: 30823} ppmm := shaman.AutoAttacks.NewPPMManager(15, core.ProcMaskMelee) @@ -66,22 +63,11 @@ func (shaman *Shaman) registerShamanisticRageCD() { }, }) - if shaman.IsUsingAPL { - shaman.AddMajorCooldown(core.MajorCooldown{ - Spell: spell, - Type: core.CooldownTypeMana, - ShouldActivate: func(sim *core.Simulation, character *core.Character) bool { - return character.CurrentManaPercent() <= 0.2 - }, - }) - } else { - shaman.AddMajorCooldown(core.MajorCooldown{ - Spell: spell, - Type: core.CooldownTypeMana, - ShouldActivate: func(sim *core.Simulation, character *core.Character) bool { - manaReserve := shaman.ShamanisticRageManaThreshold / 100 * shaman.MaxMana() - return character.CurrentMana() <= manaReserve - }, - }) - } + shaman.AddMajorCooldown(core.MajorCooldown{ + Spell: spell, + Type: core.CooldownTypeMana, + ShouldActivate: func(sim *core.Simulation, character *core.Character) bool { + return character.CurrentManaPercent() <= 0.2 + }, + }) } diff --git a/sim/shaman/totems.go b/sim/shaman/totems.go index fdf73dd247..701228ee2a 100644 --- a/sim/shaman/totems.go +++ b/sim/shaman/totems.go @@ -187,47 +187,6 @@ func (shaman *Shaman) registerCallOfTheElements() { }) } -func (shaman *Shaman) NextTotemAt(_ *core.Simulation) time.Duration { - return min(shaman.NextTotemDrops[0], shaman.NextTotemDrops[1], shaman.NextTotemDrops[2], shaman.NextTotemDrops[3]) -} - -// TryDropTotems will check to see if totems need to be re-cast. -// -// Returns whether we tried to cast a totem, regardless of whether it succeeded. -func (shaman *Shaman) TryDropTotems(sim *core.Simulation) bool { - var spell *core.Spell - - casted := false - for totemTypeIdx, totemExpiration := range shaman.NextTotemDrops { - spell = nil - nextDrop := shaman.NextTotemDropType[totemTypeIdx] - if sim.CurrentTime >= totemExpiration { - switch totemTypeIdx { - case AirTotem: - spell = shaman.getAirTotemSpell(proto.AirTotem(nextDrop)) - case EarthTotem: - spell = shaman.getEarthTotemSpell(proto.EarthTotem(nextDrop)) - case FireTotem: - spell = shaman.getFireTotemSpell(proto.FireTotem(nextDrop)) - case WaterTotem: - spell = shaman.getWaterTotemSpell(proto.WaterTotem(nextDrop)) - } - } - if spell != nil { - if success := spell.Cast(sim, shaman.CurrentTarget); !success { - shaman.WaitForMana(sim, spell.CurCast.Cost) - return true - } - casted = true - } - } - - if casted { - shaman.WaitUntil(sim, sim.CurrentTime+time.Second) - } - return casted -} - func (shaman *Shaman) getAirTotemSpell(totemType proto.AirTotem) *core.Spell { switch totemType { case proto.AirTotem_WrathOfAirTotem: diff --git a/ui/elemental_shaman/apls/advanced.apl.json b/ui/elemental_shaman/apls/advanced.apl.json index 3240d5bc13..73b7d2f0b4 100644 --- a/ui/elemental_shaman/apls/advanced.apl.json +++ b/ui/elemental_shaman/apls/advanced.apl.json @@ -1,5 +1,4 @@ { - "enabled": true, "type": "TypeAPL", "prepullActions": [ {"action":{"castSpell":{"spellId":{"spellId":59159}}},"doAtValue":{"const":{"val":"-5"}}}, From c5c01550b7b4123bcf47d4fddedc197d5ca73ae4 Mon Sep 17 00:00:00 2001 From: James Tanner Date: Sat, 6 Jan 2024 13:34:34 -0800 Subject: [PATCH 12/28] Commit before fixing warlock tests --- proto/shaman.proto | 14 - sim/shaman/apl_values.go | 8 +- sim/shaman/elemental/elemental.go | 1 - sim/shaman/fire_elemental_totem.go | 4 +- sim/shaman/fire_totems.go | 4 +- sim/shaman/restoration/restoration_test.go | 3 +- sim/shaman/shaman.go | 43 +- sim/shaman/talents.go | 2 +- sim/shaman/totems.go | 18 +- sim/warlock/inferno.go | 6 +- sim/warlock/pet.go | 1 - sim/warlock/rotation.go | 690 --------------------- sim/warlock/seed.go | 6 +- sim/warlock/warlock.go | 55 +- 14 files changed, 27 insertions(+), 828 deletions(-) delete mode 100644 sim/warlock/rotation.go diff --git a/proto/shaman.proto b/proto/shaman.proto index 43dd006743..b5fde9f161 100644 --- a/proto/shaman.proto +++ b/proto/shaman.proto @@ -176,24 +176,10 @@ message ShamanTotems { FireTotem fire = 3; WaterTotem water = 4; - // If set, will use mana tide when appropriate. - bool use_mana_tide = 5; - // If set, will use fire elemental totem at the start and revert to regular // fire totems when it expires. bool use_fire_elemental = 6; - // If set, will revert to regular fire totems when fire elemental goes OOM, - // instead of waiting the full 2 minutes. - bool recall_fire_elemental_on_oom = 7; - - // If set, any time a 2-minute totem is about to expire, will recall and - // replace all totems. - bool recall_totems = 8; - - // If set will use fire totems as an MCD instead of manually controlling when to place them. - bool use_fire_mcd = 9; - // Bonus spell power for fire elemental snapshotting. int32 bonus_spellpower = 10; diff --git a/sim/shaman/apl_values.go b/sim/shaman/apl_values.go index 447906b0b9..068726e23b 100644 --- a/sim/shaman/apl_values.go +++ b/sim/shaman/apl_values.go @@ -38,13 +38,13 @@ func (value *APLValueTotemRemainingTime) Type() proto.APLValueType { } func (value *APLValueTotemRemainingTime) GetDuration(sim *core.Simulation) time.Duration { if value.totemType == proto.ShamanTotems_Earth { - return max(0, value.shaman.NextTotemDrops[EarthTotem]-sim.CurrentTime) + return max(0, value.shaman.TotemExpirations[EarthTotem]-sim.CurrentTime) } else if value.totemType == proto.ShamanTotems_Air { - return max(0, value.shaman.NextTotemDrops[AirTotem]-sim.CurrentTime) + return max(0, value.shaman.TotemExpirations[AirTotem]-sim.CurrentTime) } else if value.totemType == proto.ShamanTotems_Fire { - return max(0, value.shaman.NextTotemDrops[FireTotem]-sim.CurrentTime) + return max(0, value.shaman.TotemExpirations[FireTotem]-sim.CurrentTime) } else if value.totemType == proto.ShamanTotems_Water { - return max(0, value.shaman.NextTotemDrops[WaterTotem]-sim.CurrentTime) + return max(0, value.shaman.TotemExpirations[WaterTotem]-sim.CurrentTime) } else { return 0 } diff --git a/sim/shaman/elemental/elemental.go b/sim/shaman/elemental/elemental.go index aa4a5e1bfd..b33058633b 100644 --- a/sim/shaman/elemental/elemental.go +++ b/sim/shaman/elemental/elemental.go @@ -35,7 +35,6 @@ func NewElementalShaman(character *core.Character, options *proto.Player) *Eleme totems := &proto.ShamanTotems{} if eleShamOptions.Options.Totems != nil { totems = eleShamOptions.Options.Totems - totems.UseFireMcd = true // Control fire totems as MCD. } inRange := eleShamOptions.Options.ThunderstormRange == proto.ElementalShaman_Options_TSInRange diff --git a/sim/shaman/fire_elemental_totem.go b/sim/shaman/fire_elemental_totem.go index cebf9fed61..c7665c4646 100644 --- a/sim/shaman/fire_elemental_totem.go +++ b/sim/shaman/fire_elemental_totem.go @@ -42,9 +42,9 @@ func (shaman *Shaman) registerFireElementalTotem() { // TODO: ToW needs a unique buff/debuff aura for each raidmember/target. // Otherwise we will be possibly disabling another ele shaman's ToW debuff/buff. if shaman.Totems.Fire == proto.FireTotem_TotemOfWrath { - shaman.NextTotemDrops[FireTotem] = sim.CurrentTime + fireTotemDuration + shaman.TotemExpirations[FireTotem] = sim.CurrentTime + fireTotemDuration } else if shaman.Totems.Fire != proto.FireTotem_NoFireTotem && !shaman.Totems.UseFireMcd { - shaman.NextTotemDrops[FireTotem] = sim.CurrentTime + fireTotemDuration + shaman.TotemExpirations[FireTotem] = sim.CurrentTime + fireTotemDuration } shaman.MagmaTotem.AOEDot().Cancel(sim) diff --git a/sim/shaman/fire_totems.go b/sim/shaman/fire_totems.go index 689a92328b..a66cc6573d 100644 --- a/sim/shaman/fire_totems.go +++ b/sim/shaman/fire_totems.go @@ -52,7 +52,7 @@ func (shaman *Shaman) registerSearingTotemSpell() { shaman.FireElemental.Disable(sim) spell.Dot(sim.GetTargetUnit(0)).Apply(sim) // +1 needed because of rounding issues with totem tick time. - shaman.NextTotemDrops[FireTotem] = sim.CurrentTime + time.Second*60 + 1 + shaman.TotemExpirations[FireTotem] = sim.CurrentTime + time.Second*60 + 1 }, }) } @@ -102,7 +102,7 @@ func (shaman *Shaman) registerMagmaTotemSpell() { shaman.FireElemental.Disable(sim) spell.AOEDot().Apply(sim) // +1 needed because of rounding issues with totem tick time. - shaman.NextTotemDrops[FireTotem] = sim.CurrentTime + time.Second*20 + 1 + shaman.TotemExpirations[FireTotem] = sim.CurrentTime + time.Second*20 + 1 }, }) } diff --git a/sim/shaman/restoration/restoration_test.go b/sim/shaman/restoration/restoration_test.go index 3944f25510..629b68812a 100644 --- a/sim/shaman/restoration/restoration_test.go +++ b/sim/shaman/restoration/restoration_test.go @@ -91,8 +91,7 @@ var restoShamOptions = &proto.RestorationShaman_Options{ } var PlayerOptionsStandard = &proto.Player_RestorationShaman{ RestorationShaman: &proto.RestorationShaman{ - Options: restoShamOptions, - Rotation: &proto.RestorationShaman_Rotation{}, + Options: restoShamOptions, }, } diff --git a/sim/shaman/shaman.go b/sim/shaman/shaman.go index a895f3acc3..ca370a75ba 100644 --- a/sim/shaman/shaman.go +++ b/sim/shaman/shaman.go @@ -85,10 +85,8 @@ type Shaman struct { Totems *proto.ShamanTotems - // The type of totem which should be dropped next and time to drop it, for - // each totem type (earth, air, fire, water). - NextTotemDropType [4]int32 - NextTotemDrops [4]time.Duration + // The expiration time of each totem (earth, air, fire, water). + TotemExpirations [4]time.Duration LightningBolt *core.Spell LightningBoltLO *core.Spell @@ -282,42 +280,9 @@ func (shaman *Shaman) RegisterHealingSpells() { } func (shaman *Shaman) Reset(sim *core.Simulation) { - // Check to see if we are casting a totem to set its expire time. - for i := range shaman.NextTotemDrops { - shaman.NextTotemDrops[i] = core.NeverExpires - switch i { - case AirTotem: - if shaman.Totems.Air != proto.AirTotem_NoAirTotem { - shaman.NextTotemDrops[i] = TotemRefreshTime5M - shaman.NextTotemDropType[i] = int32(shaman.Totems.Air) - } - case EarthTotem: - if shaman.Totems.Earth != proto.EarthTotem_NoEarthTotem { - shaman.NextTotemDrops[i] = TotemRefreshTime5M - shaman.NextTotemDropType[i] = int32(shaman.Totems.Earth) - } - case FireTotem: - shaman.NextTotemDropType[FireTotem] = int32(shaman.Totems.Fire) - if shaman.NextTotemDropType[FireTotem] != int32(proto.FireTotem_NoFireTotem) { - if shaman.NextTotemDropType[FireTotem] != int32(proto.FireTotem_TotemOfWrath) && - shaman.NextTotemDropType[FireTotem] != int32(proto.FireTotem_FlametongueTotem) { - if !shaman.Totems.UseFireMcd { - shaman.NextTotemDrops[FireTotem] = 0 - } - } else { - shaman.NextTotemDrops[FireTotem] = TotemRefreshTime5M - if shaman.NextTotemDropType[FireTotem] == int32(proto.FireTotem_TotemOfWrath) { - shaman.applyToWDebuff(sim) - } - } - } - case WaterTotem: - shaman.NextTotemDropType[i] = int32(shaman.Totems.Water) - shaman.NextTotemDrops[i] = TotemRefreshTime5M - } + if shaman.Totems.Fire == proto.FireTotem_TotemOfWrath { + shaman.applyToWDebuff(sim) } - - shaman.FlameShock.CD.Reset() } func (shaman *Shaman) ElementalCritMultiplier(secondary float64) float64 { diff --git a/sim/shaman/talents.go b/sim/shaman/talents.go index 0ea408dbbd..36701c9799 100644 --- a/sim/shaman/talents.go +++ b/sim/shaman/talents.go @@ -482,7 +482,7 @@ func (shaman *Shaman) registerManaTideTotemCD() { // TODO: Current water totem buff needs to be removed from party/raid. if shaman.Totems.Water != proto.WaterTotem_NoWaterTotem { - shaman.NextTotemDrops[WaterTotem] = sim.CurrentTime + time.Second*12 + shaman.TotemExpirations[WaterTotem] = sim.CurrentTime + time.Second*12 } }, }) diff --git a/sim/shaman/totems.go b/sim/shaman/totems.go index 701228ee2a..9b7e51ed6e 100644 --- a/sim/shaman/totems.go +++ b/sim/shaman/totems.go @@ -24,7 +24,7 @@ func (shaman *Shaman) newTotemSpellConfig(baseCost float64, spellID int32) core. func (shaman *Shaman) registerWrathOfAirTotemSpell() { config := shaman.newTotemSpellConfig(0.11, 3738) config.ApplyEffects = func(sim *core.Simulation, _ *core.Unit, _ *core.Spell) { - shaman.NextTotemDrops[AirTotem] = sim.CurrentTime + time.Second*300 + shaman.TotemExpirations[AirTotem] = sim.CurrentTime + time.Second*300 } shaman.WrathOfAirTotem = shaman.RegisterSpell(config) } @@ -32,7 +32,7 @@ func (shaman *Shaman) registerWrathOfAirTotemSpell() { func (shaman *Shaman) registerWindfuryTotemSpell() { config := shaman.newTotemSpellConfig(0.11, 8512) config.ApplyEffects = func(sim *core.Simulation, _ *core.Unit, _ *core.Spell) { - shaman.NextTotemDrops[AirTotem] = sim.CurrentTime + time.Second*300 + shaman.TotemExpirations[AirTotem] = sim.CurrentTime + time.Second*300 } shaman.WindfuryTotem = shaman.RegisterSpell(config) } @@ -40,7 +40,7 @@ func (shaman *Shaman) registerWindfuryTotemSpell() { func (shaman *Shaman) registerManaSpringTotemSpell() { config := shaman.newTotemSpellConfig(0.04, 58774) config.ApplyEffects = func(sim *core.Simulation, _ *core.Unit, _ *core.Spell) { - shaman.NextTotemDrops[WaterTotem] = sim.CurrentTime + time.Second*300 + shaman.TotemExpirations[WaterTotem] = sim.CurrentTime + time.Second*300 } shaman.ManaSpringTotem = shaman.RegisterSpell(config) } @@ -72,7 +72,7 @@ func (shaman *Shaman) registerHealingStreamTotemSpell() { }, } config.ApplyEffects = func(sim *core.Simulation, _ *core.Unit, spell *core.Spell) { - shaman.NextTotemDrops[WaterTotem] = sim.CurrentTime + time.Second*300 + shaman.TotemExpirations[WaterTotem] = sim.CurrentTime + time.Second*300 for _, agent := range shaman.Party.Players { spell.Hot(&agent.GetCharacter().Unit).Activate(sim) } @@ -83,7 +83,7 @@ func (shaman *Shaman) registerHealingStreamTotemSpell() { func (shaman *Shaman) registerTotemOfWrathSpell() { config := shaman.newTotemSpellConfig(0.05, 57722) config.ApplyEffects = func(sim *core.Simulation, _ *core.Unit, _ *core.Spell) { - shaman.NextTotemDrops[FireTotem] = sim.CurrentTime + time.Second*300 + shaman.TotemExpirations[FireTotem] = sim.CurrentTime + time.Second*300 shaman.applyToWDebuff(sim) } shaman.TotemOfWrath = shaman.RegisterSpell(config) @@ -99,7 +99,7 @@ func (shaman *Shaman) applyToWDebuff(sim *core.Simulation) { func (shaman *Shaman) registerFlametongueTotemSpell() { config := shaman.newTotemSpellConfig(0.11, 58656) config.ApplyEffects = func(sim *core.Simulation, _ *core.Unit, _ *core.Spell) { - shaman.NextTotemDrops[FireTotem] = sim.CurrentTime + time.Second*300 + shaman.TotemExpirations[FireTotem] = sim.CurrentTime + time.Second*300 } shaman.FlametongueTotem = shaman.RegisterSpell(config) } @@ -107,7 +107,7 @@ func (shaman *Shaman) registerFlametongueTotemSpell() { func (shaman *Shaman) registerStrengthOfEarthTotemSpell() { config := shaman.newTotemSpellConfig(0.1, 58643) config.ApplyEffects = func(sim *core.Simulation, _ *core.Unit, _ *core.Spell) { - shaman.NextTotemDrops[EarthTotem] = sim.CurrentTime + time.Second*300 + shaman.TotemExpirations[EarthTotem] = sim.CurrentTime + time.Second*300 } shaman.StrengthOfEarthTotem = shaman.RegisterSpell(config) } @@ -115,7 +115,7 @@ func (shaman *Shaman) registerStrengthOfEarthTotemSpell() { func (shaman *Shaman) registerTremorTotemSpell() { config := shaman.newTotemSpellConfig(0.02, 8143) config.ApplyEffects = func(sim *core.Simulation, _ *core.Unit, _ *core.Spell) { - shaman.NextTotemDrops[EarthTotem] = sim.CurrentTime + time.Second*300 + shaman.TotemExpirations[EarthTotem] = sim.CurrentTime + time.Second*300 } shaman.TremorTotem = shaman.RegisterSpell(config) } @@ -123,7 +123,7 @@ func (shaman *Shaman) registerTremorTotemSpell() { func (shaman *Shaman) registerStoneskinTotemSpell() { config := shaman.newTotemSpellConfig(0.1, 58753) config.ApplyEffects = func(sim *core.Simulation, _ *core.Unit, _ *core.Spell) { - shaman.NextTotemDrops[EarthTotem] = sim.CurrentTime + time.Second*300 + shaman.TotemExpirations[EarthTotem] = sim.CurrentTime + time.Second*300 } shaman.StoneskinTotem = shaman.RegisterSpell(config) } diff --git a/sim/warlock/inferno.go b/sim/warlock/inferno.go index 509bfc26ae..54858c9d59 100644 --- a/sim/warlock/inferno.go +++ b/sim/warlock/inferno.go @@ -59,12 +59,8 @@ func (warlock *Warlock) registerInfernoSpell() { warlock.AddMajorCooldown(core.MajorCooldown{ Spell: warlock.Inferno, - Type: core.CooldownTypeDPS, + Type: core.CooldownTypeUnknown, ShouldActivate: func(sim *core.Simulation, character *core.Character) bool { - if !warlock.Rotation.UseInfernal { - return false - } - return sim.GetRemainingDuration() <= 61*time.Second }, }) diff --git a/sim/warlock/pet.go b/sim/warlock/pet.go index 041c559854..16bcb49c3e 100644 --- a/sim/warlock/pet.go +++ b/sim/warlock/pet.go @@ -120,7 +120,6 @@ func (warlock *Warlock) NewWarlockPet() *WarlockPet { } wp.EnableManaBarWithModifier(cfg.PowerModifier) - wp.EnableResumeAfterManaWait(wp.OnGCDReady) wp.AddStatDependency(stats.Strength, stats.AttackPower, 2) wp.AddStat(stats.AttackPower, -20) diff --git a/sim/warlock/rotation.go b/sim/warlock/rotation.go deleted file mode 100644 index 601dab5b37..0000000000 --- a/sim/warlock/rotation.go +++ /dev/null @@ -1,690 +0,0 @@ -package warlock - -import ( - "math" - "sort" - "time" - - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/core/proto" - "github.com/wowsims/wotlk/sim/core/stats" -) - -const humanReactionTime = 150 * time.Millisecond - -func (warlock *Warlock) setupCooldowns(sim *core.Simulation) { - // TODO: also need to consider shared CDs that cause delays, like double on-use trinkets - - // check if waiting `waitDuration` amount of time results in fewer cooldown usages - retainUses := func(timeLeft time.Duration, spellCD time.Duration, waitDuration time.Duration) bool { - return math.Floor(float64(timeLeft)/float64(spellCD)+1) == - math.Floor(float64(timeLeft-waitDuration)/float64(spellCD)+1) - } - - // TODO: find a way of getting the duration directly from the spell instead - durMap := make(map[core.ActionID]time.Duration) - if warlock.MetamorphosisAura != nil { - durMap[core.ActionID{SpellID: 47241}] = warlock.MetamorphosisAura.Duration - } - durMap[core.ActionID{SpellID: 33697}] = 15 * time.Second - durMap[core.ActionID{SpellID: 54758}] = 12 * time.Second - durMap[core.ActionID{SpellID: 10060}.WithTag(-1)] = 15 * time.Second - durMap[core.ActionID{ItemID: 40211}] = 15 * time.Second - durMap[core.ActionID{ItemID: 40212}] = 15 * time.Second - durMap[core.ActionID{ItemID: 45466}] = 20 * time.Second - durMap[core.ActionID{ItemID: 45148}] = 20 * time.Second - durMap[core.ActionID{ItemID: 37873}] = 20 * time.Second - - ignoredCDs := make(map[core.ActionID]struct{}) - ignoredCDs[core.ActionID{ItemID: 42641}] = struct{}{} // sapper - ignoredCDs[core.ActionID{ItemID: 41119}] = struct{}{} // saronite bomb - ignoredCDs[core.ActionID{ItemID: 40536}] = struct{}{} // explosive decoy - ignoredCDs[core.BloodlustActionID.WithTag(-1)] = struct{}{} // don't mess with BL - if warlock.Inferno != nil { - ignoredCDs[warlock.Inferno.ActionID] = struct{}{} - } - - var executeActive func() bool - var executePhase time.Duration - if warlock.Talents.Decimation > 0 { - // approximation since we don't know exactly when decimation will be active - executePhase = time.Duration(float64(sim.Duration)*(1.0-sim.Encounter.ExecuteProportion_35)) + 3*time.Second - executeActive = func() bool { return warlock.DecimationAura.IsActive() } - } else if warlock.Talents.Haunt { - executePhase = time.Duration(float64(sim.Duration) * (1.0 - sim.Encounter.ExecuteProportion_25)) - executeActive = func() bool { return sim.IsExecutePhase25() } - } else { - executePhase = time.Duration(0) - executeActive = func() bool { return true } - } - - lustCD := warlock.GetMajorCooldownIgnoreTag(core.BloodlustActionID) - - for _, cd := range warlock.GetMajorCooldowns() { - if _, ignored := ignoredCDs[cd.Spell.ActionID]; ignored { - continue - } - - spellCD := max(cd.Spell.CD.Duration, cd.Spell.SharedCD.Duration) - runTime := time.Duration(float64(durMap[cd.Spell.ActionID]) * 0.75) - spell := cd.Spell - - cd.ShouldActivate = func(sim *core.Simulation, character *core.Character) bool { - timeLeft := sim.GetRemainingDuration() - runTime - timeUntilExecute := max(0, executePhase-sim.CurrentTime) - lustIsActive := lustCD != nil && character.HasActiveAura("Bloodlust-"+lustCD.Spell.ActionID.String()) - - // if time until execute is less than the CD AND remaining time minus time till execute gives - // the same amount of uses as remaining time alone then delay - if !executeActive() && timeUntilExecute < spellCD+runTime && - retainUses(timeLeft, spellCD, timeUntilExecute) { - return false - } - - if warlock.Talents.Metamorphosis && spell.ActionID != warlock.Metamorphosis.ActionID { - metaCD := warlock.GetMajorCooldown(warlock.Metamorphosis.ActionID) - if !warlock.MetamorphosisAura.IsActive() && metaCD != nil && metaCD.TimeToNextCast(sim) < spellCD+runTime && - retainUses(timeLeft, spellCD, metaCD.TimeToNextCast(sim)) { - return false - } - } - - if lustCD != nil && !lustIsActive && - lustCD.TimeToNextCast(sim) < spellCD+runTime && retainUses(timeLeft, spellCD, - lustCD.TimeToNextCast(sim)) { - return false - } - - if spell.ActionID.SameActionIgnoreTag(core.PowerInfusionActionID) && - (lustIsActive || (lustCD != nil && lustCD.TimeToNextCast(sim) < runTime)) { - return false // don't use PI while lust is active or it would overlap - } - - return true - } - } -} - -func (warlock *Warlock) calcRelativeCorruptionInc(target *core.Unit) float64 { - dot := warlock.Corruption.Dot(target) - snapshotCrit := dot.SnapshotCritChance - snapshotDmg := dot.SnapshotAttackerMultiplier * (snapshotCrit*(warlock.Corruption.CritMultiplier-1) + 1) - - attackTable := warlock.AttackTables[target.UnitIndex] - curCrit := warlock.Corruption.SpellCritChance(target) - curDmg := dot.Spell.AttackerDamageMultiplier(attackTable) * (curCrit*(warlock.Corruption.CritMultiplier-1) + 1) - - return curDmg / snapshotDmg -} - -func aclAppendSimple(acl []ActionCondition, spell *core.Spell, cond func(sim *core.Simulation) ( - bool, *core.Unit)) []ActionCondition { - return append(acl, ActionCondition{ - Spell: spell, - Condition: func(sim *core.Simulation) (ACLaction, *core.Unit) { - if cond, target := cond(sim); cond { - return ACLCast, target - } else { - return ACLNext, nil - } - }, - }) -} - -func (warlock *Warlock) defineRotation() { - acl := warlock.acl - mainTarget := warlock.CurrentTarget // assumed to be the first element in the target list - var hauntTravel time.Duration - if warlock.Talents.Haunt { - hauntTravel = warlock.Haunt.TravelTime() - } - critDebuffCat := warlock.GetEnemyExclusiveCategories(core.SpellCritEffectCategory).Get(mainTarget) - - logInfo := func(sim *core.Simulation, msg string, vals ...interface{}) { - if sim.Log != nil { - warlock.Log(sim, "[Info] "+msg, vals...) - } - } - - allUnits := warlock.Env.Encounter.TargetUnits - if mainTarget != allUnits[0] { - panic("CurrentTarget assumption violated") - } - - var multidotTargets, uaDotTargets []*core.Unit - multidotCount := min(len(allUnits), 3) - if warlock.Rotation.Type == proto.Warlock_Rotation_Affliction { - // up to 3 targets: multidot, no seed - // 4 targets: corruption+UA 3x, seed on 4th; possibly only 1x UA since it's close in value - // 5 targets: corruption x3, UA 1x, seed - // 6 targets: corruption x2, UA 1x, seed; only 1x corruption + UA is close in value - // 7-9 targets: corruption x1, no UA, seed - // 10+ targets: no corruption anymore probably - uaCount := min(len(allUnits), 3) - - if len(allUnits) > 4 { - uaCount = 1 - } - if len(allUnits) == 6 { - multidotCount = 2 - } else if len(allUnits) > 6 { - uaCount = 0 - multidotCount = core.TernaryInt(len(allUnits) > 9, 0, 1) - } - - uaDotTargets = allUnits[:uaCount] - } else if warlock.Rotation.Type == proto.Warlock_Rotation_Destruction { - multidotCount = min(len(allUnits), 4) - } - multidotTargets = allUnits[:multidotCount] - - if warlock.Talents.DemonicEmpowerment && warlock.Options.Summon != proto.Warlock_Options_NoSummon { - acl = aclAppendSimple(acl, warlock.DemonicEmpowerment, func(sim *core.Simulation) (bool, *core.Unit) { - return !warlock.Rotation.UseInfernal || warlock.Inferno.IsReady(sim), mainTarget - }) - } - - if warlock.Talents.Metamorphosis { - acl = aclAppendSimple(acl, warlock.ImmolationAura, func(sim *core.Simulation) (bool, *core.Unit) { - // TODO: potentially wait for procs - return true, nil - }) - } - - // only handles deliberate overrides of the primary spell - if warlock.Rotation.PrimarySpell == proto.Warlock_Rotation_Seed { - acl = aclAppendSimple(acl, warlock.Seed, func(sim *core.Simulation) (bool, *core.Unit) { - return warlock.Rotation.DetonateSeed || !warlock.Seed.Dot(mainTarget).IsActive(), mainTarget - }) - } - - if warlock.Talents.Conflagrate { - acl = aclAppendSimple(acl, warlock.Conflagrate, func(sim *core.Simulation) (bool, *core.Unit) { - return warlock.Immolate.Dot(mainTarget).IsActive(), mainTarget - }) - } - - if warlock.Talents.Haunt && warlock.Rotation.SpecSpell == proto.Warlock_Rotation_Haunt { - curIndex := len(acl) - - acl = aclAppendSimple(acl, warlock.Haunt, func(sim *core.Simulation) (bool, *core.Unit) { - // no need for haunt until dots are up, mostly relevant in the opener - if !warlock.Corruption.Dot(mainTarget).IsActive() && !warlock.UnstableAffliction.Dot(mainTarget).IsActive() { - return false, nil - } - - if !warlock.Haunt.CD.IsReady(sim) { - return false, nil - } - - if sim.GetRemainingDuration() < 5*time.Second { - return false, nil - } - - castTime := warlock.Haunt.CastTime() - _, nextActionTime := warlock.getAlternativeAction(sim, curIndex) - hauntRem := warlock.HauntDebuffAuras.Get(mainTarget).RemainingDuration(sim) - - // 250ms of leeway in case haste buffs run out - return hauntRem-castTime-hauntTravel < nextActionTime+250*time.Millisecond, mainTarget - }) - - acl = aclAppendSimple(acl, warlock.LifeTap, func(sim *core.Simulation) (bool, *core.Unit) { - val := warlock.ShadowBolt.DefaultCast.Cost - - if sim.IsExecutePhase25() { - dsDot := warlock.DrainSoul.CurDot() - if dsDot.IsActive() && dsDot.NumTicksRemaining(sim) >= 1 { - return false, nil // continuing to channel drain soul doesn't cost us any mana - } - - val = warlock.UnstableAffliction.DefaultCast.Cost // highest mana cost spell outside SB - } - val += warlock.Haunt.DefaultCast.Cost - - if warlock.CurrentMana() > val || sim.GetRemainingDuration() > 5*time.Second { - return false, nil - } - - logInfo(sim, "Casting life tap to not drop haunt") - return true, nil - }) - } - - // refresh corruption with shadow bolt if it's running out - if warlock.Talents.EverlastingAffliction == 5 && len(allUnits) > 1 { - travel := warlock.ShadowBolt.TravelTime() - curIndex := len(acl) - - acl = aclAppendSimple(acl, warlock.ShadowBolt, func(sim *core.Simulation) (bool, *core.Unit) { - type targetRem struct { - target *core.Unit - rem time.Duration - } - targets := make([]targetRem, 0, len(sim.Encounter.TargetUnits)) - for _, target := range sim.Encounter.TargetUnits { - // if there's already an shadowbolt on the way then skip - if warlock.corrRefreshList[target.UnitIndex] >= sim.CurrentTime-travel { - continue - } - - // same when we can't refresh in time - if warlock.Corruption.Dot(target).RemainingDuration(sim) < travel+warlock.ShadowBolt.CastTime() { - continue - } - - // assuming haunt doesn't drop, which it shouldn't, corruption will already be refreshed - if target == mainTarget && warlock.HauntDebuffAuras.Get(target).RemainingDuration(sim) < - warlock.Corruption.Dot(target).RemainingDuration(sim) { - continue - } - - rem := min(warlock.Corruption.Dot(target).RemainingDuration(sim), - warlock.ShadowEmbraceAuras.Get(target).RemainingDuration(sim)) - targets = append(targets, targetRem{rem: rem, target: target}) - } - sort.Slice(targets, func(i, j int) bool { return targets[i].rem < targets[j].rem }) - - // we know that the only higher priority action is haunt, thus the only 2 things we need to - // consider outside of shadow bolts is haunt and mana - nextSpell, timeAdvance := warlock.getAlternativeAction(sim, curIndex) - sbCastTime := warlock.ShadowBolt.EffectiveCastTime() - timeAdvance += sbCastTime - recast := false - // shadow trance proc will only speed up one cast - if warlock.ShadowBolt.CastTimeMultiplier == 0 { - // somewhat hacky, breaks if CastTimeMultiplier is ever changed by anything else - sbCastTime = time.Duration(float64(warlock.ShadowBolt.DefaultCast.CastTime) * warlock.CastSpeed) - sbCastTime = max(sbCastTime, warlock.SpellGCD()) - - if nextSpell == warlock.ShadowBolt { - timeAdvance += sbCastTime - warlock.ShadowBolt.EffectiveCastTime() - } - } - mana := warlock.CurrentMana() - warlock.ShadowBolt.DefaultCast.Cost - consideredHaunt := false - for _, ele := range targets { - if mana < warlock.ShadowBolt.DefaultCast.Cost { - timeAdvance += warlock.LifeTap.EffectiveCastTime() - mana += 10000.0 // we only need 1 life tap, so the exact value doesn't matter - } - mana -= warlock.ShadowBolt.DefaultCast.Cost - - if !consideredHaunt && timeAdvance+warlock.Haunt.CastTime()+hauntTravel >= - warlock.HauntDebuffAuras.Get(mainTarget).RemainingDuration(sim) { - timeAdvance += warlock.Haunt.EffectiveCastTime() - mana -= warlock.Haunt.DefaultCast.Cost - consideredHaunt = true - } - - // some extra time to accommodate haste buffs running out - if timeAdvance+travel+250*time.Millisecond >= ele.rem { - recast = true - break - } - - timeAdvance += sbCastTime + 50*time.Millisecond - } - - if recast { - return true, targets[0].target - } else { - return false, nil - } - }) - } - - if warlock.Rotation.Corruption && warlock.Talents.EverlastingAffliction > 0 { - acl = aclAppendSimple(acl, warlock.Corruption, func(sim *core.Simulation) (bool, *core.Unit) { - // TODO: wait for all targets SB debuff? - if !critDebuffCat.AnyActive() && - warlock.Talents.ImprovedShadowBolt > 0 && sim.CurrentTime < 25 { - return false, nil - } - - for _, target := range multidotTargets { - if !warlock.Corruption.Dot(target).IsActive() { - return true, target - } - - // check if reapplying corruption is worthwhile - relDmgInc := warlock.calcRelativeCorruptionInc(target) - snapshotDmg := warlock.Corruption.ExpectedTickDamageFromCurrentSnapshot(sim, target) - snapshotDmg *= float64(sim.GetRemainingDuration()) / float64(warlock.Corruption.Dot(target).TickPeriod()) - snapshotDmg *= (relDmgInc - 1) - snapshotDmg -= warlock.Corruption.ExpectedTickDamageFromCurrentSnapshot(sim, target) - - logInfo(sim, "Relative Corruption Inc: [%.2f], expected dmg gain: [%.2f]", relDmgInc, snapshotDmg) - - if relDmgInc > 1.15 || snapshotDmg > 10000 { - return true, target - } - } - - return false, nil - }) - } - - prefCurse := warlock.CurseOfAgony.CurDot().Aura - switch warlock.Rotation.Curse { - case proto.Warlock_Rotation_Elements: - prefCurse = warlock.CurseOfElementsAuras.Get(mainTarget) - acl = aclAppendSimple(acl, warlock.CurseOfElements, func(sim *core.Simulation) (bool, *core.Unit) { - return warlock.CurseOfElementsAuras.Get(mainTarget).RemainingDuration(sim) < 3*time.Second, mainTarget - }) - case proto.Warlock_Rotation_Weakness: - prefCurse = warlock.CurseOfWeaknessAuras.Get(mainTarget) - acl = aclAppendSimple(acl, warlock.CurseOfWeakness, func(sim *core.Simulation) (bool, *core.Unit) { - return warlock.CurseOfWeaknessAuras.Get(mainTarget).RemainingDuration(sim) < 3*time.Second, mainTarget - }) - case proto.Warlock_Rotation_Tongues: - prefCurse = warlock.CurseOfTonguesAuras.Get(mainTarget) - acl = aclAppendSimple(acl, warlock.CurseOfTongues, func(sim *core.Simulation) (bool, *core.Unit) { - return warlock.CurseOfTonguesAuras.Get(mainTarget).RemainingDuration(sim) < 3*time.Second, mainTarget - }) - } - - if warlock.HasMajorGlyph(proto.WarlockMajorGlyph_GlyphOfLifeTap) { - curIndex := len(acl) - acl = aclAppendSimple(acl, warlock.LifeTap, func(sim *core.Simulation) (bool, *core.Unit) { - // try to keep up the buff for the entire execute phase if possible - expiresAt := max(0, warlock.GlyphOfLifeTapAura.RemainingDuration(sim)) - if sim.GetRemainingDuration() <= 40*time.Second && - expiresAt+10*time.Second < sim.GetRemainingDuration() && - warlock.CurrentManaPercent() < 0.35 { - logInfo(sim, "Casting life tap to keep up GoLT (40s till EOF)") - return true, nil - } - - if _, dur := warlock.getAlternativeAction(sim, curIndex); dur > expiresAt && - sim.GetRemainingDuration() > 12*time.Second { - logInfo(sim, "Casting life tap to keep up GoLT") - return true, nil - } - - return false, nil - }) - } - - if warlock.Talents.UnstableAffliction && warlock.Rotation.SecondaryDot == proto.Warlock_Rotation_UnstableAffliction { - acl = aclAppendSimple(acl, warlock.UnstableAffliction, func(sim *core.Simulation) (bool, *core.Unit) { - castTime := warlock.UnstableAffliction.CastTime() - for _, target := range uaDotTargets { - if warlock.UnstableAffliction.Dot(target).RemainingDuration(sim)-castTime <= 0 && - sim.GetRemainingDuration() >= 9*time.Second+castTime { - return true, target - } - } - - return false, nil - }) - } - - if len(allUnits) > len(multidotTargets) { - acl = aclAppendSimple(acl, warlock.Seed, func(sim *core.Simulation) (bool, *core.Unit) { - for _, target := range sim.Encounter.TargetUnits { - // avoid mainTarget as we may want to corruption that later - if !warlock.Corruption.Dot(target).IsActive() && target != mainTarget { - return true, target - } - } - panic("No viable seed target found") - }) - } - - // TODO: automatically determine based on haunt/SE? - if warlock.Rotation.Curse == proto.Warlock_Rotation_Doom { - acl = aclAppendSimple(acl, warlock.CurseOfDoom, func(sim *core.Simulation) (bool, *core.Unit) { - return warlock.CurseOfDoom.Dot(mainTarget).RemainingDuration(sim) <= 0 && - sim.GetRemainingDuration() >= 60*time.Second, mainTarget - }) - } - - if warlock.Rotation.Corruption && warlock.Talents.EverlastingAffliction <= 0 { - acl = aclAppendSimple(acl, warlock.Corruption, func(sim *core.Simulation) (bool, *core.Unit) { - for _, target := range multidotTargets { - dot := warlock.Corruption.Dot(target) - if dot.IsActive() { - continue - } - - tickLen := dot.TickLength - if dot.AffectedByCastSpeed { - tickLen = warlock.ApplyCastSpeed(tickLen) - } - - if sim.GetRemainingDuration() >= 4*tickLen { - return true, target - } - } - return false, nil - }) - } - - if warlock.Rotation.Curse == proto.Warlock_Rotation_Agony || warlock.Rotation.Curse == proto.Warlock_Rotation_Doom { - tickHeuristic := core.TernaryDuration(warlock.Talents.Haunt, 16*time.Second, 22*time.Second) - - acl = aclAppendSimple(acl, warlock.CurseOfAgony, func(sim *core.Simulation) (bool, *core.Unit) { - for _, target := range multidotTargets { - if !warlock.CurseOfDoom.Dot(target).IsActive() && !warlock.CurseOfAgony. - Dot(target).IsActive() && sim.GetRemainingDuration() >= tickHeuristic { - return true, target - } - } - - return false, nil - }) - } - - if !warlock.Talents.UnstableAffliction && warlock.Rotation.SecondaryDot == proto.Warlock_Rotation_Immolate { - tickHeuristic := core.TernaryDuration(warlock.Talents.Conflagrate, 6*time.Second, 12*time.Second) - - acl = aclAppendSimple(acl, warlock.Immolate, func(sim *core.Simulation) (bool, *core.Unit) { - castTime := warlock.Immolate.CastTime() - for _, target := range multidotTargets { - if warlock.Immolate.Dot(target).RemainingDuration(sim)-castTime <= 0 && - sim.GetRemainingDuration() >= tickHeuristic+castTime { - return true, target - } - } - return false, nil - }) - } - - if warlock.Talents.ChaosBolt { - acl = aclAppendSimple(acl, warlock.ChaosBolt, func(sim *core.Simulation) (bool, *core.Unit) { - return true, mainTarget - }) - } - - if warlock.Talents.Haunt { - function := func(sim *core.Simulation) (ACLaction, *core.Unit) { - dsDot := warlock.DrainSoul.CurDot() - if !sim.IsExecutePhase25() { - return ACLNext, nil - } - - if !dsDot.IsActive() || dsDot.TimeUntilNextTick(sim) < dsDot.TickPeriod()-humanReactionTime { - return ACLCast, mainTarget - } - - if warlock.Corruption.CurDot().RemainingDuration(sim) < dsDot.TickPeriod() { - logInfo(sim, "Recasting drain soul to not let corruption drop") - return ACLRecast, mainTarget - } - - // check if recasting drain soul is worthwhile - - // check when UA, CoA and haunt have to be refreshed, respectively - uaRefresh := warlock.UnstableAffliction.Dot(mainTarget).RemainingDuration(sim) - - warlock.UnstableAffliction.CastTime() - - curseRefresh := max(prefCurse.RemainingDuration(sim), - warlock.CurseOfDoom.CurDot().RemainingDuration(sim)) - warlock.CurseOfAgony.CastTime() - - hauntRefresh := warlock.HauntDebuffAuras.Get(mainTarget).RemainingDuration(sim) - - warlock.Haunt.CastTime() - hauntTravel - - timeUntilRefresh := min(uaRefresh, curseRefresh) - - // the amount of ticks we have left, assuming we continue channeling - ticksLeft := int(timeUntilRefresh/dsDot.TickPeriod()) + 1 - ticksLeft = min(ticksLeft, int(hauntRefresh/dsDot.TickPeriod())) - ticksLeft = min(ticksLeft, dsDot.NumTicksRemaining(sim)) - - // amount of ticks we'd get assuming we recast drain soul - recastTicks := int(timeUntilRefresh/warlock.ApplyCastSpeed(dsDot.TickLength)) + 1 - recastTicks = min(recastTicks, int(hauntRefresh/warlock.ApplyCastSpeed(dsDot.TickLength))) - recastTicks = min(recastTicks, int(dsDot.NumberOfTicks)) - - if ticksLeft <= 0 || recastTicks <= 0 { - return ACLCast, mainTarget - } - - snapshotDmg := warlock.DrainSoul.ExpectedTickDamageFromCurrentSnapshot(sim, mainTarget) * float64(ticksLeft) - recastDmg := warlock.DrainSoul.ExpectedTickDamage(sim, mainTarget) * float64(recastTicks) - snapshotDPS := snapshotDmg / (float64(ticksLeft) * dsDot.TickPeriod().Seconds()) - recastDps := recastDmg / (float64(recastTicks)*warlock.ApplyCastSpeed(dsDot.TickLength).Seconds() + - humanReactionTime.Seconds()) - - if recastDps > snapshotDPS { - logInfo(sim, "Recasting drain soul, %.2f (%d) > %.2f (%d)", - recastDps, recastTicks, snapshotDPS, ticksLeft) - return ACLRecast, mainTarget - } - - // TODO: if number of ticks left < number of ticks until we need to recast dots/haunt - // and some proc effect falls off before the next tick, check if recasting is a DPS gain - - return ACLCast, mainTarget - } - - acl = append(acl, ActionCondition{ - Spell: warlock.DrainSoul, - Condition: function, - }) - } - - if warlock.Talents.Decimation > 0 { - acl = aclAppendSimple(acl, warlock.SoulFire, func(sim *core.Simulation) (bool, *core.Unit) { - return warlock.DecimationAura.IsActive(), mainTarget - }) - } - - if warlock.Talents.MoltenCore > 0 { - acl = aclAppendSimple(acl, warlock.Incinerate, func(sim *core.Simulation) (bool, *core.Unit) { - return warlock.MoltenCoreAura.IsActive(), mainTarget - }) - } - - if warlock.Rotation.PrimarySpell == proto.Warlock_Rotation_Incinerate { - acl = aclAppendSimple(acl, warlock.Incinerate, func(sim *core.Simulation) (bool, *core.Unit) { - return true, mainTarget - }) - } - - acl = aclAppendSimple(acl, warlock.ShadowBolt, func(sim *core.Simulation) (bool, *core.Unit) { - return true, mainTarget - }) - - if warlock.Talents.DarkPact { - acl = aclAppendSimple(acl, warlock.DarkPact, func(sim *core.Simulation) (bool, *core.Unit) { - // if pet has enough mana, prefer dark pact over life tap - return warlock.Pet.CurrentMana() > warlock.GetStat(stats.SpellPower)+1200+131, nil - }) - } - - acl = aclAppendSimple(acl, warlock.LifeTap, func(sim *core.Simulation) (bool, *core.Unit) { - return true, nil - }) - - warlock.acl = acl -} - -func aclNextAction(sim *core.Simulation, acl []ActionCondition, skipIndex int) (*core.Spell, bool) { - logfunc := sim.Log - sim.Log = nil // disable logging here since it's not useful - for _, ac := range acl[skipIndex+1:] { - if action, _ := ac.Condition(sim); action != ACLNext && ac.Spell.IsReady(sim) { - sim.Log = logfunc - return ac.Spell, action == ACLRecast - } - } - - panic("ACL list exhausted but no match found") -} - -// Returns the spell and casttime of the alternative action we'd take, if we skip skipIndex -func (warlock *Warlock) getAlternativeAction(sim *core.Simulation, skipIndex int) (*core.Spell, time.Duration) { - var nextSpellTime time.Duration - nextSpell, recast := aclNextAction(sim, warlock.acl, skipIndex) - - if nextSpell == warlock.DrainSoul { - if recast || !nextSpell.CurDot().IsActive() { - nextSpellTime = warlock.ApplyCastSpeed(nextSpell.CurDot().TickLength) + humanReactionTime - } else { - nextSpellTime = nextSpell.CurDot().TickPeriod() + humanReactionTime - } - } else { - nextSpellTime = nextSpell.EffectiveCastTime() - } - - return nextSpell, max(core.GCDMin, nextSpellTime) -} - -func (warlock *Warlock) OnGCDReady(sim *core.Simulation) { - if warlock.IsUsingAPL { - return - } - - for _, ac := range warlock.acl { - action, target := ac.Condition(sim) - if action == ACLNext || !ac.Spell.IsReady(sim) { - continue - } - - // TODO: find a more general way of dealing with channeling spells, but for now this is fine since drain - // soul is the only one being used anyway - if action == ACLRecast { - if ac.Spell != warlock.DrainSoul { - panic("Trying to recast unknown spell") - } - warlock.DrainSoul.Dot(target).Cancel(sim) - } - - if warlock.DrainSoul.CurDot().IsActive() { - if ac.Spell != warlock.DrainSoul && warlock.DrainSoul.CurDot().TickCount != 0 { - warlock.DrainSoul.CurDot().Cancel(sim) - } else { - warlock.WaitUntil(sim, sim.CurrentTime+warlock.DrainSoul.CurDot().TimeUntilNextTick(sim)+humanReactionTime) - return - } - } - - castTime := ac.Spell.CastTime() - if success := ac.Spell.Cast(sim, target); success { - // track shadowbolts "in the air" that haven't refreshed corruption yet - if ac.Spell == warlock.ShadowBolt || ac.Spell == warlock.Haunt { - warlock.corrRefreshList[target.UnitIndex] = sim.CurrentTime + castTime - } - - if !warlock.GCD.IsReady(sim) { - // after-GCD actions - if ac.Spell == warlock.Corruption && warlock.ItemSwap.IsEnabled() && warlock.ItemSwap.IsSwapped() { - warlock.ItemSwap.SwapItems(sim, []proto.ItemSlot{proto.ItemSlot_ItemSlotMainHand, - proto.ItemSlot_ItemSlotOffHand, proto.ItemSlot_ItemSlotRanged}) - } - - return - } - } else if warlock.CurrentMana() < ac.Spell.DefaultCast.Cost { - // TODO: this will only cast life tap right now - if success := warlock.acl[len(warlock.acl)-1].Spell.Cast(sim, nil); !success { - panic("Failed to cast life tap / dark pact") - } - return - } - } - - panic("ACL list exhausted but no match found") -} diff --git a/sim/warlock/seed.go b/sim/warlock/seed.go index 5cd7289d8a..d404d16861 100644 --- a/sim/warlock/seed.go +++ b/sim/warlock/seed.go @@ -108,11 +108,7 @@ func (warlock *Warlock) registerSeedSpell() { // seed is mutually exclusive with corruption warlock.Corruption.Dot(target).Deactivate(sim) - if warlock.Rotation.DetonateSeed { - seedExplosion.Cast(sim, target) - } else { - spell.Dot(target).Apply(sim) - } + spell.Dot(target).Apply(sim) } }) }, diff --git a/sim/warlock/warlock.go b/sim/warlock/warlock.go index f25546e27d..0f281e6cbb 100644 --- a/sim/warlock/warlock.go +++ b/sim/warlock/warlock.go @@ -14,9 +14,8 @@ var TalentTreeSizes = [3]int{28, 27, 26} type Warlock struct { core.Character - Talents *proto.WarlockTalents - Options *proto.Warlock_Options - Rotation *proto.Warlock_Rotation + Talents *proto.WarlockTalents + Options *proto.Warlock_Options Pet *WarlockPet @@ -73,23 +72,6 @@ type Warlock struct { PreviousTime time.Duration petStmBonusSP float64 - acl []ActionCondition - - // contains for each target the time the last shadowbolt was casted onto them - corrRefreshList []time.Duration -} - -type ACLaction int - -const ( - ACLCast ACLaction = iota - ACLNext - ACLRecast -) - -type ActionCondition struct { - Spell *core.Spell - Condition func(*core.Simulation) (ACLaction, *core.Unit) } func (warlock *Warlock) GetCharacter() *core.Character { @@ -133,12 +115,6 @@ func (warlock *Warlock) Initialize() { warlock.registerInfernoSpell() warlock.registerBlackBook() - warlock.defineRotation() - - precastSpell := warlock.ShadowBolt - if warlock.Rotation.Type == proto.Warlock_Rotation_Destruction { - precastSpell = warlock.SoulFire - } // Do this post-finalize so cast speed is updated with new stats warlock.Env.RegisterPostFinalizeEffect(func() { // if itemswap is enabled, correct for any possible haste changes @@ -164,25 +140,6 @@ func (warlock *Warlock) Initialize() { } }) } - - if warlock.IsUsingAPL { - return - } - - precastSpellAt := -warlock.ApplyCastSpeedForSpell(precastSpell.DefaultCast.CastTime, precastSpell) - - warlock.RegisterPrepullAction(precastSpellAt, func(sim *core.Simulation) { - precastSpell.Cast(sim, warlock.CurrentTarget) - }) - if warlock.GlyphOfLifeTapAura != nil || warlock.SpiritsoftheDamnedAura != nil { - warlock.RegisterPrepullAction(precastSpellAt-warlock.SpellGCD(), func(sim *core.Simulation) { - warlock.LifeTap.Cast(sim, nil) - }) - } - if warlock.ItemSwap.IsEnabled() { - warlock.AddStats(correction.Invert()) - warlock.MultiplyCastSpeed(1.0) - } }) } @@ -202,13 +159,6 @@ func (warlock *Warlock) Reset(sim *core.Simulation) { if sim.CurrentTime == 0 { warlock.petStmBonusSP = 0 } - - if !warlock.IsUsingAPL { - warlock.ItemSwap.SwapItems(sim, []proto.ItemSlot{proto.ItemSlot_ItemSlotMainHand, - proto.ItemSlot_ItemSlotOffHand, proto.ItemSlot_ItemSlotRanged}) - } - warlock.corrRefreshList = make([]time.Duration, len(warlock.Env.Encounter.TargetUnits)) - warlock.setupCooldowns(sim) } func NewWarlock(character *core.Character, options *proto.Player) *Warlock { @@ -218,7 +168,6 @@ func NewWarlock(character *core.Character, options *proto.Player) *Warlock { Character: *character, Talents: &proto.WarlockTalents{}, Options: warlockOptions.Options, - Rotation: warlockOptions.Rotation, } core.FillTalentsProto(warlock.Talents.ProtoReflect(), options.TalentsString, TalentTreeSizes) warlock.EnableManaBar() From fe1d147a48b645c928381941d00cccb3fe95e793 Mon Sep 17 00:00:00 2001 From: James Tanner Date: Sat, 6 Jan 2024 14:27:30 -0800 Subject: [PATCH 13/28] Merge from master --- sim/core/spell_snapshot.go | 90 ------ sim/rogue/TestCombat.results | 192 ++++++------- sim/warlock/TestDemonology.results | 424 ++++++++++++++-------------- sim/warlock/TestDestruction.results | 212 +++++++------- sim/warlock/inferno.go | 3 - sim/warlock/warlock_test.go | 46 +-- sim/warrior/heroic_strike_cleave.go | 3 - sim/warrior/talents.go | 3 +- 8 files changed, 418 insertions(+), 555 deletions(-) delete mode 100644 sim/core/spell_snapshot.go diff --git a/sim/core/spell_snapshot.go b/sim/core/spell_snapshot.go deleted file mode 100644 index c4f445203c..0000000000 --- a/sim/core/spell_snapshot.go +++ /dev/null @@ -1,90 +0,0 @@ -package core - -import ( - "time" -) - -type procTracker struct { - aura *Aura - didActivate bool - isActive bool - expiresAt time.Duration -} - -type SnapshotManager struct { - procTrackers []*procTracker - majorCooldowns []*MajorCooldown - character *Character -} - -func NewSnapshotManager(character *Character) *SnapshotManager { - return &SnapshotManager{ - procTrackers: make([]*procTracker, 0), - majorCooldowns: make([]*MajorCooldown, 0), - character: character, - } -} - -func (manager *SnapshotManager) AddProc(id int32, label string, isActive bool) bool { - character := manager.character - - if !character.HasAura(label) { - return false - } - - manager.procTrackers = append(manager.procTrackers, &procTracker{ - didActivate: false, - isActive: isActive, - expiresAt: -1, - aura: character.GetAura(label), - }) - return true -} - -func (manager *SnapshotManager) CanSnapShot(sim *Simulation, castTime time.Duration) bool { - success := true - - for _, procTracker := range manager.procTrackers { - if !procTracker.didActivate && procTracker.aura.IsActive() { - procTracker.didActivate = true - procTracker.expiresAt = procTracker.aura.ExpiresAt() - } - - // A proc is about to drop - if procTracker.didActivate && procTracker.expiresAt <= sim.CurrentTime+castTime { - if sim.Log != nil { - sim.Log("Proc dropping " + procTracker.aura.Label) - } - return true - } - - if !procTracker.didActivate && !procTracker.isActive { - success = false - } - } - - return success -} - -func (manager *SnapshotManager) ActivateMajorCooldowns(sim *Simulation) { - for _, majorCd := range manager.majorCooldowns { - if majorCd.IsReady(sim) { - majorCd.TryActivate(sim, manager.character) - } - } -} - -func (manager *SnapshotManager) ResetProcTrackers() { - for _, procTracker := range manager.procTrackers { - procTracker.didActivate = false - procTracker.expiresAt = -1 - } -} - -func (manager *SnapshotManager) ClearMajorCooldowns() { - manager.majorCooldowns = make([]*MajorCooldown, 0) -} - -func (manager *SnapshotManager) AddMajorCooldown(majorCd *MajorCooldown) { - manager.majorCooldowns = append(manager.majorCooldowns, majorCd) -} diff --git a/sim/rogue/TestCombat.results b/sim/rogue/TestCombat.results index 78ab4bff78..094e9c81fc 100644 --- a/sim/rogue/TestCombat.results +++ b/sim/rogue/TestCombat.results @@ -981,43 +981,43 @@ dps_results: { dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Deadly-fan_aoe-FullBuffs-LongMultiTarget" value: { - dps: 21132.20952 - tps: 15003.86876 + dps: 21435.04268 + tps: 15218.8803 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Deadly-fan_aoe-FullBuffs-LongSingleTarget" value: { - dps: 3516.89637 - tps: 2496.99642 + dps: 3539.13966 + tps: 2512.78916 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Deadly-fan_aoe-FullBuffs-ShortSingleTarget" value: { - dps: 4109.75712 - tps: 2917.92755 + dps: 4297.57812 + tps: 3051.28047 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Deadly-fan_aoe-NoBuffs-LongMultiTarget" value: { - dps: 13003.58802 - tps: 9232.54749 + dps: 13206.06312 + tps: 9376.30481 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Deadly-fan_aoe-NoBuffs-LongSingleTarget" value: { - dps: 1778.52693 - tps: 1262.75412 + dps: 1785.96568 + tps: 1268.03563 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Deadly-fan_aoe-NoBuffs-ShortSingleTarget" value: { - dps: 1863.43428 - tps: 1323.03834 + dps: 1898.48085 + tps: 1347.9214 } } dps_results: { @@ -1149,43 +1149,43 @@ dps_results: { dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Instant-fan_aoe-FullBuffs-LongMultiTarget" value: { - dps: 22695.82072 - tps: 16114.03271 + dps: 23026.48078 + tps: 16348.80135 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Instant-fan_aoe-FullBuffs-LongSingleTarget" value: { - dps: 4601.62498 - tps: 3267.15373 + dps: 4633.5605 + tps: 3289.82796 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Instant-fan_aoe-FullBuffs-ShortSingleTarget" value: { - dps: 5306.8537 - tps: 3767.86612 + dps: 5540.589 + tps: 3933.81819 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Instant-fan_aoe-NoBuffs-LongMultiTarget" value: { - dps: 13260.84412 - tps: 9415.19933 + dps: 13454.08262 + tps: 9552.39866 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Instant-fan_aoe-NoBuffs-LongSingleTarget" value: { - dps: 2301.87343 - tps: 1634.33013 + dps: 2312.07404 + tps: 1641.57257 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Instant-fan_aoe-NoBuffs-ShortSingleTarget" value: { - dps: 2337.44435 - tps: 1659.58549 + dps: 2393.64181 + tps: 1699.48569 } } dps_results: { @@ -1317,43 +1317,43 @@ dps_results: { dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Deadly-fan_aoe-FullBuffs-LongMultiTarget" value: { - dps: 25256.98021 - tps: 17932.45595 + dps: 25576.22706 + tps: 18159.12122 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Deadly-fan_aoe-FullBuffs-LongSingleTarget" value: { - dps: 5018.34623 - tps: 3563.02583 + dps: 5051.3607 + tps: 3586.46609 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Deadly-fan_aoe-FullBuffs-ShortSingleTarget" value: { - dps: 5809.23206 - tps: 4124.55476 + dps: 6092.44116 + tps: 4325.63322 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Deadly-fan_aoe-NoBuffs-LongMultiTarget" value: { - dps: 14807.07114 - tps: 10513.02051 + dps: 15002.54589 + tps: 10651.80759 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Deadly-fan_aoe-NoBuffs-LongSingleTarget" value: { - dps: 2519.14739 - tps: 1788.59464 + dps: 2529.97284 + tps: 1796.28072 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Deadly-fan_aoe-NoBuffs-ShortSingleTarget" value: { - dps: 2588.00612 - tps: 1837.48434 + dps: 2644.86445 + tps: 1877.85376 } } dps_results: { @@ -1485,43 +1485,43 @@ dps_results: { dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Instant-fan_aoe-FullBuffs-LongMultiTarget" value: { - dps: 18824.30249 - tps: 13365.25477 + dps: 19109.11172 + tps: 13567.46932 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Instant-fan_aoe-FullBuffs-LongSingleTarget" value: { - dps: 4189.47287 - tps: 2974.52573 + dps: 4217.58491 + tps: 2994.48528 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Instant-fan_aoe-FullBuffs-ShortSingleTarget" value: { - dps: 5004.60982 - tps: 3553.27297 + dps: 5274.9979 + tps: 3745.24851 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Instant-fan_aoe-NoBuffs-LongMultiTarget" value: { - dps: 10831.81586 - tps: 7690.58926 + dps: 11025.5797 + tps: 7828.16159 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Instant-fan_aoe-NoBuffs-LongSingleTarget" value: { - dps: 1983.7099 - tps: 1408.43403 + dps: 1993.74101 + tps: 1415.55612 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Instant-fan_aoe-NoBuffs-ShortSingleTarget" value: { - dps: 2101.37058 - tps: 1491.97311 + dps: 2156.33219 + tps: 1530.99585 } } dps_results: { @@ -1653,43 +1653,43 @@ dps_results: { dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Deadly-fan_aoe-FullBuffs-LongMultiTarget" value: { - dps: 21290.63515 - tps: 15116.35096 + dps: 21615.92487 + tps: 15347.30666 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Deadly-fan_aoe-FullBuffs-LongSingleTarget" value: { - dps: 3540.60866 - tps: 2513.83215 + dps: 3565.29603 + tps: 2531.36018 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Deadly-fan_aoe-FullBuffs-ShortSingleTarget" value: { - dps: 4172.47671 - tps: 2962.45847 + dps: 4362.48163 + tps: 3097.36196 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Deadly-fan_aoe-NoBuffs-LongMultiTarget" value: { - dps: 13113.07646 - tps: 9310.28429 + dps: 13327.72899 + tps: 9462.68758 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Deadly-fan_aoe-NoBuffs-LongSingleTarget" value: { - dps: 1793.27032 - tps: 1273.22193 + dps: 1801.49013 + tps: 1279.05799 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Deadly-fan_aoe-NoBuffs-ShortSingleTarget" value: { - dps: 1900.39941 - tps: 1349.28358 + dps: 1933.6019 + tps: 1372.85735 } } dps_results: { @@ -1821,43 +1821,43 @@ dps_results: { dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Instant-fan_aoe-FullBuffs-LongMultiTarget" value: { - dps: 22855.23185 - tps: 16227.21462 + dps: 23204.3601 + tps: 16475.09567 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Instant-fan_aoe-FullBuffs-LongSingleTarget" value: { - dps: 4631.68558 - tps: 3288.49676 + dps: 4667.4418 + tps: 3313.88368 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Instant-fan_aoe-FullBuffs-ShortSingleTarget" value: { - dps: 5384.15189 - tps: 3822.74784 + dps: 5622.83334 + tps: 3992.21167 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Instant-fan_aoe-NoBuffs-LongMultiTarget" value: { - dps: 13404.07154 - tps: 9516.8908 + dps: 13586.68098 + tps: 9646.54349 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Instant-fan_aoe-NoBuffs-LongSingleTarget" value: { - dps: 2322.07483 - tps: 1648.67313 + dps: 2332.01436 + tps: 1655.7302 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Instant-fan_aoe-NoBuffs-ShortSingleTarget" value: { - dps: 2383.73941 - tps: 1692.45498 + dps: 2435.28497 + tps: 1729.05233 } } dps_results: { @@ -1989,43 +1989,43 @@ dps_results: { dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Deadly-fan_aoe-FullBuffs-LongMultiTarget" value: { - dps: 25439.18557 - tps: 18061.82176 + dps: 25775.50672 + tps: 18300.60977 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Deadly-fan_aoe-FullBuffs-LongSingleTarget" value: { - dps: 5052.03546 - tps: 3586.94518 + dps: 5087.70125 + tps: 3612.26789 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Deadly-fan_aoe-FullBuffs-ShortSingleTarget" value: { - dps: 5894.33138 - tps: 4184.97528 + dps: 6179.0402 + tps: 4387.11854 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Deadly-fan_aoe-NoBuffs-LongMultiTarget" value: { - dps: 14939.32565 - tps: 10606.92121 + dps: 15142.98192 + tps: 10751.51716 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Deadly-fan_aoe-NoBuffs-LongSingleTarget" value: { - dps: 2539.17634 - tps: 1802.8152 + dps: 2550.98882 + tps: 1811.20206 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Deadly-fan_aoe-NoBuffs-ShortSingleTarget" value: { - dps: 2635.71107 - tps: 1871.35486 + dps: 2689.5647 + tps: 1909.59093 } } dps_results: { @@ -2157,43 +2157,43 @@ dps_results: { dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Instant-fan_aoe-FullBuffs-LongMultiTarget" value: { - dps: 18971.67938 - tps: 13469.89236 + dps: 19281.73013 + tps: 13690.02839 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Instant-fan_aoe-FullBuffs-LongSingleTarget" value: { - dps: 4220.37505 - tps: 2996.46629 + dps: 4255.39217 + tps: 3021.32844 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Instant-fan_aoe-FullBuffs-ShortSingleTarget" value: { - dps: 5084.05186 - tps: 3609.67682 + dps: 5352.90194 + tps: 3800.56038 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Instant-fan_aoe-NoBuffs-LongMultiTarget" value: { - dps: 10943.42878 - tps: 7769.83444 + dps: 11144.86205 + tps: 7912.85206 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Instant-fan_aoe-NoBuffs-LongSingleTarget" value: { - dps: 1997.50981 - tps: 1418.23196 + dps: 2007.95517 + tps: 1425.64817 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Instant-fan_aoe-NoBuffs-ShortSingleTarget" value: { - dps: 2147.90528 - tps: 1525.01275 + dps: 2196.75486 + tps: 1559.69595 } } dps_results: { diff --git a/sim/warlock/TestDemonology.results b/sim/warlock/TestDemonology.results index f4df027900..2ae42ae9aa 100644 --- a/sim/warlock/TestDemonology.results +++ b/sim/warlock/TestDemonology.results @@ -46,738 +46,738 @@ character_stats_results: { dps_results: { key: "TestDemonology-AllItems-Althor'sAbacus-50359" value: { - dps: 13417.31696 - tps: 11658.64291 + dps: 13243.90588 + tps: 11492.86523 } } dps_results: { key: "TestDemonology-AllItems-Althor'sAbacus-50366" value: { - dps: 13436.63519 - tps: 11673.70642 + dps: 13278.4155 + tps: 11523.00644 } } dps_results: { key: "TestDemonology-AllItems-AshtongueTalismanofShadows-32493" value: { - dps: 13245.14315 - tps: 11501.91282 + dps: 13074.67441 + tps: 11336.3098 } } dps_results: { key: "TestDemonology-AllItems-AustereEarthsiegeDiamond" value: { - dps: 13620.57761 - tps: 11843.39499 + dps: 13418.79874 + tps: 11655.82175 } } dps_results: { key: "TestDemonology-AllItems-Bandit'sInsignia-40371" value: { - dps: 13080.90366 - tps: 11356.64575 + dps: 12900.43003 + tps: 11180.48019 } } dps_results: { key: "TestDemonology-AllItems-BaubleofTrueBlood-50354" value: { - dps: 13077.13033 - tps: 11353.0749 - hps: 102.49336 + dps: 12896.06082 + tps: 11177.10371 + hps: 100.95364 } } dps_results: { key: "TestDemonology-AllItems-BaubleofTrueBlood-50726" value: { - dps: 13077.13033 - tps: 11353.0749 - hps: 102.49336 + dps: 12896.06082 + tps: 11177.10371 + hps: 100.95364 } } dps_results: { key: "TestDemonology-AllItems-BeamingEarthsiegeDiamond" value: { - dps: 13642.25995 - tps: 11864.89637 + dps: 13401.77362 + tps: 11638.54725 } } dps_results: { key: "TestDemonology-AllItems-BlessedRegaliaofUndeadCleansing" value: { - dps: 9921.59431 - tps: 8459.24974 + dps: 9817.47634 + tps: 8342.96725 } } dps_results: { key: "TestDemonology-AllItems-BracingEarthsiegeDiamond" value: { - dps: 13655.78385 - tps: 11638.99091 + dps: 13449.10871 + tps: 11449.20433 } } dps_results: { key: "TestDemonology-AllItems-ChaoticSkyflareDiamond" value: { - dps: 13987.55061 - tps: 12211.3241 + dps: 13766.09428 + tps: 12003.46809 } } dps_results: { key: "TestDemonology-AllItems-CorpseTongueCoin-50349" value: { - dps: 13080.90366 - tps: 11356.64575 + dps: 12900.43003 + tps: 11180.48019 } } dps_results: { key: "TestDemonology-AllItems-CorpseTongueCoin-50352" value: { - dps: 13080.90366 - tps: 11356.64575 + dps: 12900.43003 + tps: 11180.48019 } } dps_results: { key: "TestDemonology-AllItems-CorrodedSkeletonKey-50356" value: { - dps: 13143.97526 - tps: 11413.75089 + dps: 12950.07749 + tps: 11226.26804 hps: 64 } } dps_results: { key: "TestDemonology-AllItems-DarkCoven'sRegalia" value: { - dps: 12755.71414 - tps: 11061.01924 + dps: 12601.16483 + tps: 10909.94106 } } dps_results: { key: "TestDemonology-AllItems-DarkmoonCard:Berserker!-42989" value: { - dps: 13240.73419 - tps: 11516.47627 + dps: 13069.14213 + tps: 11349.19229 } } dps_results: { key: "TestDemonology-AllItems-DarkmoonCard:Death-42990" value: { - dps: 13264.93211 - tps: 11540.79981 + dps: 13108.2148 + tps: 11388.41437 } } dps_results: { key: "TestDemonology-AllItems-DarkmoonCard:Greatness-44255" value: { - dps: 13181.03399 - tps: 11450.98376 + dps: 12992.95845 + tps: 11268.3201 } } dps_results: { key: "TestDemonology-AllItems-Death'sChoice-47464" value: { - dps: 13080.90366 - tps: 11356.64575 + dps: 12900.43003 + tps: 11180.48019 } } dps_results: { key: "TestDemonology-AllItems-DeathKnight'sAnguish-38212" value: { - dps: 13133.75022 - tps: 11409.4923 + dps: 12949.96635 + tps: 11230.01651 } } dps_results: { key: "TestDemonology-AllItems-Deathbringer'sWill-50362" value: { - dps: 13080.90366 - tps: 11356.64575 + dps: 12900.43003 + tps: 11180.48019 } } dps_results: { key: "TestDemonology-AllItems-Deathbringer'sWill-50363" value: { - dps: 13080.90366 - tps: 11356.64575 + dps: 12900.43003 + tps: 11180.48019 } } dps_results: { key: "TestDemonology-AllItems-DeathbringerGarb" value: { - dps: 10851.44914 - tps: 9282.50751 + dps: 10738.51563 + tps: 9156.02028 } } dps_results: { key: "TestDemonology-AllItems-Defender'sCode-40257" value: { - dps: 13080.90366 - tps: 11356.64575 + dps: 12900.43003 + tps: 11180.48019 } } dps_results: { key: "TestDemonology-AllItems-DestructiveSkyflareDiamond" value: { - dps: 13652.50644 - tps: 11876.27993 + dps: 13439.12732 + tps: 11676.50114 } } dps_results: { key: "TestDemonology-AllItems-DislodgedForeignObject-50353" value: { - dps: 13874.94151 - tps: 12104.63929 + dps: 13680.51811 + tps: 11918.02187 } } dps_results: { key: "TestDemonology-AllItems-EffulgentSkyflareDiamond" value: { - dps: 13620.57761 - tps: 11843.39499 + dps: 13418.79874 + tps: 11655.82175 } } dps_results: { key: "TestDemonology-AllItems-EmberSkyflareDiamond" value: { - dps: 13677.75974 - tps: 11895.67881 + dps: 13453.51023 + tps: 11686.79689 } } dps_results: { key: "TestDemonology-AllItems-EnigmaticSkyflareDiamond" value: { - dps: 13646.0225 - tps: 11869.79598 + dps: 13432.54537 + tps: 11669.91919 } } dps_results: { key: "TestDemonology-AllItems-EnigmaticStarflareDiamond" value: { - dps: 13637.52959 - tps: 11861.30307 + dps: 13424.03982 + tps: 11661.41364 } } dps_results: { key: "TestDemonology-AllItems-EphemeralSnowflake-50260" value: { - dps: 13260.66392 - tps: 11537.05537 + dps: 13053.22335 + tps: 11338.404 } } dps_results: { key: "TestDemonology-AllItems-EssenceofGossamer-37220" value: { - dps: 13105.61399 - tps: 11378.55729 + dps: 12906.6269 + tps: 11185.18743 } } dps_results: { key: "TestDemonology-AllItems-EternalEarthsiegeDiamond" value: { - dps: 13609.78634 - tps: 11833.55983 + dps: 13398.47567 + tps: 11635.84948 } } dps_results: { key: "TestDemonology-AllItems-ExtractofNecromanticPower-40373" value: { - dps: 13206.33109 - tps: 11482.04155 + dps: 13122.05364 + tps: 11402.52929 } } dps_results: { key: "TestDemonology-AllItems-EyeoftheBroodmother-45308" value: { - dps: 13456.75793 - tps: 11707.82466 + dps: 13283.42777 + tps: 11540.1986 } } dps_results: { key: "TestDemonology-AllItems-Figurine-SapphireOwl-42413" value: { - dps: 13099.69744 - tps: 11374.06795 + dps: 12918.53373 + tps: 11201.64113 } } dps_results: { key: "TestDemonology-AllItems-ForethoughtTalisman-40258" value: { - dps: 13272.02443 - tps: 11527.43425 + dps: 13107.02913 + tps: 11366.94101 } } dps_results: { key: "TestDemonology-AllItems-ForgeEmber-37660" value: { - dps: 13414.74685 - tps: 11668.49755 + dps: 13248.07367 + tps: 11508.02234 } } dps_results: { key: "TestDemonology-AllItems-ForlornSkyflareDiamond" value: { - dps: 13655.78385 - tps: 11874.35204 + dps: 13449.10871 + tps: 11680.5325 } } dps_results: { key: "TestDemonology-AllItems-ForlornStarflareDiamond" value: { - dps: 13654.90049 - tps: 11874.46637 + dps: 13453.88096 + tps: 11686.13342 } } dps_results: { key: "TestDemonology-AllItems-FuryoftheFiveFlights-40431" value: { - dps: 13080.90366 - tps: 11356.64575 + dps: 12900.43003 + tps: 11180.48019 } } dps_results: { key: "TestDemonology-AllItems-FuturesightRune-38763" value: { - dps: 13244.55905 - tps: 11503.83787 + dps: 13095.96384 + tps: 11358.30044 } } dps_results: { key: "TestDemonology-AllItems-Gladiator'sFelshroud" value: { - dps: 10687.3293 - tps: 9107.41386 + dps: 10560.32217 + tps: 8973.36025 } } dps_results: { key: "TestDemonology-AllItems-GlowingTwilightScale-54573" value: { - dps: 13435.16729 - tps: 11674.16246 + dps: 13266.94683 + tps: 11513.37249 } } dps_results: { key: "TestDemonology-AllItems-GlowingTwilightScale-54589" value: { - dps: 13473.9598 - tps: 11707.62348 + dps: 13309.51349 + tps: 11550.47562 } } dps_results: { key: "TestDemonology-AllItems-GnomishLightningGenerator-41121" value: { - dps: 13231.96529 - tps: 11507.84404 + dps: 13062.08411 + tps: 11343.78646 } } dps_results: { key: "TestDemonology-AllItems-Gul'dan'sRegalia" value: { - dps: 11188.33387 - tps: 9443.73545 + dps: 11045.2536 + tps: 9314.45004 } } dps_results: { key: "TestDemonology-AllItems-IllustrationoftheDragonSoul-40432" value: { - dps: 13435.95467 - tps: 11673.61487 + dps: 13271.82086 + tps: 11517.03807 } } dps_results: { key: "TestDemonology-AllItems-ImpassiveSkyflareDiamond" value: { - dps: 13646.0225 - tps: 11869.79598 + dps: 13432.54537 + tps: 11669.91919 } } dps_results: { key: "TestDemonology-AllItems-ImpassiveStarflareDiamond" value: { - dps: 13637.52959 - tps: 11861.30307 + dps: 13424.03982 + tps: 11661.41364 } } dps_results: { key: "TestDemonology-AllItems-IncisorFragment-37723" value: { - dps: 13080.90366 - tps: 11356.64575 + dps: 12900.43003 + tps: 11180.48019 } } dps_results: { key: "TestDemonology-AllItems-InsightfulEarthsiegeDiamond" value: { - dps: 13657.68356 - tps: 11882.59037 + dps: 13427.78541 + tps: 11661.40926 } } dps_results: { key: "TestDemonology-AllItems-InvigoratingEarthsiegeDiamond" value: { - dps: 13609.78634 - tps: 11833.55983 + dps: 13398.47567 + tps: 11635.84948 } } dps_results: { key: "TestDemonology-AllItems-Lavanthor'sTalisman-37872" value: { - dps: 13080.90366 - tps: 11356.64575 + dps: 12900.43003 + tps: 11180.48019 } } dps_results: { key: "TestDemonology-AllItems-MajesticDragonFigurine-40430" value: { - dps: 13275.52579 - tps: 11529.87007 + dps: 13093.97928 + tps: 11353.32214 } } dps_results: { key: "TestDemonology-AllItems-MaleficRaiment" value: { - dps: 8523.72687 - tps: 7157.22159 + dps: 8418.28288 + tps: 7041.57676 } } dps_results: { key: "TestDemonology-AllItems-MeteoriteWhetstone-37390" value: { - dps: 13196.82754 - tps: 11472.56962 + dps: 13020.35249 + tps: 11300.40265 } } dps_results: { key: "TestDemonology-AllItems-NevermeltingIceCrystal-50259" value: { - dps: 13342.65729 - tps: 11598.0671 + dps: 13171.60746 + tps: 11431.51935 } } dps_results: { key: "TestDemonology-AllItems-OfferingofSacrifice-37638" value: { - dps: 13080.90366 - tps: 11356.64575 + dps: 12900.43003 + tps: 11180.48019 } } dps_results: { key: "TestDemonology-AllItems-PersistentEarthshatterDiamond" value: { - dps: 13609.78634 - tps: 11833.55983 + dps: 13398.47567 + tps: 11635.84948 } } dps_results: { key: "TestDemonology-AllItems-PersistentEarthsiegeDiamond" value: { - dps: 13609.78634 - tps: 11833.55983 + dps: 13398.47567 + tps: 11635.84948 } } dps_results: { key: "TestDemonology-AllItems-PetrifiedScarab-21685" value: { - dps: 13080.90366 - tps: 11356.64575 + dps: 12900.43003 + tps: 11180.48019 } } dps_results: { key: "TestDemonology-AllItems-PetrifiedTwilightScale-54571" value: { - dps: 13080.90366 - tps: 11356.64575 + dps: 12900.43003 + tps: 11180.48019 } } dps_results: { key: "TestDemonology-AllItems-PetrifiedTwilightScale-54591" value: { - dps: 13080.90366 - tps: 11356.64575 + dps: 12900.43003 + tps: 11180.48019 } } dps_results: { key: "TestDemonology-AllItems-PlagueheartGarb" value: { - dps: 10360.85416 - tps: 8820.18392 + dps: 10266.66359 + tps: 8716.63581 } } dps_results: { key: "TestDemonology-AllItems-PowerfulEarthshatterDiamond" value: { - dps: 13618.779 - tps: 11841.74809 + dps: 13417.36058 + tps: 11654.52072 } } dps_results: { key: "TestDemonology-AllItems-PowerfulEarthsiegeDiamond" value: { - dps: 13620.57761 - tps: 11843.39499 + dps: 13418.79874 + tps: 11655.82175 } } dps_results: { key: "TestDemonology-AllItems-PurifiedShardoftheGods" value: { - dps: 13080.90366 - tps: 11356.64575 + dps: 12900.43003 + tps: 11180.48019 } } dps_results: { key: "TestDemonology-AllItems-ReignoftheDead-47316" value: { - dps: 13615.25479 - tps: 11861.71483 + dps: 13407.68508 + tps: 11661.54729 } } dps_results: { key: "TestDemonology-AllItems-ReignoftheDead-47477" value: { - dps: 13668.67641 - tps: 11912.65287 + dps: 13469.23514 + tps: 11720.19531 } } dps_results: { key: "TestDemonology-AllItems-RelentlessEarthsiegeDiamond" value: { - dps: 13948.0532 - tps: 12171.82669 + dps: 13728.9583 + tps: 11966.33211 } } dps_results: { key: "TestDemonology-AllItems-RevitalizingSkyflareDiamond" value: { - dps: 13605.83603 - tps: 11830.72831 + dps: 13405.02361 + tps: 11639.40886 } } dps_results: { key: "TestDemonology-AllItems-RuneofRepulsion-40372" value: { - dps: 13080.90366 - tps: 11356.64575 + dps: 12900.43003 + tps: 11180.48019 } } dps_results: { key: "TestDemonology-AllItems-SealofthePantheon-36993" value: { - dps: 13080.90366 - tps: 11356.64575 + dps: 12900.43003 + tps: 11180.48019 } } dps_results: { key: "TestDemonology-AllItems-ShinyShardoftheGods" value: { - dps: 13080.90366 - tps: 11356.64575 + dps: 12900.43003 + tps: 11180.48019 } } dps_results: { key: "TestDemonology-AllItems-Sindragosa'sFlawlessFang-50361" value: { - dps: 13143.97526 - tps: 11413.75089 + dps: 12950.06 + tps: 11226.25054 } } dps_results: { key: "TestDemonology-AllItems-SliverofPureIce-50339" value: { - dps: 13393.37816 - tps: 11638.48125 + dps: 13220.81763 + tps: 11472.0353 } } dps_results: { key: "TestDemonology-AllItems-SliverofPureIce-50346" value: { - dps: 13433.76001 - tps: 11672.68692 + dps: 13239.16958 + tps: 11485.33592 } } dps_results: { key: "TestDemonology-AllItems-SoulPreserver-37111" value: { - dps: 13192.98633 - tps: 11456.81998 + dps: 13041.95765 + tps: 11308.77052 } } dps_results: { key: "TestDemonology-AllItems-SouloftheDead-40382" value: { - dps: 13205.81551 - tps: 11482.4252 + dps: 13069.23424 + tps: 11351.11117 } } dps_results: { key: "TestDemonology-AllItems-SparkofLife-37657" value: { - dps: 13219.18241 - tps: 11490.95906 + dps: 13064.67402 + tps: 11346.30818 } } dps_results: { key: "TestDemonology-AllItems-SphereofRedDragon'sBlood-37166" value: { - dps: 13094.19975 - tps: 11355.22268 + dps: 12920.45511 + tps: 11186.49878 } } dps_results: { key: "TestDemonology-AllItems-SwiftSkyflareDiamond" value: { - dps: 13609.78634 - tps: 11833.55983 + dps: 13398.47567 + tps: 11635.84948 } } dps_results: { key: "TestDemonology-AllItems-SwiftStarflareDiamond" value: { - dps: 13609.78634 - tps: 11833.55983 + dps: 13398.47567 + tps: 11635.84948 } } dps_results: { key: "TestDemonology-AllItems-SwiftWindfireDiamond" value: { - dps: 13609.78634 - tps: 11833.55983 + dps: 13398.47567 + tps: 11635.84948 } } dps_results: { key: "TestDemonology-AllItems-TalismanofTrollDivinity-37734" value: { - dps: 13162.97939 - tps: 11430.78677 + dps: 12984.04915 + tps: 11256.55694 } } dps_results: { key: "TestDemonology-AllItems-TearsoftheVanquished-47215" value: { - dps: 13124.68662 - tps: 11395.09828 + dps: 12936.43462 + tps: 11217.1032 } } dps_results: { key: "TestDemonology-AllItems-TheGeneral'sHeart-45507" value: { - dps: 13080.90366 - tps: 11356.64575 + dps: 12900.43003 + tps: 11180.48019 } } dps_results: { key: "TestDemonology-AllItems-ThunderingSkyflareDiamond" value: { - dps: 13609.78634 - tps: 11833.55983 + dps: 13398.47567 + tps: 11635.84948 } } dps_results: { key: "TestDemonology-AllItems-TinyAbominationinaJar-50351" value: { - dps: 13088.36912 - tps: 11343.35538 + dps: 12931.5795 + tps: 11189.2114 } } dps_results: { key: "TestDemonology-AllItems-TinyAbominationinaJar-50706" value: { - dps: 13088.36912 - tps: 11343.35538 + dps: 12931.5795 + tps: 11189.2114 } } dps_results: { key: "TestDemonology-AllItems-TirelessSkyflareDiamond" value: { - dps: 13655.78385 - tps: 11874.35204 + dps: 13449.10871 + tps: 11680.5325 } } dps_results: { key: "TestDemonology-AllItems-TirelessStarflareDiamond" value: { - dps: 13654.90049 - tps: 11874.46637 + dps: 13453.88096 + tps: 11686.13342 } } dps_results: { key: "TestDemonology-AllItems-TomeofArcanePhenomena-36972" value: { - dps: 13318.20984 - tps: 11585.33436 + dps: 13135.3056 + tps: 11407.64705 } } dps_results: { key: "TestDemonology-AllItems-TrenchantEarthshatterDiamond" value: { - dps: 13654.90049 - tps: 11874.46637 + dps: 13453.88096 + tps: 11686.13342 } } dps_results: { key: "TestDemonology-AllItems-TrenchantEarthsiegeDiamond" value: { - dps: 13655.78385 - tps: 11874.35204 + dps: 13449.10871 + tps: 11680.5325 } } dps_results: { key: "TestDemonology-AllItems-WingedTalisman-37844" value: { - dps: 13285.8383 - tps: 11543.08569 + dps: 13090.00588 + tps: 11354.54378 } } dps_results: { key: "TestDemonology-Average-Default" value: { - dps: 14120.88245 - tps: 12330.57619 + dps: 13946.57103 + tps: 12163.30576 } } dps_results: { key: "TestDemonology-Settings-Orc-p4_demo-Demonology Warlock-demo-FullBuffs-LongMultiTarget" value: { - dps: 17438.86787 - tps: 17278.70009 + dps: 17361.12567 + tps: 17435.98697 } } dps_results: { key: "TestDemonology-Settings-Orc-p4_demo-Demonology Warlock-demo-FullBuffs-LongSingleTarget" value: { - dps: 13987.55061 - tps: 12211.3241 + dps: 13766.09428 + tps: 12003.46809 } } dps_results: { key: "TestDemonology-Settings-Orc-p4_demo-Demonology Warlock-demo-FullBuffs-ShortSingleTarget" value: { - dps: 15867.80813 - tps: 13801.53668 + dps: 14524.59149 + tps: 12818.53577 } } dps_results: { key: "TestDemonology-Settings-Orc-p4_demo-Demonology Warlock-demo-NoBuffs-LongMultiTarget" value: { - dps: 10675.54295 - tps: 12403.23872 + dps: 10287.07914 + tps: 12106.19892 } } dps_results: { key: "TestDemonology-Settings-Orc-p4_demo-Demonology Warlock-demo-NoBuffs-LongSingleTarget" value: { - dps: 8150.0904 - tps: 7534.10248 + dps: 7943.25049 + tps: 7314.42382 } } dps_results: { key: "TestDemonology-Settings-Orc-p4_demo-Demonology Warlock-demo-NoBuffs-ShortSingleTarget" value: { - dps: 8579.77973 - tps: 7822.12309 + dps: 6929.63748 + tps: 6137.98157 } } dps_results: { key: "TestDemonology-SwitchInFrontOfTarget-Default" value: { - dps: 13872.1688 - tps: 12238.92734 + dps: 13685.59167 + tps: 12068.09598 } } diff --git a/sim/warlock/TestDestruction.results b/sim/warlock/TestDestruction.results index 72ed924ef4..dfd0bc5387 100644 --- a/sim/warlock/TestDestruction.results +++ b/sim/warlock/TestDestruction.results @@ -47,42 +47,42 @@ dps_results: { key: "TestDestruction-AllItems-Althor'sAbacus-50359" value: { dps: 13389.20634 - tps: 11054.85323 + tps: 11055.91814 } } dps_results: { key: "TestDestruction-AllItems-Althor'sAbacus-50366" value: { dps: 13435.121 - tps: 11094.08882 + tps: 11095.13998 } } dps_results: { key: "TestDestruction-AllItems-AshtongueTalismanofShadows-32493" value: { dps: 13015.62797 - tps: 10735.61276 + tps: 10736.77646 } } dps_results: { key: "TestDestruction-AllItems-AustereEarthsiegeDiamond" value: { dps: 13278.35585 - tps: 10956.83061 + tps: 10958.03654 } } dps_results: { key: "TestDestruction-AllItems-Bandit'sInsignia-40371" value: { dps: 13015.62797 - tps: 10735.61276 + tps: 10736.77646 } } dps_results: { key: "TestDestruction-AllItems-BaubleofTrueBlood-50354" value: { dps: 13020.8403 - tps: 10740.73409 + tps: 10741.89779 hps: 102.01591 } } @@ -90,7 +90,7 @@ dps_results: { key: "TestDestruction-AllItems-BaubleofTrueBlood-50726" value: { dps: 13020.8403 - tps: 10740.73409 + tps: 10741.89779 hps: 102.01591 } } @@ -98,49 +98,49 @@ dps_results: { key: "TestDestruction-AllItems-BeamingEarthsiegeDiamond" value: { dps: 13313.85188 - tps: 10989.40455 + tps: 10990.42966 } } dps_results: { key: "TestDestruction-AllItems-BlessedRegaliaofUndeadCleansing" value: { - dps: 10034.11635 - tps: 8161.63757 + dps: 10049.22959 + tps: 8178.14603 } } dps_results: { key: "TestDestruction-AllItems-BracingEarthsiegeDiamond" value: { dps: 13329.62911 - tps: 10783.32088 + tps: 10784.50569 } } dps_results: { key: "TestDestruction-AllItems-ChaoticSkyflareDiamond" value: { dps: 13740.25849 - tps: 11372.58946 + tps: 11373.79539 } } dps_results: { key: "TestDestruction-AllItems-CorpseTongueCoin-50349" value: { dps: 13015.62797 - tps: 10735.61276 + tps: 10736.77646 } } dps_results: { key: "TestDestruction-AllItems-CorpseTongueCoin-50352" value: { dps: 13015.62797 - tps: 10735.61276 + tps: 10736.77646 } } dps_results: { key: "TestDestruction-AllItems-CorrodedSkeletonKey-50356" value: { dps: 13015.62797 - tps: 10735.61276 + tps: 10736.77646 hps: 64 } } @@ -148,609 +148,609 @@ dps_results: { key: "TestDestruction-AllItems-DarkCoven'sRegalia" value: { dps: 12529.42945 - tps: 10306.09456 + tps: 10307.31339 } } dps_results: { key: "TestDestruction-AllItems-DarkmoonCard:Berserker!-42989" value: { dps: 13172.29251 - tps: 10876.66872 + tps: 10877.83242 } } dps_results: { key: "TestDestruction-AllItems-DarkmoonCard:Death-42990" value: { dps: 13228.31371 - tps: 10937.94004 + tps: 10939.10375 } } dps_results: { key: "TestDestruction-AllItems-DarkmoonCard:Greatness-44255" value: { dps: 13111.70956 - tps: 10827.76372 + tps: 10823.45164 } } dps_results: { key: "TestDestruction-AllItems-Death'sChoice-47464" value: { dps: 13015.62797 - tps: 10735.61276 + tps: 10736.77646 } } dps_results: { key: "TestDestruction-AllItems-DeathKnight'sAnguish-38212" value: { dps: 13060.88686 - tps: 10776.3729 + tps: 10777.5366 } } dps_results: { key: "TestDestruction-AllItems-Deathbringer'sWill-50362" value: { dps: 13015.62797 - tps: 10735.61276 + tps: 10736.77646 } } dps_results: { key: "TestDestruction-AllItems-Deathbringer'sWill-50363" value: { dps: 13015.62797 - tps: 10735.61276 + tps: 10736.77646 } } dps_results: { key: "TestDestruction-AllItems-DeathbringerGarb" value: { dps: 10977.39094 - tps: 8957.62965 + tps: 8960.47538 } } dps_results: { key: "TestDestruction-AllItems-Defender'sCode-40257" value: { dps: 13015.62797 - tps: 10735.61276 + tps: 10736.77646 } } dps_results: { key: "TestDestruction-AllItems-DestructiveSkyflareDiamond" value: { dps: 13321.92919 - tps: 10996.04661 + tps: 10997.25254 } } dps_results: { key: "TestDestruction-AllItems-DislodgedForeignObject-50353" value: { dps: 13702.8365 - tps: 11338.76511 + tps: 11340.05406 } } dps_results: { key: "TestDestruction-AllItems-EffulgentSkyflareDiamond" value: { dps: 13278.35585 - tps: 10956.83061 + tps: 10958.03654 } } dps_results: { key: "TestDestruction-AllItems-EmberSkyflareDiamond" value: { dps: 13347.01795 - tps: 11016.56304 + tps: 11017.59017 } } dps_results: { key: "TestDestruction-AllItems-EnigmaticSkyflareDiamond" value: { dps: 13313.85188 - tps: 10988.77703 + tps: 10989.98297 } } dps_results: { key: "TestDestruction-AllItems-EnigmaticStarflareDiamond" value: { dps: 13306.40413 - tps: 10982.07406 + tps: 10983.27999 } } dps_results: { key: "TestDestruction-AllItems-EphemeralSnowflake-50260" value: { dps: 13131.99417 - tps: 10846.45349 + tps: 10847.91554 } } dps_results: { key: "TestDestruction-AllItems-EssenceofGossamer-37220" value: { dps: 13015.62797 - tps: 10735.61276 + tps: 10736.77646 } } dps_results: { key: "TestDestruction-AllItems-EternalEarthsiegeDiamond" value: { dps: 13278.35585 - tps: 10956.83061 + tps: 10958.03654 } } dps_results: { key: "TestDestruction-AllItems-ExtractofNecromanticPower-40373" value: { dps: 13225.57447 - tps: 10934.13049 + tps: 10935.29419 } } dps_results: { key: "TestDestruction-AllItems-EyeoftheBroodmother-45308" value: { dps: 13414.44181 - tps: 11082.22826 + tps: 11083.32309 } } dps_results: { key: "TestDestruction-AllItems-Figurine-SapphireOwl-42413" value: { dps: 13037.33164 - tps: 10755.25739 + tps: 10756.38657 } } dps_results: { key: "TestDestruction-AllItems-ForethoughtTalisman-40258" value: { dps: 13247.2883 - tps: 10933.57834 + tps: 10934.68446 } } dps_results: { key: "TestDestruction-AllItems-ForgeEmber-37660" value: { dps: 13317.79421 - tps: 10998.73333 + tps: 10999.84184 } } dps_results: { key: "TestDestruction-AllItems-ForlornSkyflareDiamond" value: { dps: 13329.62911 - tps: 11000.62695 + tps: 11001.81176 } } dps_results: { key: "TestDestruction-AllItems-ForlornStarflareDiamond" value: { dps: 13319.37446 - tps: 10991.8685 + tps: 10993.05691 } } dps_results: { key: "TestDestruction-AllItems-FuryoftheFiveFlights-40431" value: { dps: 13015.62797 - tps: 10735.61276 + tps: 10736.77646 } } dps_results: { key: "TestDestruction-AllItems-FuturesightRune-38763" value: { dps: 13197.44343 - tps: 10891.01264 + tps: 10892.14568 } } dps_results: { key: "TestDestruction-AllItems-Gladiator'sFelshroud" value: { dps: 10539.28532 - tps: 8572.46637 + tps: 8575.85313 } } dps_results: { key: "TestDestruction-AllItems-GlowingTwilightScale-54573" value: { dps: 13412.16367 - tps: 11074.47102 + tps: 11075.52906 } } dps_results: { key: "TestDestruction-AllItems-GlowingTwilightScale-54589" value: { dps: 13464.33942 - tps: 11119.05713 + tps: 11120.09955 } } dps_results: { key: "TestDestruction-AllItems-GnomishLightningGenerator-41121" value: { dps: 13178.65941 - tps: 10887.49102 + tps: 10888.65472 } } dps_results: { key: "TestDestruction-AllItems-Gul'dan'sRegalia" value: { dps: 11239.39468 - tps: 9123.46118 + tps: 9125.35069 } } dps_results: { key: "TestDestruction-AllItems-IllustrationoftheDragonSoul-40432" value: { dps: 13424.99484 - tps: 11085.1676 + tps: 11086.21939 } } dps_results: { key: "TestDestruction-AllItems-ImpassiveSkyflareDiamond" value: { dps: 13313.85188 - tps: 10988.77703 + tps: 10989.98297 } } dps_results: { key: "TestDestruction-AllItems-ImpassiveStarflareDiamond" value: { dps: 13306.40413 - tps: 10982.07406 + tps: 10983.27999 } } dps_results: { key: "TestDestruction-AllItems-IncisorFragment-37723" value: { dps: 13015.62797 - tps: 10735.61276 + tps: 10736.77646 } } dps_results: { key: "TestDestruction-AllItems-InsightfulEarthsiegeDiamond" value: { dps: 13293.59654 - tps: 10975.31009 + tps: 10975.74093 } } dps_results: { key: "TestDestruction-AllItems-InvigoratingEarthsiegeDiamond" value: { dps: 13278.35585 - tps: 10956.83061 + tps: 10958.03654 } } dps_results: { key: "TestDestruction-AllItems-Lavanthor'sTalisman-37872" value: { dps: 13015.62797 - tps: 10735.61276 + tps: 10736.77646 } } dps_results: { key: "TestDestruction-AllItems-MajesticDragonFigurine-40430" value: { dps: 13254.73916 - tps: 10939.77219 + tps: 10940.87656 } } dps_results: { key: "TestDestruction-AllItems-MaleficRaiment" value: { - dps: 8360.99106 - tps: 6692.24704 + dps: 8391.03484 + tps: 6711.58647 } } dps_results: { key: "TestDestruction-AllItems-MeteoriteWhetstone-37390" value: { dps: 13123.39121 - tps: 10832.62682 + tps: 10833.79052 } } dps_results: { key: "TestDestruction-AllItems-NevermeltingIceCrystal-50259" value: { dps: 13280.06074 - tps: 10963.07354 + tps: 10964.17965 } } dps_results: { key: "TestDestruction-AllItems-OfferingofSacrifice-37638" value: { dps: 13015.62797 - tps: 10735.61276 + tps: 10736.77646 } } dps_results: { key: "TestDestruction-AllItems-PersistentEarthshatterDiamond" value: { dps: 13278.35585 - tps: 10956.83061 + tps: 10958.03654 } } dps_results: { key: "TestDestruction-AllItems-PersistentEarthsiegeDiamond" value: { dps: 13278.35585 - tps: 10956.83061 + tps: 10958.03654 } } dps_results: { key: "TestDestruction-AllItems-PetrifiedScarab-21685" value: { dps: 13015.62797 - tps: 10735.61276 + tps: 10736.77646 } } dps_results: { key: "TestDestruction-AllItems-PetrifiedTwilightScale-54571" value: { dps: 13015.62797 - tps: 10735.61276 + tps: 10736.77646 } } dps_results: { key: "TestDestruction-AllItems-PetrifiedTwilightScale-54591" value: { dps: 13015.62797 - tps: 10735.61276 + tps: 10736.77646 } } dps_results: { key: "TestDestruction-AllItems-PlagueheartGarb" value: { - dps: 10206.67303 - tps: 8267.41117 + dps: 10210.45501 + tps: 8273.69263 } } dps_results: { key: "TestDestruction-AllItems-PowerfulEarthshatterDiamond" value: { dps: 13278.35585 - tps: 10956.83061 + tps: 10958.03654 } } dps_results: { key: "TestDestruction-AllItems-PowerfulEarthsiegeDiamond" value: { dps: 13278.35585 - tps: 10956.83061 + tps: 10958.03654 } } dps_results: { key: "TestDestruction-AllItems-PurifiedShardoftheGods" value: { dps: 13015.62797 - tps: 10735.61276 + tps: 10736.77646 } } dps_results: { key: "TestDestruction-AllItems-ReignoftheDead-47316" value: { dps: 13577.13263 - tps: 11251.09524 + tps: 11252.17796 } } dps_results: { key: "TestDestruction-AllItems-ReignoftheDead-47477" value: { dps: 13647.53166 - tps: 11316.03299 + tps: 11317.10478 } } dps_results: { key: "TestDestruction-AllItems-RelentlessEarthsiegeDiamond" value: { dps: 13701.66868 - tps: 11337.85863 + tps: 11339.06456 } } dps_results: { key: "TestDestruction-AllItems-RevitalizingSkyflareDiamond" value: { dps: 13278.35585 - tps: 10956.48724 + tps: 10957.58633 } } dps_results: { key: "TestDestruction-AllItems-RuneofRepulsion-40372" value: { dps: 13015.62797 - tps: 10735.61276 + tps: 10736.77646 } } dps_results: { key: "TestDestruction-AllItems-SealofthePantheon-36993" value: { dps: 13015.62797 - tps: 10735.61276 + tps: 10736.77646 } } dps_results: { key: "TestDestruction-AllItems-ShinyShardoftheGods" value: { dps: 13015.62797 - tps: 10735.61276 + tps: 10736.77646 } } dps_results: { key: "TestDestruction-AllItems-Sindragosa'sFlawlessFang-50361" value: { dps: 13015.62797 - tps: 10735.61276 + tps: 10736.77646 } } dps_results: { key: "TestDestruction-AllItems-SliverofPureIce-50339" value: { dps: 13345.37871 - tps: 11021.69552 + tps: 11022.52196 } } dps_results: { key: "TestDestruction-AllItems-SliverofPureIce-50346" value: { dps: 13387.11931 - tps: 11057.84275 + tps: 11058.55731 } } dps_results: { key: "TestDestruction-AllItems-SoulPreserver-37111" value: { dps: 13172.15522 - tps: 10869.37274 + tps: 10870.49874 } } dps_results: { key: "TestDestruction-AllItems-SouloftheDead-40382" value: { dps: 13149.20484 - tps: 10860.8469 + tps: 10861.13615 } } dps_results: { key: "TestDestruction-AllItems-SparkofLife-37657" value: { dps: 13065.8288 - tps: 10778.64012 + tps: 10779.53333 } } dps_results: { key: "TestDestruction-AllItems-SphereofRedDragon'sBlood-37166" value: { dps: 13022.23918 - tps: 10735.61276 + tps: 10736.77646 } } dps_results: { key: "TestDestruction-AllItems-SwiftSkyflareDiamond" value: { dps: 13278.35585 - tps: 10956.83061 + tps: 10958.03654 } } dps_results: { key: "TestDestruction-AllItems-SwiftStarflareDiamond" value: { dps: 13278.35585 - tps: 10956.83061 + tps: 10958.03654 } } dps_results: { key: "TestDestruction-AllItems-SwiftWindfireDiamond" value: { dps: 13278.35585 - tps: 10956.83061 + tps: 10958.03654 } } dps_results: { key: "TestDestruction-AllItems-TalismanofTrollDivinity-37734" value: { dps: 13114.50519 - tps: 10820.09928 + tps: 10821.24086 } } dps_results: { key: "TestDestruction-AllItems-TearsoftheVanquished-47215" value: { dps: 13060.91843 - tps: 10776.01541 + tps: 10776.83215 } } dps_results: { key: "TestDestruction-AllItems-TheGeneral'sHeart-45507" value: { dps: 13015.62797 - tps: 10735.61276 + tps: 10736.77646 } } dps_results: { key: "TestDestruction-AllItems-ThunderingSkyflareDiamond" value: { dps: 13278.35585 - tps: 10956.83061 + tps: 10958.03654 } } dps_results: { key: "TestDestruction-AllItems-TinyAbominationinaJar-50351" value: { dps: 13023.96692 - tps: 10735.61276 + tps: 10736.77646 } } dps_results: { key: "TestDestruction-AllItems-TinyAbominationinaJar-50706" value: { dps: 13023.96692 - tps: 10735.61276 + tps: 10736.77646 } } dps_results: { key: "TestDestruction-AllItems-TirelessSkyflareDiamond" value: { dps: 13329.62911 - tps: 11000.62695 + tps: 11001.81176 } } dps_results: { key: "TestDestruction-AllItems-TirelessStarflareDiamond" value: { dps: 13319.37446 - tps: 10991.8685 + tps: 10993.05691 } } dps_results: { key: "TestDestruction-AllItems-TomeofArcanePhenomena-36972" value: { dps: 13293.92049 - tps: 10985.03588 + tps: 10986.16105 } } dps_results: { key: "TestDestruction-AllItems-TrenchantEarthshatterDiamond" value: { dps: 13319.37446 - tps: 10991.8685 + tps: 10993.05691 } } dps_results: { key: "TestDestruction-AllItems-TrenchantEarthsiegeDiamond" value: { dps: 13329.62911 - tps: 11000.62695 + tps: 11001.81176 } } dps_results: { key: "TestDestruction-AllItems-WingedTalisman-37844" value: { dps: 13167.51032 - tps: 10865.49212 + tps: 10866.65582 } } dps_results: { key: "TestDestruction-Average-Default" value: { dps: 13933.56914 - tps: 11535.47493 + tps: 11536.39471 } } dps_results: { key: "TestDestruction-Settings-Orc-p4_destro-Destruction Warlock-destro-FullBuffs-LongMultiTarget" value: { dps: 13954.55789 - tps: 14157.31002 + tps: 14181.4287 } } dps_results: { key: "TestDestruction-Settings-Orc-p4_destro-Destruction Warlock-destro-FullBuffs-LongSingleTarget" value: { dps: 13740.25849 - tps: 11372.58946 + tps: 11373.79539 } } dps_results: { key: "TestDestruction-Settings-Orc-p4_destro-Destruction Warlock-destro-FullBuffs-ShortSingleTarget" value: { - dps: 15068.92765 - tps: 12278.35906 + dps: 15092.54473 + tps: 12305.56218 } } dps_results: { @@ -778,6 +778,6 @@ dps_results: { key: "TestDestruction-SwitchInFrontOfTarget-Default" value: { dps: 13707.6834 - tps: 11372.58946 + tps: 11373.79539 } } diff --git a/sim/warlock/inferno.go b/sim/warlock/inferno.go index 54858c9d59..da4b7740f3 100644 --- a/sim/warlock/inferno.go +++ b/sim/warlock/inferno.go @@ -60,9 +60,6 @@ func (warlock *Warlock) registerInfernoSpell() { warlock.AddMajorCooldown(core.MajorCooldown{ Spell: warlock.Inferno, Type: core.CooldownTypeUnknown, - ShouldActivate: func(sim *core.Simulation, character *core.Character) bool { - return sim.GetRemainingDuration() <= 61*time.Second - }, }) } diff --git a/sim/warlock/warlock_test.go b/sim/warlock/warlock_test.go index fcb4dbb066..1e8e56443e 100644 --- a/sim/warlock/warlock_test.go +++ b/sim/warlock/warlock_test.go @@ -110,16 +110,14 @@ var defaultDestroOptions = &proto.Warlock_Options{ var DefaultDestroWarlock = &proto.Player_Warlock{ Warlock: &proto.Warlock{ - Options: defaultDestroOptions, - Rotation: defaultDestroRotation, + Options: defaultDestroOptions, }, } // --------------------------------------- var DefaultAfflictionWarlock = &proto.Player_Warlock{ Warlock: &proto.Warlock{ - Options: defaultAfflictionOptions, - Rotation: defaultAfflictionRotation, + Options: defaultAfflictionOptions, }, } @@ -129,39 +127,10 @@ var defaultAfflictionOptions = &proto.Warlock_Options{ WeaponImbue: proto.Warlock_Options_GrandSpellstone, } -var defaultAfflictionRotation = &proto.Warlock_Rotation{ - Type: proto.Warlock_Rotation_Affliction, - PrimarySpell: proto.Warlock_Rotation_ShadowBolt, - SecondaryDot: proto.Warlock_Rotation_UnstableAffliction, - SpecSpell: proto.Warlock_Rotation_Haunt, - Curse: proto.Warlock_Rotation_Agony, - Corruption: true, - DetonateSeed: true, -} - -var afflictionItemSwapRotation = &proto.Warlock_Rotation{ - Type: proto.Warlock_Rotation_Affliction, - PrimarySpell: proto.Warlock_Rotation_ShadowBolt, - SecondaryDot: proto.Warlock_Rotation_UnstableAffliction, - SpecSpell: proto.Warlock_Rotation_Haunt, - Curse: proto.Warlock_Rotation_Agony, - Corruption: true, - DetonateSeed: true, - EnableWeaponSwap: true, - WeaponSwap: &proto.ItemSwap{ - MhItem: &proto.ItemSpec{ - Id: 45457, - Enchant: 3790, - Gems: []int32{40013, 40013}, - }, - }, -} - // --------------------------------------- var DefaultDemonologyWarlock = &proto.Player_Warlock{ Warlock: &proto.Warlock{ - Options: defaultDemonologyOptions, - Rotation: defaultDemonologyRotation, + Options: defaultDemonologyOptions, }, } @@ -171,15 +140,6 @@ var defaultDemonologyOptions = &proto.Warlock_Options{ WeaponImbue: proto.Warlock_Options_GrandSpellstone, } -var defaultDemonologyRotation = &proto.Warlock_Rotation{ - Type: proto.Warlock_Rotation_Demonology, - PrimarySpell: proto.Warlock_Rotation_ShadowBolt, - SecondaryDot: proto.Warlock_Rotation_Immolate, - Curse: proto.Warlock_Rotation_Doom, - Corruption: true, - DetonateSeed: true, -} - // --------------------------------------------------------- var FullConsumes = &proto.Consumes{ diff --git a/sim/warrior/heroic_strike_cleave.go b/sim/warrior/heroic_strike_cleave.go index c828d76424..b75f455c6d 100644 --- a/sim/warrior/heroic_strike_cleave.go +++ b/sim/warrior/heroic_strike_cleave.go @@ -181,7 +181,4 @@ func (warrior *Warrior) RegisterHSOrCleave(useCleave bool, rageThreshold float64 } warrior.HSRageThreshold = max(autoSpell.DefaultCast.Cost, rageThreshold) - if warrior.IsUsingAPL { - warrior.HSRageThreshold = 0 - } } diff --git a/sim/warrior/talents.go b/sim/warrior/talents.go index e32b8f066a..af8f2bdded 100644 --- a/sim/warrior/talents.go +++ b/sim/warrior/talents.go @@ -812,8 +812,7 @@ func (warrior *Warrior) RegisterBladestormCD() { }, Cast: core.CastConfig{ DefaultCast: core.Cast{ - ChannelTime: time.Second * 6, - GCD: core.GCDDefault, + GCD: core.GCDDefault, }, CD: core.Cooldown{ Timer: warrior.NewTimer(), From 8ebb2f7f159d007418335016b7078a57c0b7e054 Mon Sep 17 00:00:00 2001 From: James Tanner Date: Sat, 6 Jan 2024 15:18:58 -0800 Subject: [PATCH 14/28] Backend code all compiles now --- sim/deathknight/dps/TestBlood.results | 12 +- sim/deathknight/dps/TestUnholy.results | 568 ++++++------ sim/priest/healing/TestHoly.results | 4 +- sim/priest/smite/TestSmite.results | 2 +- sim/rogue/TestCombat.results | 192 ++-- .../enhancement/TestEnhancement.results | 832 +++++++++--------- sim/shaman/fire_elemental_totem.go | 4 +- .../restoration/TestRestoration.results | 559 +++--------- sim/warlock/TestDemonology.results | 416 ++++----- sim/warrior/berserker_rage.go | 4 - sim/warrior/bloodthirst.go | 6 +- sim/warrior/demoralizing_shout.go | 15 - sim/warrior/dps/TestArms.results | 534 +++++------ sim/warrior/dps/TestFury.results | 532 +++++------ sim/warrior/dps/dps_warrior.go | 58 +- sim/warrior/dps/dps_warrior_test.go | 6 +- sim/warrior/dps/rotation.go | 451 ---------- sim/warrior/execute.go | 8 - sim/warrior/heroic_strike_cleave.go | 41 +- sim/warrior/overpower.go | 24 - .../protection/TestProtectionWarrior.results | 540 ++++++------ sim/warrior/protection/protection_warrior.go | 15 +- sim/warrior/protection/rotation.go | 113 --- sim/warrior/rend.go | 23 +- sim/warrior/shouts.go | 18 +- sim/warrior/warrior.go | 37 +- 26 files changed, 1990 insertions(+), 3024 deletions(-) delete mode 100644 sim/warrior/dps/rotation.go delete mode 100644 sim/warrior/protection/rotation.go diff --git a/sim/deathknight/dps/TestBlood.results b/sim/deathknight/dps/TestBlood.results index fb42a80807..350f451b81 100644 --- a/sim/deathknight/dps/TestBlood.results +++ b/sim/deathknight/dps/TestBlood.results @@ -287,8 +287,8 @@ dps_results: { dps_results: { key: "TestBlood-AllItems-EphemeralSnowflake-50260" value: { - dps: 6896.49505 - tps: 3364.06484 + dps: 7006.33997 + tps: 3423.96806 } } dps_results: { @@ -666,8 +666,8 @@ dps_results: { dps_results: { key: "TestBlood-AllItems-SphereofRedDragon'sBlood-37166" value: { - dps: 6949.06461 - tps: 3403.90157 + dps: 6975.8539 + tps: 3419.25098 } } dps_results: { @@ -778,8 +778,8 @@ dps_results: { dps_results: { key: "TestBlood-AllItems-TomeofArcanePhenomena-36972" value: { - dps: 6904.99937 - tps: 3377.67182 + dps: 6936.74073 + tps: 3393.67215 } } dps_results: { diff --git a/sim/deathknight/dps/TestUnholy.results b/sim/deathknight/dps/TestUnholy.results index feb5304359..7b1a4caecc 100644 --- a/sim/deathknight/dps/TestUnholy.results +++ b/sim/deathknight/dps/TestUnholy.results @@ -46,984 +46,984 @@ character_stats_results: { dps_results: { key: "TestUnholy-AllItems-Althor'sAbacus-50359" value: { - dps: 9922.78043 - tps: 6086.42693 + dps: 9951.338 + tps: 6092.27674 hps: 63.09596 } } dps_results: { key: "TestUnholy-AllItems-Althor'sAbacus-50366" value: { - dps: 9922.78043 - tps: 6086.42693 + dps: 9951.338 + tps: 6092.27674 hps: 65.85359 } } dps_results: { key: "TestUnholy-AllItems-AustereEarthsiegeDiamond" value: { - dps: 10430.00844 - tps: 6390.24383 + dps: 10460.21938 + tps: 6397.00184 hps: 42.71551 } } dps_results: { key: "TestUnholy-AllItems-Bandit'sInsignia-40371" value: { - dps: 10140.71531 - tps: 6245.81979 + dps: 10169.13695 + tps: 6251.48805 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-BaubleofTrueBlood-50354" value: { - dps: 9922.77419 - tps: 6086.49657 + dps: 9951.33176 + tps: 6092.34637 hps: 134.70651 } } dps_results: { key: "TestUnholy-AllItems-BaubleofTrueBlood-50726" value: { - dps: 9922.77419 - tps: 6086.49657 + dps: 9951.33176 + tps: 6092.34637 hps: 134.70651 } } dps_results: { key: "TestUnholy-AllItems-BeamingEarthsiegeDiamond" value: { - dps: 10455.19915 - tps: 6410.93066 + dps: 10485.43439 + tps: 6417.68614 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Beast-tamer'sShoulders-30892" value: { - dps: 9846.78215 - tps: 5955.98182 + dps: 9876.75662 + tps: 5962.69236 hps: 40.4349 } } dps_results: { key: "TestUnholy-AllItems-BlessedBattlegearofUndeadSlaying" value: { - dps: 7658.49304 - tps: 4665.49202 + dps: 7686.05311 + tps: 4672.10685 hps: 34.38394 } } dps_results: { key: "TestUnholy-AllItems-BlessedGarboftheUndeadSlayer" value: { - dps: 7538.22509 - tps: 4625.91137 + dps: 7565.46676 + tps: 4632.19878 hps: 32.96775 } } dps_results: { key: "TestUnholy-AllItems-BlessedRegaliaofUndeadCleansing" value: { - dps: 7286.40425 - tps: 4429.18278 + dps: 7313.0717 + tps: 4435.17023 hps: 32.72866 } } dps_results: { key: "TestUnholy-AllItems-BracingEarthsiegeDiamond" value: { - dps: 10430.00844 - tps: 6262.43896 + dps: 10460.21938 + tps: 6269.0618 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Bryntroll,theBoneArbiter-50415" value: { - dps: 10573.70985 - tps: 6509.45394 + dps: 10604.08736 + tps: 6516.32402 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Bryntroll,theBoneArbiter-50709" value: { - dps: 10573.70985 - tps: 6509.45394 + dps: 10604.08736 + tps: 6516.32402 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ChaoticSkyflareDiamond" value: { - dps: 10584.03517 - tps: 6518.15774 + dps: 10614.41705 + tps: 6525.02957 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-CorpseTongueCoin-50349" value: { - dps: 9922.7413 - tps: 6086.4498 + dps: 9951.29887 + tps: 6092.29961 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-CorpseTongueCoin-50352" value: { - dps: 9922.7413 - tps: 6086.4498 + dps: 9951.29887 + tps: 6092.29961 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-CorrodedSkeletonKey-50356" value: { - dps: 9922.7413 - tps: 6086.4498 + dps: 9951.29887 + tps: 6092.29961 hps: 110.32034 } } dps_results: { key: "TestUnholy-AllItems-DarkmoonCard:Berserker!-42989" value: { - dps: 10068.4566 - tps: 6205.16448 + dps: 10097.13017 + tps: 6211.0806 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-DarkmoonCard:Death-42990" value: { - dps: 10121.75867 - tps: 6244.79637 + dps: 10150.34231 + tps: 6250.56469 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-DarkmoonCard:Greatness-44255" value: { - dps: 10241.54185 - tps: 6241.52025 + dps: 10270.09942 + tps: 6247.37005 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-DarkrunedBattlegear" value: { - dps: 8496.17872 - tps: 5163.63257 + dps: 8524.35203 + tps: 5169.97326 hps: 38.90837 } } dps_results: { key: "TestUnholy-AllItems-DarkrunedPlate" value: { - dps: 7511.80491 - tps: 4529.17514 + dps: 7538.72973 + tps: 4535.38488 hps: 40.98666 } } dps_results: { key: "TestUnholy-AllItems-DeadlyGladiator'sSigilofStrife-42620" value: { - dps: 10671.19243 - tps: 6578.7694 + dps: 10701.56994 + tps: 6585.63948 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-DeathKnight'sAnguish-38212" value: { - dps: 10038.19826 - tps: 6183.10117 + dps: 10066.91028 + tps: 6189.0192 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Deathbringer'sWill-50362" value: { - dps: 10492.31799 - tps: 6459.5456 + dps: 10523.45653 + tps: 6466.4946 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Deathbringer'sWill-50363" value: { - dps: 10550.63046 - tps: 6526.63462 + dps: 10581.1952 + tps: 6533.19654 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Defender'sCode-40257" value: { - dps: 9922.7413 - tps: 6086.4498 + dps: 9951.29887 + tps: 6092.29961 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-DestructiveSkyflareDiamond" value: { - dps: 10458.48929 - tps: 6413.51148 + dps: 10488.76642 + tps: 6420.30481 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-DislodgedForeignObject-50348" value: { - dps: 10297.5309 - tps: 6344.6214 + dps: 10328.43271 + tps: 6351.44496 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-DislodgedForeignObject-50353" value: { - dps: 10234.97586 - tps: 6256.43357 + dps: 10265.45773 + tps: 6262.88224 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-EffulgentSkyflareDiamond" value: { - dps: 10430.00844 - tps: 6390.24383 + dps: 10460.21938 + tps: 6397.00184 hps: 42.71551 } } dps_results: { key: "TestUnholy-AllItems-EmberSkyflareDiamond" value: { - dps: 10430.00844 - tps: 6390.24383 + dps: 10460.21938 + tps: 6397.00184 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-EnigmaticSkyflareDiamond" value: { - dps: 10455.19915 - tps: 6410.93066 + dps: 10485.43439 + tps: 6417.68614 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-EnigmaticStarflareDiamond" value: { - dps: 10451.33499 - tps: 6407.77762 + dps: 10481.55787 + tps: 6414.52322 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-EphemeralSnowflake-50260" value: { - dps: 10158.62422 - tps: 6177.3893 + dps: 10199.29803 + tps: 6233.23221 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-EssenceofGossamer-37220" value: { - dps: 9922.7413 - tps: 6086.4498 + dps: 9951.29887 + tps: 6092.29961 hps: 44.16848 } } dps_results: { key: "TestUnholy-AllItems-EternalEarthsiegeDiamond" value: { - dps: 10430.00844 - tps: 6390.24383 + dps: 10460.21938 + tps: 6397.00184 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ExtractofNecromanticPower-40373" value: { - dps: 10101.84556 - tps: 6231.78998 + dps: 10130.32277 + tps: 6237.53952 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-EyeoftheBroodmother-45308" value: { - dps: 10051.19915 - tps: 6191.80096 + dps: 10079.77279 + tps: 6197.65957 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Figurine-SapphireOwl-42413" value: { - dps: 9922.7413 - tps: 6086.4498 + dps: 9951.29887 + tps: 6092.29961 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ForethoughtTalisman-40258" value: { - dps: 9922.7413 - tps: 6086.4498 + dps: 9951.29887 + tps: 6092.29961 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ForgeEmber-37660" value: { - dps: 10030.72681 - tps: 6175.63071 + dps: 10059.33603 + tps: 6181.50535 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ForlornSkyflareDiamond" value: { - dps: 10430.00844 - tps: 6390.24383 + dps: 10460.21938 + tps: 6397.00184 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ForlornStarflareDiamond" value: { - dps: 10430.00844 - tps: 6390.24383 + dps: 10460.21938 + tps: 6397.00184 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-FuriousGladiator'sSigilofStrife-42621" value: { - dps: 10690.68894 - tps: 6592.6325 + dps: 10721.06645 + tps: 6599.50258 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-FuryoftheFiveFlights-40431" value: { - dps: 10167.17894 - tps: 6262.54681 + dps: 10195.73651 + tps: 6268.39662 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-FuturesightRune-38763" value: { - dps: 9922.7413 - tps: 6086.4498 + dps: 9951.29887 + tps: 6092.29961 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-GlowingTwilightScale-54573" value: { - dps: 9922.7413 - tps: 6086.4498 + dps: 9951.29887 + tps: 6092.29961 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-GlowingTwilightScale-54589" value: { - dps: 9922.7413 - tps: 6086.4498 + dps: 9951.29887 + tps: 6092.29961 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-GnomishLightningGenerator-41121" value: { - dps: 10084.45394 - tps: 6213.80463 + dps: 10113.06173 + tps: 6219.59022 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-HatefulGladiator'sSigilofStrife-42619" value: { - dps: 10638.92445 - tps: 6553.50409 + dps: 10669.30196 + tps: 6560.37417 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-IllustrationoftheDragonSoul-40432" value: { - dps: 9922.7413 - tps: 6086.4498 + dps: 9951.29887 + tps: 6092.29961 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ImpassiveSkyflareDiamond" value: { - dps: 10455.19915 - tps: 6410.93066 + dps: 10485.43439 + tps: 6417.68614 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ImpassiveStarflareDiamond" value: { - dps: 10451.33499 - tps: 6407.77762 + dps: 10481.55787 + tps: 6414.52322 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-IncisorFragment-37723" value: { - dps: 10115.90059 - tps: 6237.30216 + dps: 10145.46508 + tps: 6243.97919 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-InsightfulEarthsiegeDiamond" value: { - dps: 10430.00844 - tps: 6390.24383 + dps: 10460.21938 + tps: 6397.00184 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-InvigoratingEarthsiegeDiamond" value: { - dps: 10463.88929 - tps: 6414.35598 + dps: 10494.10024 + tps: 6421.11398 hps: 58.71565 } } dps_results: { key: "TestUnholy-AllItems-LastWord-50179" value: { - dps: 10573.70985 - tps: 6509.45394 + dps: 10604.08736 + tps: 6516.32402 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-LastWord-50708" value: { - dps: 10573.70985 - tps: 6509.45394 + dps: 10604.08736 + tps: 6516.32402 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Lavanthor'sTalisman-37872" value: { - dps: 9922.7413 - tps: 6086.4498 + dps: 9951.29887 + tps: 6092.29961 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-MajesticDragonFigurine-40430" value: { - dps: 9922.7413 - tps: 6086.4498 + dps: 9951.29887 + tps: 6092.29961 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-MeteoriteWhetstone-37390" value: { - dps: 10281.96583 - tps: 6397.7295 + dps: 10312.44062 + tps: 6404.84993 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-NevermeltingIceCrystal-50259" value: { - dps: 10041.86928 - tps: 6191.38589 + dps: 10070.71225 + tps: 6197.56001 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-OfferingofSacrifice-37638" value: { - dps: 9922.7413 - tps: 6086.4498 + dps: 9951.29887 + tps: 6092.29961 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-PersistentEarthshatterDiamond" value: { - dps: 10457.4358 - tps: 6409.76319 + dps: 10487.64674 + tps: 6416.52119 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-PersistentEarthsiegeDiamond" value: { - dps: 10463.88929 - tps: 6414.35598 + dps: 10494.10024 + tps: 6421.11398 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-PetrifiedScarab-21685" value: { - dps: 9922.7413 - tps: 6086.4498 + dps: 9951.29887 + tps: 6092.29961 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-PetrifiedTwilightScale-54571" value: { - dps: 9922.7413 - tps: 6086.4498 + dps: 9951.29887 + tps: 6092.29961 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-PetrifiedTwilightScale-54591" value: { - dps: 9922.7413 - tps: 6086.4498 + dps: 9951.29887 + tps: 6092.29961 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-PowerfulEarthshatterDiamond" value: { - dps: 10430.00844 - tps: 6390.24383 + dps: 10460.21938 + tps: 6397.00184 hps: 42.60516 } } dps_results: { key: "TestUnholy-AllItems-PowerfulEarthsiegeDiamond" value: { - dps: 10430.00844 - tps: 6390.24383 + dps: 10460.21938 + tps: 6397.00184 hps: 42.71551 } } dps_results: { key: "TestUnholy-AllItems-PurifiedShardoftheGods" value: { - dps: 9922.7413 - tps: 6086.4498 + dps: 9951.29887 + tps: 6092.29961 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ReignoftheDead-47316" value: { - dps: 10040.41016 - tps: 6178.60998 + dps: 10069.22365 + tps: 6184.61313 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ReignoftheDead-47477" value: { - dps: 10054.02498 - tps: 6189.82165 + dps: 10082.83847 + tps: 6195.8248 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-RelentlessEarthsiegeDiamond" value: { - dps: 10573.70985 - tps: 6509.45394 + dps: 10604.08736 + tps: 6516.32402 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-RelentlessGladiator'sSigilofStrife-42622" value: { - dps: 10713.43488 - tps: 6608.8061 + dps: 10743.81239 + tps: 6615.67618 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-RevitalizingSkyflareDiamond" value: { - dps: 10430.00844 - tps: 6390.24383 + dps: 10460.21938 + tps: 6397.00184 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-RuneofRepulsion-40372" value: { - dps: 9922.7413 - tps: 6086.4498 + dps: 9951.29887 + tps: 6092.29961 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SavageGladiator'sSigilofStrife-42618" value: { - dps: 10631.54167 - tps: 6548.51728 + dps: 10661.91918 + tps: 6555.38736 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ScourgeborneBattlegear" value: { - dps: 8154.20256 - tps: 4967.45223 + dps: 8182.92506 + tps: 4974.35252 hps: 36.48062 } } dps_results: { key: "TestUnholy-AllItems-ScourgebornePlate" value: { - dps: 7458.41543 - tps: 4483.91626 + dps: 7485.29071 + tps: 4489.99814 hps: 38.04394 } } dps_results: { key: "TestUnholy-AllItems-Scourgelord'sBattlegear" value: { - dps: 9705.69014 - tps: 6081.2567 + dps: 9733.87841 + tps: 6088.28622 hps: 44.60989 } } dps_results: { key: "TestUnholy-AllItems-Scourgelord'sPlate" value: { - dps: 8277.82101 - tps: 4960.67431 + dps: 8304.60081 + tps: 4966.63547 hps: 48.06758 } } dps_results: { key: "TestUnholy-AllItems-SealofthePantheon-36993" value: { - dps: 9922.7413 - tps: 6086.4498 + dps: 9951.29887 + tps: 6092.29961 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Shadowmourne-49623" value: { - dps: 10573.70985 - tps: 6509.45394 + dps: 10604.08736 + tps: 6516.32402 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ShinyShardoftheGods" value: { - dps: 9922.7413 - tps: 6086.4498 + dps: 9951.29887 + tps: 6092.29961 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SigilofDeflection-45144" value: { - dps: 10573.70985 - tps: 6509.45394 + dps: 10604.08736 + tps: 6516.32402 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SigilofHauntedDreams-40715" value: { - dps: 10611.42935 - tps: 6539.70724 + dps: 10641.93598 + tps: 6546.65478 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SigilofInsolence-47672" value: { - dps: 10573.70985 - tps: 6509.45394 + dps: 10604.08736 + tps: 6516.32402 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SigiloftheBoneGryphon-50462" value: { - dps: 10573.70985 - tps: 6509.45394 + dps: 10604.08736 + tps: 6516.32402 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SigiloftheHangedMan-50459" value: { - dps: 10573.70985 - tps: 6509.45394 + dps: 10604.08736 + tps: 6516.32402 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SigiloftheUnfalteringKnight-40714" value: { - dps: 10573.70985 - tps: 6509.45394 + dps: 10604.08736 + tps: 6516.32402 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Sindragosa'sFlawlessFang-50361" value: { - dps: 9922.7413 - tps: 6086.4498 + dps: 9951.29887 + tps: 6092.29961 hps: 46.32034 } } dps_results: { key: "TestUnholy-AllItems-SliverofPureIce-50339" value: { - dps: 9922.7413 - tps: 6086.4498 + dps: 9951.29887 + tps: 6092.29961 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SliverofPureIce-50346" value: { - dps: 9922.7413 - tps: 6086.4498 + dps: 9951.29887 + tps: 6092.29961 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SoulPreserver-37111" value: { - dps: 9922.7413 - tps: 6086.4498 + dps: 9951.29887 + tps: 6092.29961 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SouloftheDead-40382" value: { - dps: 10057.09451 - tps: 6196.45815 + dps: 10085.7005 + tps: 6202.34138 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SparkofLife-37657" value: { - dps: 10085.00246 - tps: 6173.51437 + dps: 10114.43165 + tps: 6179.65119 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SphereofRedDragon'sBlood-37166" value: { - dps: 10062.46216 - tps: 6206.54716 + dps: 10161.26061 + tps: 6233.20408 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-StormshroudArmor" value: { - dps: 7154.90213 - tps: 4377.4337 + dps: 7180.45811 + tps: 4383.13828 hps: 30.7975 } } dps_results: { key: "TestUnholy-AllItems-SwiftSkyflareDiamond" value: { - dps: 10463.88929 - tps: 6414.35598 + dps: 10494.10024 + tps: 6421.11398 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SwiftStarflareDiamond" value: { - dps: 10457.4358 - tps: 6409.76319 + dps: 10487.64674 + tps: 6416.52119 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SwiftWindfireDiamond" value: { - dps: 10446.14218 - tps: 6401.72581 + dps: 10476.35312 + tps: 6408.48381 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TalismanofTrollDivinity-37734" value: { - dps: 9922.7413 - tps: 6086.4498 + dps: 9951.29887 + tps: 6092.29961 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TearsoftheVanquished-47215" value: { - dps: 9922.7413 - tps: 6086.4498 + dps: 9951.29887 + tps: 6092.29961 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Thassarian'sBattlegear" value: { - dps: 8723.79314 - tps: 5354.1717 + dps: 8751.89481 + tps: 5360.73152 hps: 38.68766 } } dps_results: { key: "TestUnholy-AllItems-Thassarian'sPlate" value: { - dps: 7520.05866 - tps: 4522.58541 + dps: 7546.77609 + tps: 4528.56765 hps: 40.30616 } } dps_results: { key: "TestUnholy-AllItems-TheGeneral'sHeart-45507" value: { - dps: 9922.7413 - tps: 6086.4498 + dps: 9951.29887 + tps: 6092.29961 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TheTwinBladesofAzzinoth" value: { - dps: 9092.76004 - tps: 5477.55947 + dps: 9123.34118 + tps: 5484.52488 hps: 40.74757 } } dps_results: { key: "TestUnholy-AllItems-ThunderingSkyflareDiamond" value: { - dps: 10553.1811 - tps: 6445.70617 + dps: 10584.28638 + tps: 6452.81963 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TinyAbominationinaJar-50351" value: { - dps: 10181.80388 - tps: 6309.64479 + dps: 10211.64921 + tps: 6316.5035 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TinyAbominationinaJar-50706" value: { - dps: 10197.97827 - tps: 6314.84165 + dps: 10227.38494 + tps: 6321.31812 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TirelessSkyflareDiamond" value: { - dps: 10430.00844 - tps: 6390.24383 + dps: 10460.21938 + tps: 6397.00184 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TirelessStarflareDiamond" value: { - dps: 10430.00844 - tps: 6390.24383 + dps: 10460.21938 + tps: 6397.00184 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TomeofArcanePhenomena-36972" value: { - dps: 10052.06286 - tps: 6182.44029 + dps: 10091.66213 + tps: 6216.2165 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TrenchantEarthshatterDiamond" value: { - dps: 10430.00844 - tps: 6390.24383 + dps: 10460.21938 + tps: 6397.00184 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TrenchantEarthsiegeDiamond" value: { - dps: 10430.00844 - tps: 6390.24383 + dps: 10460.21938 + tps: 6397.00184 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-UndeadSlayer'sBlessedArmor" value: { - dps: 7548.03803 - tps: 4626.05614 + dps: 7574.98389 + tps: 4632.27698 hps: 33.68504 } } dps_results: { key: "TestUnholy-AllItems-Val'anyr,HammerofAncientKings-46017" value: { - dps: 9816.38871 - tps: 5946.71882 + dps: 9846.88961 + tps: 5953.65973 hps: 42.81036 } } dps_results: { key: "TestUnholy-AllItems-WingedTalisman-37844" value: { - dps: 9922.7413 - tps: 6086.4498 + dps: 9951.29887 + tps: 6092.29961 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-WrathfulGladiator'sSigilofStrife-51417" value: { - dps: 10739.43023 - tps: 6627.29023 + dps: 10769.80774 + tps: 6634.16031 hps: 42.12697 } } dps_results: { key: "TestUnholy-Average-Default" value: { - dps: 10554.64816 - tps: 6494.67871 + dps: 10585.28189 + tps: 6501.70107 hps: 42.14164 } } @@ -1174,152 +1174,152 @@ dps_results: { dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_2h_ss-FullBuffs-LongMultiTarget" value: { - dps: 13295.6274 - tps: 8750.5226 + dps: 13330.8778 + tps: 8761.22702 hps: 42.12697 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_2h_ss-FullBuffs-LongSingleTarget" value: { - dps: 10573.70985 - tps: 6509.45394 + dps: 10604.08736 + tps: 6516.32402 hps: 42.12697 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_2h_ss-FullBuffs-ShortSingleTarget" value: { - dps: 14607.97681 - tps: 8255.15077 + dps: 14714.54643 + tps: 8253.24683 hps: 210.63484 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_2h_ss-NoBuffs-LongMultiTarget" value: { - dps: 6470.56088 - tps: 4464.0143 + dps: 6489.15968 + tps: 4469.42626 hps: 27.7272 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_2h_ss-NoBuffs-LongSingleTarget" value: { - dps: 5264.32478 - tps: 3463.83227 + dps: 5281.0176 + tps: 3467.76472 hps: 27.7272 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_2h_ss-NoBuffs-ShortSingleTarget" value: { - dps: 6520.66801 - tps: 4200.50101 + dps: 6575.03317 + tps: 4196.88405 hps: 138.636 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_dnd_aoe-FullBuffs-LongMultiTarget" value: { - dps: 34536.31268 - tps: 26123.72876 + dps: 34597.44338 + tps: 26150.38042 hps: 187.04374 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_dnd_aoe-FullBuffs-LongSingleTarget" value: { - dps: 10399.27957 - tps: 6285.11904 + dps: 10428.49399 + tps: 6290.99572 hps: 185.35866 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_dnd_aoe-FullBuffs-ShortSingleTarget" value: { - dps: 14265.93791 - tps: 7821.68174 + dps: 14370.90078 + tps: 7818.17776 hps: 421.26968 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_dnd_aoe-NoBuffs-LongMultiTarget" value: { - dps: 21452.09038 - tps: 16812.98236 + dps: 21506.52324 + tps: 16844.45945 hps: 58.22712 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_dnd_aoe-NoBuffs-LongSingleTarget" value: { - dps: 5110.62663 - tps: 3335.81335 + dps: 5127.53854 + tps: 3339.88717 hps: 56.84076 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_dnd_aoe-NoBuffs-ShortSingleTarget" value: { - dps: 6331.61226 - tps: 4002.18567 + dps: 6385.38574 + tps: 3997.92592 hps: 275.88564 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-unholy_dw_ss-FullBuffs-LongMultiTarget" value: { - dps: 13120.36841 - tps: 8476.68206 + dps: 13155.35462 + tps: 8487.31602 hps: 235.91102 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-unholy_dw_ss-FullBuffs-LongSingleTarget" value: { - dps: 10427.85852 - tps: 6259.85959 + dps: 10457.69537 + tps: 6266.31718 hps: 235.91102 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-unholy_dw_ss-FullBuffs-ShortSingleTarget" value: { - dps: 14453.14559 - tps: 7918.89701 + dps: 14557.52485 + tps: 7915.30954 hps: 337.01574 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-unholy_dw_ss-NoBuffs-LongMultiTarget" value: { - dps: 6489.06625 - tps: 4413.82845 + dps: 6509.12224 + tps: 4420.4188 hps: 155.27232 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-unholy_dw_ss-NoBuffs-LongSingleTarget" value: { - dps: 5302.30751 - tps: 3435.96613 + dps: 5319.40919 + tps: 3440.16963 hps: 155.27232 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-unholy_dw_ss-NoBuffs-ShortSingleTarget" value: { - dps: 6361.79663 - tps: 3924.97701 + dps: 6414.90391 + tps: 3920.0793 hps: 221.8176 } } dps_results: { key: "TestUnholy-SwitchInFrontOfTarget-Default" value: { - dps: 9945.03108 - tps: 6110.9625 + dps: 9974.31232 + tps: 6117.20239 hps: 42.12697 } } diff --git a/sim/priest/healing/TestHoly.results b/sim/priest/healing/TestHoly.results index 91517efd66..7de62a4da8 100644 --- a/sim/priest/healing/TestHoly.results +++ b/sim/priest/healing/TestHoly.results @@ -172,8 +172,8 @@ dps_results: { dps_results: { key: "TestHoly-AllItems-DarkmoonCard:Greatness-44255" value: { - tps: 36.25385 - hps: 4991.42137 + tps: 35.9717 + hps: 4983.05245 } } dps_results: { diff --git a/sim/priest/smite/TestSmite.results b/sim/priest/smite/TestSmite.results index d4ee33a0d2..110aae8059 100644 --- a/sim/priest/smite/TestSmite.results +++ b/sim/priest/smite/TestSmite.results @@ -855,7 +855,7 @@ dps_results: { key: "TestSmite-Settings-Undead-p1-Basic-default-NoBuffs-ShortSingleTarget" value: { dps: 2520.9093 - tps: 2134.74022 + tps: 2126.72097 } } dps_results: { diff --git a/sim/rogue/TestCombat.results b/sim/rogue/TestCombat.results index 094e9c81fc..78ab4bff78 100644 --- a/sim/rogue/TestCombat.results +++ b/sim/rogue/TestCombat.results @@ -981,43 +981,43 @@ dps_results: { dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Deadly-fan_aoe-FullBuffs-LongMultiTarget" value: { - dps: 21435.04268 - tps: 15218.8803 + dps: 21132.20952 + tps: 15003.86876 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Deadly-fan_aoe-FullBuffs-LongSingleTarget" value: { - dps: 3539.13966 - tps: 2512.78916 + dps: 3516.89637 + tps: 2496.99642 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Deadly-fan_aoe-FullBuffs-ShortSingleTarget" value: { - dps: 4297.57812 - tps: 3051.28047 + dps: 4109.75712 + tps: 2917.92755 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Deadly-fan_aoe-NoBuffs-LongMultiTarget" value: { - dps: 13206.06312 - tps: 9376.30481 + dps: 13003.58802 + tps: 9232.54749 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Deadly-fan_aoe-NoBuffs-LongSingleTarget" value: { - dps: 1785.96568 - tps: 1268.03563 + dps: 1778.52693 + tps: 1262.75412 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Deadly-fan_aoe-NoBuffs-ShortSingleTarget" value: { - dps: 1898.48085 - tps: 1347.9214 + dps: 1863.43428 + tps: 1323.03834 } } dps_results: { @@ -1149,43 +1149,43 @@ dps_results: { dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Instant-fan_aoe-FullBuffs-LongMultiTarget" value: { - dps: 23026.48078 - tps: 16348.80135 + dps: 22695.82072 + tps: 16114.03271 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Instant-fan_aoe-FullBuffs-LongSingleTarget" value: { - dps: 4633.5605 - tps: 3289.82796 + dps: 4601.62498 + tps: 3267.15373 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Instant-fan_aoe-FullBuffs-ShortSingleTarget" value: { - dps: 5540.589 - tps: 3933.81819 + dps: 5306.8537 + tps: 3767.86612 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Instant-fan_aoe-NoBuffs-LongMultiTarget" value: { - dps: 13454.08262 - tps: 9552.39866 + dps: 13260.84412 + tps: 9415.19933 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Instant-fan_aoe-NoBuffs-LongSingleTarget" value: { - dps: 2312.07404 - tps: 1641.57257 + dps: 2301.87343 + tps: 1634.33013 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Deadly OH Instant-fan_aoe-NoBuffs-ShortSingleTarget" value: { - dps: 2393.64181 - tps: 1699.48569 + dps: 2337.44435 + tps: 1659.58549 } } dps_results: { @@ -1317,43 +1317,43 @@ dps_results: { dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Deadly-fan_aoe-FullBuffs-LongMultiTarget" value: { - dps: 25576.22706 - tps: 18159.12122 + dps: 25256.98021 + tps: 17932.45595 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Deadly-fan_aoe-FullBuffs-LongSingleTarget" value: { - dps: 5051.3607 - tps: 3586.46609 + dps: 5018.34623 + tps: 3563.02583 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Deadly-fan_aoe-FullBuffs-ShortSingleTarget" value: { - dps: 6092.44116 - tps: 4325.63322 + dps: 5809.23206 + tps: 4124.55476 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Deadly-fan_aoe-NoBuffs-LongMultiTarget" value: { - dps: 15002.54589 - tps: 10651.80759 + dps: 14807.07114 + tps: 10513.02051 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Deadly-fan_aoe-NoBuffs-LongSingleTarget" value: { - dps: 2529.97284 - tps: 1796.28072 + dps: 2519.14739 + tps: 1788.59464 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Deadly-fan_aoe-NoBuffs-ShortSingleTarget" value: { - dps: 2644.86445 - tps: 1877.85376 + dps: 2588.00612 + tps: 1837.48434 } } dps_results: { @@ -1485,43 +1485,43 @@ dps_results: { dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Instant-fan_aoe-FullBuffs-LongMultiTarget" value: { - dps: 19109.11172 - tps: 13567.46932 + dps: 18824.30249 + tps: 13365.25477 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Instant-fan_aoe-FullBuffs-LongSingleTarget" value: { - dps: 4217.58491 - tps: 2994.48528 + dps: 4189.47287 + tps: 2974.52573 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Instant-fan_aoe-FullBuffs-ShortSingleTarget" value: { - dps: 5274.9979 - tps: 3745.24851 + dps: 5004.60982 + tps: 3553.27297 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Instant-fan_aoe-NoBuffs-LongMultiTarget" value: { - dps: 11025.5797 - tps: 7828.16159 + dps: 10831.81586 + tps: 7690.58926 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Instant-fan_aoe-NoBuffs-LongSingleTarget" value: { - dps: 1993.74101 - tps: 1415.55612 + dps: 1983.7099 + tps: 1408.43403 } } dps_results: { key: "TestCombat-Settings-Human-p1_combat-MH Instant OH Instant-fan_aoe-NoBuffs-ShortSingleTarget" value: { - dps: 2156.33219 - tps: 1530.99585 + dps: 2101.37058 + tps: 1491.97311 } } dps_results: { @@ -1653,43 +1653,43 @@ dps_results: { dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Deadly-fan_aoe-FullBuffs-LongMultiTarget" value: { - dps: 21615.92487 - tps: 15347.30666 + dps: 21290.63515 + tps: 15116.35096 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Deadly-fan_aoe-FullBuffs-LongSingleTarget" value: { - dps: 3565.29603 - tps: 2531.36018 + dps: 3540.60866 + tps: 2513.83215 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Deadly-fan_aoe-FullBuffs-ShortSingleTarget" value: { - dps: 4362.48163 - tps: 3097.36196 + dps: 4172.47671 + tps: 2962.45847 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Deadly-fan_aoe-NoBuffs-LongMultiTarget" value: { - dps: 13327.72899 - tps: 9462.68758 + dps: 13113.07646 + tps: 9310.28429 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Deadly-fan_aoe-NoBuffs-LongSingleTarget" value: { - dps: 1801.49013 - tps: 1279.05799 + dps: 1793.27032 + tps: 1273.22193 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Deadly-fan_aoe-NoBuffs-ShortSingleTarget" value: { - dps: 1933.6019 - tps: 1372.85735 + dps: 1900.39941 + tps: 1349.28358 } } dps_results: { @@ -1821,43 +1821,43 @@ dps_results: { dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Instant-fan_aoe-FullBuffs-LongMultiTarget" value: { - dps: 23204.3601 - tps: 16475.09567 + dps: 22855.23185 + tps: 16227.21462 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Instant-fan_aoe-FullBuffs-LongSingleTarget" value: { - dps: 4667.4418 - tps: 3313.88368 + dps: 4631.68558 + tps: 3288.49676 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Instant-fan_aoe-FullBuffs-ShortSingleTarget" value: { - dps: 5622.83334 - tps: 3992.21167 + dps: 5384.15189 + tps: 3822.74784 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Instant-fan_aoe-NoBuffs-LongMultiTarget" value: { - dps: 13586.68098 - tps: 9646.54349 + dps: 13404.07154 + tps: 9516.8908 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Instant-fan_aoe-NoBuffs-LongSingleTarget" value: { - dps: 2332.01436 - tps: 1655.7302 + dps: 2322.07483 + tps: 1648.67313 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Deadly OH Instant-fan_aoe-NoBuffs-ShortSingleTarget" value: { - dps: 2435.28497 - tps: 1729.05233 + dps: 2383.73941 + tps: 1692.45498 } } dps_results: { @@ -1989,43 +1989,43 @@ dps_results: { dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Deadly-fan_aoe-FullBuffs-LongMultiTarget" value: { - dps: 25775.50672 - tps: 18300.60977 + dps: 25439.18557 + tps: 18061.82176 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Deadly-fan_aoe-FullBuffs-LongSingleTarget" value: { - dps: 5087.70125 - tps: 3612.26789 + dps: 5052.03546 + tps: 3586.94518 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Deadly-fan_aoe-FullBuffs-ShortSingleTarget" value: { - dps: 6179.0402 - tps: 4387.11854 + dps: 5894.33138 + tps: 4184.97528 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Deadly-fan_aoe-NoBuffs-LongMultiTarget" value: { - dps: 15142.98192 - tps: 10751.51716 + dps: 14939.32565 + tps: 10606.92121 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Deadly-fan_aoe-NoBuffs-LongSingleTarget" value: { - dps: 2550.98882 - tps: 1811.20206 + dps: 2539.17634 + tps: 1802.8152 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Deadly-fan_aoe-NoBuffs-ShortSingleTarget" value: { - dps: 2689.5647 - tps: 1909.59093 + dps: 2635.71107 + tps: 1871.35486 } } dps_results: { @@ -2157,43 +2157,43 @@ dps_results: { dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Instant-fan_aoe-FullBuffs-LongMultiTarget" value: { - dps: 19281.73013 - tps: 13690.02839 + dps: 18971.67938 + tps: 13469.89236 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Instant-fan_aoe-FullBuffs-LongSingleTarget" value: { - dps: 4255.39217 - tps: 3021.32844 + dps: 4220.37505 + tps: 2996.46629 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Instant-fan_aoe-FullBuffs-ShortSingleTarget" value: { - dps: 5352.90194 - tps: 3800.56038 + dps: 5084.05186 + tps: 3609.67682 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Instant-fan_aoe-NoBuffs-LongMultiTarget" value: { - dps: 11144.86205 - tps: 7912.85206 + dps: 10943.42878 + tps: 7769.83444 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Instant-fan_aoe-NoBuffs-LongSingleTarget" value: { - dps: 2007.95517 - tps: 1425.64817 + dps: 1997.50981 + tps: 1418.23196 } } dps_results: { key: "TestCombat-Settings-Orc-p1_combat-MH Instant OH Instant-fan_aoe-NoBuffs-ShortSingleTarget" value: { - dps: 2196.75486 - tps: 1559.69595 + dps: 2147.90528 + tps: 1525.01275 } } dps_results: { diff --git a/sim/shaman/enhancement/TestEnhancement.results b/sim/shaman/enhancement/TestEnhancement.results index 28ef007254..c72deb447e 100644 --- a/sim/shaman/enhancement/TestEnhancement.results +++ b/sim/shaman/enhancement/TestEnhancement.results @@ -46,1453 +46,1453 @@ character_stats_results: { dps_results: { key: "TestEnhancement-AllItems-Althor'sAbacus-50359" value: { - dps: 7488.38178 - tps: 4471.14087 + dps: 7473.62711 + tps: 4486.98496 } } dps_results: { key: "TestEnhancement-AllItems-Althor'sAbacus-50366" value: { - dps: 7508.33354 - tps: 4482.66852 + dps: 7493.67413 + tps: 4498.5665 } } dps_results: { key: "TestEnhancement-AllItems-AustereEarthsiegeDiamond" value: { - dps: 7454.30839 - tps: 4467.9134 + dps: 7346.00201 + tps: 4424.4531 } } dps_results: { key: "TestEnhancement-AllItems-Bandit'sInsignia-40371" value: { - dps: 7551.1502 - tps: 4523.95606 + dps: 7483.83142 + tps: 4502.49884 } } dps_results: { key: "TestEnhancement-AllItems-BaubleofTrueBlood-50354" value: { - dps: 7325.51947 - tps: 4376.95395 - hps: 95.31154 + dps: 7311.07446 + tps: 4393.1357 + hps: 95.27757 } } dps_results: { key: "TestEnhancement-AllItems-BaubleofTrueBlood-50726" value: { - dps: 7325.51947 - tps: 4376.95395 - hps: 95.31154 + dps: 7311.07446 + tps: 4393.1357 + hps: 95.27757 } } dps_results: { key: "TestEnhancement-AllItems-BeamingEarthsiegeDiamond" value: { - dps: 7475.31026 - tps: 4477.63467 + dps: 7369.56511 + tps: 4446.94008 } } dps_results: { key: "TestEnhancement-AllItems-Beast-tamer'sShoulders-30892" value: { - dps: 7225.49395 - tps: 4309.69546 + dps: 7159.69031 + tps: 4287.40809 } } dps_results: { key: "TestEnhancement-AllItems-Bizuri'sTotemofShatteredIce-50458" value: { - dps: 7850.22382 - tps: 4735.79827 + dps: 7809.01135 + tps: 4742.91513 } } dps_results: { key: "TestEnhancement-AllItems-BlackBruise-50035" value: { - dps: 7408.99601 - tps: 4486.81619 + dps: 7374.11885 + tps: 4494.75561 } } dps_results: { key: "TestEnhancement-AllItems-BlackBruise-50692" value: { - dps: 7467.32762 - tps: 4529.60019 + dps: 7444.47342 + tps: 4543.98809 } } dps_results: { key: "TestEnhancement-AllItems-BlessedGarboftheUndeadSlayer" value: { - dps: 6078.33371 - tps: 3593.5615 + dps: 6068.11402 + tps: 3613.64186 } } dps_results: { key: "TestEnhancement-AllItems-BlessedRegaliaofUndeadCleansing" value: { - dps: 6037.69839 - tps: 3568.06345 + dps: 5987.99364 + tps: 3553.7404 } } dps_results: { key: "TestEnhancement-AllItems-BracingEarthsiegeDiamond" value: { - dps: 7477.31137 - tps: 4394.33877 + dps: 7368.87371 + tps: 4351.65413 } } dps_results: { key: "TestEnhancement-AllItems-Bryntroll,theBoneArbiter-50415" value: { - dps: 7635.18572 - tps: 4587.17383 + dps: 7514.92387 + tps: 4535.31429 } } dps_results: { key: "TestEnhancement-AllItems-Bryntroll,theBoneArbiter-50709" value: { - dps: 7635.18572 - tps: 4587.17383 + dps: 7514.92387 + tps: 4535.31429 } } dps_results: { key: "TestEnhancement-AllItems-ChaoticSkyflareDiamond" value: { - dps: 7649.96101 - tps: 4595.0705 + dps: 7517.5956 + tps: 4541.24132 } } dps_results: { key: "TestEnhancement-AllItems-CorpseTongueCoin-50349" value: { - dps: 7326.04701 - tps: 4377.34772 + dps: 7310.51729 + tps: 4392.75331 } } dps_results: { key: "TestEnhancement-AllItems-CorpseTongueCoin-50352" value: { - dps: 7326.04701 - tps: 4377.34772 + dps: 7310.51729 + tps: 4392.75331 } } dps_results: { key: "TestEnhancement-AllItems-CorrodedSkeletonKey-50356" value: { - dps: 7326.04701 - tps: 4377.34772 + dps: 7310.52686 + tps: 4392.75331 hps: 64 } } dps_results: { key: "TestEnhancement-AllItems-DarkmoonCard:Berserker!-42989" value: { - dps: 7480.62028 - tps: 4484.86315 + dps: 7440.73677 + tps: 4482.07352 } } dps_results: { key: "TestEnhancement-AllItems-DarkmoonCard:Death-42990" value: { - dps: 7536.82052 - tps: 4525.80141 + dps: 7463.71029 + tps: 4500.08788 } } dps_results: { key: "TestEnhancement-AllItems-DarkmoonCard:Greatness-44255" value: { - dps: 7567.771 - tps: 4527.38423 + dps: 7501.11996 + tps: 4512.2353 } } dps_results: { key: "TestEnhancement-AllItems-DeadlyGladiator'sTotemofSurvival-42602" value: { - dps: 7605.77405 - tps: 4560.46893 + dps: 7533.22744 + tps: 4546.50828 } } dps_results: { key: "TestEnhancement-AllItems-Death'sChoice-47464" value: { - dps: 7748.22319 - tps: 4642.15728 + dps: 7666.13304 + tps: 4612.98322 } } dps_results: { key: "TestEnhancement-AllItems-DeathKnight'sAnguish-38212" value: { - dps: 7439.44615 - tps: 4452.1961 + dps: 7386.26048 + tps: 4446.99909 } } dps_results: { key: "TestEnhancement-AllItems-Deathbringer'sWill-50362" value: { - dps: 7684.63476 - tps: 4600.66827 + dps: 7647.62612 + tps: 4612.82201 } } dps_results: { key: "TestEnhancement-AllItems-Deathbringer'sWill-50363" value: { - dps: 7721.15526 - tps: 4614.3344 + dps: 7665.11029 + tps: 4624.98575 } } dps_results: { key: "TestEnhancement-AllItems-Defender'sCode-40257" value: { - dps: 7326.04039 - tps: 4377.34772 + dps: 7310.51899 + tps: 4392.75331 } } dps_results: { key: "TestEnhancement-AllItems-DestructiveSkyflareDiamond" value: { - dps: 7489.31743 - tps: 4490.14626 + dps: 7367.83375 + tps: 4442.52403 } } dps_results: { key: "TestEnhancement-AllItems-DislodgedForeignObject-50348" value: { - dps: 7837.08279 - tps: 4702.31422 + dps: 7768.88608 + tps: 4713.91149 } } dps_results: { key: "TestEnhancement-AllItems-DislodgedForeignObject-50353" value: { - dps: 7788.78419 - tps: 4672.36168 + dps: 7710.46663 + tps: 4670.88412 } } dps_results: { key: "TestEnhancement-AllItems-EarthshatterBattlegear" value: { - dps: 6768.69336 - tps: 4016.83039 + dps: 6790.91636 + tps: 4060.30955 } } dps_results: { key: "TestEnhancement-AllItems-EarthshatterGarb" value: { - dps: 6439.2724 - tps: 3775.26162 + dps: 6411.15303 + tps: 3792.23839 } } dps_results: { key: "TestEnhancement-AllItems-EffulgentSkyflareDiamond" value: { - dps: 7454.30839 - tps: 4467.9134 + dps: 7346.00201 + tps: 4424.4531 } } dps_results: { key: "TestEnhancement-AllItems-EmberSkyflareDiamond" value: { - dps: 7494.90311 - tps: 4490.38641 + dps: 7398.33067 + tps: 4463.95773 } } dps_results: { key: "TestEnhancement-AllItems-EnigmaticSkyflareDiamond" value: { - dps: 7492.09984 - tps: 4490.98333 + dps: 7364.28305 + tps: 4440.3837 } } dps_results: { key: "TestEnhancement-AllItems-EnigmaticStarflareDiamond" value: { - dps: 7486.19024 - tps: 4487.04024 + dps: 7361.70024 + tps: 4438.28352 } } dps_results: { key: "TestEnhancement-AllItems-EphemeralSnowflake-50260" value: { - dps: 7487.40223 - tps: 4485.81416 + dps: 7432.50027 + tps: 4479.01577 } } dps_results: { key: "TestEnhancement-AllItems-EssenceofGossamer-37220" value: { - dps: 7326.04701 - tps: 4377.34772 + dps: 7310.51729 + tps: 4392.75331 } } dps_results: { key: "TestEnhancement-AllItems-EternalEarthsiegeDiamond" value: { - dps: 7454.30839 - tps: 4467.9134 + dps: 7346.00201 + tps: 4424.4531 } } dps_results: { key: "TestEnhancement-AllItems-ExtractofNecromanticPower-40373" value: { - dps: 7527.85274 - tps: 4512.88071 + dps: 7449.0404 + tps: 4487.33614 } } dps_results: { key: "TestEnhancement-AllItems-EyeoftheBroodmother-45308" value: { - dps: 7566.43894 - tps: 4529.09878 + dps: 7535.20879 + tps: 4536.34072 } } dps_results: { key: "TestEnhancement-AllItems-Figurine-SapphireOwl-42413" value: { - dps: 7413.90482 - tps: 4429.84018 + dps: 7349.67101 + tps: 4419.81447 } } dps_results: { key: "TestEnhancement-AllItems-ForethoughtTalisman-40258" value: { - dps: 7426.7127 - tps: 4435.50995 + dps: 7411.6636 + tps: 4451.18746 } } dps_results: { key: "TestEnhancement-AllItems-ForgeEmber-37660" value: { - dps: 7508.3818 - tps: 4480.52349 + dps: 7446.75936 + tps: 4482.46708 } } dps_results: { key: "TestEnhancement-AllItems-ForlornSkyflareDiamond" value: { - dps: 7477.31137 - tps: 4481.24083 + dps: 7368.87371 + tps: 4437.68613 } } dps_results: { key: "TestEnhancement-AllItems-ForlornStarflareDiamond" value: { - dps: 7472.71077 - tps: 4478.57534 + dps: 7364.29937 + tps: 4435.03952 } } dps_results: { key: "TestEnhancement-AllItems-FrostWitch'sBattlegear" value: { - dps: 8289.67868 - tps: 4957.34432 + dps: 8292.39442 + tps: 5005.20533 } } dps_results: { key: "TestEnhancement-AllItems-FrostWitch'sRegalia" value: { - dps: 7857.35684 - tps: 4666.28332 + dps: 7786.14051 + tps: 4653.95555 } } dps_results: { key: "TestEnhancement-AllItems-FuriousGladiator'sTotemofSurvival-42603" value: { - dps: 7618.64095 - tps: 4567.92265 + dps: 7544.46386 + tps: 4553.89617 } } dps_results: { key: "TestEnhancement-AllItems-FuryoftheFiveFlights-40431" value: { - dps: 7541.64458 - tps: 4511.40204 + dps: 7504.73215 + tps: 4517.74575 } } dps_results: { key: "TestEnhancement-AllItems-FuturesightRune-38763" value: { - dps: 7382.27072 - tps: 4409.83473 + dps: 7367.01513 + tps: 4425.3922 } } dps_results: { key: "TestEnhancement-AllItems-Gladiator'sEarthshaker" value: { - dps: 7079.86321 - tps: 4194.74302 + dps: 7052.82376 + tps: 4197.98938 } } dps_results: { key: "TestEnhancement-AllItems-Gladiator'sWartide" value: { - dps: 6225.70802 - tps: 3614.913 + dps: 6106.41819 + tps: 3560.73425 } } dps_results: { key: "TestEnhancement-AllItems-GlowingTwilightScale-54573" value: { - dps: 7498.35368 - tps: 4476.90469 + dps: 7483.65725 + tps: 4492.77573 } } dps_results: { key: "TestEnhancement-AllItems-GlowingTwilightScale-54589" value: { - dps: 7521.02613 - tps: 4490.00429 + dps: 7506.43795 + tps: 4505.93657 } } dps_results: { key: "TestEnhancement-AllItems-GnomishLightningGenerator-41121" value: { - dps: 7517.24951 - tps: 4510.94307 + dps: 7479.35095 + tps: 4505.02624 } } dps_results: { key: "TestEnhancement-AllItems-HatefulGladiator'sTotemofSurvival-42601" value: { - dps: 7581.74793 - tps: 4545.65553 + dps: 7511.21886 + tps: 4531.78909 } } dps_results: { key: "TestEnhancement-AllItems-Heartpierce-49982" value: { - dps: 7635.18572 - tps: 4587.17383 + dps: 7514.92387 + tps: 4535.31429 } } dps_results: { key: "TestEnhancement-AllItems-Heartpierce-50641" value: { - dps: 7635.18572 - tps: 4587.17383 + dps: 7514.92387 + tps: 4535.31429 } } dps_results: { key: "TestEnhancement-AllItems-IllustrationoftheDragonSoul-40432" value: { - dps: 7495.13054 - tps: 4477.927 + dps: 7463.92839 + tps: 4493.31303 } } dps_results: { key: "TestEnhancement-AllItems-ImpassiveSkyflareDiamond" value: { - dps: 7492.09984 - tps: 4490.98333 + dps: 7364.28305 + tps: 4440.3837 } } dps_results: { key: "TestEnhancement-AllItems-ImpassiveStarflareDiamond" value: { - dps: 7486.19024 - tps: 4487.04024 + dps: 7361.70024 + tps: 4438.28352 } } dps_results: { key: "TestEnhancement-AllItems-IncisorFragment-37723" value: { - dps: 7467.3505 - tps: 4467.95531 + dps: 7442.21357 + tps: 4477.08692 } } dps_results: { key: "TestEnhancement-AllItems-InsightfulEarthsiegeDiamond" value: { - dps: 7472.58982 - tps: 4472.94689 + dps: 7373.84111 + tps: 4441.65494 } } dps_results: { key: "TestEnhancement-AllItems-InvigoratingEarthsiegeDiamond" value: { - dps: 7479.29241 - tps: 4483.20242 + dps: 7373.58906 + tps: 4440.37085 hps: 11.01615 } } dps_results: { key: "TestEnhancement-AllItems-LastWord-50179" value: { - dps: 7635.18572 - tps: 4587.17383 + dps: 7514.92387 + tps: 4535.31429 } } dps_results: { key: "TestEnhancement-AllItems-LastWord-50708" value: { - dps: 7635.18572 - tps: 4587.17383 + dps: 7514.92387 + tps: 4535.31429 } } dps_results: { key: "TestEnhancement-AllItems-Lavanthor'sTalisman-37872" value: { - dps: 7326.04039 - tps: 4377.34772 + dps: 7310.51729 + tps: 4392.75331 } } dps_results: { key: "TestEnhancement-AllItems-MajesticDragonFigurine-40430" value: { - dps: 7326.04701 - tps: 4377.34772 + dps: 7310.51729 + tps: 4392.75331 } } dps_results: { key: "TestEnhancement-AllItems-NevermeltingIceCrystal-50259" value: { - dps: 7453.37936 - tps: 4454.31711 + dps: 7430.17249 + tps: 4467.08842 } } dps_results: { key: "TestEnhancement-AllItems-Nibelung-49992" value: { - dps: 7635.18572 - tps: 4587.17383 + dps: 7514.92387 + tps: 4535.31429 } } dps_results: { key: "TestEnhancement-AllItems-Nibelung-50648" value: { - dps: 7635.18572 - tps: 4587.17383 + dps: 7514.92387 + tps: 4535.31429 } } dps_results: { key: "TestEnhancement-AllItems-OfferingofSacrifice-37638" value: { - dps: 7326.04039 - tps: 4377.34772 + dps: 7310.51729 + tps: 4392.75331 } } dps_results: { key: "TestEnhancement-AllItems-PersistentEarthshatterDiamond" value: { - dps: 7476.53862 - tps: 4481.57701 + dps: 7369.45757 + tps: 4438.06891 } } dps_results: { key: "TestEnhancement-AllItems-PersistentEarthsiegeDiamond" value: { - dps: 7479.29241 - tps: 4483.20242 + dps: 7373.58906 + tps: 4440.37085 } } dps_results: { key: "TestEnhancement-AllItems-PetrifiedScarab-21685" value: { - dps: 7326.04996 - tps: 4377.34772 + dps: 7310.51729 + tps: 4392.75331 } } dps_results: { key: "TestEnhancement-AllItems-PetrifiedTwilightScale-54571" value: { - dps: 7326.04701 - tps: 4377.34772 + dps: 7310.51729 + tps: 4392.75331 } } dps_results: { key: "TestEnhancement-AllItems-PetrifiedTwilightScale-54591" value: { - dps: 7326.04701 - tps: 4377.34772 + dps: 7310.51729 + tps: 4392.75331 } } dps_results: { key: "TestEnhancement-AllItems-PowerfulEarthshatterDiamond" value: { - dps: 7454.30839 - tps: 4467.9134 + dps: 7346.00201 + tps: 4424.4531 } } dps_results: { key: "TestEnhancement-AllItems-PowerfulEarthsiegeDiamond" value: { - dps: 7454.30839 - tps: 4467.9134 + dps: 7346.00201 + tps: 4424.4531 } } dps_results: { key: "TestEnhancement-AllItems-PurifiedShardoftheGods" value: { - dps: 7326.04701 - tps: 4377.34772 + dps: 7310.51729 + tps: 4392.75331 } } dps_results: { key: "TestEnhancement-AllItems-ReignoftheDead-47316" value: { - dps: 7751.32915 - tps: 4658.15276 + dps: 7705.61896 + tps: 4647.09065 } } dps_results: { key: "TestEnhancement-AllItems-ReignoftheDead-47477" value: { - dps: 7801.95946 - tps: 4691.59031 + dps: 7755.80612 + tps: 4680.20393 } } dps_results: { key: "TestEnhancement-AllItems-RelentlessEarthsiegeDiamond" value: { - dps: 7635.18572 - tps: 4587.17383 + dps: 7514.92387 + tps: 4535.31429 } } dps_results: { key: "TestEnhancement-AllItems-RelentlessGladiator'sTotemofSurvival-42604" value: { - dps: 7634.26504 - tps: 4576.97358 + dps: 7558.10809 + tps: 4562.86718 } } dps_results: { key: "TestEnhancement-AllItems-RevitalizingSkyflareDiamond" value: { - dps: 7437.4123 - tps: 4452.94097 + dps: 7345.32488 + tps: 4428.24202 } } dps_results: { key: "TestEnhancement-AllItems-RuneofRepulsion-40372" value: { - dps: 7326.04039 - tps: 4377.34772 + dps: 7310.51899 + tps: 4392.75331 } } dps_results: { key: "TestEnhancement-AllItems-SavageGladiator'sTotemofSurvival-42594" value: { - dps: 7575.24551 - tps: 4542.03373 + dps: 7505.70742 + tps: 4528.20518 } } dps_results: { key: "TestEnhancement-AllItems-SealofthePantheon-36993" value: { - dps: 7326.04039 - tps: 4377.34772 + dps: 7310.51899 + tps: 4392.75331 } } dps_results: { key: "TestEnhancement-AllItems-Shadowmourne-49623" value: { - dps: 7635.18572 - tps: 4587.17383 + dps: 7514.92387 + tps: 4535.31429 } } dps_results: { key: "TestEnhancement-AllItems-ShinyShardoftheGods" value: { - dps: 7326.04701 - tps: 4377.34772 + dps: 7310.51729 + tps: 4392.75331 } } dps_results: { key: "TestEnhancement-AllItems-Sindragosa'sFlawlessFang-50361" value: { - dps: 7326.04966 - tps: 4377.34772 + dps: 7310.51729 + tps: 4392.75331 } } dps_results: { key: "TestEnhancement-AllItems-SkycallTotem-33506" value: { - dps: 7545.59324 - tps: 4529.74767 + dps: 7499.23724 + tps: 4523.8858 } } dps_results: { key: "TestEnhancement-AllItems-SkyshatterHarness" value: { - dps: 5479.81786 - tps: 3192.07373 + dps: 5377.30907 + tps: 3148.78494 } } dps_results: { key: "TestEnhancement-AllItems-SkyshatterRegalia" value: { - dps: 5353.82473 - tps: 3091.78696 + dps: 5328.79735 + tps: 3108.14322 } } dps_results: { key: "TestEnhancement-AllItems-SliverofPureIce-50339" value: { - dps: 7516.4109 - tps: 4494.16019 + dps: 7432.94579 + tps: 4464.48378 } } dps_results: { key: "TestEnhancement-AllItems-SliverofPureIce-50346" value: { - dps: 7534.10476 - tps: 4507.56808 + dps: 7459.91829 + tps: 4485.43717 } } dps_results: { key: "TestEnhancement-AllItems-SoulPreserver-37111" value: { - dps: 7394.06437 - tps: 4416.64653 + dps: 7378.85939 + tps: 4432.23584 } } dps_results: { key: "TestEnhancement-AllItems-SouloftheDead-40382" value: { - dps: 7488.25177 - tps: 4482.96447 + dps: 7423.00569 + tps: 4469.89189 } } dps_results: { key: "TestEnhancement-AllItems-SparkofLife-37657" value: { - dps: 7457.55827 - tps: 4462.34188 + dps: 7425.72719 + tps: 4466.47322 } } dps_results: { key: "TestEnhancement-AllItems-SphereofRedDragon'sBlood-37166" value: { - dps: 7516.72509 - tps: 4483.3304 + dps: 7487.72802 + tps: 4492.83758 } } dps_results: { key: "TestEnhancement-AllItems-Stonebreaker'sTotem-33507" value: { - dps: 7575.53117 - tps: 4543.60715 + dps: 7510.17313 + tps: 4531.32076 } } dps_results: { key: "TestEnhancement-AllItems-StormshroudArmor" value: { - dps: 5699.86409 - tps: 3340.55525 + dps: 5640.69027 + tps: 3328.95814 } } dps_results: { key: "TestEnhancement-AllItems-SwiftSkyflareDiamond" value: { - dps: 7479.29241 - tps: 4483.20242 + dps: 7373.58906 + tps: 4440.37085 } } dps_results: { key: "TestEnhancement-AllItems-SwiftStarflareDiamond" value: { - dps: 7476.53862 - tps: 4481.57701 + dps: 7369.45757 + tps: 4438.06891 } } dps_results: { key: "TestEnhancement-AllItems-SwiftWindfireDiamond" value: { - dps: 7467.385 - tps: 4475.9521 + dps: 7360.61396 + tps: 4432.53129 } } dps_results: { key: "TestEnhancement-AllItems-TalismanofTrollDivinity-37734" value: { - dps: 7326.04304 - tps: 4377.34772 + dps: 7310.51899 + tps: 4392.75331 } } dps_results: { key: "TestEnhancement-AllItems-TearsoftheVanquished-47215" value: { - dps: 7450.73558 - tps: 4458.91097 + dps: 7384.72736 + tps: 4441.7823 } } dps_results: { key: "TestEnhancement-AllItems-TheFistsofFury" value: { - dps: 6540.77571 - tps: 3888.80346 + dps: 6490.46123 + tps: 3890.07641 } } dps_results: { key: "TestEnhancement-AllItems-TheGeneral'sHeart-45507" value: { - dps: 7326.04701 - tps: 4377.34772 + dps: 7310.51729 + tps: 4392.75331 } } dps_results: { key: "TestEnhancement-AllItems-Thrall'sBattlegear" value: { - dps: 7325.74284 - tps: 4372.24836 + dps: 7316.99807 + tps: 4397.73496 } } dps_results: { key: "TestEnhancement-AllItems-Thrall'sRegalia" value: { - dps: 6965.97053 - tps: 4129.37226 + dps: 6927.61904 + tps: 4135.00625 } } dps_results: { key: "TestEnhancement-AllItems-ThunderingSkyflareDiamond" value: { - dps: 7499.48909 - tps: 4502.25812 + dps: 7417.24688 + tps: 4476.96946 } } dps_results: { key: "TestEnhancement-AllItems-TidefuryRaiment" value: { - dps: 5384.78965 - tps: 3132.68235 + dps: 5341.61716 + tps: 3131.02818 } } dps_results: { key: "TestEnhancement-AllItems-TinyAbominationinaJar-50351" value: { - dps: 7553.51272 - tps: 4530.87655 + dps: 7557.70262 + tps: 4566.4818 } } dps_results: { key: "TestEnhancement-AllItems-TinyAbominationinaJar-50706" value: { - dps: 7582.46255 - tps: 4561.50757 + dps: 7507.05358 + tps: 4535.88636 } } dps_results: { key: "TestEnhancement-AllItems-TirelessSkyflareDiamond" value: { - dps: 7477.31137 - tps: 4481.24083 + dps: 7368.87371 + tps: 4437.68613 } } dps_results: { key: "TestEnhancement-AllItems-TirelessStarflareDiamond" value: { - dps: 7472.71077 - tps: 4478.57534 + dps: 7364.29937 + tps: 4435.03952 } } dps_results: { key: "TestEnhancement-AllItems-TomeofArcanePhenomena-36972" value: { - dps: 7513.5459 - tps: 4499.33652 + dps: 7466.78591 + tps: 4494.58726 } } dps_results: { key: "TestEnhancement-AllItems-TotemofElectrifyingWind-47666" value: { - dps: 7764.51652 - tps: 4675.42464 + dps: 7738.81881 + tps: 4697.85822 } } dps_results: { key: "TestEnhancement-AllItems-TotemofQuakingEarth-47667" value: { - dps: 7676.40426 - tps: 4603.89695 + dps: 7612.07948 + tps: 4597.09556 } } dps_results: { key: "TestEnhancement-AllItems-TotemoftheAvalanche-50463" value: { - dps: 7824.11343 - tps: 4696.03853 + dps: 7771.52696 + tps: 4699.8162 } } dps_results: { key: "TestEnhancement-AllItems-TotemoftheElementalPlane-40708" value: { - dps: 7604.09352 - tps: 4569.75049 + dps: 7532.79546 + tps: 4547.11215 } } dps_results: { key: "TestEnhancement-AllItems-TrenchantEarthshatterDiamond" value: { - dps: 7472.71077 - tps: 4478.57534 + dps: 7364.29937 + tps: 4435.03952 } } dps_results: { key: "TestEnhancement-AllItems-TrenchantEarthsiegeDiamond" value: { - dps: 7477.31137 - tps: 4481.24083 + dps: 7368.87371 + tps: 4437.68613 } } dps_results: { key: "TestEnhancement-AllItems-UndeadSlayer'sBlessedArmor" value: { - dps: 6035.89435 - tps: 3564.18686 + dps: 5986.31819 + tps: 3560.20524 } } dps_results: { key: "TestEnhancement-AllItems-Val'anyr,HammerofAncientKings-46017" value: { - dps: 7801.25237 - tps: 4676.6669 + dps: 7740.5687 + tps: 4661.99781 } } dps_results: { key: "TestEnhancement-AllItems-WingedTalisman-37844" value: { - dps: 7423.62048 - tps: 4416.6578 + dps: 7409.1555 + tps: 4432.57624 } } dps_results: { key: "TestEnhancement-AllItems-WorldbreakerBattlegear" value: { - dps: 7290.8706 - tps: 4361.38972 + dps: 7267.06856 + tps: 4379.67499 } } dps_results: { key: "TestEnhancement-AllItems-WorldbreakerGarb" value: { - dps: 6980.85326 - tps: 4135.00877 + dps: 6954.483 + tps: 4146.43269 } } dps_results: { key: "TestEnhancement-AllItems-WrathfulGladiator'sTotemofSurvival-51513" value: { - dps: 7650.8082 - tps: 4586.55693 + dps: 7572.55491 + tps: 4572.36589 } } dps_results: { key: "TestEnhancement-Average-Default" value: { - dps: 7600.83868 - tps: 4561.9259 + dps: 7551.26338 + tps: 4560.96266 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-FT-default_ft-FullBuffs-LongMultiTarget" value: { - dps: 26186.16858 - tps: 16106.84594 + dps: 26077.94558 + tps: 16183.27196 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-FT-default_ft-FullBuffs-LongSingleTarget" value: { - dps: 7669.91337 - tps: 4561.42622 + dps: 7593.77146 + tps: 4540.16784 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-FT-default_ft-FullBuffs-ShortSingleTarget" value: { - dps: 9574.68404 - tps: 5036.32873 + dps: 9568.76656 + tps: 5009.87027 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-FT-default_ft-NoBuffs-LongMultiTarget" value: { - dps: 13684.23297 - tps: 9030.60783 + dps: 13399.27666 + tps: 8959.44778 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-FT-default_ft-NoBuffs-LongSingleTarget" value: { - dps: 4003.19283 - tps: 2340.75866 + dps: 3979.21808 + tps: 2354.00911 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-FT-default_ft-NoBuffs-ShortSingleTarget" value: { - dps: 5184.0533 - tps: 2660.2416 + dps: 5205.48107 + tps: 2660.50992 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-FT-default_wf-FullBuffs-LongMultiTarget" value: { - dps: 25622.96296 - tps: 15671.56499 + dps: 25457.87272 + tps: 15797.21094 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-FT-default_wf-FullBuffs-LongSingleTarget" value: { - dps: 7784.50899 - tps: 4630.54117 + dps: 7688.44885 + tps: 4598.79125 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-FT-default_wf-FullBuffs-ShortSingleTarget" value: { - dps: 9652.83704 - tps: 5090.78406 + dps: 9647.51631 + tps: 5053.88397 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-FT-default_wf-NoBuffs-LongMultiTarget" value: { - dps: 13049.53241 - tps: 8581.42761 + dps: 12914.12299 + tps: 8621.4819 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-FT-default_wf-NoBuffs-LongSingleTarget" value: { - dps: 4042.05522 - tps: 2367.85095 + dps: 4029.71242 + tps: 2385.73443 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-FT-default_wf-NoBuffs-ShortSingleTarget" value: { - dps: 5271.2156 - tps: 2724.6169 + dps: 5243.81734 + tps: 2678.68179 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-FT-phase_3-FullBuffs-LongMultiTarget" value: { - dps: 26133.29171 - tps: 16058.07007 + dps: 25743.35726 + tps: 15961.23808 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-FT-phase_3-FullBuffs-LongSingleTarget" value: { - dps: 7640.22094 - tps: 4536.36977 + dps: 7616.89185 + tps: 4549.13163 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-FT-phase_3-FullBuffs-ShortSingleTarget" value: { - dps: 9609.50631 - tps: 5070.27954 + dps: 9507.62827 + tps: 4968.53777 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-FT-phase_3-NoBuffs-LongMultiTarget" value: { - dps: 13381.84078 - tps: 8804.64771 + dps: 13299.98095 + tps: 8851.89346 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-FT-phase_3-NoBuffs-LongSingleTarget" value: { - dps: 4001.65647 - tps: 2339.19254 + dps: 3958.89816 + tps: 2336.15864 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-FT-phase_3-NoBuffs-ShortSingleTarget" value: { - dps: 5240.91568 - tps: 2718.50875 + dps: 5279.82633 + tps: 2705.3678 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-default_ft-FullBuffs-LongMultiTarget" value: { - dps: 21680.16437 - tps: 13638.71484 + dps: 4944.24822 + tps: 4008.12786 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-default_ft-FullBuffs-LongSingleTarget" value: { - dps: 6507.784 - tps: 3861.80638 + dps: 4944.24822 + tps: 3210.89845 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-default_ft-FullBuffs-ShortSingleTarget" value: { - dps: 8428.97103 - tps: 4349.02986 + dps: 6208.66309 + tps: 3584.79758 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-default_ft-NoBuffs-LongMultiTarget" value: { - dps: 10610.24642 - tps: 7579.48976 + dps: 2440.10311 + tps: 2574.46437 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-default_ft-NoBuffs-LongSingleTarget" value: { - dps: 2968.93615 - tps: 1778.93524 + dps: 2440.10311 + tps: 1639.91575 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-default_ft-NoBuffs-ShortSingleTarget" value: { - dps: 3957.85135 - tps: 2025.16372 + dps: 2708.33712 + tps: 1602.97462 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-default_wf-FullBuffs-LongMultiTarget" value: { - dps: 21032.76479 - tps: 13230.12753 + dps: 5091.26951 + tps: 4166.23495 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-default_wf-FullBuffs-LongSingleTarget" value: { - dps: 6576.80932 - tps: 3913.78725 + dps: 5091.26951 + tps: 3317.31698 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-default_wf-FullBuffs-ShortSingleTarget" value: { - dps: 8516.56232 - tps: 4409.27557 + dps: 6396.28053 + tps: 3720.37032 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-default_wf-NoBuffs-LongMultiTarget" value: { - dps: 10063.51092 - tps: 7218.51259 + dps: 2568.28624 + tps: 2810.23722 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-default_wf-NoBuffs-LongSingleTarget" value: { - dps: 3037.8618 - tps: 1827.22131 + dps: 2568.28624 + tps: 1736.89243 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-default_wf-NoBuffs-ShortSingleTarget" value: { - dps: 4047.1475 - tps: 2089.28001 + dps: 2834.49133 + tps: 1691.14902 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-phase_3-FullBuffs-LongMultiTarget" value: { - dps: 21374.01664 - tps: 13399.67835 + dps: 4866.76982 + tps: 3900.96896 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-phase_3-FullBuffs-LongSingleTarget" value: { - dps: 6519.95465 - tps: 3877.31261 + dps: 4866.76982 + tps: 3154.8846 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-phase_3-FullBuffs-ShortSingleTarget" value: { - dps: 8411.63234 - tps: 4372.2593 + dps: 6155.11998 + tps: 3552.33946 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-phase_3-NoBuffs-LongMultiTarget" value: { - dps: 10422.08541 - tps: 7382.86132 + dps: 2357.03434 + tps: 2371.87381 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-phase_3-NoBuffs-LongSingleTarget" value: { - dps: 2981.21683 - tps: 1783.52357 + dps: 2357.03434 + tps: 1574.49498 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-phase_3-NoBuffs-ShortSingleTarget" value: { - dps: 3991.83663 - tps: 2064.13251 + dps: 2620.98068 + tps: 1541.92994 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-FT-default_ft-FullBuffs-LongMultiTarget" value: { - dps: 25913.97202 - tps: 16067.76099 + dps: 25768.84208 + tps: 16137.21693 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-FT-default_ft-FullBuffs-LongSingleTarget" value: { - dps: 7635.18572 - tps: 4587.17383 + dps: 7514.92387 + tps: 4535.31429 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-FT-default_ft-FullBuffs-ShortSingleTarget" value: { - dps: 9545.73434 - tps: 5164.04585 + dps: 9447.28966 + tps: 5071.64701 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-FT-default_ft-NoBuffs-LongMultiTarget" value: { - dps: 13359.69933 - tps: 8949.04097 + dps: 13155.51262 + tps: 8891.92044 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-FT-default_ft-NoBuffs-LongSingleTarget" value: { - dps: 3975.08621 - tps: 2363.4439 + dps: 3920.6067 + tps: 2353.44766 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-FT-default_ft-NoBuffs-ShortSingleTarget" value: { - dps: 5122.08272 - tps: 2715.87209 + dps: 5121.77357 + tps: 2698.80099 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-FT-default_wf-FullBuffs-LongMultiTarget" value: { - dps: 25269.54423 - tps: 15670.5321 + dps: 25078.91942 + tps: 15673.4403 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-FT-default_wf-FullBuffs-LongSingleTarget" value: { - dps: 7725.30017 - tps: 4646.1106 + dps: 7654.6546 + tps: 4639.04206 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-FT-default_wf-FullBuffs-ShortSingleTarget" value: { - dps: 9624.68112 - tps: 5215.72835 + dps: 9610.38768 + tps: 5179.52556 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-FT-default_wf-NoBuffs-LongMultiTarget" value: { - dps: 12859.48482 - tps: 8553.43215 + dps: 12538.4128 + tps: 8449.78826 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-FT-default_wf-NoBuffs-LongSingleTarget" value: { - dps: 4014.39743 - tps: 2388.65633 + dps: 3987.51408 + tps: 2396.1965 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-FT-default_wf-NoBuffs-ShortSingleTarget" value: { - dps: 5198.75134 - tps: 2761.36177 + dps: 5236.52106 + tps: 2780.66198 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-FT-phase_3-FullBuffs-LongMultiTarget" value: { - dps: 25703.26 - tps: 15982.49007 + dps: 25540.59993 + tps: 15991.23922 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-FT-phase_3-FullBuffs-LongSingleTarget" value: { - dps: 7622.92899 - tps: 4581.17305 + dps: 7575.70226 + tps: 4576.6514 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-FT-phase_3-FullBuffs-ShortSingleTarget" value: { - dps: 9438.30258 - tps: 5075.60119 + dps: 9558.20946 + tps: 5142.99358 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-FT-phase_3-NoBuffs-LongMultiTarget" value: { - dps: 13316.59458 - tps: 8887.90176 + dps: 12906.59189 + tps: 8691.88066 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-FT-phase_3-NoBuffs-LongSingleTarget" value: { - dps: 3954.93812 - tps: 2342.72141 + dps: 3901.46747 + tps: 2334.1986 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-FT-phase_3-NoBuffs-ShortSingleTarget" value: { - dps: 5131.35099 - tps: 2723.9177 + dps: 5177.22241 + tps: 2729.37239 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-default_ft-FullBuffs-LongMultiTarget" value: { - dps: 21384.38777 - tps: 13548.39071 + dps: 4987.1598 + tps: 4061.9771 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-default_ft-FullBuffs-LongSingleTarget" value: { - dps: 6514.51764 - tps: 3900.36173 + dps: 4987.1598 + tps: 3258.62378 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-default_ft-FullBuffs-ShortSingleTarget" value: { - dps: 8379.37137 - tps: 4403.48572 + dps: 6308.24779 + tps: 3709.32128 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-default_ft-NoBuffs-LongMultiTarget" value: { - dps: 10416.80384 - tps: 7502.68723 + dps: 2444.83649 + tps: 2561.92902 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-default_ft-NoBuffs-LongSingleTarget" value: { - dps: 2955.47922 - tps: 1785.17477 + dps: 2444.83649 + tps: 1648.29155 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-default_ft-NoBuffs-ShortSingleTarget" value: { - dps: 3959.33256 - tps: 2076.57379 + dps: 2711.86435 + tps: 1621.83785 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-default_wf-FullBuffs-LongMultiTarget" value: { - dps: 20990.67972 - tps: 13266.53791 + dps: 5115.23319 + tps: 4209.88967 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-default_wf-FullBuffs-LongSingleTarget" value: { - dps: 6554.30878 - tps: 3931.71223 + dps: 5115.23319 + tps: 3351.39836 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-default_wf-FullBuffs-ShortSingleTarget" value: { - dps: 8471.25083 - tps: 4465.71853 + dps: 6447.86216 + tps: 3809.26534 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-default_wf-NoBuffs-LongMultiTarget" value: { - dps: 9914.00758 - tps: 7151.38029 + dps: 2558.15125 + tps: 2852.05761 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-default_wf-NoBuffs-LongSingleTarget" value: { - dps: 3022.61476 - tps: 1832.60228 + dps: 2558.15125 + tps: 1737.43083 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-default_wf-NoBuffs-ShortSingleTarget" value: { - dps: 3986.52439 - tps: 2093.66433 + dps: 2841.24541 + tps: 1712.38615 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-phase_3-FullBuffs-LongMultiTarget" value: { - dps: 21260.44814 - tps: 13290.20528 + dps: 4868.01714 + tps: 3921.40877 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-phase_3-FullBuffs-LongSingleTarget" value: { - dps: 6449.72884 - tps: 3857.26454 + dps: 4868.01714 + tps: 3172.16547 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-phase_3-FullBuffs-ShortSingleTarget" value: { - dps: 8333.66807 - tps: 4388.32522 + dps: 6181.81733 + tps: 3618.34966 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-phase_3-NoBuffs-LongMultiTarget" value: { - dps: 10399.48238 - tps: 7461.54358 + dps: 2362.5928 + tps: 2365.21563 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-phase_3-NoBuffs-LongSingleTarget" value: { - dps: 2937.7638 - tps: 1776.65144 + dps: 2362.5928 + tps: 1583.3199 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-phase_3-NoBuffs-ShortSingleTarget" value: { - dps: 3993.04766 - tps: 2107.34847 + dps: 2633.31988 + tps: 1567.36545 } } dps_results: { key: "TestEnhancement-SwitchInFrontOfTarget-Default" value: { - dps: 7267.23608 - tps: 4331.58151 + dps: 7188.35082 + tps: 4308.63993 } } diff --git a/sim/shaman/fire_elemental_totem.go b/sim/shaman/fire_elemental_totem.go index c7665c4646..893fc5ab8c 100644 --- a/sim/shaman/fire_elemental_totem.go +++ b/sim/shaman/fire_elemental_totem.go @@ -41,9 +41,7 @@ func (shaman *Shaman) registerFireElementalTotem() { ApplyEffects: func(sim *core.Simulation, target *core.Unit, _ *core.Spell) { // TODO: ToW needs a unique buff/debuff aura for each raidmember/target. // Otherwise we will be possibly disabling another ele shaman's ToW debuff/buff. - if shaman.Totems.Fire == proto.FireTotem_TotemOfWrath { - shaman.TotemExpirations[FireTotem] = sim.CurrentTime + fireTotemDuration - } else if shaman.Totems.Fire != proto.FireTotem_NoFireTotem && !shaman.Totems.UseFireMcd { + if shaman.Totems.Fire != proto.FireTotem_NoFireTotem { shaman.TotemExpirations[FireTotem] = sim.CurrentTime + fireTotemDuration } diff --git a/sim/shaman/restoration/TestRestoration.results b/sim/shaman/restoration/TestRestoration.results index e6a1571e31..b35c797e1a 100644 --- a/sim/shaman/restoration/TestRestoration.results +++ b/sim/shaman/restoration/TestRestoration.results @@ -45,852 +45,573 @@ character_stats_results: { } dps_results: { key: "TestRestoration-AllItems-Althor'sAbacus-50359" - value: { - dps: 438.74262 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-Althor'sAbacus-50366" - value: { - dps: 440.81894 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-AustereEarthsiegeDiamond" - value: { - dps: 430.41777 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-Bandit'sInsignia-40371" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-BaubleofTrueBlood-50354" value: { - dps: 421.75678 - hps: 93.56546 + hps: 93.75404 } } dps_results: { key: "TestRestoration-AllItems-BaubleofTrueBlood-50726" value: { - dps: 421.75678 - hps: 93.56546 + hps: 93.75404 } } dps_results: { key: "TestRestoration-AllItems-BeamingEarthsiegeDiamond" - value: { - dps: 430.41777 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-Beast-tamer'sShoulders-30892" - value: { - dps: 417.58166 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-Bizuri'sTotemofShatteredIce-50458" - value: { - dps: 431.09798 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-BlackBruise-50035" - value: { - dps: 374.4883 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-BlackBruise-50692" - value: { - dps: 374.4883 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-BlessedGarboftheUndeadSlayer" - value: { - dps: 372.35338 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-BlessedRegaliaofUndeadCleansing" - value: { - dps: 388.58783 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-BracingEarthsiegeDiamond" - value: { - dps: 432.77723 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-Bryntroll,theBoneArbiter-50415" - value: { - dps: 431.09798 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-Bryntroll,theBoneArbiter-50709" - value: { - dps: 431.09798 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-ChaoticSkyflareDiamond" - value: { - dps: 430.41777 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-CorpseTongueCoin-50349" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-CorpseTongueCoin-50352" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-CorrodedSkeletonKey-50356" value: { - dps: 421.84891 hps: 64 } } dps_results: { key: "TestRestoration-AllItems-DarkmoonCard:Berserker!-42989" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-DarkmoonCard:Death-42990" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-DarkmoonCard:Greatness-44255" - value: { - dps: 425.45728 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-DeadlyGladiator'sTotemofSurvival-42602" - value: { - dps: 431.09798 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-Death'sChoice-47464" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-DeathKnight'sAnguish-38212" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-Deathbringer'sWill-50362" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-Deathbringer'sWill-50363" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-Defender'sCode-40257" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-DestructiveSkyflareDiamond" - value: { - dps: 430.41777 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-DislodgedForeignObject-50348" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-DislodgedForeignObject-50353" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-EarthshatterBattlegear" - value: { - dps: 384.11985 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-EarthshatterGarb" - value: { - dps: 433.095 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-EffulgentSkyflareDiamond" - value: { - dps: 430.41777 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-EmberSkyflareDiamond" - value: { - dps: 433.46002 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-EnigmaticSkyflareDiamond" - value: { - dps: 430.41777 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-EnigmaticStarflareDiamond" - value: { - dps: 430.41777 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-EphemeralSnowflake-50260" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-EssenceofGossamer-37220" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-EternalEarthsiegeDiamond" - value: { - dps: 430.41777 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-ExtractofNecromanticPower-40373" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-EyeoftheBroodmother-45308" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-Figurine-SapphireOwl-42413" - value: { - dps: 423.67646 - tps: 0.975 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-ForethoughtTalisman-40258" - value: { - dps: 432.32489 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-ForgeEmber-37660" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-ForlornSkyflareDiamond" - value: { - dps: 432.77723 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-ForlornStarflareDiamond" - value: { - dps: 432.30534 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-FrostWitch'sBattlegear" - value: { - dps: 395.23715 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-FrostWitch'sRegalia" - value: { - dps: 497.92526 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-FuriousGladiator'sTotemofSurvival-42603" - value: { - dps: 431.09798 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-FuryoftheFiveFlights-40431" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-FuturesightRune-38763" - value: { - dps: 427.70036 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-Gladiator'sEarthshaker" - value: { - dps: 365.19514 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-Gladiator'sWartide" - value: { - dps: 454.19385 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-GlowingTwilightScale-54573" - value: { - dps: 439.78078 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-GlowingTwilightScale-54589" - value: { - dps: 442.14023 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-GnomishLightningGenerator-41121" value: { - dps: 422.07575 - dtps: 32.22786 + dtps: 32.07764 } } dps_results: { key: "TestRestoration-AllItems-HatefulGladiator'sTotemofSurvival-42601" - value: { - dps: 431.09798 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-Heartpierce-49982" - value: { - dps: 431.09798 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-Heartpierce-50641" - value: { - dps: 431.09798 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-IllustrationoftheDragonSoul-40432" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-ImpassiveSkyflareDiamond" - value: { - dps: 430.41777 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-ImpassiveStarflareDiamond" - value: { - dps: 430.41777 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-IncisorFragment-37723" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-InsightfulEarthsiegeDiamond" - value: { - dps: 431.09798 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-InvigoratingEarthsiegeDiamond" - value: { - dps: 430.41777 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-LastWord-50179" - value: { - dps: 431.09798 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-LastWord-50708" - value: { - dps: 431.09798 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-Lavanthor'sTalisman-37872" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-MajesticDragonFigurine-40430" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-MeteoriteWhetstone-37390" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-NevermeltingIceCrystal-50259" - value: { - dps: 432.32489 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-Nibelung-49992" - value: { - dps: 431.09798 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-Nibelung-50648" - value: { - dps: 431.09798 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-OfferingofSacrifice-37638" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-PersistentEarthshatterDiamond" - value: { - dps: 430.41777 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-PersistentEarthsiegeDiamond" - value: { - dps: 430.41777 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-PetrifiedScarab-21685" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-PetrifiedTwilightScale-54571" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-PetrifiedTwilightScale-54591" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-PowerfulEarthshatterDiamond" - value: { - dps: 430.41777 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-PowerfulEarthsiegeDiamond" - value: { - dps: 430.41777 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-PurifiedShardoftheGods" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-ReignoftheDead-47316" - value: { - dps: 436.00565 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-ReignoftheDead-47477" - value: { - dps: 437.70446 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-RelentlessEarthsiegeDiamond" - value: { - dps: 430.41777 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-RelentlessGladiator'sTotemofSurvival-42604" - value: { - dps: 431.09798 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-RevitalizingSkyflareDiamond" - value: { - dps: 430.41777 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-RuneofRepulsion-40372" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-SavageGladiator'sTotemofSurvival-42594" - value: { - dps: 431.09798 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-SealofthePantheon-36993" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-Shadowmourne-49623" - value: { - dps: 431.09798 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-ShinyShardoftheGods" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-Sindragosa'sFlawlessFang-50361" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-SkycallTotem-33506" - value: { - dps: 431.09798 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-SkyshatterHarness" - value: { - dps: 338.77387 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-SkyshatterRegalia" - value: { - dps: 382.87779 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-SliverofPureIce-50339" - value: { - dps: 436.76067 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-SliverofPureIce-50346" - value: { - dps: 438.64824 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-SouloftheDead-40382" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-SparkofLife-37657" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-SphereofRedDragon'sBlood-37166" - value: { - dps: 432.60699 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-Stonebreaker'sTotem-33507" - value: { - dps: 431.09798 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-StormshroudArmor" - value: { - dps: 368.87888 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-SwiftSkyflareDiamond" - value: { - dps: 430.41777 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-SwiftStarflareDiamond" - value: { - dps: 430.41777 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-SwiftWindfireDiamond" - value: { - dps: 430.41777 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-TalismanofTrollDivinity-37734" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-TearsoftheVanquished-47215" - value: { - dps: 425.26267 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-TheFistsofFury" - value: { - dps: 379.15057 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-TheGeneral'sHeart-45507" - value: { - dps: 421.84891 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-Thrall'sBattlegear" - value: { - dps: 393.85565 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-Thrall'sRegalia" - value: { - dps: 461.60137 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-ThunderingSkyflareDiamond" - value: { - dps: 430.41777 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-TidefuryRaiment" - value: { - dps: 370.22169 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-TinyAbominationinaJar-50351" - value: { - dps: 439.95675 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-TinyAbominationinaJar-50706" - value: { - dps: 439.95675 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-TirelessSkyflareDiamond" - value: { - dps: 432.77723 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-TirelessStarflareDiamond" - value: { - dps: 432.30534 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-TomeofArcanePhenomena-36972" - value: { - dps: 428.26663 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-TotemofElectrifyingWind-47666" - value: { - dps: 431.09798 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-TotemofQuakingEarth-47667" - value: { - dps: 431.09798 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-TotemoftheAvalanche-50463" - value: { - dps: 431.09798 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-TotemoftheElementalPlane-40708" - value: { - dps: 431.09798 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-TrenchantEarthshatterDiamond" - value: { - dps: 432.30534 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-TrenchantEarthsiegeDiamond" - value: { - dps: 432.77723 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-UndeadSlayer'sBlessedArmor" - value: { - dps: 368.87888 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-Val'anyr,HammerofAncientKings-46017" - value: { - dps: 442.98141 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-WingedTalisman-37844" - value: { - dps: 454.50379 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-WorldbreakerBattlegear" - value: { - dps: 389.7915 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-WorldbreakerGarb" - value: { - dps: 456.87971 - } + value: {} } dps_results: { key: "TestRestoration-AllItems-WrathfulGladiator'sTotemofSurvival-51513" - value: { - dps: 431.09798 - } + value: {} } dps_results: { key: "TestRestoration-Average-Default" - value: { - dps: 433.28018 - } + value: {} } dps_results: { key: "TestRestoration-Settings-Troll-p1-Standard-Default-FullBuffs-LongMultiTarget" - value: { - dps: 1991.73894 - } + value: {} } dps_results: { key: "TestRestoration-Settings-Troll-p1-Standard-Default-FullBuffs-LongSingleTarget" - value: { - dps: 431.09798 - } + value: {} } dps_results: { key: "TestRestoration-Settings-Troll-p1-Standard-Default-FullBuffs-ShortSingleTarget" - value: { - dps: 1119.20682 - } + value: {} } dps_results: { key: "TestRestoration-Settings-Troll-p1-Standard-Default-NoBuffs-LongMultiTarget" - value: { - dps: 1513.25039 - } + value: {} } dps_results: { key: "TestRestoration-Settings-Troll-p1-Standard-Default-NoBuffs-LongSingleTarget" - value: { - dps: 317.58927 - } + value: {} } dps_results: { key: "TestRestoration-Settings-Troll-p1-Standard-Default-NoBuffs-ShortSingleTarget" - value: { - dps: 832.65007 - } + value: {} } dps_results: { key: "TestRestoration-SwitchInFrontOfTarget-Default" - value: { - dps: 394.56405 - } + value: {} } diff --git a/sim/warlock/TestDemonology.results b/sim/warlock/TestDemonology.results index 2ae42ae9aa..536e7e6fb0 100644 --- a/sim/warlock/TestDemonology.results +++ b/sim/warlock/TestDemonology.results @@ -46,704 +46,704 @@ character_stats_results: { dps_results: { key: "TestDemonology-AllItems-Althor'sAbacus-50359" value: { - dps: 13243.90588 - tps: 11492.86523 + dps: 11029.86291 + tps: 10767.28533 } } dps_results: { key: "TestDemonology-AllItems-Althor'sAbacus-50366" value: { - dps: 13278.4155 - tps: 11523.00644 + dps: 11055.04985 + tps: 10791.31034 } } dps_results: { key: "TestDemonology-AllItems-AshtongueTalismanofShadows-32493" value: { - dps: 13074.67441 - tps: 11336.3098 + dps: 10875.72599 + tps: 10616.72071 } } dps_results: { key: "TestDemonology-AllItems-AustereEarthsiegeDiamond" value: { - dps: 13418.79874 - tps: 11655.82175 + dps: 11073.18055 + tps: 10814.91661 } } dps_results: { key: "TestDemonology-AllItems-Bandit'sInsignia-40371" value: { - dps: 12900.43003 - tps: 11180.48019 + dps: 10720.55552 + tps: 10464.17138 } } dps_results: { key: "TestDemonology-AllItems-BaubleofTrueBlood-50354" value: { - dps: 12896.06082 - tps: 11177.10371 - hps: 100.95364 + dps: 10722.16856 + tps: 10465.85596 + hps: 101.80272 } } dps_results: { key: "TestDemonology-AllItems-BaubleofTrueBlood-50726" value: { - dps: 12896.06082 - tps: 11177.10371 - hps: 100.95364 + dps: 10722.16856 + tps: 10465.85596 + hps: 101.80272 } } dps_results: { key: "TestDemonology-AllItems-BeamingEarthsiegeDiamond" value: { - dps: 13401.77362 - tps: 11638.54725 + dps: 11099.41588 + tps: 10841.25543 } } dps_results: { key: "TestDemonology-AllItems-BlessedRegaliaofUndeadCleansing" value: { - dps: 9817.47634 - tps: 8342.96725 + dps: 8005.70237 + tps: 7802.7555 } } dps_results: { key: "TestDemonology-AllItems-BracingEarthsiegeDiamond" value: { - dps: 13449.10871 - tps: 11449.20433 + dps: 11119.66976 + tps: 10645.99435 } } dps_results: { key: "TestDemonology-AllItems-ChaoticSkyflareDiamond" value: { - dps: 13766.09428 - tps: 12003.46809 + dps: 11410.3423 + tps: 11152.09819 } } dps_results: { key: "TestDemonology-AllItems-CorpseTongueCoin-50349" value: { - dps: 12900.43003 - tps: 11180.48019 + dps: 10720.55552 + tps: 10464.17138 } } dps_results: { key: "TestDemonology-AllItems-CorpseTongueCoin-50352" value: { - dps: 12900.43003 - tps: 11180.48019 + dps: 10720.55552 + tps: 10464.17138 } } dps_results: { key: "TestDemonology-AllItems-CorrodedSkeletonKey-50356" value: { - dps: 12950.07749 - tps: 11226.26804 + dps: 10770.42571 + tps: 10513.39859 hps: 64 } } dps_results: { key: "TestDemonology-AllItems-DarkCoven'sRegalia" value: { - dps: 12601.16483 - tps: 10909.94106 + dps: 10425.18922 + tps: 10175.94046 } } dps_results: { key: "TestDemonology-AllItems-DarkmoonCard:Berserker!-42989" value: { - dps: 13069.14213 - tps: 11349.19229 + dps: 10864.3927 + tps: 10608.00856 } } dps_results: { key: "TestDemonology-AllItems-DarkmoonCard:Death-42990" value: { - dps: 13108.2148 - tps: 11388.41437 + dps: 10914.04201 + tps: 10657.69731 } } dps_results: { key: "TestDemonology-AllItems-DarkmoonCard:Greatness-44255" value: { - dps: 12992.95845 - tps: 11268.3201 + dps: 10827.49237 + tps: 10566.12402 } } dps_results: { key: "TestDemonology-AllItems-Death'sChoice-47464" value: { - dps: 12900.43003 - tps: 11180.48019 + dps: 10720.49094 + tps: 10464.1068 } } dps_results: { key: "TestDemonology-AllItems-DeathKnight'sAnguish-38212" value: { - dps: 12949.96635 - tps: 11230.01651 + dps: 10768.14946 + tps: 10511.76532 } } dps_results: { key: "TestDemonology-AllItems-Deathbringer'sWill-50362" value: { - dps: 12900.43003 - tps: 11180.48019 + dps: 10720.55552 + tps: 10464.17138 } } dps_results: { key: "TestDemonology-AllItems-Deathbringer'sWill-50363" value: { - dps: 12900.43003 - tps: 11180.48019 + dps: 10720.55552 + tps: 10464.17138 } } dps_results: { key: "TestDemonology-AllItems-DeathbringerGarb" value: { - dps: 10738.51563 - tps: 9156.02028 + dps: 8750.45172 + tps: 8513.7745 } } dps_results: { key: "TestDemonology-AllItems-Defender'sCode-40257" value: { - dps: 12900.43003 - tps: 11180.48019 + dps: 10720.55552 + tps: 10464.17138 } } dps_results: { key: "TestDemonology-AllItems-DestructiveSkyflareDiamond" value: { - dps: 13439.12732 - tps: 11676.50114 + dps: 11104.72076 + tps: 10846.47665 } } dps_results: { key: "TestDemonology-AllItems-DislodgedForeignObject-50353" value: { - dps: 13680.51811 - tps: 11918.02187 + dps: 11327.35486 + tps: 11069.91946 } } dps_results: { key: "TestDemonology-AllItems-EffulgentSkyflareDiamond" value: { - dps: 13418.79874 - tps: 11655.82175 + dps: 11073.18055 + tps: 10814.91661 } } dps_results: { key: "TestDemonology-AllItems-EmberSkyflareDiamond" value: { - dps: 13453.51023 - tps: 11686.79689 + dps: 11134.3961 + tps: 10875.5855 } } dps_results: { key: "TestDemonology-AllItems-EnigmaticSkyflareDiamond" value: { - dps: 13432.54537 - tps: 11669.91919 + dps: 11100.49894 + tps: 10842.25483 } } dps_results: { key: "TestDemonology-AllItems-EnigmaticStarflareDiamond" value: { - dps: 13424.03982 - tps: 11661.41364 + dps: 11092.43436 + tps: 10834.19025 } } dps_results: { key: "TestDemonology-AllItems-EphemeralSnowflake-50260" value: { - dps: 13053.22335 - tps: 11338.404 + dps: 10879.10858 + tps: 10625.58514 } } dps_results: { key: "TestDemonology-AllItems-EssenceofGossamer-37220" value: { - dps: 12906.6269 - tps: 11185.18743 + dps: 10742.56294 + tps: 10485.89317 } } dps_results: { key: "TestDemonology-AllItems-EternalEarthsiegeDiamond" value: { - dps: 13398.47567 - tps: 11635.84948 + dps: 11067.81225 + tps: 10809.56813 } } dps_results: { key: "TestDemonology-AllItems-ExtractofNecromanticPower-40373" value: { - dps: 13122.05364 - tps: 11402.52929 + dps: 10953.30393 + tps: 10696.91978 } } dps_results: { key: "TestDemonology-AllItems-EyeoftheBroodmother-45308" value: { - dps: 13283.42777 - tps: 11540.1986 + dps: 11069.28 + tps: 10808.5171 } } dps_results: { key: "TestDemonology-AllItems-Figurine-SapphireOwl-42413" value: { - dps: 12918.53373 - tps: 11201.64113 + dps: 10754.22395 + tps: 10497.0465 } } dps_results: { key: "TestDemonology-AllItems-ForethoughtTalisman-40258" value: { - dps: 13107.02913 - tps: 11366.94101 + dps: 10918.00416 + tps: 10657.22787 } } dps_results: { key: "TestDemonology-AllItems-ForgeEmber-37660" value: { - dps: 13248.07367 - tps: 11508.02234 + dps: 10966.72513 + tps: 10707.20814 } } dps_results: { key: "TestDemonology-AllItems-ForlornSkyflareDiamond" value: { - dps: 13449.10871 - tps: 11680.5325 + dps: 11119.66976 + tps: 10860.98248 } } dps_results: { key: "TestDemonology-AllItems-ForlornStarflareDiamond" value: { - dps: 13453.88096 - tps: 11686.13342 + dps: 11105.65831 + tps: 10847.10119 } } dps_results: { key: "TestDemonology-AllItems-FuryoftheFiveFlights-40431" value: { - dps: 12900.43003 - tps: 11180.48019 + dps: 10720.55552 + tps: 10464.17138 } } dps_results: { key: "TestDemonology-AllItems-FuturesightRune-38763" value: { - dps: 13095.96384 - tps: 11358.30044 + dps: 10877.79011 + tps: 10618.64538 } } dps_results: { key: "TestDemonology-AllItems-Gladiator'sFelshroud" value: { - dps: 10560.32217 - tps: 8973.36025 + dps: 8575.50793 + tps: 8343.43479 } } dps_results: { key: "TestDemonology-AllItems-GlowingTwilightScale-54573" value: { - dps: 13266.94683 - tps: 11513.37249 + dps: 11034.67418 + tps: 10771.5057 } } dps_results: { key: "TestDemonology-AllItems-GlowingTwilightScale-54589" value: { - dps: 13309.51349 - tps: 11550.47562 + dps: 11080.46799 + tps: 10816.04753 } } dps_results: { key: "TestDemonology-AllItems-GnomishLightningGenerator-41121" value: { - dps: 13062.08411 - tps: 11343.78646 + dps: 10896.47429 + tps: 10640.15174 } } dps_results: { key: "TestDemonology-AllItems-Gul'dan'sRegalia" value: { - dps: 11045.2536 - tps: 9314.45004 + dps: 8893.35742 + tps: 8648.53034 } } dps_results: { key: "TestDemonology-AllItems-IllustrationoftheDragonSoul-40432" value: { - dps: 13271.82086 - tps: 11517.03807 + dps: 11019.97936 + tps: 10757.4527 } } dps_results: { key: "TestDemonology-AllItems-ImpassiveSkyflareDiamond" value: { - dps: 13432.54537 - tps: 11669.91919 + dps: 11100.49894 + tps: 10842.25483 } } dps_results: { key: "TestDemonology-AllItems-ImpassiveStarflareDiamond" value: { - dps: 13424.03982 - tps: 11661.41364 + dps: 11092.43436 + tps: 10834.19025 } } dps_results: { key: "TestDemonology-AllItems-IncisorFragment-37723" value: { - dps: 12900.43003 - tps: 11180.48019 + dps: 10720.55552 + tps: 10464.17138 } } dps_results: { key: "TestDemonology-AllItems-InsightfulEarthsiegeDiamond" value: { - dps: 13427.78541 - tps: 11661.40926 + dps: 11111.06498 + tps: 10852.30362 } } dps_results: { key: "TestDemonology-AllItems-InvigoratingEarthsiegeDiamond" value: { - dps: 13398.47567 - tps: 11635.84948 + dps: 11067.81225 + tps: 10809.56813 } } dps_results: { key: "TestDemonology-AllItems-Lavanthor'sTalisman-37872" value: { - dps: 12900.43003 - tps: 11180.48019 + dps: 10720.55552 + tps: 10464.17138 } } dps_results: { key: "TestDemonology-AllItems-MajesticDragonFigurine-40430" value: { - dps: 13093.97928 - tps: 11353.32214 + dps: 10912.86436 + tps: 10652.26582 } } dps_results: { key: "TestDemonology-AllItems-MaleficRaiment" value: { - dps: 8418.28288 - tps: 7041.57676 + dps: 6854.13966 + tps: 6659.45182 } } dps_results: { key: "TestDemonology-AllItems-MeteoriteWhetstone-37390" value: { - dps: 13020.35249 - tps: 11300.40265 + dps: 10825.62748 + tps: 10569.24333 } } dps_results: { key: "TestDemonology-AllItems-NevermeltingIceCrystal-50259" value: { - dps: 13171.60746 - tps: 11431.51935 + dps: 10983.322 + tps: 10722.54571 } } dps_results: { key: "TestDemonology-AllItems-OfferingofSacrifice-37638" value: { - dps: 12900.43003 - tps: 11180.48019 + dps: 10720.55552 + tps: 10464.17138 } } dps_results: { key: "TestDemonology-AllItems-PersistentEarthshatterDiamond" value: { - dps: 13398.47567 - tps: 11635.84948 + dps: 11067.81225 + tps: 10809.56813 } } dps_results: { key: "TestDemonology-AllItems-PersistentEarthsiegeDiamond" value: { - dps: 13398.47567 - tps: 11635.84948 + dps: 11067.81225 + tps: 10809.56813 } } dps_results: { key: "TestDemonology-AllItems-PetrifiedScarab-21685" value: { - dps: 12900.43003 - tps: 11180.48019 + dps: 10720.55552 + tps: 10464.17138 } } dps_results: { key: "TestDemonology-AllItems-PetrifiedTwilightScale-54571" value: { - dps: 12900.43003 - tps: 11180.48019 + dps: 10720.55552 + tps: 10464.17138 } } dps_results: { key: "TestDemonology-AllItems-PetrifiedTwilightScale-54591" value: { - dps: 12900.43003 - tps: 11180.48019 + dps: 10720.55552 + tps: 10464.17138 } } dps_results: { key: "TestDemonology-AllItems-PlagueheartGarb" value: { - dps: 10266.66359 - tps: 8716.63581 + dps: 8326.41706 + tps: 8103.48409 } } dps_results: { key: "TestDemonology-AllItems-PowerfulEarthshatterDiamond" value: { - dps: 13417.36058 - tps: 11654.52072 + dps: 11071.97708 + tps: 10813.72807 } } dps_results: { key: "TestDemonology-AllItems-PowerfulEarthsiegeDiamond" value: { - dps: 13418.79874 - tps: 11655.82175 + dps: 11073.18055 + tps: 10814.91661 } } dps_results: { key: "TestDemonology-AllItems-PurifiedShardoftheGods" value: { - dps: 12900.43003 - tps: 11180.48019 + dps: 10720.55552 + tps: 10464.17138 } } dps_results: { key: "TestDemonology-AllItems-ReignoftheDead-47316" value: { - dps: 13407.68508 - tps: 11661.54729 + dps: 11182.591 + tps: 10920.47378 } } dps_results: { key: "TestDemonology-AllItems-ReignoftheDead-47477" value: { - dps: 13469.23514 - tps: 11720.19531 + dps: 11238.80768 + tps: 10976.33941 } } dps_results: { key: "TestDemonology-AllItems-RelentlessEarthsiegeDiamond" value: { - dps: 13728.9583 - tps: 11966.33211 + dps: 11374.7138 + tps: 11116.46969 } } dps_results: { key: "TestDemonology-AllItems-RevitalizingSkyflareDiamond" value: { - dps: 13405.02361 - tps: 11639.40886 + dps: 11055.59429 + tps: 10797.48576 } } dps_results: { key: "TestDemonology-AllItems-RuneofRepulsion-40372" value: { - dps: 12900.43003 - tps: 11180.48019 + dps: 10720.55552 + tps: 10464.17138 } } dps_results: { key: "TestDemonology-AllItems-SealofthePantheon-36993" value: { - dps: 12900.43003 - tps: 11180.48019 + dps: 10720.55552 + tps: 10464.17138 } } dps_results: { key: "TestDemonology-AllItems-ShinyShardoftheGods" value: { - dps: 12900.43003 - tps: 11180.48019 + dps: 10720.55552 + tps: 10464.17138 } } dps_results: { key: "TestDemonology-AllItems-Sindragosa'sFlawlessFang-50361" value: { - dps: 12950.06 - tps: 11226.25054 + dps: 10770.41707 + tps: 10513.38995 } } dps_results: { key: "TestDemonology-AllItems-SliverofPureIce-50339" value: { - dps: 13220.81763 - tps: 11472.0353 + dps: 11018.87465 + tps: 10759.96064 } } dps_results: { key: "TestDemonology-AllItems-SliverofPureIce-50346" value: { - dps: 13239.16958 - tps: 11485.33592 + dps: 11045.70793 + tps: 10785.47065 } } dps_results: { key: "TestDemonology-AllItems-SoulPreserver-37111" value: { - dps: 13041.95765 - tps: 11308.77052 + dps: 10853.08201 + tps: 10594.90656 } } dps_results: { key: "TestDemonology-AllItems-SouloftheDead-40382" value: { - dps: 13069.23424 - tps: 11351.11117 + dps: 10904.13536 + tps: 10648.91037 } } dps_results: { key: "TestDemonology-AllItems-SparkofLife-37657" value: { - dps: 13064.67402 - tps: 11346.30818 + dps: 10875.52441 + tps: 10614.81598 } } dps_results: { key: "TestDemonology-AllItems-SphereofRedDragon'sBlood-37166" value: { - dps: 12920.45511 - tps: 11186.49878 + dps: 10727.3943 + tps: 10464.17138 } } dps_results: { key: "TestDemonology-AllItems-SwiftSkyflareDiamond" value: { - dps: 13398.47567 - tps: 11635.84948 + dps: 11067.81225 + tps: 10809.56813 } } dps_results: { key: "TestDemonology-AllItems-SwiftStarflareDiamond" value: { - dps: 13398.47567 - tps: 11635.84948 + dps: 11067.81225 + tps: 10809.56813 } } dps_results: { key: "TestDemonology-AllItems-SwiftWindfireDiamond" value: { - dps: 13398.47567 - tps: 11635.84948 + dps: 11067.81225 + tps: 10809.56813 } } dps_results: { key: "TestDemonology-AllItems-TalismanofTrollDivinity-37734" value: { - dps: 12984.04915 - tps: 11256.55694 + dps: 10798.36596 + tps: 10541.0729 } } dps_results: { key: "TestDemonology-AllItems-TearsoftheVanquished-47215" value: { - dps: 12936.43462 - tps: 11217.1032 + dps: 10776.36851 + tps: 10515.78096 } } dps_results: { key: "TestDemonology-AllItems-TheGeneral'sHeart-45507" value: { - dps: 12900.43003 - tps: 11180.48019 + dps: 10720.55552 + tps: 10464.17138 } } dps_results: { key: "TestDemonology-AllItems-ThunderingSkyflareDiamond" value: { - dps: 13398.47567 - tps: 11635.84948 + dps: 11067.81225 + tps: 10809.56813 } } dps_results: { key: "TestDemonology-AllItems-TinyAbominationinaJar-50351" value: { - dps: 12931.5795 - tps: 11189.2114 + dps: 10729.22572 + tps: 10464.17138 } } dps_results: { key: "TestDemonology-AllItems-TinyAbominationinaJar-50706" value: { - dps: 12931.5795 - tps: 11189.2114 + dps: 10729.22572 + tps: 10464.17138 } } dps_results: { key: "TestDemonology-AllItems-TirelessSkyflareDiamond" value: { - dps: 13449.10871 - tps: 11680.5325 + dps: 11119.66976 + tps: 10860.98248 } } dps_results: { key: "TestDemonology-AllItems-TirelessStarflareDiamond" value: { - dps: 13453.88096 - tps: 11686.13342 + dps: 11105.65831 + tps: 10847.10119 } } dps_results: { key: "TestDemonology-AllItems-TomeofArcanePhenomena-36972" value: { - dps: 13135.3056 - tps: 11407.64705 + dps: 10917.10386 + tps: 10661.13027 } } dps_results: { key: "TestDemonology-AllItems-TrenchantEarthshatterDiamond" value: { - dps: 13453.88096 - tps: 11686.13342 + dps: 11105.65831 + tps: 10847.10119 } } dps_results: { key: "TestDemonology-AllItems-TrenchantEarthsiegeDiamond" value: { - dps: 13449.10871 - tps: 11680.5325 + dps: 11119.66976 + tps: 10860.98248 } } dps_results: { key: "TestDemonology-AllItems-WingedTalisman-37844" value: { - dps: 13090.00588 - tps: 11354.54378 + dps: 10843.78785 + tps: 10585.1107 } } dps_results: { key: "TestDemonology-Average-Default" value: { - dps: 13946.57103 - tps: 12163.30576 + dps: 11508.98797 + tps: 11252.67784 } } dps_results: { key: "TestDemonology-Settings-Orc-p4_demo-Demonology Warlock-demo-FullBuffs-LongMultiTarget" value: { - dps: 17361.12567 - tps: 17435.98697 + dps: 14569.48158 + tps: 16422.33574 } } dps_results: { key: "TestDemonology-Settings-Orc-p4_demo-Demonology Warlock-demo-FullBuffs-LongSingleTarget" value: { - dps: 13766.09428 - tps: 12003.46809 + dps: 11410.3423 + tps: 11152.09819 } } dps_results: { @@ -756,15 +756,15 @@ dps_results: { dps_results: { key: "TestDemonology-Settings-Orc-p4_demo-Demonology Warlock-demo-NoBuffs-LongMultiTarget" value: { - dps: 10287.07914 - tps: 12106.19892 + dps: 6562.7132 + tps: 8970.11008 } } dps_results: { key: "TestDemonology-Settings-Orc-p4_demo-Demonology Warlock-demo-NoBuffs-LongSingleTarget" value: { - dps: 7943.25049 - tps: 7314.42382 + dps: 6266.27386 + tps: 6225.81786 } } dps_results: { @@ -777,7 +777,7 @@ dps_results: { dps_results: { key: "TestDemonology-SwitchInFrontOfTarget-Default" value: { - dps: 13685.59167 - tps: 12068.09598 + dps: 11359.99577 + tps: 11138.46347 } } diff --git a/sim/warrior/berserker_rage.go b/sim/warrior/berserker_rage.go index 9ee4fea03f..471862409d 100644 --- a/sim/warrior/berserker_rage.go +++ b/sim/warrior/berserker_rage.go @@ -31,7 +31,3 @@ func (warrior *Warrior) registerBerserkerRageSpell() { }, }) } - -func (warrior *Warrior) ShouldBerserkerRage(sim *core.Simulation) bool { - return warrior.Talents.ImprovedBerserkerRage > 0 && warrior.CurrentRage() < 80 && warrior.BerserkerRage.IsReady(sim) -} diff --git a/sim/warrior/bloodthirst.go b/sim/warrior/bloodthirst.go index 6a88e10a46..19f50b5f25 100644 --- a/sim/warrior/bloodthirst.go +++ b/sim/warrior/bloodthirst.go @@ -46,11 +46,7 @@ func (warrior *Warrior) registerBloodthirstSpell(cdTimer *core.Timer) { core.StartDelayedAction(sim, core.DelayedActionOptions{ DoAt: sim.CurrentTime + warrior.Bloodthirst.CD.Duration, OnAction: func(_ *core.Simulation) { - if warrior.IsUsingAPL { - warrior.Rotation.DoNextAction(sim) - } else if warrior.Bloodthirst.CanCast(sim, target) { - warrior.Bloodthirst.Cast(sim, target) - } + warrior.Rotation.DoNextAction(sim) }, }) }, diff --git a/sim/warrior/demoralizing_shout.go b/sim/warrior/demoralizing_shout.go index 5645ab9eea..e6afa7f1ae 100644 --- a/sim/warrior/demoralizing_shout.go +++ b/sim/warrior/demoralizing_shout.go @@ -1,8 +1,6 @@ package warrior import ( - "time" - "github.com/wowsims/wotlk/sim/core" ) @@ -42,16 +40,3 @@ func (warrior *Warrior) registerDemoralizingShoutSpell() { RelatedAuras: []core.AuraArray{warrior.DemoralizingShoutAuras}, }) } - -func (warrior *Warrior) ShouldDemoralizingShout(sim *core.Simulation, target *core.Unit, filler bool, maintainOnly bool) bool { - if !warrior.DemoralizingShout.CanCast(sim, target) { - return false - } - - if filler { - return true - } - - return maintainOnly && - warrior.DemoralizingShoutAuras.Get(target).ShouldRefreshExclusiveEffects(sim, time.Second*2) -} diff --git a/sim/warrior/dps/TestArms.results b/sim/warrior/dps/TestArms.results index 8790407454..8c4f33cd79 100644 --- a/sim/warrior/dps/TestArms.results +++ b/sim/warrior/dps/TestArms.results @@ -46,935 +46,935 @@ character_stats_results: { dps_results: { key: "TestArms-AllItems-Althor'sAbacus-50359" value: { - dps: 6396.86675 - tps: 5166.94332 + dps: 6262.82724 + tps: 5037.96938 } } dps_results: { key: "TestArms-AllItems-Althor'sAbacus-50366" value: { - dps: 6396.86675 - tps: 5166.94332 + dps: 6262.82724 + tps: 5037.96938 } } dps_results: { key: "TestArms-AllItems-AustereEarthsiegeDiamond" value: { - dps: 6578.76707 - tps: 5317.04783 + dps: 6482.41744 + tps: 5220.02072 } } dps_results: { key: "TestArms-AllItems-Bandit'sInsignia-40371" value: { - dps: 6602.04105 - tps: 5330.43346 + dps: 6431.93917 + tps: 5172.33986 } } dps_results: { key: "TestArms-AllItems-BaubleofTrueBlood-50354" value: { - dps: 6413.27476 - tps: 5182.03283 + dps: 6264.67869 + tps: 5039.7388 hps: 89.11518 } } dps_results: { key: "TestArms-AllItems-BaubleofTrueBlood-50726" value: { - dps: 6413.27476 - tps: 5182.03283 + dps: 6264.67869 + tps: 5039.7388 hps: 89.11518 } } dps_results: { key: "TestArms-AllItems-BeamingEarthsiegeDiamond" value: { - dps: 6610.9396 - tps: 5341.97634 + dps: 6495.57286 + tps: 5230.5847 } } dps_results: { key: "TestArms-AllItems-Beast-tamer'sShoulders-30892" value: { - dps: 6412.14717 - tps: 5185.57512 + dps: 6301.65452 + tps: 5073.33708 } } dps_results: { key: "TestArms-AllItems-BlackBruise-50035" value: { - dps: 4866.62556 - tps: 3976.19228 + dps: 4742.24633 + tps: 3856.45854 } } dps_results: { key: "TestArms-AllItems-BlackBruise-50692" value: { - dps: 5008.30845 - tps: 4090.90401 + dps: 4893.49698 + tps: 3974.34796 } } dps_results: { key: "TestArms-AllItems-BlessedBattlegearofUndeadSlaying" value: { - dps: 5388.84594 - tps: 4344.16473 + dps: 5271.93662 + tps: 4227.7173 } } dps_results: { key: "TestArms-AllItems-BlessedGarboftheUndeadSlayer" value: { - dps: 5315.57686 - tps: 4281.49162 + dps: 5222.59026 + tps: 4193.75014 } } dps_results: { key: "TestArms-AllItems-BlessedRegaliaofUndeadCleansing" value: { - dps: 5097.37072 - tps: 4108.59101 + dps: 5026.17849 + tps: 4038.78586 } } dps_results: { key: "TestArms-AllItems-BracingEarthsiegeDiamond" value: { - dps: 6588.02377 - tps: 5218.54295 + dps: 6478.84863 + tps: 5112.88003 } } dps_results: { key: "TestArms-AllItems-Bryntroll,theBoneArbiter-50415" value: { - dps: 8625.42745 - tps: 7032.99268 + dps: 8016.6666 + tps: 6494.27378 } } dps_results: { key: "TestArms-AllItems-Bryntroll,theBoneArbiter-50709" value: { - dps: 8730.89242 - tps: 7119.83335 + dps: 8109.90868 + tps: 6570.52233 } } dps_results: { key: "TestArms-AllItems-ChaoticSkyflareDiamond" value: { - dps: 6756.72828 - tps: 5463.2377 + dps: 6616.85785 + tps: 5325.93338 } } dps_results: { key: "TestArms-AllItems-CorpseTongueCoin-50349" value: { - dps: 6396.86675 - tps: 5166.94332 + dps: 6262.82724 + tps: 5037.96938 } } dps_results: { key: "TestArms-AllItems-CorpseTongueCoin-50352" value: { - dps: 6396.86675 - tps: 5166.94332 + dps: 6262.82724 + tps: 5037.96938 } } dps_results: { key: "TestArms-AllItems-CorrodedSkeletonKey-50356" value: { - dps: 6396.86675 - tps: 5166.94332 + dps: 6262.82724 + tps: 5037.96938 hps: 64 } } dps_results: { key: "TestArms-AllItems-DarkmoonCard:Berserker!-42989" value: { - dps: 6538.00848 - tps: 5284.59243 + dps: 6374.41061 + tps: 5130.23029 } } dps_results: { key: "TestArms-AllItems-DarkmoonCard:Death-42990" value: { - dps: 6564.50621 - tps: 5304.87423 + dps: 6412.14822 + tps: 5159.52149 } } dps_results: { key: "TestArms-AllItems-DarkmoonCard:Greatness-44255" value: { - dps: 6396.86675 - tps: 5166.94332 + dps: 6262.82724 + tps: 5037.96938 } } dps_results: { key: "TestArms-AllItems-Death'sChoice-47464" value: { - dps: 6918.19694 - tps: 5580.28194 + dps: 6726.16041 + tps: 5407.81841 } } dps_results: { key: "TestArms-AllItems-DeathKnight'sAnguish-38212" value: { - dps: 6469.83394 - tps: 5227.78913 + dps: 6335.28796 + tps: 5097.65887 } } dps_results: { key: "TestArms-AllItems-Deathbringer'sWill-50362" value: { - dps: 6843.76924 - tps: 5525.74706 + dps: 6665.69456 + tps: 5361.54303 } } dps_results: { key: "TestArms-AllItems-Deathbringer'sWill-50363" value: { - dps: 6960.67426 - tps: 5623.80389 + dps: 6724.67718 + tps: 5407.8647 } } dps_results: { key: "TestArms-AllItems-Defender'sCode-40257" value: { - dps: 6422.85912 - tps: 5185.94926 + dps: 6274.81353 + tps: 5047.61817 } } dps_results: { key: "TestArms-AllItems-DestructiveSkyflareDiamond" value: { - dps: 6620.04877 - tps: 5349.00093 + dps: 6501.0713 + tps: 5235.03075 } } dps_results: { key: "TestArms-AllItems-DislodgedForeignObject-50348" value: { - dps: 6541.00488 - tps: 5284.47045 + dps: 6350.28984 + tps: 5105.87855 } } dps_results: { key: "TestArms-AllItems-DislodgedForeignObject-50353" value: { - dps: 6536.58567 - tps: 5284.43361 + dps: 6346.59736 + tps: 5105.06065 } } dps_results: { key: "TestArms-AllItems-DreadnaughtBattlegear" value: { - dps: 6000.16096 - tps: 4864.19104 + dps: 5920.25992 + tps: 4781.31769 } } dps_results: { key: "TestArms-AllItems-DreadnaughtPlate" value: { - dps: 5270.20256 - tps: 4251.79768 + dps: 5211.25695 + tps: 4187.74189 } } dps_results: { key: "TestArms-AllItems-EffulgentSkyflareDiamond" value: { - dps: 6588.02377 - tps: 5324.94752 + dps: 6478.84863 + tps: 5217.20055 } } dps_results: { key: "TestArms-AllItems-EmberSkyflareDiamond" value: { - dps: 6588.02377 - tps: 5324.94752 + dps: 6478.84863 + tps: 5217.20055 } } dps_results: { key: "TestArms-AllItems-EnigmaticSkyflareDiamond" value: { - dps: 6610.9396 - tps: 5341.97634 + dps: 6495.57286 + tps: 5230.5847 } } dps_results: { key: "TestArms-AllItems-EnigmaticStarflareDiamond" value: { - dps: 6604.9531 - tps: 5337.21903 + dps: 6493.76947 + tps: 5229.12812 } } dps_results: { key: "TestArms-AllItems-EphemeralSnowflake-50260" value: { - dps: 6462.73667 - tps: 5216.73975 + dps: 6306.94826 + tps: 5070.34131 } } dps_results: { key: "TestArms-AllItems-EssenceofGossamer-37220" value: { - dps: 6396.86675 - tps: 5166.94332 + dps: 6262.82724 + tps: 5037.96938 } } dps_results: { key: "TestArms-AllItems-EternalEarthsiegeDiamond" value: { - dps: 6588.02377 - tps: 5324.94752 + dps: 6478.84863 + tps: 5217.20055 } } dps_results: { key: "TestArms-AllItems-ExtractofNecromanticPower-40373" value: { - dps: 6573.00582 - tps: 5312.30228 + dps: 6415.35315 + tps: 5162.44931 } } dps_results: { key: "TestArms-AllItems-EyeoftheBroodmother-45308" value: { - dps: 6518.02929 - tps: 5267.89084 + dps: 6364.14747 + tps: 5121.48477 } } dps_results: { key: "TestArms-AllItems-Figurine-SapphireOwl-42413" value: { - dps: 6396.86675 - tps: 5166.94332 + dps: 6262.82724 + tps: 5037.96938 } } dps_results: { key: "TestArms-AllItems-ForethoughtTalisman-40258" value: { - dps: 6396.86675 - tps: 5166.94332 + dps: 6262.82724 + tps: 5037.96938 } } dps_results: { key: "TestArms-AllItems-ForgeEmber-37660" value: { - dps: 6482.54489 - tps: 5238.39086 + dps: 6348.70584 + tps: 5108.3564 } } dps_results: { key: "TestArms-AllItems-ForlornSkyflareDiamond" value: { - dps: 6588.02377 - tps: 5324.94752 + dps: 6478.84863 + tps: 5217.20055 } } dps_results: { key: "TestArms-AllItems-ForlornStarflareDiamond" value: { - dps: 6588.02377 - tps: 5324.94752 + dps: 6478.84863 + tps: 5217.20055 } } dps_results: { key: "TestArms-AllItems-FuryoftheFiveFlights-40431" value: { - dps: 6638.27271 - tps: 5355.17518 + dps: 6464.14941 + tps: 5197.35269 } } dps_results: { key: "TestArms-AllItems-FuturesightRune-38763" value: { - dps: 6396.86675 - tps: 5166.94332 + dps: 6262.82724 + tps: 5037.96938 } } dps_results: { key: "TestArms-AllItems-Gladiator'sBattlegear" value: { - dps: 6391.56308 - tps: 5139.96721 + dps: 6213.38971 + tps: 4971.99584 } } dps_results: { key: "TestArms-AllItems-GlowingTwilightScale-54573" value: { - dps: 6396.86675 - tps: 5166.94332 + dps: 6262.82724 + tps: 5037.96938 } } dps_results: { key: "TestArms-AllItems-GlowingTwilightScale-54589" value: { - dps: 6396.86675 - tps: 5166.94332 + dps: 6262.82724 + tps: 5037.96938 } } dps_results: { key: "TestArms-AllItems-GnomishLightningGenerator-41121" value: { - dps: 6542.384 - tps: 5287.07103 + dps: 6390.97801 + tps: 5142.58532 } } dps_results: { key: "TestArms-AllItems-Heartpierce-49982" value: { - dps: 7994.21671 - tps: 6504.30258 + dps: 7444.30414 + tps: 6007.8764 } } dps_results: { key: "TestArms-AllItems-Heartpierce-50641" value: { - dps: 8082.17352 - tps: 6572.49427 + dps: 7475.93535 + tps: 6035.59142 } } dps_results: { key: "TestArms-AllItems-IllustrationoftheDragonSoul-40432" value: { - dps: 6396.86675 - tps: 5166.94332 + dps: 6262.82724 + tps: 5037.96938 } } dps_results: { key: "TestArms-AllItems-ImpassiveSkyflareDiamond" value: { - dps: 6610.9396 - tps: 5341.97634 + dps: 6495.57286 + tps: 5230.5847 } } dps_results: { key: "TestArms-AllItems-ImpassiveStarflareDiamond" value: { - dps: 6604.9531 - tps: 5337.21903 + dps: 6493.76947 + tps: 5229.12812 } } dps_results: { key: "TestArms-AllItems-IncisorFragment-37723" value: { - dps: 6619.05428 - tps: 5343.00426 + dps: 6455.69968 + tps: 5193.01856 } } dps_results: { key: "TestArms-AllItems-InsightfulEarthsiegeDiamond" value: { - dps: 6588.02377 - tps: 5324.94752 + dps: 6478.84863 + tps: 5217.20055 } } dps_results: { key: "TestArms-AllItems-InvigoratingEarthsiegeDiamond" value: { - dps: 6614.63311 - tps: 5350.04895 - hps: 12.91576 + dps: 6509.46429 + tps: 5241.50367 + hps: 13.00101 } } dps_results: { key: "TestArms-AllItems-LastWord-50179" value: { - dps: 8092.06147 - tps: 6585.99095 + dps: 7563.0174 + tps: 6106.2864 } } dps_results: { key: "TestArms-AllItems-LastWord-50708" value: { - dps: 8207.14873 - tps: 6678.32817 + dps: 7618.9608 + tps: 6151.49898 } } dps_results: { key: "TestArms-AllItems-Lavanthor'sTalisman-37872" value: { - dps: 6396.86675 - tps: 5166.94332 + dps: 6262.82724 + tps: 5037.96938 } } dps_results: { key: "TestArms-AllItems-MajesticDragonFigurine-40430" value: { - dps: 6396.86675 - tps: 5166.94332 + dps: 6262.82724 + tps: 5037.96938 } } dps_results: { key: "TestArms-AllItems-MeteoriteWhetstone-37390" value: { - dps: 6576.42366 - tps: 5311.90634 + dps: 6433.64558 + tps: 5170.07371 } } dps_results: { key: "TestArms-AllItems-NevermeltingIceCrystal-50259" value: { - dps: 6560.20246 - tps: 5306.49729 + dps: 6439.79417 + tps: 5187.48571 } } dps_results: { key: "TestArms-AllItems-OfferingofSacrifice-37638" value: { - dps: 6427.44377 - tps: 5190.8189 + dps: 6269.28658 + tps: 5043.25365 } } dps_results: { key: "TestArms-AllItems-OnslaughtArmor" value: { - dps: 4275.89386 - tps: 3454.96674 + dps: 4249.68079 + tps: 3420.45651 } } dps_results: { key: "TestArms-AllItems-OnslaughtBattlegear" value: { - dps: 4912.08281 - tps: 3968.95214 + dps: 4855.76003 + tps: 3906.0545 } } dps_results: { key: "TestArms-AllItems-PersistentEarthshatterDiamond" value: { - dps: 6605.13756 - tps: 5339.31511 + dps: 6502.12946 + tps: 5235.59711 } } dps_results: { key: "TestArms-AllItems-PersistentEarthsiegeDiamond" value: { - dps: 6615.60889 - tps: 5348.2666 + dps: 6507.6073 + tps: 5239.92558 } } dps_results: { key: "TestArms-AllItems-PetrifiedScarab-21685" value: { - dps: 6396.86675 - tps: 5166.94332 + dps: 6262.82724 + tps: 5037.96938 } } dps_results: { key: "TestArms-AllItems-PetrifiedTwilightScale-54571" value: { - dps: 6450.7036 - tps: 5211.08658 + dps: 6301.19551 + tps: 5068.45148 } } dps_results: { key: "TestArms-AllItems-PetrifiedTwilightScale-54591" value: { - dps: 6452.11243 - tps: 5210.71614 + dps: 6306.61193 + tps: 5072.72871 } } dps_results: { key: "TestArms-AllItems-PowerfulEarthshatterDiamond" value: { - dps: 6588.02377 - tps: 5324.94752 + dps: 6478.84863 + tps: 5217.20055 } } dps_results: { key: "TestArms-AllItems-PowerfulEarthsiegeDiamond" value: { - dps: 6588.02377 - tps: 5324.94752 + dps: 6478.84863 + tps: 5217.20055 } } dps_results: { key: "TestArms-AllItems-PurifiedShardoftheGods" value: { - dps: 6396.86675 - tps: 5166.94332 + dps: 6262.82724 + tps: 5037.96938 } } dps_results: { key: "TestArms-AllItems-ReignoftheDead-47316" value: { - dps: 6396.86675 - tps: 5166.94332 + dps: 6262.82724 + tps: 5037.96938 } } dps_results: { key: "TestArms-AllItems-ReignoftheDead-47477" value: { - dps: 6396.86675 - tps: 5166.94332 + dps: 6262.82724 + tps: 5037.96938 } } dps_results: { key: "TestArms-AllItems-RelentlessEarthsiegeDiamond" value: { - dps: 6750.31463 - tps: 5459.33646 + dps: 6615.86001 + tps: 5325.11157 } } dps_results: { key: "TestArms-AllItems-RevitalizingSkyflareDiamond" value: { - dps: 6588.02377 - tps: 5324.94752 + dps: 6478.84863 + tps: 5217.20055 } } dps_results: { key: "TestArms-AllItems-RuneofRepulsion-40372" value: { - dps: 6396.86675 - tps: 5166.94332 + dps: 6262.82724 + tps: 5037.96938 } } dps_results: { key: "TestArms-AllItems-SealofthePantheon-36993" value: { - dps: 6428.76892 - tps: 5195.23185 + dps: 6277.61903 + tps: 5049.92266 } } dps_results: { key: "TestArms-AllItems-Shadowmourne-49623" value: { - dps: 9652.97606 - tps: 7861.34906 + dps: 9038.57363 + tps: 7317.90816 } } dps_results: { key: "TestArms-AllItems-ShinyShardoftheGods" value: { - dps: 6396.86675 - tps: 5166.94332 + dps: 6262.82724 + tps: 5037.96938 } } dps_results: { key: "TestArms-AllItems-SiegebreakerBattlegear" value: { - dps: 6186.50477 - tps: 5003.29305 + dps: 6056.90359 + tps: 4885.56365 } } dps_results: { key: "TestArms-AllItems-SiegebreakerPlate" value: { - dps: 5424.27098 - tps: 4379.25955 + dps: 5354.47251 + tps: 4302.15286 } } dps_results: { key: "TestArms-AllItems-Sindragosa'sFlawlessFang-50361" value: { - dps: 6396.86675 - tps: 5166.94332 + dps: 6262.82724 + tps: 5037.96938 } } dps_results: { key: "TestArms-AllItems-SliverofPureIce-50339" value: { - dps: 6396.86675 - tps: 5166.94332 + dps: 6262.82724 + tps: 5037.96938 } } dps_results: { key: "TestArms-AllItems-SliverofPureIce-50346" value: { - dps: 6396.86675 - tps: 5166.94332 + dps: 6262.82724 + tps: 5037.96938 } } dps_results: { key: "TestArms-AllItems-SoulPreserver-37111" value: { - dps: 6396.86675 - tps: 5166.94332 + dps: 6262.82724 + tps: 5037.96938 } } dps_results: { key: "TestArms-AllItems-SouloftheDead-40382" value: { - dps: 6524.84379 - tps: 5273.77265 + dps: 6366.26913 + tps: 5123.1821 } } dps_results: { key: "TestArms-AllItems-SparkofLife-37657" value: { - dps: 6461.52646 - tps: 5219.97511 + dps: 6317.02843 + tps: 5079.75626 } } dps_results: { key: "TestArms-AllItems-SphereofRedDragon'sBlood-37166" value: { - dps: 6581.50708 - tps: 5315.95236 + dps: 6453.84761 + tps: 5186.09003 } } dps_results: { key: "TestArms-AllItems-StormshroudArmor" value: { - dps: 5028.40827 - tps: 4051.7972 + dps: 5018.15938 + tps: 4030.1328 } } dps_results: { key: "TestArms-AllItems-SwiftSkyflareDiamond" value: { - dps: 6615.60889 - tps: 5348.2666 + dps: 6507.6073 + tps: 5239.92558 } } dps_results: { key: "TestArms-AllItems-SwiftStarflareDiamond" value: { - dps: 6605.13756 - tps: 5339.31511 + dps: 6502.12946 + tps: 5235.59711 } } dps_results: { key: "TestArms-AllItems-SwiftWindfireDiamond" value: { - dps: 6591.23359 - tps: 5327.78051 + dps: 6492.54324 + tps: 5228.02215 } } dps_results: { key: "TestArms-AllItems-TalismanofTrollDivinity-37734" value: { - dps: 6396.86675 - tps: 5166.94332 + dps: 6262.82724 + tps: 5037.96938 } } dps_results: { key: "TestArms-AllItems-TearsoftheVanquished-47215" value: { - dps: 6396.86675 - tps: 5166.94332 + dps: 6262.82724 + tps: 5037.96938 } } dps_results: { key: "TestArms-AllItems-TheFistsofFury" value: { - dps: 4805.32956 - tps: 3995.02084 + dps: 4568.08818 + tps: 3767.77424 } } dps_results: { key: "TestArms-AllItems-TheGeneral'sHeart-45507" value: { - dps: 6396.86675 - tps: 5166.94332 + dps: 6262.82724 + tps: 5037.96938 } } dps_results: { key: "TestArms-AllItems-TheTwinBladesofAzzinoth" value: { - dps: 5146.53578 - tps: 4258.94583 + dps: 4862.05922 + tps: 3989.98278 } } dps_results: { key: "TestArms-AllItems-ThunderingSkyflareDiamond" value: { - dps: 6594.14082 - tps: 5330.03796 + dps: 6508.13877 + tps: 5243.09018 } } dps_results: { key: "TestArms-AllItems-TinyAbominationinaJar-50351" value: { - dps: 6726.39326 - tps: 5433.60078 + dps: 6584.29713 + tps: 5296.3194 } } dps_results: { key: "TestArms-AllItems-TinyAbominationinaJar-50706" value: { - dps: 6806.24088 - tps: 5498.45942 + dps: 6630.29753 + tps: 5335.32952 } } dps_results: { key: "TestArms-AllItems-TirelessSkyflareDiamond" value: { - dps: 6588.02377 - tps: 5324.94752 + dps: 6478.84863 + tps: 5217.20055 } } dps_results: { key: "TestArms-AllItems-TirelessStarflareDiamond" value: { - dps: 6588.02377 - tps: 5324.94752 + dps: 6478.84863 + tps: 5217.20055 } } dps_results: { key: "TestArms-AllItems-TomeofArcanePhenomena-36972" value: { - dps: 6423.42924 - tps: 5189.68115 + dps: 6324.60419 + tps: 5086.9172 } } dps_results: { key: "TestArms-AllItems-TrenchantEarthshatterDiamond" value: { - dps: 6588.02377 - tps: 5324.94752 + dps: 6478.84863 + tps: 5217.20055 } } dps_results: { key: "TestArms-AllItems-TrenchantEarthsiegeDiamond" value: { - dps: 6588.02377 - tps: 5324.94752 + dps: 6478.84863 + tps: 5217.20055 } } dps_results: { key: "TestArms-AllItems-UndeadSlayer'sBlessedArmor" value: { - dps: 5335.20061 - tps: 4299.41414 + dps: 5209.00537 + tps: 4182.56264 } } dps_results: { key: "TestArms-AllItems-Val'anyr,HammerofAncientKings-46017" value: { - dps: 3822.06397 - tps: 3168.78811 + dps: 3739.49527 + tps: 3074.84622 } } dps_results: { key: "TestArms-AllItems-WingedTalisman-37844" value: { - dps: 6396.86675 - tps: 5166.94332 + dps: 6262.82724 + tps: 5037.96938 } } dps_results: { key: "TestArms-AllItems-Wrynn'sBattlegear" value: { - dps: 6890.70917 - tps: 5566.1016 + dps: 6714.43279 + tps: 5406.58323 } } dps_results: { key: "TestArms-AllItems-Wrynn'sPlate" value: { - dps: 5640.39847 - tps: 4546.03583 + dps: 5548.49888 + tps: 4454.25 } } dps_results: { key: "TestArms-AllItems-YmirjarLord'sBattlegear" value: { - dps: 7494.64482 - tps: 6071.88535 + dps: 7349.16566 + tps: 5931.73881 } } dps_results: { key: "TestArms-AllItems-YmirjarLord'sPlate" value: { - dps: 5937.65653 - tps: 4794.79385 + dps: 5808.61237 + tps: 4674.27625 } } dps_results: { key: "TestArms-Average-Default" value: { - dps: 6832.06862 - tps: 5520.34473 + dps: 6659.68361 + tps: 5357.47752 } } dps_results: { key: "TestArms-Settings-Human-p1_arms-Basic-arms-FullBuffs-LongMultiTarget" value: { - dps: 11924.62575 - tps: 11028.5597 + dps: 11184.11318 + tps: 10321.38091 } } dps_results: { key: "TestArms-Settings-Human-p1_arms-Basic-arms-FullBuffs-LongSingleTarget" value: { - dps: 6744.86884 - tps: 5435.64421 + dps: 6552.42865 + tps: 5252.94836 } } dps_results: { key: "TestArms-Settings-Human-p1_arms-Basic-arms-FullBuffs-ShortSingleTarget" value: { - dps: 7303.9868 - tps: 5943.01221 + dps: 6969.43738 + tps: 5653.47586 } } dps_results: { key: "TestArms-Settings-Human-p1_arms-Basic-arms-NoBuffs-LongMultiTarget" value: { - dps: 6201.566 - tps: 5886.67849 + dps: 6170.00187 + tps: 5850.70513 } } dps_results: { key: "TestArms-Settings-Human-p1_arms-Basic-arms-NoBuffs-LongSingleTarget" value: { - dps: 3507.48553 - tps: 2829.64022 + dps: 3543.41931 + tps: 2859.62352 } } dps_results: { key: "TestArms-Settings-Human-p1_arms-Basic-arms-NoBuffs-ShortSingleTarget" value: { - dps: 3700.71515 - tps: 3012.98824 + dps: 3711.29059 + tps: 3024.56901 } } dps_results: { key: "TestArms-Settings-Orc-p1_arms-Basic-arms-FullBuffs-LongMultiTarget" value: { - dps: 11974.1173 - tps: 11074.57371 + dps: 11336.28583 + tps: 10480.36946 } } dps_results: { key: "TestArms-Settings-Orc-p1_arms-Basic-arms-FullBuffs-LongSingleTarget" value: { - dps: 6750.31463 - tps: 5459.33646 + dps: 6615.86001 + tps: 5325.11157 } } dps_results: { key: "TestArms-Settings-Orc-p1_arms-Basic-arms-FullBuffs-ShortSingleTarget" value: { - dps: 7373.00838 - tps: 6033.37017 + dps: 7108.58976 + tps: 5787.99086 } } dps_results: { key: "TestArms-Settings-Orc-p1_arms-Basic-arms-NoBuffs-LongMultiTarget" value: { - dps: 6352.90441 - tps: 6027.91913 + dps: 6335.42532 + tps: 6013.61723 } } dps_results: { key: "TestArms-Settings-Orc-p1_arms-Basic-arms-NoBuffs-LongSingleTarget" value: { - dps: 3536.91307 - tps: 2857.80735 + dps: 3576.94646 + tps: 2890.00901 } } dps_results: { key: "TestArms-Settings-Orc-p1_arms-Basic-arms-NoBuffs-ShortSingleTarget" value: { - dps: 3767.68859 - tps: 3083.31246 + dps: 3779.35597 + tps: 3094.87687 } } dps_results: { key: "TestArms-SwitchInFrontOfTarget-Default" value: { - dps: 6322.40706 - tps: 5086.99074 + dps: 6140.51847 + tps: 4918.78951 } } diff --git a/sim/warrior/dps/TestFury.results b/sim/warrior/dps/TestFury.results index 2450f6b563..1288ac4796 100644 --- a/sim/warrior/dps/TestFury.results +++ b/sim/warrior/dps/TestFury.results @@ -46,935 +46,935 @@ character_stats_results: { dps_results: { key: "TestFury-AllItems-Althor'sAbacus-50359" value: { - dps: 6559.28013 - tps: 4874.20474 + dps: 6068.64055 + tps: 4458.98045 } } dps_results: { key: "TestFury-AllItems-Althor'sAbacus-50366" value: { - dps: 6559.28013 - tps: 4874.20474 + dps: 6068.64055 + tps: 4458.98045 } } dps_results: { key: "TestFury-AllItems-AustereEarthsiegeDiamond" value: { - dps: 6864.87671 - tps: 5103.38904 + dps: 6285.39617 + tps: 4617.84989 } } dps_results: { key: "TestFury-AllItems-Bandit'sInsignia-40371" value: { - dps: 6776.94205 - tps: 5031.73545 + dps: 6242.67815 + tps: 4584.7029 } } dps_results: { key: "TestFury-AllItems-BaubleofTrueBlood-50354" value: { - dps: 6576.11035 - tps: 4886.41831 + dps: 6070.00097 + tps: 4459.82625 hps: 90.47701 } } dps_results: { key: "TestFury-AllItems-BaubleofTrueBlood-50726" value: { - dps: 6576.11035 - tps: 4886.41831 + dps: 6070.00097 + tps: 4459.82625 hps: 90.47701 } } dps_results: { key: "TestFury-AllItems-BeamingEarthsiegeDiamond" value: { - dps: 6868.88557 - tps: 5105.07983 + dps: 6308.37895 + tps: 4634.43174 } } dps_results: { key: "TestFury-AllItems-Beast-tamer'sShoulders-30892" value: { - dps: 6643.31619 - tps: 4936.52029 + dps: 6105.97004 + tps: 4489.27971 } } dps_results: { key: "TestFury-AllItems-BlackBruise-50035" value: { - dps: 5912.90398 - tps: 4415.24024 + dps: 5437.88412 + tps: 3997.69695 } } dps_results: { key: "TestFury-AllItems-BlackBruise-50692" value: { - dps: 5993.38342 - tps: 4473.93155 + dps: 5535.51042 + tps: 4067.26735 } } dps_results: { key: "TestFury-AllItems-BlessedBattlegearofUndeadSlaying" value: { - dps: 5402.16423 - tps: 4017.57594 + dps: 5046.84075 + tps: 3707.15469 } } dps_results: { key: "TestFury-AllItems-BlessedGarboftheUndeadSlayer" value: { - dps: 5344.32106 - tps: 3981.71498 + dps: 5022.57195 + tps: 3691.86742 } } dps_results: { key: "TestFury-AllItems-BlessedRegaliaofUndeadCleansing" value: { - dps: 5037.55692 - tps: 3754.11053 + dps: 4729.19706 + tps: 3476.65924 } } dps_results: { key: "TestFury-AllItems-BracingEarthsiegeDiamond" value: { - dps: 6885.18545 - tps: 5017.06984 + dps: 6282.08305 + tps: 4523.20391 } } dps_results: { key: "TestFury-AllItems-Bryntroll,theBoneArbiter-50415" value: { - dps: 6964.93261 - tps: 5177.34824 + dps: 6423.92566 + tps: 4719.63158 } } dps_results: { key: "TestFury-AllItems-Bryntroll,theBoneArbiter-50709" value: { - dps: 6964.93261 - tps: 5177.34824 + dps: 6423.92566 + tps: 4719.63158 } } dps_results: { key: "TestFury-AllItems-ChaoticSkyflareDiamond" value: { - dps: 6964.93261 - tps: 5177.34824 + dps: 6423.92566 + tps: 4719.63158 } } dps_results: { key: "TestFury-AllItems-CorpseTongueCoin-50349" value: { - dps: 6559.28013 - tps: 4874.20474 + dps: 6068.64055 + tps: 4458.98045 } } dps_results: { key: "TestFury-AllItems-CorpseTongueCoin-50352" value: { - dps: 6559.28013 - tps: 4874.20474 + dps: 6068.64055 + tps: 4458.98045 } } dps_results: { key: "TestFury-AllItems-CorrodedSkeletonKey-50356" value: { - dps: 6559.28013 - tps: 4874.20474 + dps: 6068.64055 + tps: 4458.98045 hps: 64 } } dps_results: { key: "TestFury-AllItems-DarkmoonCard:Berserker!-42989" value: { - dps: 6772.21685 - tps: 5026.11285 + dps: 6203.41318 + tps: 4555.80129 } } dps_results: { key: "TestFury-AllItems-DarkmoonCard:Death-42990" value: { - dps: 6766.62895 - tps: 5024.21231 + dps: 6236.15781 + tps: 4578.8361 } } dps_results: { key: "TestFury-AllItems-DarkmoonCard:Greatness-44255" value: { - dps: 6559.28013 - tps: 4874.20474 + dps: 6068.64055 + tps: 4458.98045 } } dps_results: { key: "TestFury-AllItems-Death'sChoice-47464" value: { - dps: 7160.83725 - tps: 5311.32515 + dps: 6602.64112 + tps: 4849.8309 } } dps_results: { key: "TestFury-AllItems-DeathKnight'sAnguish-38212" value: { - dps: 6735.37032 - tps: 4998.68447 + dps: 6195.32949 + tps: 4547.48663 } } dps_results: { key: "TestFury-AllItems-Deathbringer'sWill-50362" value: { - dps: 7181.01403 - tps: 5330.98337 + dps: 6493.06269 + tps: 4766.0526 } } dps_results: { key: "TestFury-AllItems-Deathbringer'sWill-50363" value: { - dps: 7248.12327 - tps: 5377.03041 + dps: 6551.19253 + tps: 4809.30975 } } dps_results: { key: "TestFury-AllItems-Defender'sCode-40257" value: { - dps: 6596.66988 - tps: 4898.49101 + dps: 6084.47406 + tps: 4470.52004 } } dps_results: { key: "TestFury-AllItems-DestructiveSkyflareDiamond" value: { - dps: 6874.8921 - tps: 5109.55671 + dps: 6302.17513 + tps: 4630.51897 } } dps_results: { key: "TestFury-AllItems-DislodgedForeignObject-50348" value: { - dps: 6768.86309 - tps: 5020.85517 + dps: 6224.77452 + tps: 4564.93063 } } dps_results: { key: "TestFury-AllItems-DislodgedForeignObject-50353" value: { - dps: 6729.96579 - tps: 4989.43781 + dps: 6185.24566 + tps: 4539.96506 } } dps_results: { key: "TestFury-AllItems-DreadnaughtBattlegear" value: { - dps: 6227.13442 - tps: 4636.21994 + dps: 5719.89221 + tps: 4210.60192 } } dps_results: { key: "TestFury-AllItems-DreadnaughtPlate" value: { - dps: 5328.10898 - tps: 3971.17866 + dps: 5029.00135 + tps: 3700.982 } } dps_results: { key: "TestFury-AllItems-EffulgentSkyflareDiamond" value: { - dps: 6885.18545 - tps: 5119.12412 + dps: 6282.08305 + tps: 4615.43576 } } dps_results: { key: "TestFury-AllItems-EmberSkyflareDiamond" value: { - dps: 6885.18545 - tps: 5119.12412 + dps: 6282.08305 + tps: 4615.43576 } } dps_results: { key: "TestFury-AllItems-EnigmaticSkyflareDiamond" value: { - dps: 6868.88557 - tps: 5105.07983 + dps: 6308.37895 + tps: 4634.43174 } } dps_results: { key: "TestFury-AllItems-EnigmaticStarflareDiamond" value: { - dps: 6874.11509 - tps: 5110.75442 + dps: 6308.8863 + tps: 4634.79924 } } dps_results: { key: "TestFury-AllItems-EphemeralSnowflake-50260" value: { - dps: 6687.25612 - tps: 4967.56472 + dps: 6198.69096 + tps: 4553.2291 } } dps_results: { key: "TestFury-AllItems-EssenceofGossamer-37220" value: { - dps: 6559.28013 - tps: 4874.20474 + dps: 6068.64055 + tps: 4458.98045 } } dps_results: { key: "TestFury-AllItems-EternalEarthsiegeDiamond" value: { - dps: 6885.18545 - tps: 5119.12412 + dps: 6282.08305 + tps: 4615.43576 } } dps_results: { key: "TestFury-AllItems-ExtractofNecromanticPower-40373" value: { - dps: 6760.84201 - tps: 5019.53926 + dps: 6235.09401 + tps: 4578.01366 } } dps_results: { key: "TestFury-AllItems-EyeoftheBroodmother-45308" value: { - dps: 6704.97271 - tps: 4980.45534 + dps: 6189.43599 + tps: 4545.7705 } } dps_results: { key: "TestFury-AllItems-Figurine-SapphireOwl-42413" value: { - dps: 6584.90525 - tps: 4893.12317 + dps: 6077.42867 + tps: 4464.82713 } } dps_results: { key: "TestFury-AllItems-ForethoughtTalisman-40258" value: { - dps: 6559.28013 - tps: 4874.20474 + dps: 6068.64055 + tps: 4458.98045 } } dps_results: { key: "TestFury-AllItems-ForgeEmber-37660" value: { - dps: 6687.15497 - tps: 4970.63554 + dps: 6167.90206 + tps: 4529.76924 } } dps_results: { key: "TestFury-AllItems-ForlornSkyflareDiamond" value: { - dps: 6885.18545 - tps: 5119.12412 + dps: 6282.08305 + tps: 4615.43576 } } dps_results: { key: "TestFury-AllItems-ForlornStarflareDiamond" value: { - dps: 6885.18545 - tps: 5119.12412 + dps: 6282.08305 + tps: 4615.43576 } } dps_results: { key: "TestFury-AllItems-FuryoftheFiveFlights-40431" value: { - dps: 6784.00223 - tps: 5039.12821 + dps: 6282.77567 + tps: 4614.70076 } } dps_results: { key: "TestFury-AllItems-FuturesightRune-38763" value: { - dps: 6559.28013 - tps: 4874.20474 + dps: 6068.64055 + tps: 4458.98045 } } dps_results: { key: "TestFury-AllItems-Gladiator'sBattlegear" value: { - dps: 6570.55313 - tps: 4873.70756 + dps: 6112.49241 + tps: 4488.96448 } } dps_results: { key: "TestFury-AllItems-GlowingTwilightScale-54573" value: { - dps: 6559.28013 - tps: 4874.20474 + dps: 6068.64055 + tps: 4458.98045 } } dps_results: { key: "TestFury-AllItems-GlowingTwilightScale-54589" value: { - dps: 6559.28013 - tps: 4874.20474 + dps: 6068.64055 + tps: 4458.98045 } } dps_results: { key: "TestFury-AllItems-GnomishLightningGenerator-41121" value: { - dps: 6732.63239 - tps: 5001.11317 + dps: 6214.57201 + tps: 4563.14193 } } dps_results: { key: "TestFury-AllItems-Heartpierce-49982" value: { - dps: 6964.93261 - tps: 5177.34824 + dps: 6423.92566 + tps: 4719.63158 } } dps_results: { key: "TestFury-AllItems-Heartpierce-50641" value: { - dps: 6964.93261 - tps: 5177.34824 + dps: 6423.92566 + tps: 4719.63158 } } dps_results: { key: "TestFury-AllItems-IllustrationoftheDragonSoul-40432" value: { - dps: 6559.28013 - tps: 4874.20474 + dps: 6068.64055 + tps: 4458.98045 } } dps_results: { key: "TestFury-AllItems-ImpassiveSkyflareDiamond" value: { - dps: 6868.88557 - tps: 5105.07983 + dps: 6308.37895 + tps: 4634.43174 } } dps_results: { key: "TestFury-AllItems-ImpassiveStarflareDiamond" value: { - dps: 6874.11509 - tps: 5110.75442 + dps: 6308.8863 + tps: 4634.79924 } } dps_results: { key: "TestFury-AllItems-IncisorFragment-37723" value: { - dps: 6823.56239 - tps: 5065.85738 + dps: 6266.13203 + tps: 4604.24723 } } dps_results: { key: "TestFury-AllItems-InsightfulEarthsiegeDiamond" value: { - dps: 6885.18545 - tps: 5119.12412 + dps: 6282.08305 + tps: 4615.43576 } } dps_results: { key: "TestFury-AllItems-InvigoratingEarthsiegeDiamond" value: { - dps: 6901.3274 - tps: 5130.02631 + dps: 6311.85119 + tps: 4637.13045 hps: 13.7626 } } dps_results: { key: "TestFury-AllItems-LastWord-50179" value: { - dps: 6964.93261 - tps: 5177.34824 + dps: 6423.92566 + tps: 4719.63158 } } dps_results: { key: "TestFury-AllItems-LastWord-50708" value: { - dps: 6964.93261 - tps: 5177.34824 + dps: 6423.92566 + tps: 4719.63158 } } dps_results: { key: "TestFury-AllItems-Lavanthor'sTalisman-37872" value: { - dps: 6559.28013 - tps: 4874.20474 + dps: 6068.64055 + tps: 4458.98045 } } dps_results: { key: "TestFury-AllItems-MajesticDragonFigurine-40430" value: { - dps: 6559.28013 - tps: 4874.20474 + dps: 6068.64055 + tps: 4458.98045 } } dps_results: { key: "TestFury-AllItems-MeteoriteWhetstone-37390" value: { - dps: 6806.36961 - tps: 5051.69152 + dps: 6251.76275 + tps: 4593.72518 } } dps_results: { key: "TestFury-AllItems-NevermeltingIceCrystal-50259" value: { - dps: 6792.6766 - tps: 5044.42421 + dps: 6161.9534 + tps: 4525.70484 } } dps_results: { key: "TestFury-AllItems-OfferingofSacrifice-37638" value: { - dps: 6589.2357 - tps: 4893.12034 + dps: 6078.88576 + tps: 4466.4473 } } dps_results: { key: "TestFury-AllItems-OnslaughtArmor" value: { - dps: 4116.35794 - tps: 3078.01119 + dps: 3940.83335 + tps: 2909.62123 } } dps_results: { key: "TestFury-AllItems-OnslaughtBattlegear" value: { - dps: 4936.60791 - tps: 3686.08324 + dps: 4706.60413 + tps: 3464.23862 } } dps_results: { key: "TestFury-AllItems-PersistentEarthshatterDiamond" value: { - dps: 6887.6853 - tps: 5120.31582 + dps: 6305.68102 + tps: 4632.63106 } } dps_results: { key: "TestFury-AllItems-PersistentEarthsiegeDiamond" value: { - dps: 6891.5717 - tps: 5123.87783 + dps: 6311.23348 + tps: 4636.67698 } } dps_results: { key: "TestFury-AllItems-PetrifiedScarab-21685" value: { - dps: 6559.28013 - tps: 4874.20474 + dps: 6068.64055 + tps: 4458.98045 } } dps_results: { key: "TestFury-AllItems-PetrifiedTwilightScale-54571" value: { - dps: 6650.5469 - tps: 4940.36559 + dps: 6111.91006 + tps: 4490.4593 } } dps_results: { key: "TestFury-AllItems-PetrifiedTwilightScale-54591" value: { - dps: 6653.49639 - tps: 4940.1973 + dps: 6117.38687 + tps: 4494.45067 } } dps_results: { key: "TestFury-AllItems-PowerfulEarthshatterDiamond" value: { - dps: 6885.18545 - tps: 5119.12412 + dps: 6282.08305 + tps: 4615.43576 } } dps_results: { key: "TestFury-AllItems-PowerfulEarthsiegeDiamond" value: { - dps: 6885.18545 - tps: 5119.12412 + dps: 6282.08305 + tps: 4615.43576 } } dps_results: { key: "TestFury-AllItems-PurifiedShardoftheGods" value: { - dps: 6559.28013 - tps: 4874.20474 + dps: 6068.64055 + tps: 4458.98045 } } dps_results: { key: "TestFury-AllItems-ReignoftheDead-47316" value: { - dps: 6559.28013 - tps: 4874.20474 + dps: 6068.64055 + tps: 4458.98045 } } dps_results: { key: "TestFury-AllItems-ReignoftheDead-47477" value: { - dps: 6559.28013 - tps: 4874.20474 + dps: 6068.64055 + tps: 4458.98045 } } dps_results: { key: "TestFury-AllItems-RelentlessEarthsiegeDiamond" value: { - dps: 6960.0882 - tps: 5172.83324 + dps: 6425.2442 + tps: 4720.58779 } } dps_results: { key: "TestFury-AllItems-RevitalizingSkyflareDiamond" value: { - dps: 6885.18545 - tps: 5119.12412 + dps: 6282.08305 + tps: 4615.43576 } } dps_results: { key: "TestFury-AllItems-RuneofRepulsion-40372" value: { - dps: 6559.28013 - tps: 4874.20474 + dps: 6068.64055 + tps: 4458.98045 } } dps_results: { key: "TestFury-AllItems-SealofthePantheon-36993" value: { - dps: 6575.61208 - tps: 4885.8321 + dps: 6085.67296 + tps: 4471.39282 } } dps_results: { key: "TestFury-AllItems-Shadowmourne-49623" value: { - dps: 6964.93261 - tps: 5177.34824 + dps: 6423.92566 + tps: 4719.63158 } } dps_results: { key: "TestFury-AllItems-ShinyShardoftheGods" value: { - dps: 6559.28013 - tps: 4874.20474 + dps: 6068.64055 + tps: 4458.98045 } } dps_results: { key: "TestFury-AllItems-SiegebreakerBattlegear" value: { - dps: 6538.17097 - tps: 4855.89342 + dps: 6011.43514 + tps: 4416.30194 } } dps_results: { key: "TestFury-AllItems-SiegebreakerPlate" value: { - dps: 5485.8763 - tps: 4084.22545 + dps: 5195.06886 + tps: 3822.59421 } } dps_results: { key: "TestFury-AllItems-Sindragosa'sFlawlessFang-50361" value: { - dps: 6559.28013 - tps: 4874.20474 + dps: 6068.64055 + tps: 4458.98045 } } dps_results: { key: "TestFury-AllItems-SliverofPureIce-50339" value: { - dps: 6559.28013 - tps: 4874.20474 + dps: 6068.64055 + tps: 4458.98045 } } dps_results: { key: "TestFury-AllItems-SliverofPureIce-50346" value: { - dps: 6559.28013 - tps: 4874.20474 + dps: 6068.64055 + tps: 4458.98045 } } dps_results: { key: "TestFury-AllItems-SoulPreserver-37111" value: { - dps: 6559.28013 - tps: 4874.20474 + dps: 6068.64055 + tps: 4458.98045 } } dps_results: { key: "TestFury-AllItems-SouloftheDead-40382" value: { - dps: 6717.34147 - tps: 4988.78197 + dps: 6191.58883 + tps: 4547.35385 } } dps_results: { key: "TestFury-AllItems-SparkofLife-37657" value: { - dps: 6638.30084 - tps: 4923.44284 + dps: 6127.85832 + tps: 4496.68067 } } dps_results: { key: "TestFury-AllItems-SphereofRedDragon'sBlood-37166" value: { - dps: 6856.62273 - tps: 5088.22252 + dps: 6325.26769 + tps: 4648.06878 } } dps_results: { key: "TestFury-AllItems-StormshroudArmor" value: { - dps: 5041.64657 - tps: 3761.17074 + dps: 4734.56855 + tps: 3486.58656 } } dps_results: { key: "TestFury-AllItems-SwiftSkyflareDiamond" value: { - dps: 6891.5717 - tps: 5123.87783 + dps: 6311.23348 + tps: 4636.67698 } } dps_results: { key: "TestFury-AllItems-SwiftStarflareDiamond" value: { - dps: 6887.6853 - tps: 5120.31582 + dps: 6305.68102 + tps: 4632.63106 } } dps_results: { key: "TestFury-AllItems-SwiftWindfireDiamond" value: { - dps: 6871.46861 - tps: 5109.19871 + dps: 6295.96421 + tps: 4625.55079 } } dps_results: { key: "TestFury-AllItems-TalismanofTrollDivinity-37734" value: { - dps: 6559.28013 - tps: 4874.20474 + dps: 6068.64055 + tps: 4458.98045 } } dps_results: { key: "TestFury-AllItems-TearsoftheVanquished-47215" value: { - dps: 6559.28013 - tps: 4874.20474 + dps: 6068.64055 + tps: 4458.98045 } } dps_results: { key: "TestFury-AllItems-TheFistsofFury" value: { - dps: 4965.9252 - tps: 3701.06728 + dps: 4701.8964 + tps: 3441.99943 } } dps_results: { key: "TestFury-AllItems-TheGeneral'sHeart-45507" value: { - dps: 6559.28013 - tps: 4874.20474 + dps: 6068.64055 + tps: 4458.98045 } } dps_results: { key: "TestFury-AllItems-TheTwinBladesofAzzinoth" value: { - dps: 5099.68017 - tps: 3798.55202 + dps: 4945.02638 + tps: 3617.54645 } } dps_results: { key: "TestFury-AllItems-ThunderingSkyflareDiamond" value: { - dps: 6864.56544 - tps: 5101.01566 + dps: 6307.79817 + tps: 4632.78041 } } dps_results: { key: "TestFury-AllItems-TinyAbominationinaJar-50351" value: { - dps: 6971.6567 - tps: 5171.68032 + dps: 6419.39976 + tps: 4712.21557 } } dps_results: { key: "TestFury-AllItems-TinyAbominationinaJar-50706" value: { - dps: 6969.68545 - tps: 5166.48933 + dps: 6473.31079 + tps: 4750.92795 } } dps_results: { key: "TestFury-AllItems-TirelessSkyflareDiamond" value: { - dps: 6885.18545 - tps: 5119.12412 + dps: 6282.08305 + tps: 4615.43576 } } dps_results: { key: "TestFury-AllItems-TirelessStarflareDiamond" value: { - dps: 6885.18545 - tps: 5119.12412 + dps: 6282.08305 + tps: 4615.43576 } } dps_results: { key: "TestFury-AllItems-TomeofArcanePhenomena-36972" value: { - dps: 6683.01256 - tps: 4964.43213 + dps: 6202.53723 + tps: 4553.28874 } } dps_results: { key: "TestFury-AllItems-TrenchantEarthshatterDiamond" value: { - dps: 6885.18545 - tps: 5119.12412 + dps: 6282.08305 + tps: 4615.43576 } } dps_results: { key: "TestFury-AllItems-TrenchantEarthsiegeDiamond" value: { - dps: 6885.18545 - tps: 5119.12412 + dps: 6282.08305 + tps: 4615.43576 } } dps_results: { key: "TestFury-AllItems-UndeadSlayer'sBlessedArmor" value: { - dps: 5320.23269 - tps: 3960.22988 + dps: 5013.02305 + tps: 3682.17626 } } dps_results: { key: "TestFury-AllItems-Val'anyr,HammerofAncientKings-46017" value: { - dps: 5196.53795 - tps: 3921.70656 + dps: 4752.73581 + tps: 3499.1314 } } dps_results: { key: "TestFury-AllItems-WingedTalisman-37844" value: { - dps: 6559.28013 - tps: 4874.20474 + dps: 6068.64055 + tps: 4458.98045 } } dps_results: { key: "TestFury-AllItems-Wrynn'sBattlegear" value: { - dps: 7357.98622 - tps: 5453.94083 + dps: 6659.09505 + tps: 4890.56157 } } dps_results: { key: "TestFury-AllItems-Wrynn'sPlate" value: { - dps: 5786.67168 - tps: 4305.73513 + dps: 5451.43473 + tps: 4008.11611 } } dps_results: { key: "TestFury-AllItems-YmirjarLord'sBattlegear" value: { - dps: 8067.43407 - tps: 5973.43415 + dps: 7377.42047 + tps: 5413.47443 } } dps_results: { key: "TestFury-AllItems-YmirjarLord'sPlate" value: { - dps: 6174.83894 - tps: 4593.70936 + dps: 5755.86045 + tps: 4233.42579 } } dps_results: { key: "TestFury-Average-Default" value: { - dps: 7015.89861 - tps: 5207.27726 + dps: 6423.99337 + tps: 4721.09766 } } dps_results: { key: "TestFury-Settings-Human-p1_fury-Basic-fury-FullBuffs-LongMultiTarget" value: { - dps: 10294.60824 - tps: 8016.90735 + dps: 8643.58521 + tps: 6686.76935 } } dps_results: { key: "TestFury-Settings-Human-p1_fury-Basic-fury-FullBuffs-LongSingleTarget" value: { - dps: 6955.40821 - tps: 5169.2826 + dps: 6333.29509 + tps: 4652.58237 } } dps_results: { key: "TestFury-Settings-Human-p1_fury-Basic-fury-FullBuffs-ShortSingleTarget" value: { - dps: 8347.45997 - tps: 6188.65399 + dps: 7404.71574 + tps: 5425.96083 } } dps_results: { key: "TestFury-Settings-Human-p1_fury-Basic-fury-NoBuffs-LongMultiTarget" value: { - dps: 4394.68747 - tps: 3569.94332 + dps: 4307.27459 + tps: 3451.63161 } } dps_results: { key: "TestFury-Settings-Human-p1_fury-Basic-fury-NoBuffs-LongSingleTarget" value: { - dps: 2797.06729 - tps: 2107.61812 + dps: 2871.0366 + tps: 2139.06489 } } dps_results: { key: "TestFury-Settings-Human-p1_fury-Basic-fury-NoBuffs-ShortSingleTarget" value: { - dps: 3038.98566 - tps: 2297.15898 + dps: 3272.65818 + tps: 2447.12949 } } dps_results: { key: "TestFury-Settings-Orc-p1_fury-Basic-fury-FullBuffs-LongMultiTarget" value: { - dps: 10435.10341 - tps: 8132.46118 + dps: 8694.98225 + tps: 6729.1045 } } dps_results: { key: "TestFury-Settings-Orc-p1_fury-Basic-fury-FullBuffs-LongSingleTarget" value: { - dps: 6964.93261 - tps: 5177.34824 + dps: 6423.92566 + tps: 4719.63158 } } dps_results: { key: "TestFury-Settings-Orc-p1_fury-Basic-fury-FullBuffs-ShortSingleTarget" value: { - dps: 8385.2664 - tps: 6218.08828 + dps: 7516.95896 + tps: 5506.71715 } } dps_results: { key: "TestFury-Settings-Orc-p1_fury-Basic-fury-NoBuffs-LongMultiTarget" value: { - dps: 4418.12696 - tps: 3589.70524 + dps: 4334.00204 + tps: 3472.20866 } } dps_results: { key: "TestFury-Settings-Orc-p1_fury-Basic-fury-NoBuffs-LongSingleTarget" value: { - dps: 2797.24399 - tps: 2107.99386 + dps: 2910.72975 + tps: 2168.2564 } } dps_results: { key: "TestFury-Settings-Orc-p1_fury-Basic-fury-NoBuffs-ShortSingleTarget" value: { - dps: 3131.51163 - tps: 2357.99182 + dps: 3338.8731 + tps: 2494.623 } } dps_results: { key: "TestFury-SwitchInFrontOfTarget-Default" value: { - dps: 6468.4034 - tps: 4804.77961 + dps: 5887.98903 + tps: 4330.99525 } } diff --git a/sim/warrior/dps/dps_warrior.go b/sim/warrior/dps/dps_warrior.go index fcc5c19535..0ab0d5c20e 100644 --- a/sim/warrior/dps/dps_warrior.go +++ b/sim/warrior/dps/dps_warrior.go @@ -1,9 +1,6 @@ package dps import ( - "time" - - "github.com/wowsims/wotlk/sim/common" "github.com/wowsims/wotlk/sim/core" "github.com/wowsims/wotlk/sim/core/proto" "github.com/wowsims/wotlk/sim/warrior" @@ -29,19 +26,7 @@ func RegisterDpsWarrior() { type DpsWarrior struct { *warrior.Warrior - Options *proto.Warrior_Options - Rotation *proto.Warrior_Rotation - CustomRotation *common.CustomRotation - - // Prevent swapping stances until this time, to account for human reaction time. - canSwapStanceAt time.Duration - // Last time sunder was applied. Used for maintaining sunder even if sunder is enabled as debuff in individual sim - lastSunderAt time.Duration - - maintainSunder bool - thunderClapNext bool - - castSlamAt time.Duration + Options *proto.Warrior_Options } func NewDpsWarrior(character *core.Character, options *proto.Player) *DpsWarrior { @@ -49,13 +34,9 @@ func NewDpsWarrior(character *core.Character, options *proto.Player) *DpsWarrior war := &DpsWarrior{ Warrior: warrior.NewWarrior(character, options.TalentsString, warrior.WarriorInputs{ - ShoutType: warOptions.Options.Shout, - RendCdThreshold: core.DurationFromSeconds(warOptions.Rotation.RendCdThreshold), - BloodsurgeDurationThreshold: core.DurationFromSeconds(warOptions.Rotation.BloodsurgeDurationThreshold), - StanceSnapshot: warOptions.Options.StanceSnapshot, + StanceSnapshot: warOptions.Options.StanceSnapshot, }), - Rotation: warOptions.Rotation, - Options: warOptions.Options, + Options: warOptions.Options, } rbo := core.RageBarOptions{ @@ -87,10 +68,6 @@ func (war *DpsWarrior) GetWarrior() *warrior.Warrior { func (war *DpsWarrior) Initialize() { war.Warrior.Initialize() - war.RegisterHSOrCleave(war.Rotation.UseCleave, war.Rotation.HsRageThreshold) - war.RegisterRendSpell(war.Rotation.RendRageThresholdBelow, war.Rotation.RendHealthThresholdAbove) - war.CustomRotation = war.makeCustomRotation() - if war.Options.UseRecklessness { war.RegisterRecklessnessCD() } @@ -99,42 +76,21 @@ func (war *DpsWarrior) Initialize() { war.RegisterShatteringThrowCD() } - // This makes the behavior of these options more intuitive in the individual sim. - if war.Env.Raid.Size() == 1 { - if war.Rotation.SunderArmor == proto.Warrior_Rotation_SunderArmorHelpStack { - war.SunderArmorAuras.Get(war.CurrentTarget).Duration = core.NeverExpires - } else if war.Rotation.SunderArmor == proto.Warrior_Rotation_SunderArmorMaintain { - war.SunderArmorAuras.Get(war.CurrentTarget).Duration = time.Second * 30 - } - } - - if war.Rotation.StanceOption == proto.Warrior_Rotation_DefaultStance { - if war.Warrior.PrimaryTalentTree == warrior.FuryTree { - war.Rotation.StanceOption = proto.Warrior_Rotation_BerserkerStance - } else { - war.Rotation.StanceOption = proto.Warrior_Rotation_BattleStance - } - } - - if war.Rotation.StanceOption == proto.Warrior_Rotation_BerserkerStance { + if war.PrimaryTalentTree == warrior.FuryTree { war.BerserkerStanceAura.BuildPhase = core.CharacterBuildPhaseTalents - } else if war.Rotation.StanceOption == proto.Warrior_Rotation_BattleStance { + } else if war.PrimaryTalentTree == warrior.ArmsTree { war.BattleStanceAura.BuildPhase = core.CharacterBuildPhaseTalents } } func (war *DpsWarrior) Reset(sim *core.Simulation) { - if war.Rotation.StanceOption == proto.Warrior_Rotation_BerserkerStance { + if war.PrimaryTalentTree == warrior.FuryTree { war.Warrior.Reset(sim) war.BerserkerStanceAura.Activate(sim) war.Stance = warrior.BerserkerStance - } else if war.Rotation.StanceOption == proto.Warrior_Rotation_BattleStance { + } else if war.PrimaryTalentTree == warrior.ArmsTree { war.Warrior.Reset(sim) war.BattleStanceAura.Activate(sim) war.Stance = warrior.BattleStance } - war.canSwapStanceAt = 0 - war.maintainSunder = war.Rotation.SunderArmor != proto.Warrior_Rotation_SunderArmorNone - war.castSlamAt = 0 - war.thunderClapNext = false } diff --git a/sim/warrior/dps/dps_warrior_test.go b/sim/warrior/dps/dps_warrior_test.go index 798b983f76..dbac975c74 100644 --- a/sim/warrior/dps/dps_warrior_test.go +++ b/sim/warrior/dps/dps_warrior_test.go @@ -110,15 +110,13 @@ var ArmsGlyphs = &proto.Glyphs{ var PlayerOptionsArms = &proto.Player_Warrior{ Warrior: &proto.Warrior{ - Options: warriorOptions, - Rotation: &proto.Warrior_Rotation{}, + Options: warriorOptions, }, } var PlayerOptionsFury = &proto.Player_Warrior{ Warrior: &proto.Warrior{ - Options: warriorOptions, - Rotation: &proto.Warrior_Rotation{}, + Options: warriorOptions, }, } diff --git a/sim/warrior/dps/rotation.go b/sim/warrior/dps/rotation.go deleted file mode 100644 index fb469d1236..0000000000 --- a/sim/warrior/dps/rotation.go +++ /dev/null @@ -1,451 +0,0 @@ -package dps - -import ( - "time" - - "github.com/wowsims/wotlk/sim/common" - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/core/proto" - "github.com/wowsims/wotlk/sim/warrior" -) - -const DebuffRefreshWindow = time.Second * 2 - -func (war *DpsWarrior) OnGCDReady(sim *core.Simulation) { - war.doRotation(sim) - - if war.GCD.IsReady(sim) && !war.IsWaiting() { - // This means we did nothing - war.DoNothing() - } -} - -func (war *DpsWarrior) OnAutoAttack(sim *core.Simulation, _ *core.Spell) { - war.tryQueueHsCleave(sim) -} - -func (war *DpsWarrior) doRotation(sim *core.Simulation) { - if war.thunderClapNext { - if war.ThunderClap.CanCast(sim, war.CurrentTarget) { - if war.ThunderClap.Cast(sim, war.CurrentTarget) { - if war.ThunderClapAuras.Get(war.CurrentTarget).RemainingDuration(sim) > DebuffRefreshWindow { - war.thunderClapNext = false - - // Switching back to berserker immediately is unrealistic because the player needs - // to visually confirm the TC landed. Instead we add a delay to model that. - war.canSwapStanceAt = sim.CurrentTime + time.Millisecond*300 - } - return - } - } - } else { - if war.Rotation.StanceOption == proto.Warrior_Rotation_BerserkerStance { - war.trySwapToBerserker(sim) - } else if war.Rotation.StanceOption == proto.Warrior_Rotation_BattleStance { - war.trySwapToBattle(sim) - } - } - - if war.shouldSunder(sim) { - if war.Devastate != nil { - war.Devastate.Cast(sim, war.CurrentTarget) - } else { - war.SunderArmor.Cast(sim, war.CurrentTarget) - war.lastSunderAt = sim.CurrentTime - } - war.tryQueueHsCleave(sim) - return - } - - IsExecutePhase20 := sim.IsExecutePhase20() - if war.Rotation.CustomRotationOption && war.GCD.IsReady(sim) { - war.CustomRotation.Cast(sim) - } else if IsExecutePhase20 { - war.executeRotation(sim) - } else { - war.normalRotation(sim) - } - - if war.GCD.IsReady(sim) && !war.thunderClapNext { - // We didn't cast anything, so wait for the next CD. - nextCD := war.Whirlwind.CD.ReadyAt() - if war.Bloodthirst != nil && war.Bloodthirst.CD.ReadyAt() < nextCD { - nextCD = war.Bloodthirst.CD.ReadyAt() - } else if war.MortalStrike != nil && war.MortalStrike.CD.ReadyAt() < nextCD { - nextCD = war.MortalStrike.CD.ReadyAt() - } - - if war.Rotation.SunderArmor == proto.Warrior_Rotation_SunderArmorMaintain { - nextSunderAt := war.lastSunderAt + 30*time.Second - sim.CurrentTime - SunderWindow - // TODO looks fishy, nextCD is unused - nextCD = min(nextCD, nextSunderAt) - } - } -} - -func (war *DpsWarrior) normalRotation(sim *core.Simulation) { - if war.GCD.IsReady(sim) { - if war.Warrior.PrimaryTalentTree == warrior.FuryTree { - war.furyNormalRotation(sim) - } else if war.Warrior.PrimaryTalentTree == warrior.ArmsTree { - war.armsNormalRotation(sim) - } - } - war.tryQueueHsCleave(sim) -} - -func (war *DpsWarrior) executeRotation(sim *core.Simulation) { - if war.GCD.IsReady(sim) { - if war.Warrior.PrimaryTalentTree == warrior.FuryTree { - war.furyExecuteRotation(sim) - } else if war.Warrior.PrimaryTalentTree == warrior.ArmsTree { - war.armsExecuteRotation(sim) - } - } - - war.tryQueueHsCleave(sim) -} - -func (war *DpsWarrior) furyNormalRotation(sim *core.Simulation) { - if war.tryMaintainDebuffs(sim) { - war.DoNothing() - } else if war.Rotation.MainGcd == proto.Warrior_Rotation_Slam && war.ShouldInstantSlam(sim) { - war.Slam.Cast(sim, war.CurrentTarget) - } else if war.Rotation.MainGcd == proto.Warrior_Rotation_Bloodthirst && war.Bloodthirst.CanCast(sim, war.CurrentTarget) { - war.Bloodthirst.Cast(sim, war.CurrentTarget) - } else if war.Rotation.MainGcd == proto.Warrior_Rotation_Whirlwind && war.CanWhirlwind(sim) { - war.Whirlwind.Cast(sim, war.CurrentTarget) - } else if war.Rotation.MainGcd != proto.Warrior_Rotation_Bloodthirst && war.Bloodthirst.CanCast(sim, war.CurrentTarget) { - war.Bloodthirst.Cast(sim, war.CurrentTarget) - } else if war.Rotation.MainGcd != proto.Warrior_Rotation_Slam && war.ShouldInstantSlam(sim) { - war.Slam.Cast(sim, war.CurrentTarget) - } else if war.Rotation.MainGcd != proto.Warrior_Rotation_Whirlwind && war.CanWhirlwind(sim) { - war.Whirlwind.Cast(sim, war.CurrentTarget) - } else if war.Rotation.UseRend && war.ShouldRend(sim) { - if !war.StanceMatches(warrior.BattleStance) { - if !war.BattleStance.IsReady(sim) { - return - } - war.BattleStance.Cast(sim, nil) - } - war.Rend.Cast(sim, war.CurrentTarget) - } else if war.Rotation.UseOverpower && war.ShouldOverpower(sim) { - if !war.StanceMatches(warrior.BattleStance) { - if !war.BattleStance.IsReady(sim) { - return - } - war.BattleStance.Cast(sim, nil) - } - war.Overpower.Cast(sim, war.CurrentTarget) - } -} - -func (war *DpsWarrior) armsNormalRotation(sim *core.Simulation) { - if war.tryMaintainDebuffs(sim) { - war.DoNothing() - } else if war.Execute.CanCast(sim, war.CurrentTarget) { - war.CastExecute(sim, war.CurrentTarget) - } else if war.Rotation.UseRend && war.ShouldRend(sim) { - if !war.StanceMatches(warrior.BattleStance) { - if !war.BattleStance.IsReady(sim) { - return - } - war.BattleStance.Cast(sim, nil) - } - war.Rend.Cast(sim, war.CurrentTarget) - } else if war.ShouldOverpower(sim) { - if !war.StanceMatches(warrior.BattleStance) { - if !war.BattleStance.IsReady(sim) { - return - } - war.BattleStance.Cast(sim, nil) - } - war.Overpower.Cast(sim, war.CurrentTarget) - } else if war.Rotation.UseMs && war.MortalStrike.CanCast(sim, war.CurrentTarget) && war.CurrentRage() >= war.Rotation.MsRageThreshold { - war.MortalStrike.Cast(sim, war.CurrentTarget) - } else if war.Slam.CanCast(sim, war.CurrentTarget) && war.CurrentRage() >= war.Rotation.SlamRageThreshold { - war.Slam.Cast(sim, war.CurrentTarget) - } -} - -func (war *DpsWarrior) furyExecuteRotation(sim *core.Simulation) { - if war.tryMaintainDebuffs(sim) { - war.DoNothing() - } else if war.SpamExecute(war.Rotation.SpamExecute) { - war.CastExecute(sim, war.CurrentTarget) - } else if war.Rotation.MainGcd == proto.Warrior_Rotation_Slam && - war.Rotation.UseSlamOverExecute && war.ShouldInstantSlam(sim) { - war.Slam.Cast(sim, war.CurrentTarget) - } else if war.Rotation.MainGcd == proto.Warrior_Rotation_Bloodthirst && - war.Rotation.UseBtDuringExecute && war.Bloodthirst.CanCast(sim, war.CurrentTarget) { - war.Bloodthirst.Cast(sim, war.CurrentTarget) - } else if war.Rotation.MainGcd == proto.Warrior_Rotation_Whirlwind && - war.Rotation.UseWwDuringExecute && war.CanWhirlwind(sim) { - war.Whirlwind.Cast(sim, war.CurrentTarget) - } else if war.Rotation.MainGcd != proto.Warrior_Rotation_Bloodthirst && - war.Rotation.UseBtDuringExecute && war.Bloodthirst.CanCast(sim, war.CurrentTarget) { - war.Bloodthirst.Cast(sim, war.CurrentTarget) - } else if war.Rotation.MainGcd != proto.Warrior_Rotation_Slam && - war.Rotation.UseSlamOverExecute && war.ShouldInstantSlam(sim) { - war.Slam.Cast(sim, war.CurrentTarget) - } else if war.Rotation.MainGcd != proto.Warrior_Rotation_Whirlwind && - war.Rotation.UseWwDuringExecute && war.CanWhirlwind(sim) { - war.Whirlwind.Cast(sim, war.CurrentTarget) - } else if war.Rotation.UseRend && war.ShouldRend(sim) { - if !war.StanceMatches(warrior.BattleStance) { - if !war.BattleStance.IsReady(sim) { - return - } - war.BattleStance.Cast(sim, nil) - } - war.Rend.Cast(sim, war.CurrentTarget) - } else if war.Rotation.UseOverpower && war.Rotation.ExecutePhaseOverpower && - war.ShouldOverpower(sim) { - if !war.StanceMatches(warrior.BattleStance) { - if !war.BattleStance.IsReady(sim) { - return - } - war.BattleStance.Cast(sim, nil) - } - war.Overpower.Cast(sim, war.CurrentTarget) - } else if war.Execute.CanCast(sim, war.CurrentTarget) { - war.CastExecute(sim, war.CurrentTarget) - } -} - -func (war *DpsWarrior) armsExecuteRotation(sim *core.Simulation) { - if war.tryMaintainDebuffs(sim) { - war.DoNothing() - } else if war.IsSuddenDeathActive() && war.Execute.CanCast(sim, war.CurrentTarget) { - war.CastExecute(sim, war.CurrentTarget) - } else if war.Rotation.UseRend && war.ShouldRend(sim) { - if !war.StanceMatches(warrior.BattleStance) { - if !war.BattleStance.IsReady(sim) { - return - } - war.BattleStance.Cast(sim, nil) - } - war.Rend.Cast(sim, war.CurrentTarget) - } else if war.ShouldOverpower(sim) { - if !war.StanceMatches(warrior.BattleStance) { - if !war.BattleStance.IsReady(sim) { - return - } - war.BattleStance.Cast(sim, nil) - } - war.Overpower.Cast(sim, war.CurrentTarget) - } else if war.SpamExecute(war.Rotation.SpamExecute) { - war.CastExecute(sim, war.CurrentTarget) - } else if war.Rotation.UseRend && war.ShouldRend(sim) { - if !war.StanceMatches(warrior.BattleStance) { - if !war.BattleStance.IsReady(sim) { - return - } - war.BattleStance.Cast(sim, nil) - } - war.Rend.Cast(sim, war.CurrentTarget) - } else if war.Rotation.UseMs && war.MortalStrike.CanCast(sim, war.CurrentTarget) && war.CurrentRage() >= war.Rotation.MsRageThreshold { - war.MortalStrike.Cast(sim, war.CurrentTarget) - } else if war.Execute.CanCast(sim, war.CurrentTarget) { - war.CastExecute(sim, war.CurrentTarget) - } -} - -func (war *DpsWarrior) trySwapToBerserker(sim *core.Simulation) bool { - if !war.StanceMatches(warrior.BerserkerStance) && war.BerserkerStance.IsReady(sim) && sim.CurrentTime >= war.canSwapStanceAt { - war.BerserkerStance.Cast(sim, nil) - return true - } - return false -} - -func (war *DpsWarrior) trySwapToBattle(sim *core.Simulation) bool { - if !war.StanceMatches(warrior.BattleStance) && war.BattleStance.IsReady(sim) && sim.CurrentTime >= war.canSwapStanceAt { - war.BattleStance.Cast(sim, nil) - return true - } - return false -} - -const SunderWindow = time.Second * 3 - -func (war *DpsWarrior) shouldSunder(sim *core.Simulation) bool { - if !war.maintainSunder { - return false - } - - if !war.SunderArmor.CanCast(sim, war.CurrentTarget) { - return false - } - - saAura := war.SunderArmorAuras.Get(war.CurrentTarget) - stacks := saAura.GetStacks() - if war.Rotation.SunderArmor == proto.Warrior_Rotation_SunderArmorHelpStack && stacks == 5 { - war.maintainSunder = false - } - - return stacks < 5 || (war.lastSunderAt+30*time.Second-sim.CurrentTime) <= SunderWindow -} - -// Returns whether any ability was cast. -func (war *DpsWarrior) tryMaintainDebuffs(sim *core.Simulation) bool { - if war.ShouldShout(sim) { - war.Shout.Cast(sim, nil) - return true - } else if war.Rotation.MaintainDemoShout && war.ShouldDemoralizingShout(sim, war.CurrentTarget, false, true) { - war.DemoralizingShout.Cast(sim, war.CurrentTarget) - return true - } else if war.Rotation.MaintainThunderClap && war.ShouldThunderClap(sim, war.CurrentTarget, false, true, true) { - war.thunderClapNext = true - if !war.StanceMatches(warrior.BattleStance) { - if !war.BattleStance.IsReady(sim) { - return false - } - war.BattleStance.Cast(sim, nil) - } - // Need to check again because we might have lost rage from switching stances. - if war.ThunderClap.CanCast(sim, war.CurrentTarget) { - war.ThunderClap.Cast(sim, war.CurrentTarget) - if war.ThunderClapAuras.Get(war.CurrentTarget).RemainingDuration(sim) > DebuffRefreshWindow { - war.thunderClapNext = false - } - } - return true - } - return false -} - -func (war *DpsWarrior) tryQueueHsCleave(sim *core.Simulation) { - if sim.IsExecutePhase20() && !war.Rotation.UseHsDuringExecute { - return - } - - if war.ShouldQueueHSOrCleave(sim) { - war.QueueHSOrCleave(sim) - } -} - -func (war *DpsWarrior) makeCustomRotation() *common.CustomRotation { - return common.NewCustomRotation(war.Rotation.CustomRotation, war.GetCharacter(), map[int32]common.CustomSpell{ - int32(proto.Warrior_Rotation_BloodthirstCustom): { - Spell: war.Bloodthirst, - Condition: func(sim *core.Simulation) bool { - if sim.IsExecutePhase20() && !war.Rotation.UseBtDuringExecute { - return false - } - return war.Bloodthirst.CanCast(sim, war.CurrentTarget) - }, - }, - int32(proto.Warrior_Rotation_MortalStrike): { - Spell: war.MortalStrike, - Condition: func(sim *core.Simulation) bool { - return war.MortalStrike.CanCast(sim, war.CurrentTarget) && war.CurrentRage() >= war.Rotation.MsRageThreshold - }, - }, - int32(proto.Warrior_Rotation_WhirlwindCustom): { - Spell: war.Whirlwind, - Condition: func(sim *core.Simulation) bool { - if sim.IsExecutePhase20() && !war.Rotation.UseWwDuringExecute { - return false - } - - if !war.StanceMatches(warrior.BerserkerStance) { - if !war.BerserkerStance.IsReady(sim) { - return false - } - war.BerserkerStance.Cast(sim, nil) - } - return war.Whirlwind.CanCast(sim, war.CurrentTarget) - }, - }, - int32(proto.Warrior_Rotation_SlamCustom): { - Spell: war.Slam, - Condition: func(sim *core.Simulation) bool { - if sim.IsExecutePhase20() && !war.Rotation.UseSlamOverExecute { - return false - } - - if (war.ShouldSlam(sim) && war.CurrentRage() >= war.Rotation.SlamRageThreshold || war.ShouldInstantSlam(sim)) && - war.Slam.CanCast(sim, war.CurrentTarget) { - war.AutoAttacks.DelayMeleeBy(sim, war.Slam.CurCast.CastTime) - return true - } - return false - }, - }, - - int32(proto.Warrior_Rotation_SlamExpiring): { - Spell: war.Slam, - Condition: func(sim *core.Simulation) bool { - if !war.ShouldInstantSlam(sim) { - return false - } - - if (war.BloodsurgeValidUntil - sim.CurrentTime) > war.BloodsurgeDurationThreshold { - return false - } - - if sim.IsExecutePhase20() && !war.Rotation.UseSlamOverExecute { - return false - } - - if war.CurrentRage() >= war.Rotation.SlamRageThreshold && war.Slam.CanCast(sim, war.CurrentTarget) { - war.AutoAttacks.DelayMeleeBy(sim, war.Slam.CurCast.CastTime) - return true - } - return false - }, - }, - - int32(proto.Warrior_Rotation_Rend): { - Spell: war.Rend, - Condition: func(sim *core.Simulation) bool { - if !war.ShouldRend(sim) { - return false - } - - if !war.StanceMatches(warrior.BattleStance) { - if !war.BattleStance.IsReady(sim) { - return false - } - war.BattleStance.Cast(sim, nil) - } - return war.Rend.CanCast(sim, war.CurrentTarget) - }, - }, - int32(proto.Warrior_Rotation_Overpower): { - Spell: war.Overpower, - Condition: func(sim *core.Simulation) bool { - if !war.ShouldOverpower(sim) { - return false - } - if sim.IsExecutePhase20() && !war.Rotation.ExecutePhaseOverpower && war.PrimaryTalentTree == warrior.FuryTree { - return false - } - - if !war.StanceMatches(warrior.BattleStance) { - if !war.BattleStance.IsReady(sim) { - return false - } - war.BattleStance.Cast(sim, nil) - } - return war.Overpower.CanCast(sim, war.CurrentTarget) - }, - }, - int32(proto.Warrior_Rotation_Execute): { - Spell: war.Execute, - }, - int32(proto.Warrior_Rotation_ThunderClap): { - Spell: war.ThunderClap, - Condition: func(sim *core.Simulation) bool { - if !war.StanceMatches(warrior.BattleStance) { - if !war.BattleStance.IsReady(sim) { - return false - } - war.BattleStance.Cast(sim, nil) - } - return war.ThunderClap.CanCast(sim, war.CurrentTarget) - }, - }, - }) -} diff --git a/sim/warrior/execute.go b/sim/warrior/execute.go index 1451477a39..8b3e659954 100644 --- a/sim/warrior/execute.go +++ b/sim/warrior/execute.go @@ -59,11 +59,3 @@ func (warrior *Warrior) registerExecuteSpell() { }) rageMetrics = warrior.Execute.Cost.(*core.RageCost).ResourceMetrics } - -func (warrior *Warrior) SpamExecute(spam bool) bool { - return warrior.CurrentRage() >= warrior.Execute.DefaultCast.Cost && spam && warrior.PrimaryTalentTree == ArmsTree -} - -func (warrior *Warrior) CastExecute(sim *core.Simulation, target *core.Unit) bool { - return warrior.Execute.Cast(sim, target) -} diff --git a/sim/warrior/heroic_strike_cleave.go b/sim/warrior/heroic_strike_cleave.go index b75f455c6d..defe4fa625 100644 --- a/sim/warrior/heroic_strike_cleave.go +++ b/sim/warrior/heroic_strike_cleave.go @@ -5,14 +5,14 @@ import ( "github.com/wowsims/wotlk/sim/core/proto" ) -func (warrior *Warrior) registerHeroicStrikeSpell() *core.Spell { +func (warrior *Warrior) registerHeroicStrikeSpell() { hasGlyph := warrior.HasMajorGlyph(proto.WarriorMajorGlyph_GlyphOfHeroicStrike) var rageMetrics *core.ResourceMetrics if hasGlyph { rageMetrics = warrior.NewRageMetrics(core.ActionID{ItemID: 43418}) } - return warrior.RegisterSpell(core.SpellConfig{ + warrior.HeroicStrike = warrior.RegisterSpell(core.SpellConfig{ ActionID: core.ActionID{SpellID: 47450}, SpellSchool: core.SpellSchoolPhysical, ProcMask: core.ProcMaskMeleeMHSpecial, @@ -50,14 +50,14 @@ func (warrior *Warrior) registerHeroicStrikeSpell() *core.Spell { }) } -func (warrior *Warrior) registerCleaveSpell() *core.Spell { +func (warrior *Warrior) registerCleaveSpell() { flatDamageBonus := 222 * (1 + 0.4*float64(warrior.Talents.ImprovedCleave)) targets := core.TernaryInt32(warrior.HasMajorGlyph(proto.WarriorMajorGlyph_GlyphOfCleaving), 3, 2) numHits := min(targets, warrior.Env.GetNumTargets()) results := make([]*core.SpellResult, numHits) - return warrior.RegisterSpell(core.SpellConfig{ + warrior.Cleave = warrior.RegisterSpell(core.SpellConfig{ ActionID: core.ActionID{SpellID: 47520}, SpellSchool: core.SpellSchoolPhysical, ProcMask: core.ProcMaskMeleeMHSpecial, @@ -136,23 +136,12 @@ func (warrior *Warrior) makeQueueSpellsAndAura(srcSpell *core.Spell) *core.Spell return queueSpell } -func (warrior *Warrior) QueueHSOrCleave(sim *core.Simulation) { - if warrior.hsOrCleaveQueueSpell.CanCast(sim, warrior.CurrentTarget) { - warrior.hsOrCleaveQueueSpell.Cast(sim, warrior.CurrentTarget) - } -} - // Returns true if the regular melee swing should be used, false otherwise. func (warrior *Warrior) TryHSOrCleave(sim *core.Simulation, mhSwingSpell *core.Spell) *core.Spell { if !warrior.curQueueAura.IsActive() { return mhSwingSpell } - if warrior.CurrentRage() < warrior.HSRageThreshold { - warrior.curQueueAura.Deactivate(sim) - return mhSwingSpell - } - if !warrior.curQueuedAutoSpell.CanCast(sim, warrior.CurrentTarget) { warrior.curQueueAura.Deactivate(sim) return mhSwingSpell @@ -160,25 +149,3 @@ func (warrior *Warrior) TryHSOrCleave(sim *core.Simulation, mhSwingSpell *core.S return warrior.curQueuedAutoSpell } - -func (warrior *Warrior) ShouldQueueHSOrCleave(sim *core.Simulation) bool { - return warrior.CurrentRage() >= warrior.HSRageThreshold && sim.CurrentTime >= warrior.Hardcast.Expires -} - -func (warrior *Warrior) RegisterHSOrCleave(useCleave bool, rageThreshold float64) { - warrior.HeroicStrike = warrior.registerCleaveSpell() - hsQueueSpell := warrior.makeQueueSpellsAndAura(warrior.HeroicStrike) - warrior.Cleave = warrior.registerHeroicStrikeSpell() - cleaveQueueSpell := warrior.makeQueueSpellsAndAura(warrior.Cleave) - - var autoSpell *core.Spell - if useCleave { - autoSpell = warrior.HeroicStrike - warrior.hsOrCleaveQueueSpell = hsQueueSpell - } else { - autoSpell = warrior.Cleave - warrior.hsOrCleaveQueueSpell = cleaveQueueSpell - } - - warrior.HSRageThreshold = max(autoSpell.DefaultCast.Cost, rageThreshold) -} diff --git a/sim/warrior/overpower.go b/sim/warrior/overpower.go index b4337c53d4..056cc1a3c1 100644 --- a/sim/warrior/overpower.go +++ b/sim/warrior/overpower.go @@ -84,27 +84,3 @@ func (warrior *Warrior) registerOverpowerSpell(cdTimer *core.Timer) { }, }) } - -func (warrior *Warrior) ShouldOverpower(sim *core.Simulation) bool { - return warrior.OverpowerAura.IsActive() && warrior.Overpower.IsReady(sim) && - warrior.CurrentRage() >= warrior.Overpower.DefaultCast.Cost && - sim.CurrentTime > (warrior.lastOverpowerProc+warrior.reactionTime) -} - -// Queue Overpower to be cast at every 6s if talented for 3/3 TfB -func (warrior *Warrior) CastFullTfbOverpower(sim *core.Simulation, target *core.Unit) bool { - if warrior.Talents.TasteForBlood < 3 { - return false - } - - core.StartDelayedAction(sim, core.DelayedActionOptions{ - DoAt: sim.CurrentTime + time.Second*6, - OnAction: func(_ *core.Simulation) { - if warrior.Overpower.CanCast(sim, target) && warrior.ShouldOverpower(sim) { - warrior.CastFullTfbOverpower(sim, target) - } - }, - }) - - return warrior.Overpower.Cast(sim, target) -} diff --git a/sim/warrior/protection/TestProtectionWarrior.results b/sim/warrior/protection/TestProtectionWarrior.results index c86c6c7975..8f624c145c 100644 --- a/sim/warrior/protection/TestProtectionWarrior.results +++ b/sim/warrior/protection/TestProtectionWarrior.results @@ -46,7 +46,7 @@ character_stats_results: { stat_weights_results: { key: "TestProtectionWarrior-StatWeights-Default" value: { - weights: 0.76367 + weights: 0.71312 weights: 0 weights: 0 weights: 0 @@ -57,7 +57,7 @@ stat_weights_results: { weights: 0 weights: 0 weights: 0 - weights: 0.2638 + weights: 0.19612 weights: 0 weights: 0 weights: 0 @@ -66,12 +66,12 @@ stat_weights_results: { weights: 0 weights: 0 weights: 0 - weights: -3e-05 + weights: 0.00611 weights: 0 weights: 0 weights: 0 - weights: 0.43043 - weights: 0.09932 + weights: 0.43871 + weights: 0.05727 weights: 0 weights: 0 weights: 0 @@ -91,874 +91,874 @@ stat_weights_results: { dps_results: { key: "TestProtectionWarrior-AllItems-Althor'sAbacus-50359" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-Althor'sAbacus-50366" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-AustereEarthsiegeDiamond" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-Bandit'sInsignia-40371" value: { - dps: 1497.4236 - tps: 3865.5531 + dps: 1349.67155 + tps: 3452.90509 } } dps_results: { key: "TestProtectionWarrior-AllItems-BaubleofTrueBlood-50354" value: { - dps: 1443.61597 - tps: 3757.74334 - hps: 82.16554 + dps: 1289.68012 + tps: 3328.53102 + hps: 82.28496 } } dps_results: { key: "TestProtectionWarrior-AllItems-BaubleofTrueBlood-50726" value: { - dps: 1443.61597 - tps: 3757.74334 - hps: 82.16554 + dps: 1289.68012 + tps: 3328.53102 + hps: 82.28496 } } dps_results: { key: "TestProtectionWarrior-AllItems-BeamingEarthsiegeDiamond" value: { - dps: 1436.29269 - tps: 3738.87948 + dps: 1296.93101 + tps: 3344.72411 } } dps_results: { key: "TestProtectionWarrior-AllItems-Beast-tamer'sShoulders-30892" value: { - dps: 1403.06881 - tps: 3652.51629 + dps: 1268.62008 + tps: 3272.93157 } } dps_results: { key: "TestProtectionWarrior-AllItems-BlackBruise-50035" value: { - dps: 1502.62813 - tps: 3840.29252 + dps: 1366.40693 + tps: 3480.65126 } } dps_results: { key: "TestProtectionWarrior-AllItems-BlackBruise-50692" value: { - dps: 1532.82854 - tps: 3902.58233 + dps: 1393.43275 + tps: 3536.68929 } } dps_results: { key: "TestProtectionWarrior-AllItems-BlessedBattlegearofUndeadSlaying" value: { - dps: 1236.90562 - tps: 3226.4392 + dps: 1095.91679 + tps: 2830.7771 } } dps_results: { key: "TestProtectionWarrior-AllItems-BlessedGarboftheUndeadSlayer" value: { - dps: 1213.25286 - tps: 3161.94609 + dps: 1083.97911 + tps: 2801.35142 } } dps_results: { key: "TestProtectionWarrior-AllItems-BlessedRegaliaofUndeadCleansing" value: { - dps: 1149.45808 - tps: 3021.01244 + dps: 1038.79449 + tps: 2703.60683 } } dps_results: { key: "TestProtectionWarrior-AllItems-BracingEarthsiegeDiamond" value: { - dps: 1429.13677 - tps: 3649.22353 + dps: 1288.48948 + tps: 3259.55894 } } dps_results: { key: "TestProtectionWarrior-AllItems-Bryntroll,theBoneArbiter-50415" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-Bryntroll,theBoneArbiter-50709" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-ChaoticSkyflareDiamond" value: { - dps: 1464.89347 - tps: 3806.56276 + dps: 1312.2867 + tps: 3382.90933 } } dps_results: { key: "TestProtectionWarrior-AllItems-CorpseTongueCoin-50349" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-CorpseTongueCoin-50352" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-CorrodedSkeletonKey-50356" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 hps: 64 } } dps_results: { key: "TestProtectionWarrior-AllItems-DarkmoonCard:Berserker!-42989" value: { - dps: 1482.8109 - tps: 3850.33623 + dps: 1326.14307 + tps: 3412.47151 } } dps_results: { key: "TestProtectionWarrior-AllItems-DarkmoonCard:Death-42990" value: { - dps: 1514.2653 - tps: 3906.78831 + dps: 1370.16223 + tps: 3503.06341 } } dps_results: { key: "TestProtectionWarrior-AllItems-DarkmoonCard:Greatness-44255" value: { - dps: 1475.90374 - tps: 3829.1951 + dps: 1320.20348 + tps: 3397.32538 } } dps_results: { key: "TestProtectionWarrior-AllItems-Death'sChoice-47464" value: { - dps: 1516.88738 - tps: 3908.179 + dps: 1362.44929 + tps: 3485.44146 } } dps_results: { key: "TestProtectionWarrior-AllItems-DeathKnight'sAnguish-38212" value: { - dps: 1458.84083 - tps: 3789.00873 + dps: 1315.30651 + tps: 3386.90955 } } dps_results: { key: "TestProtectionWarrior-AllItems-Deathbringer'sWill-50362" value: { - dps: 1550.72349 - tps: 4003.56481 + dps: 1379.04866 + tps: 3530.54996 } } dps_results: { key: "TestProtectionWarrior-AllItems-Deathbringer'sWill-50363" value: { - dps: 1559.26933 - tps: 4021.26044 + dps: 1402.27748 + tps: 3586.09731 } } dps_results: { key: "TestProtectionWarrior-AllItems-DestructiveSkyflareDiamond" value: { - dps: 1438.34767 - tps: 3744.86385 + dps: 1297.77538 + tps: 3346.47492 } } dps_results: { key: "TestProtectionWarrior-AllItems-DislodgedForeignObject-50348" value: { - dps: 1471.50005 - tps: 3813.02114 + dps: 1332.44248 + tps: 3426.37457 } } dps_results: { key: "TestProtectionWarrior-AllItems-DislodgedForeignObject-50353" value: { - dps: 1470.21311 - tps: 3812.0458 + dps: 1327.12982 + tps: 3414.81696 } } dps_results: { key: "TestProtectionWarrior-AllItems-DreadnaughtBattlegear" value: { - dps: 1474.02677 - tps: 3793.84899 + dps: 1309.91106 + tps: 3337.8708 } } dps_results: { key: "TestProtectionWarrior-AllItems-DreadnaughtPlate" value: { - dps: 1354.59803 - tps: 3527.38642 + dps: 1216.07089 + tps: 3142.58615 } } dps_results: { key: "TestProtectionWarrior-AllItems-EffulgentSkyflareDiamond" value: { - dps: 1429.13677 - tps: 3723.6434 + dps: 1288.48948 + tps: 3326.07038 } } dps_results: { key: "TestProtectionWarrior-AllItems-EmberSkyflareDiamond" value: { - dps: 1429.13677 - tps: 3723.6434 + dps: 1288.48948 + tps: 3326.07038 } } dps_results: { key: "TestProtectionWarrior-AllItems-EnigmaticSkyflareDiamond" value: { - dps: 1436.29269 - tps: 3738.87948 + dps: 1296.93101 + tps: 3344.72411 } } dps_results: { key: "TestProtectionWarrior-AllItems-EnigmaticStarflareDiamond" value: { - dps: 1436.28313 - tps: 3739.17223 + dps: 1295.62188 + tps: 3341.52155 } } dps_results: { key: "TestProtectionWarrior-AllItems-EphemeralSnowflake-50260" value: { - dps: 1452.25212 - tps: 3775.3647 + dps: 1314.10173 + tps: 3386.07585 } } dps_results: { key: "TestProtectionWarrior-AllItems-EssenceofGossamer-37220" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-EternalEarthsiegeDiamond" value: { - dps: 1442.7152 - tps: 3760.24472 + dps: 1302.09935 + tps: 3362.75646 } } dps_results: { key: "TestProtectionWarrior-AllItems-ExtractofNecromanticPower-40373" value: { - dps: 1503.39455 - tps: 3880.58924 + dps: 1359.5275 + tps: 3481.35292 } } dps_results: { key: "TestProtectionWarrior-AllItems-EyeoftheBroodmother-45308" value: { - dps: 1466.27182 - tps: 3802.47188 + dps: 1323.63574 + tps: 3406.9386 } } dps_results: { key: "TestProtectionWarrior-AllItems-Figurine-SapphireOwl-42413" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-ForethoughtTalisman-40258" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-ForgeEmber-37660" value: { - dps: 1464.82611 - tps: 3806.06243 + dps: 1315.49823 + tps: 3387.44624 } } dps_results: { key: "TestProtectionWarrior-AllItems-ForlornSkyflareDiamond" value: { - dps: 1429.13677 - tps: 3723.6434 + dps: 1288.48948 + tps: 3326.07038 } } dps_results: { key: "TestProtectionWarrior-AllItems-ForlornStarflareDiamond" value: { - dps: 1429.13677 - tps: 3723.6434 + dps: 1288.48948 + tps: 3326.07038 } } dps_results: { key: "TestProtectionWarrior-AllItems-FuryoftheFiveFlights-40431" value: { - dps: 1473.63265 - tps: 3820.71002 + dps: 1318.14001 + tps: 3387.55053 } } dps_results: { key: "TestProtectionWarrior-AllItems-FuturesightRune-38763" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-Gladiator'sBattlegear" value: { - dps: 1546.55353 - tps: 3917.21448 + dps: 1390.13929 + tps: 3488.94895 } } dps_results: { key: "TestProtectionWarrior-AllItems-GlowingTwilightScale-54573" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-GlowingTwilightScale-54589" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-GnomishLightningGenerator-41121" value: { - dps: 1499.30293 - tps: 3876.2045 + dps: 1357.44157 + tps: 3476.42661 } } dps_results: { key: "TestProtectionWarrior-AllItems-Heartpierce-49982" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-Heartpierce-50641" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-IllustrationoftheDragonSoul-40432" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-ImpassiveSkyflareDiamond" value: { - dps: 1436.29269 - tps: 3738.87948 + dps: 1296.93101 + tps: 3344.72411 } } dps_results: { key: "TestProtectionWarrior-AllItems-ImpassiveStarflareDiamond" value: { - dps: 1436.28313 - tps: 3739.17223 + dps: 1295.62188 + tps: 3341.52155 } } dps_results: { key: "TestProtectionWarrior-AllItems-IncisorFragment-37723" value: { - dps: 1477.31363 - tps: 3830.89904 + dps: 1325.06872 + tps: 3409.61163 } } dps_results: { key: "TestProtectionWarrior-AllItems-InsightfulEarthsiegeDiamond" value: { - dps: 1429.13677 - tps: 3723.6434 + dps: 1288.48948 + tps: 3326.07038 } } dps_results: { key: "TestProtectionWarrior-AllItems-InvigoratingEarthsiegeDiamond" value: { - dps: 1439.81394 - tps: 3750.17262 - hps: 16.38289 + dps: 1292.37353 + tps: 3334.12396 + hps: 15.35543 } } dps_results: { key: "TestProtectionWarrior-AllItems-LastWord-50179" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-LastWord-50708" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-Lavanthor'sTalisman-37872" value: { - dps: 1456.808 - tps: 3793.30312 + dps: 1302.08299 + tps: 3361.96359 } } dps_results: { key: "TestProtectionWarrior-AllItems-MajesticDragonFigurine-40430" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-MeteoriteWhetstone-37390" value: { - dps: 1487.95987 - tps: 3858.19024 + dps: 1342.00137 + tps: 3451.0587 } } dps_results: { key: "TestProtectionWarrior-AllItems-NevermeltingIceCrystal-50259" value: { - dps: 1488.45581 - tps: 3857.26512 + dps: 1341.11428 + tps: 3446.17637 } } dps_results: { key: "TestProtectionWarrior-AllItems-OfferingofSacrifice-37638" value: { - dps: 1439.06283 - tps: 3744.35518 + dps: 1291.10608 + tps: 3331.4959 } } dps_results: { key: "TestProtectionWarrior-AllItems-OnslaughtArmor" value: { - dps: 1143.96277 - tps: 3010.38028 + dps: 1032.96893 + tps: 2697.01584 } } dps_results: { key: "TestProtectionWarrior-AllItems-OnslaughtBattlegear" value: { - dps: 1212.73705 - tps: 3132.14296 + dps: 1073.2847 + tps: 2744.73876 } } dps_results: { key: "TestProtectionWarrior-AllItems-PersistentEarthshatterDiamond" value: { - dps: 1441.44826 - tps: 3755.28496 + dps: 1291.63371 + tps: 3332.58995 } } dps_results: { key: "TestProtectionWarrior-AllItems-PersistentEarthsiegeDiamond" value: { - dps: 1439.81394 - tps: 3750.17262 + dps: 1292.37353 + tps: 3334.12396 } } dps_results: { key: "TestProtectionWarrior-AllItems-PetrifiedScarab-21685" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-PetrifiedTwilightScale-54571" value: { - dps: 1438.52633 - tps: 3741.00002 + dps: 1295.55527 + tps: 3340.7213 } } dps_results: { key: "TestProtectionWarrior-AllItems-PetrifiedTwilightScale-54591" value: { - dps: 1437.28281 - tps: 3735.73938 + dps: 1296.3105 + tps: 3342.28727 } } dps_results: { key: "TestProtectionWarrior-AllItems-PowerfulEarthshatterDiamond" value: { - dps: 1429.13677 - tps: 3723.6434 + dps: 1288.48948 + tps: 3326.07038 } } dps_results: { key: "TestProtectionWarrior-AllItems-PowerfulEarthsiegeDiamond" value: { - dps: 1429.13677 - tps: 3723.6434 + dps: 1288.48948 + tps: 3326.07038 } } dps_results: { key: "TestProtectionWarrior-AllItems-PurifiedShardoftheGods" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-ReignoftheDead-47316" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-ReignoftheDead-47477" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-RelentlessEarthsiegeDiamond" value: { - dps: 1464.99517 - tps: 3809.20556 + dps: 1311.03851 + tps: 3379.80384 } } dps_results: { key: "TestProtectionWarrior-AllItems-RevitalizingSkyflareDiamond" value: { - dps: 1429.13677 - tps: 3723.6434 + dps: 1288.48948 + tps: 3326.07038 } } dps_results: { key: "TestProtectionWarrior-AllItems-RuneofRepulsion-40372" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-SealofthePantheon-36993" value: { - dps: 1432.85618 - tps: 3727.67586 + dps: 1291.56894 + tps: 3332.45565 } } dps_results: { key: "TestProtectionWarrior-AllItems-Shadowmourne-49623" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-ShinyShardoftheGods" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-SiegebreakerBattlegear" value: { - dps: 1528.60272 - tps: 3922.80255 + dps: 1348.66714 + tps: 3431.43035 } } dps_results: { key: "TestProtectionWarrior-AllItems-SiegebreakerPlate" value: { - dps: 1362.18488 - tps: 3534.24554 + dps: 1226.35732 + tps: 3155.63414 } } dps_results: { key: "TestProtectionWarrior-AllItems-Sindragosa'sFlawlessFang-50361" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-SliverofPureIce-50339" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-SliverofPureIce-50346" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-SoulPreserver-37111" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-SouloftheDead-40382" value: { - dps: 1468.61799 - tps: 3808.46535 + dps: 1324.25226 + tps: 3408.21696 } } dps_results: { key: "TestProtectionWarrior-AllItems-SparkofLife-37657" value: { - dps: 1440.66133 - tps: 3742.16595 + dps: 1309.36532 + tps: 3376.66033 } } dps_results: { key: "TestProtectionWarrior-AllItems-SphereofRedDragon'sBlood-37166" value: { - dps: 1478.71065 - tps: 3846.54338 + dps: 1322.14884 + tps: 3404.71972 } } dps_results: { key: "TestProtectionWarrior-AllItems-StormshroudArmor" value: { - dps: 1131.41118 - tps: 2973.77697 + dps: 1027.97703 + tps: 2682.10178 } } dps_results: { key: "TestProtectionWarrior-AllItems-SwiftSkyflareDiamond" value: { - dps: 1439.81394 - tps: 3750.17262 + dps: 1292.37353 + tps: 3334.12396 } } dps_results: { key: "TestProtectionWarrior-AllItems-SwiftStarflareDiamond" value: { - dps: 1441.44826 - tps: 3755.28496 + dps: 1291.63371 + tps: 3332.58995 } } dps_results: { key: "TestProtectionWarrior-AllItems-SwiftWindfireDiamond" value: { - dps: 1434.21835 - tps: 3734.84239 + dps: 1290.33903 + tps: 3329.90542 } } dps_results: { key: "TestProtectionWarrior-AllItems-TalismanofTrollDivinity-37734" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-TearsoftheVanquished-47215" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-TheFistsofFury" value: { - dps: 1002.18698 - tps: 2269.92269 + dps: 638.3805 + tps: 1332.04643 } } dps_results: { key: "TestProtectionWarrior-AllItems-TheGeneral'sHeart-45507" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-TheTwinBladesofAzzinoth" value: { - dps: 1067.10265 - tps: 2408.07406 + dps: 672.48703 + tps: 1402.91131 } } dps_results: { key: "TestProtectionWarrior-AllItems-ThunderingSkyflareDiamond" value: { - dps: 1433.77973 - tps: 3730.22067 + dps: 1295.25946 + tps: 3338.84336 } } dps_results: { key: "TestProtectionWarrior-AllItems-TinyAbominationinaJar-50351" value: { - dps: 1478.24422 - tps: 3833.2328 + dps: 1336.15076 + tps: 3441.80734 } } dps_results: { key: "TestProtectionWarrior-AllItems-TinyAbominationinaJar-50706" value: { - dps: 1467.27925 - tps: 3802.76201 + dps: 1350.48168 + tps: 3475.99802 } } dps_results: { key: "TestProtectionWarrior-AllItems-TirelessSkyflareDiamond" value: { - dps: 1429.13677 - tps: 3723.6434 + dps: 1288.48948 + tps: 3326.07038 } } dps_results: { key: "TestProtectionWarrior-AllItems-TirelessStarflareDiamond" value: { - dps: 1429.13677 - tps: 3723.6434 + dps: 1288.48948 + tps: 3326.07038 } } dps_results: { key: "TestProtectionWarrior-AllItems-TomeofArcanePhenomena-36972" value: { - dps: 1436.78984 - tps: 3728.88041 + dps: 1308.92313 + tps: 3378.26678 } } dps_results: { key: "TestProtectionWarrior-AllItems-TrenchantEarthshatterDiamond" value: { - dps: 1429.13677 - tps: 3723.6434 + dps: 1288.48948 + tps: 3326.07038 } } dps_results: { key: "TestProtectionWarrior-AllItems-TrenchantEarthsiegeDiamond" value: { - dps: 1429.13677 - tps: 3723.6434 + dps: 1288.48948 + tps: 3326.07038 } } dps_results: { key: "TestProtectionWarrior-AllItems-UndeadSlayer'sBlessedArmor" value: { - dps: 1207.40792 - tps: 3148.8019 + dps: 1086.63762 + tps: 2805.44607 } } dps_results: { key: "TestProtectionWarrior-AllItems-Val'anyr,HammerofAncientKings-46017" value: { - dps: 1320.86781 - tps: 3455.68965 + dps: 1216.28045 + tps: 3164.34375 } } dps_results: { key: "TestProtectionWarrior-AllItems-WingedTalisman-37844" value: { - dps: 1443.50947 - tps: 3757.45627 + dps: 1289.69323 + tps: 3328.56635 } } dps_results: { key: "TestProtectionWarrior-AllItems-Wrynn'sBattlegear" value: { - dps: 1715.22713 - tps: 4343.02026 + dps: 1501.65236 + tps: 3779.411 } } dps_results: { key: "TestProtectionWarrior-AllItems-Wrynn'sPlate" value: { - dps: 1438.9139 - tps: 3715.52095 + dps: 1310.8597 + tps: 3363.59082 } } dps_results: { key: "TestProtectionWarrior-AllItems-YmirjarLord'sBattlegear" value: { - dps: 1915.35055 - tps: 4811.31977 + dps: 1681.60003 + tps: 4188.20074 } } dps_results: { key: "TestProtectionWarrior-AllItems-YmirjarLord'sPlate" value: { - dps: 1565.56182 - tps: 4034.16559 + dps: 1425.09691 + tps: 3644.74776 } } dps_results: { key: "TestProtectionWarrior-Average-Default" value: { - dps: 2771.65176 - tps: 6733.04173 - dtps: 127.4897 + dps: 2540.72733 + tps: 6095.0764 + dtps: 127.44615 } } dps_results: { key: "TestProtectionWarrior-Settings-Human-p1_balanced-Basic-default-FullBuffs-LongMultiTarget" value: { - dps: 1476.36368 - tps: 3891.49394 + dps: 1353.97589 + tps: 3511.30182 } } dps_results: { key: "TestProtectionWarrior-Settings-Human-p1_balanced-Basic-default-FullBuffs-LongSingleTarget" value: { - dps: 1476.36368 - tps: 3840.82728 + dps: 1353.97589 + tps: 3501.81765 } } dps_results: { key: "TestProtectionWarrior-Settings-Human-p1_balanced-Basic-default-FullBuffs-ShortSingleTarget" value: { - dps: 1639.76544 - tps: 4236.26058 + dps: 1561.83404 + tps: 4024.60825 } } dps_results: { key: "TestProtectionWarrior-Settings-Human-p1_balanced-Basic-default-NoBuffs-LongMultiTarget" value: { - dps: 1084.94322 - tps: 3407.20547 + dps: 1094.86734 + tps: 3435.07618 } } dps_results: { key: "TestProtectionWarrior-Settings-Human-p1_balanced-Basic-default-NoBuffs-LongSingleTarget" value: { - dps: 866.97075 - tps: 2487.10038 + dps: 882.0064 + tps: 2533.03893 } } dps_results: { @@ -971,36 +971,36 @@ dps_results: { dps_results: { key: "TestProtectionWarrior-Settings-Orc-p1_balanced-Basic-default-FullBuffs-LongMultiTarget" value: { - dps: 1493.10216 - tps: 3930.30504 + dps: 1360.20142 + tps: 3524.55292 } } dps_results: { key: "TestProtectionWarrior-Settings-Orc-p1_balanced-Basic-default-FullBuffs-LongSingleTarget" value: { - dps: 1493.10216 - tps: 3879.63837 + dps: 1360.20142 + tps: 3515.09003 } } dps_results: { key: "TestProtectionWarrior-Settings-Orc-p1_balanced-Basic-default-FullBuffs-ShortSingleTarget" value: { - dps: 1681.29892 - tps: 4344.50046 + dps: 1573.75672 + tps: 4049.75167 } } dps_results: { key: "TestProtectionWarrior-Settings-Orc-p1_balanced-Basic-default-NoBuffs-LongMultiTarget" value: { - dps: 1097.36592 - tps: 3443.56821 + dps: 1104.93219 + tps: 3468.9695 } } dps_results: { key: "TestProtectionWarrior-Settings-Orc-p1_balanced-Basic-default-NoBuffs-LongSingleTarget" value: { - dps: 881.93425 - tps: 2531.41294 + dps: 885.75406 + tps: 2542.0882 } } dps_results: { @@ -1013,8 +1013,8 @@ dps_results: { dps_results: { key: "TestProtectionWarrior-SwitchInFrontOfTarget-Default" value: { - dps: 2890.35455 - tps: 7022.68811 - dtps: 120.81343 + dps: 2658.90648 + tps: 6391.54637 + dtps: 120.61498 } } diff --git a/sim/warrior/protection/protection_warrior.go b/sim/warrior/protection/protection_warrior.go index d8c4ce30fb..7b9ab5899d 100644 --- a/sim/warrior/protection/protection_warrior.go +++ b/sim/warrior/protection/protection_warrior.go @@ -1,7 +1,6 @@ package protection import ( - "github.com/wowsims/wotlk/sim/common" "github.com/wowsims/wotlk/sim/core" "github.com/wowsims/wotlk/sim/core/proto" "github.com/wowsims/wotlk/sim/warrior" @@ -27,21 +26,15 @@ func RegisterProtectionWarrior() { type ProtectionWarrior struct { *warrior.Warrior - Rotation *proto.ProtectionWarrior_Rotation - Options *proto.ProtectionWarrior_Options - - CustomRotation *common.CustomRotation + Options *proto.ProtectionWarrior_Options } func NewProtectionWarrior(character *core.Character, options *proto.Player) *ProtectionWarrior { warOptions := options.GetProtectionWarrior() war := &ProtectionWarrior{ - Warrior: warrior.NewWarrior(character, options.TalentsString, warrior.WarriorInputs{ - ShoutType: warOptions.Options.Shout, - }), - Rotation: warOptions.Rotation, - Options: warOptions.Options, + Warrior: warrior.NewWarrior(character, options.TalentsString, warrior.WarriorInputs{}), + Options: warOptions.Options, } rbo := core.RageBarOptions{ @@ -80,8 +73,6 @@ func (war *ProtectionWarrior) GetWarrior() *warrior.Warrior { func (war *ProtectionWarrior) Initialize() { war.Warrior.Initialize() - war.RegisterHSOrCleave(false, war.Rotation.HsRageThreshold) - war.RegisterRendSpell(0, 0) war.RegisterShieldWallCD() war.RegisterShieldBlockCD() war.DefensiveStanceAura.BuildPhase = core.CharacterBuildPhaseTalents diff --git a/sim/warrior/protection/rotation.go b/sim/warrior/protection/rotation.go deleted file mode 100644 index eac4131895..0000000000 --- a/sim/warrior/protection/rotation.go +++ /dev/null @@ -1,113 +0,0 @@ -package protection - -import ( - "github.com/wowsims/wotlk/sim/common" - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/core/proto" - "github.com/wowsims/wotlk/sim/warrior" -) - -func (war *ProtectionWarrior) OnGCDReady(sim *core.Simulation) { - war.doRotation(sim) -} - -func (war *ProtectionWarrior) OnAutoAttack(sim *core.Simulation, spell *core.Spell) { - war.tryQueueHsCleave(sim) -} - -func (war *ProtectionWarrior) doRotation(sim *core.Simulation) { - war.trySwapToDefensive(sim) - war.CustomRotation.Cast(sim) - - // if we did nothing else, mark we intentionally did nothing here. - if war.GCD.IsReady(sim) { - war.DoNothing() - } -} - -func (war *ProtectionWarrior) tryQueueHsCleave(sim *core.Simulation) { - if war.ShouldQueueHSOrCleave(sim) { - war.QueueHSOrCleave(sim) - } -} - -func (war *ProtectionWarrior) shouldDemoShout(sim *core.Simulation) bool { - return war.ShouldDemoralizingShout(sim, war.CurrentTarget, - war.Rotation.DemoShoutChoice == proto.ProtectionWarrior_Rotation_DemoShoutChoiceFiller, - war.Rotation.DemoShoutChoice == proto.ProtectionWarrior_Rotation_DemoShoutChoiceMaintain) -} - -func (war *ProtectionWarrior) shouldThunderClap(sim *core.Simulation) bool { - return war.ShouldThunderClap(sim, war.CurrentTarget, - war.Rotation.ThunderClapChoice == proto.ProtectionWarrior_Rotation_ThunderClapChoiceOnCD, - war.Rotation.ThunderClapChoice == proto.ProtectionWarrior_Rotation_ThunderClapChoiceMaintain, - false) -} - -func (war *ProtectionWarrior) trySwapToDefensive(sim *core.Simulation) bool { - if !war.StanceMatches(warrior.DefensiveStance) && war.DefensiveStance.IsReady(sim) { - war.DefensiveStance.Cast(sim, nil) - return true - } - return false -} - -func (war *ProtectionWarrior) makeCustomRotation() *common.CustomRotation { - return common.NewCustomRotation(war.Rotation.CustomRotation, war.GetCharacter(), map[int32]common.CustomSpell{ - int32(proto.ProtectionWarrior_Rotation_Revenge): { - Spell: war.Revenge, - Condition: func(sim *core.Simulation) bool { - if !war.Rotation.PrioSslamOnShieldBlock { - return war.Revenge.CanCast(sim, war.CurrentTarget) - } - - if war.ShieldBlockAura.IsActive() { - return !war.ShieldSlam.CanCast(sim, war.CurrentTarget) && war.Revenge.CanCast(sim, war.CurrentTarget) - } else { - return war.Revenge.CanCast(sim, war.CurrentTarget) - } - }, - }, - int32(proto.ProtectionWarrior_Rotation_ShieldSlam): { - Spell: war.ShieldSlam, - Condition: func(sim *core.Simulation) bool { - if !war.Rotation.PrioSslamOnShieldBlock { - return war.ShieldSlam.CanCast(sim, war.CurrentTarget) - } - - if war.ShieldBlockAura.IsActive() { - return war.ShieldSlam.CanCast(sim, war.CurrentTarget) - } else { - return !war.Revenge.CanCast(sim, war.CurrentTarget) && war.ShieldSlam.CanCast(sim, war.CurrentTarget) - } - }, - }, - int32(proto.ProtectionWarrior_Rotation_Devastate): { - Spell: war.Devastate, - }, - int32(proto.ProtectionWarrior_Rotation_SunderArmor): { - Spell: war.SunderArmor, - }, - int32(proto.ProtectionWarrior_Rotation_DemoralizingShout): { - Spell: war.DemoralizingShout, - Condition: war.shouldDemoShout, - }, - int32(proto.ProtectionWarrior_Rotation_ThunderClap): { - Spell: war.ThunderClap, - Condition: war.shouldThunderClap, - }, - int32(proto.ProtectionWarrior_Rotation_Shout): { - Spell: war.Shout, - Condition: war.ShouldShout, - }, - int32(proto.ProtectionWarrior_Rotation_MortalStrike): { - Spell: war.MortalStrike, - }, - int32(proto.ProtectionWarrior_Rotation_ConcussionBlow): { - Spell: war.ConcussionBlow, - }, - int32(proto.ProtectionWarrior_Rotation_Shockwave): { - Spell: war.Shockwave, - }, - }) -} diff --git a/sim/warrior/rend.go b/sim/warrior/rend.go index 06df46ca63..9efc680e2e 100644 --- a/sim/warrior/rend.go +++ b/sim/warrior/rend.go @@ -8,7 +8,7 @@ import ( ) // TODO (maybe) https://github.com/magey/wotlk-warrior/issues/23 - Rend is not benefitting from Two-Handed Weapon Specialization -func (warrior *Warrior) RegisterRendSpell(rageThreshold float64, healthThreshold float64) { +func (warrior *Warrior) RegisterRendSpell() { dotDuration := time.Second * 15 dotTicks := int32(5) if warrior.HasMajorGlyph(proto.WarriorMajorGlyph_GlyphOfRending) { @@ -70,27 +70,6 @@ func (warrior *Warrior) RegisterRendSpell(rageThreshold float64, healthThreshold } spell.DealOutcome(sim, result) - - // Queue Overpower to be cast at 3s after rend if talented for 3/3 TfB - if warrior.Talents.TasteForBlood == 3 { - core.StartDelayedAction(sim, core.DelayedActionOptions{ - DoAt: sim.CurrentTime + time.Second*3, - OnAction: func(_ *core.Simulation) { - // Force to use OP on first 3s due to AM ticks that happens before TfB procs and break that - if warrior.Overpower.CanCast(sim, target) && (warrior.ShouldOverpower(sim) || sim.CurrentTime >= time.Second*3 && sim.CurrentTime <= time.Second*4) { - warrior.CastFullTfbOverpower(sim, target) - } - }, - }) - } }, }) - - warrior.RendHealthThresholdAbove = healthThreshold / 100 - warrior.RendRageThresholdBelow = max(warrior.Rend.DefaultCast.Cost, rageThreshold) -} - -func (warrior *Warrior) ShouldRend(sim *core.Simulation) bool { - return warrior.Rend.IsReady(sim) && sim.CurrentTime >= (warrior.RendValidUntil-warrior.RendCdThreshold) && - warrior.CurrentRage() >= warrior.Rend.DefaultCast.Cost && warrior.RendHealthThresholdAbove < sim.GetRemainingDurationPercent() } diff --git a/sim/warrior/shouts.go b/sim/warrior/shouts.go index 8bf929945a..e592990b1b 100644 --- a/sim/warrior/shouts.go +++ b/sim/warrior/shouts.go @@ -36,24 +36,12 @@ func (warrior *Warrior) makeShoutSpellHelper(actionID core.ActionID, allyAuras c }) } -func (warrior *Warrior) makeShoutSpell() *core.Spell { - battleShout := warrior.makeShoutSpellHelper(core.ActionID{SpellID: 47436}, warrior.NewAllyAuraArray(func(unit *core.Unit) *core.Aura { +func (warrior *Warrior) registerShouts() { + warrior.BattleShout = warrior.makeShoutSpellHelper(core.ActionID{SpellID: 47436}, warrior.NewAllyAuraArray(func(unit *core.Unit) *core.Aura { return core.BattleShoutAura(unit, warrior.Talents.CommandingPresence, warrior.Talents.BoomingVoice, warrior.HasMinorGlyph(proto.WarriorMinorGlyph_GlyphOfBattle)) })) - commandingShout := warrior.makeShoutSpellHelper(core.ActionID{SpellID: 47440}, warrior.NewAllyAuraArray(func(unit *core.Unit) *core.Aura { + warrior.CommandingShout = warrior.makeShoutSpellHelper(core.ActionID{SpellID: 47440}, warrior.NewAllyAuraArray(func(unit *core.Unit) *core.Aura { return core.CommandingShoutAura(unit, warrior.Talents.CommandingPresence, warrior.Talents.BoomingVoice, warrior.HasMinorGlyph(proto.WarriorMinorGlyph_GlyphOfCommand)) })) - - if warrior.ShoutType == proto.WarriorShout_WarriorShoutBattle { - return battleShout - } else if warrior.ShoutType == proto.WarriorShout_WarriorShoutCommanding { - return commandingShout - } else { - return nil - } -} - -func (warrior *Warrior) ShouldShout(sim *core.Simulation) bool { - return warrior.Shout != nil && warrior.CurrentRage() >= warrior.Shout.DefaultCast.Cost && warrior.Shout.ShouldRefreshExclusiveEffects(sim, &warrior.Unit, ShoutExpirationThreshold) } diff --git a/sim/warrior/warrior.go b/sim/warrior/warrior.go index 0075ca70bb..17d48abdf7 100644 --- a/sim/warrior/warrior.go +++ b/sim/warrior/warrior.go @@ -11,13 +11,7 @@ import ( var TalentTreeSizes = [3]int{31, 27, 27} type WarriorInputs struct { - ShoutType proto.WarriorShout - PrecastShout bool - PrecastShoutSapphire bool - PrecastShoutT2 bool - RendCdThreshold time.Duration - BloodsurgeDurationThreshold time.Duration - StanceSnapshot bool + StanceSnapshot bool } const ( @@ -48,7 +42,8 @@ type Warrior struct { lastOverpowerProc time.Duration LastAMTick time.Duration - Shout *core.Spell + BattleShout *core.Spell + CommandingShout *core.Spell BattleStance *core.Spell DefensiveStance *core.Spell BerserkerStance *core.Spell @@ -76,16 +71,12 @@ type Warrior struct { Bladestorm *core.Spell BladestormOH *core.Spell - HeroicStrike *core.Spell - Cleave *core.Spell - hsOrCleaveQueueSpell *core.Spell - curQueueAura *core.Aura - curQueuedAutoSpell *core.Spell + HeroicStrike *core.Spell + Cleave *core.Spell + curQueueAura *core.Aura + curQueuedAutoSpell *core.Spell - OverpowerAura *core.Aura - HSRageThreshold float64 - RendRageThresholdBelow float64 - RendHealthThresholdAbove float64 + OverpowerAura *core.Aura BattleStanceAura *core.Aura DefensiveStanceAura *core.Aura @@ -117,19 +108,20 @@ func (warrior *Warrior) Initialize() { warrior.AutoAttacks.MHConfig().CritMultiplier = warrior.autoCritMultiplier(mh) warrior.AutoAttacks.OHConfig().CritMultiplier = warrior.autoCritMultiplier(oh) - warrior.Shout = warrior.makeShoutSpell() - primaryTimer := warrior.NewTimer() overpowerRevengeTimer := warrior.NewTimer() warrior.reactionTime = time.Millisecond * 500 + warrior.registerShouts() warrior.registerStances() warrior.registerBerserkerRageSpell() warrior.registerBloodthirstSpell(primaryTimer) + warrior.registerCleaveSpell() warrior.registerDemoralizingShoutSpell() warrior.registerDevastateSpell() warrior.registerExecuteSpell() + warrior.registerHeroicStrikeSpell() warrior.registerMortalStrikeSpell(primaryTimer) warrior.registerOverpowerSpell(overpowerRevengeTimer) warrior.registerRevengeSpell(overpowerRevengeTimer) @@ -140,17 +132,12 @@ func (warrior *Warrior) Initialize() { warrior.registerShockwaveSpell() warrior.registerConcussionBlowSpell() warrior.RegisterHeroicThrow() + warrior.RegisterRendSpell() warrior.SunderArmor = warrior.newSunderArmorSpell(false) warrior.SunderArmorDevastate = warrior.newSunderArmorSpell(true) warrior.registerBloodrageCD() - - if !warrior.IsUsingAPL && warrior.Shout != nil && warrior.PrecastShout { - warrior.RegisterPrepullAction(-10*time.Second, func(sim *core.Simulation) { - warrior.Shout.SkipCastAndApplyEffects(sim, nil) - }) - } } func (warrior *Warrior) Reset(_ *core.Simulation) { From 10f8370260a73181c8719aefca4efba5e50f0c13 Mon Sep 17 00:00:00 2001 From: James Tanner Date: Sat, 6 Jan 2024 15:21:56 -0800 Subject: [PATCH 15/28] Fix ui compile error --- ui/core/components/individual_sim_ui/apl_values.ts | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/ui/core/components/individual_sim_ui/apl_values.ts b/ui/core/components/individual_sim_ui/apl_values.ts index a74c7a6aca..85cecb6e28 100644 --- a/ui/core/components/individual_sim_ui/apl_values.ts +++ b/ui/core/components/individual_sim_ui/apl_values.ts @@ -48,7 +48,6 @@ import { APLValueSpellTimeToReady, APLValueSpellCastTime, APLValueSpellTravelTime, - APLValueSpellChannelTime, APLValueSpellCPM, APLValueSpellIsChanneling, APLValueSpellChanneledTicks, @@ -825,15 +824,6 @@ const valueKindFactories: {[f in NonNullable]: ValueKindConfig Date: Sat, 6 Jan 2024 19:23:48 -0800 Subject: [PATCH 16/28] Commit before making another DK fix on master --- proto/deathknight.proto | 133 ------------------ sim/deathknight/anti_magic_shell.go | 6 +- sim/deathknight/deathknight.go | 48 ++----- sim/deathknight/dps/dps_deathknight.go | 26 ++-- sim/deathknight/dps/dps_deathknight_test.go | 56 ++------ sim/deathknight/horn_of_winter.go | 27 ---- sim/deathknight/summon_gargoyle.go | 27 ++-- sim/deathknight/tank/tank_deathknight.go | 2 +- sim/deathknight/tank/tank_deathknight_test.go | 1 - 9 files changed, 42 insertions(+), 284 deletions(-) diff --git a/proto/deathknight.proto b/proto/deathknight.proto index 4f9d2955ff..feeaa4083c 100644 --- a/proto/deathknight.proto +++ b/proto/deathknight.proto @@ -143,143 +143,12 @@ enum DeathknightMinorGlyph { message Deathknight { message Rotation { - enum DrwDiseases { - DoNotApply = 0; - Normal = 1; - Pestilence = 2; - } - - enum ArmyOfTheDead { - DoNotUse = 0; - PreCast = 1; - AsMajorCd = 2; - } - - enum BloodTap { - GhoulFrenzy = 0; - IcyTouch = 1; - BloodStrikeBT = 2; - BloodBoilBT = 3; - } - - enum DeathAndDecayPrio { - MaxRuneDowntime = 0; - MaxDndUptime = 1; - } - - enum FirstDisease { - FrostFever = 0; - BloodPlague = 1; - } - - enum BloodRuneFiller { - BloodStrike = 0; - BloodBoil = 1; - } - - enum Presence { - Blood = 0; - Unholy = 1; - Frost = 2; - } - - enum FrostRotationType { - UnknownType = 0; - SingleTarget = 1; - Custom = 2; - } - FrostRotationType frost_rotation_type = 19; - - enum BloodOpener { - Standard = 0; - Experimental_1 = 1; - Experimental_2 = 2; - } - - enum BloodSpell { - HS = 0; - BB = 1; - BS = 2; - } - - enum CustomSpellOption { - CustomNoSpell = 0; - CustomIcyTouch = 1; - CustomPlagueStrike = 2; - CustomPestilence = 3; - CustomObliterate = 4; - CustomHowlingBlast = 5; - CustomHowlingBlastRime = 6; - CustomBloodBoil = 7; - CustomBloodStrike = 8; - CustomDeathAndDecay = 9; - CustomHornOfWinter = 10; - CustomUnbreakableArmor = 11; - CustomBloodTap = 12; - CustomEmpoweredRuneWeapon = 13; - CustomFrostStrike = 14; - } - CustomRotation frost_custom_rotation = 20; - - ArmyOfTheDead army_of_the_dead = 1; - bool use_death_and_decay = 2; - - bool bt_ghoul_frenzy = 3; - - double disease_refresh_duration = 4; - bool refresh_horn_of_winter = 5; - - FirstDisease first_disease = 6; - - DeathAndDecayPrio death_and_decay_prio = 7; - - bool use_empower_rune_weapon = 8; - - BloodRuneFiller blood_rune_filler = 9; - - Presence starting_presence = 10; - BloodTap blood_tap = 11; - - bool use_ams = 13 [deprecated = true]; - double avg_ams_success_rate = 14 [deprecated = true]; - double avg_ams_hit = 15 [deprecated = true]; - - bool auto_rotation = 16; - - bool desync_rotation = 17; - - Presence bl_presence = 18; - - Presence presence = 21; - - bool hold_erw_army = 22; - - bool use_gargoyle = 23; - - bool pre_nerfed_gargoyle = 24; - - Presence gargoyle_presence = 25; - - DrwDiseases drw_diseases = 26; - BloodOpener blood_opener = 27; - - bool enable_weapon_swap = 28; - ItemSwap weapon_swap = 29; - - bool use_dancing_rune_weapon = 30; - - BloodSpell blood_spender = 31; - - double virulence_refresh = 32; } Rotation rotation = 1; message Options { double starting_runic_power = 1; double pet_uptime = 2; - - bool precast_ghoul_frenzy = 3; - bool precast_horn_of_winter = 4; UnitReference unholy_frenzy_target = 5; @@ -287,8 +156,6 @@ message Deathknight { bool new_drw = 7; - double disease_downtime = 8; - bool use_ams = 9; double avg_ams_success_rate = 10; double avg_ams_hit = 11; diff --git a/sim/deathknight/anti_magic_shell.go b/sim/deathknight/anti_magic_shell.go index 79a70d47d8..d46cf66bc3 100644 --- a/sim/deathknight/anti_magic_shell.go +++ b/sim/deathknight/anti_magic_shell.go @@ -10,8 +10,6 @@ import ( func (dk *Deathknight) registerAntiMagicShellSpell() { actionID := core.ActionID{SpellID: 48707} - cdTimer := dk.NewTimer() - cd := time.Second * 45 dk.AntiMagicShell = dk.RegisterSpell(core.SpellConfig{ ActionID: actionID, @@ -22,8 +20,8 @@ func (dk *Deathknight) registerAntiMagicShellSpell() { }, Cast: core.CastConfig{ CD: core.Cooldown{ - Timer: cdTimer, - Duration: cd, + Timer: dk.NewTimer(), + Duration: time.Second * 45, }, IgnoreHaste: true, }, diff --git a/sim/deathknight/deathknight.go b/sim/deathknight/deathknight.go index 9c05192037..61c53fe706 100644 --- a/sim/deathknight/deathknight.go +++ b/sim/deathknight/deathknight.go @@ -10,14 +10,6 @@ import ( "github.com/wowsims/wotlk/sim/core/stats" ) -type Rotation_FuStrike int32 - -const ( - FuStrike_DeathStrike Rotation_FuStrike = 0 - FuStrike_ScourgeStrike Rotation_FuStrike = 1 - FuStrike_Obliterate Rotation_FuStrike = 2 -) - const ( PetSpellHitScale = 17.0 / 8.0 * core.SpellHitRatingPerHitChance / core.MeleeHitRatingPerHitChance // 1.7 PetExpertiseScale = 3.25 * core.ExpertisePerQuarterPercentReduction / core.MeleeHitRatingPerHitChance // 0.8125 @@ -33,23 +25,14 @@ type DeathknightInputs struct { UnholyFrenzyTarget *proto.UnitReference - StartingRunicPower float64 - PrecastGhoulFrenzy bool - PrecastHornOfWinter bool - PetUptime float64 - DrwPestiApply bool - BloodOpener proto.Deathknight_Rotation_BloodOpener + StartingRunicPower float64 + PetUptime float64 + DrwPestiApply bool // Rotation Vars - RefreshHornOfWinter bool - ArmyOfTheDeadType proto.Deathknight_Rotation_ArmyOfTheDead - StartingPresence proto.Deathknight_Rotation_Presence - UseAMS bool - AvgAMSSuccessRate float64 - AvgAMSHit float64 - FuStrike Rotation_FuStrike - DiseaseDowntime float64 - VirulenceRefresh float64 + UseAMS bool + AvgAMSSuccessRate float64 + AvgAMSHit float64 } type DeathknightCoeffs struct { @@ -143,10 +126,8 @@ type Deathknight struct { HowlingBlast *core.Spell - HasDraeneiHitAura bool - OtherRelevantStrAgiActive bool - HornOfWinter *core.Spell - HornOfWinterAura *core.Aura + HasDraeneiHitAura bool + HornOfWinter *core.Spell // "CDs" RuneTap *core.Spell @@ -257,14 +238,7 @@ func (dk *Deathknight) AddRaidBuffs(raidBuffs *proto.RaidBuffs) { raidBuffs.IcyTalons = true } - raidBuffs.HornOfWinter = !dk.Inputs.RefreshHornOfWinter - - if raidBuffs.StrengthOfEarthTotem == proto.TristateEffect_TristateEffectImproved || - raidBuffs.StrengthOfEarthTotem == proto.TristateEffect_TristateEffectRegular { - dk.OtherRelevantStrAgiActive = true - } else { - dk.OtherRelevantStrAgiActive = false - } + raidBuffs.HornOfWinter = true } func (dk *Deathknight) ApplyTalents() { @@ -379,7 +353,7 @@ func (dk *Deathknight) HasMinorGlyph(glyph proto.DeathknightMinorGlyph) bool { return dk.HasGlyph(int32(glyph)) } -func NewDeathknight(character *core.Character, inputs DeathknightInputs, talents string, preNerfedGargoyle bool) *Deathknight { +func NewDeathknight(character *core.Character, inputs DeathknightInputs, talents string) *Deathknight { dk := &Deathknight{ Character: *character, Talents: &proto.DeathknightTalents{}, @@ -421,7 +395,7 @@ func NewDeathknight(character *core.Character, inputs DeathknightInputs, talents dk.PseudoStats.MeleeHasteRatingPerHastePercent /= 1.3 if dk.Talents.SummonGargoyle { - dk.Gargoyle = dk.NewGargoyle(!preNerfedGargoyle) + dk.Gargoyle = dk.NewGargoyle() } dk.Ghoul = dk.NewGhoulPet(dk.Talents.MasterOfGhouls) diff --git a/sim/deathknight/dps/dps_deathknight.go b/sim/deathknight/dps/dps_deathknight.go index b5d8c369d1..de021426d0 100644 --- a/sim/deathknight/dps/dps_deathknight.go +++ b/sim/deathknight/dps/dps_deathknight.go @@ -32,24 +32,16 @@ func NewDpsDeathknight(character *core.Character, player *proto.Player) *DpsDeat dpsDk := &DpsDeathknight{ Deathknight: deathknight.NewDeathknight(character, deathknight.DeathknightInputs{ - StartingRunicPower: dk.Options.StartingRunicPower, - PrecastGhoulFrenzy: dk.Options.PrecastGhoulFrenzy, - PrecastHornOfWinter: dk.Options.PrecastHornOfWinter, - PetUptime: dk.Options.PetUptime, - DrwPestiApply: dk.Options.DrwPestiApply, - BloodOpener: dk.Rotation.BloodOpener, - IsDps: true, - NewDrw: true, - DiseaseDowntime: dk.Options.DiseaseDowntime, - VirulenceRefresh: dk.Rotation.VirulenceRefresh, + StartingRunicPower: dk.Options.StartingRunicPower, + PetUptime: dk.Options.PetUptime, + DrwPestiApply: dk.Options.DrwPestiApply, + IsDps: true, + NewDrw: true, - RefreshHornOfWinter: dk.Rotation.RefreshHornOfWinter, - ArmyOfTheDeadType: dk.Rotation.ArmyOfTheDead, - StartingPresence: dk.Rotation.StartingPresence, - UseAMS: dk.Options.UseAms, - AvgAMSSuccessRate: dk.Options.AvgAmsSuccessRate, - AvgAMSHit: dk.Options.AvgAmsHit, - }, player.TalentsString, dk.Rotation.PreNerfedGargoyle), + UseAMS: dk.Options.UseAms, + AvgAMSSuccessRate: dk.Options.AvgAmsSuccessRate, + AvgAMSHit: dk.Options.AvgAmsHit, + }, player.TalentsString), } dpsDk.Inputs.UnholyFrenzyTarget = dk.Options.UnholyFrenzyTarget diff --git a/sim/deathknight/dps/dps_deathknight_test.go b/sim/deathknight/dps/dps_deathknight_test.go index 4aff6eb371..f0db8878b3 100644 --- a/sim/deathknight/dps/dps_deathknight_test.go +++ b/sim/deathknight/dps/dps_deathknight_test.go @@ -126,73 +126,33 @@ var UnholyDefaultGlyphs = &proto.Glyphs{ var PlayerOptionsBlood = &proto.Player_Deathknight{ Deathknight: &proto.Deathknight{ - Options: deathKnightOptions, - Rotation: bloodRotation, + Options: deathKnightOptions, }, } var PlayerOptionsUnholy = &proto.Player_Deathknight{ Deathknight: &proto.Deathknight{ - Options: deathKnightOptions, - Rotation: unholyRotation, + Options: deathKnightOptions, }, } var PlayerOptionsFrost = &proto.Player_Deathknight{ Deathknight: &proto.Deathknight{ - Options: deathKnightOptions, - Rotation: frostRotation, + Options: deathKnightOptions, }, } var PlayerOptionsDesyncFrost = &proto.Player_Deathknight{ Deathknight: &proto.Deathknight{ - Options: deathKnightOptions, - Rotation: frostDesyncRotation, + Options: deathKnightOptions, }, } -var bloodRotation = &proto.Deathknight_Rotation{ - ArmyOfTheDead: proto.Deathknight_Rotation_PreCast, - DrwDiseases: proto.Deathknight_Rotation_Pestilence, - UseEmpowerRuneWeapon: true, - PreNerfedGargoyle: false, - UseDancingRuneWeapon: true, - BloodSpender: proto.Deathknight_Rotation_HS, -} - -var unholyRotation = &proto.Deathknight_Rotation{ - UseDeathAndDecay: true, - StartingPresence: proto.Deathknight_Rotation_Unholy, - BlPresence: proto.Deathknight_Rotation_Blood, - Presence: proto.Deathknight_Rotation_Blood, - GargoylePresence: proto.Deathknight_Rotation_Unholy, - UseEmpowerRuneWeapon: true, - UseGargoyle: true, - BtGhoulFrenzy: false, - HoldErwArmy: false, - PreNerfedGargoyle: false, - BloodRuneFiller: proto.Deathknight_Rotation_BloodBoil, - ArmyOfTheDead: proto.Deathknight_Rotation_AsMajorCd, - BloodTap: proto.Deathknight_Rotation_GhoulFrenzy, -} - -var frostRotation = &proto.Deathknight_Rotation{ - UseEmpowerRuneWeapon: true, -} - -var frostDesyncRotation = &proto.Deathknight_Rotation{ - UseEmpowerRuneWeapon: true, - DesyncRotation: true, -} - var deathKnightOptions = &proto.Deathknight_Options{ - UnholyFrenzyTarget: &proto.UnitReference{Type: proto.UnitReference_Player, Index: 0}, - DrwPestiApply: true, - StartingRunicPower: 0, - PetUptime: 1, - PrecastGhoulFrenzy: false, - PrecastHornOfWinter: true, + UnholyFrenzyTarget: &proto.UnitReference{Type: proto.UnitReference_Player, Index: 0}, + DrwPestiApply: true, + StartingRunicPower: 0, + PetUptime: 1, } var FullConsumes = &proto.Consumes{ diff --git a/sim/deathknight/horn_of_winter.go b/sim/deathknight/horn_of_winter.go index 8554b8a488..1ef67ae6e6 100644 --- a/sim/deathknight/horn_of_winter.go +++ b/sim/deathknight/horn_of_winter.go @@ -4,35 +4,12 @@ import ( "time" "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/core/proto" - "github.com/wowsims/wotlk/sim/core/stats" ) func (dk *Deathknight) registerHornOfWinterSpell() { actionID := core.ActionID{SpellID: 57623} - duration := time.Minute * time.Duration((2.0 + core.TernaryFloat64(dk.HasMinorGlyph(proto.DeathknightMinorGlyph_GlyphOfHornOfWinter), 1.0, 0.0))) rpMetrics := dk.NewRunicPowerMetrics(actionID) - bonusStats := stats.Stats{stats.Strength: 155.0, stats.Agility: 155.0} - negativeStats := bonusStats.Invert() - - dk.HornOfWinterAura = dk.RegisterAura(core.Aura{ - Label: "Horn of Winter", - ActionID: actionID, - Duration: duration, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - if !dk.OtherRelevantStrAgiActive { - dk.HornOfWinterAura.Unit.AddStatsDynamic(sim, bonusStats) - } - }, - - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - if !dk.OtherRelevantStrAgiActive { - dk.HornOfWinterAura.Unit.AddStatsDynamic(sim, negativeStats) - } - }, - }) - dk.HornOfWinter = dk.RegisterSpell(core.SpellConfig{ ActionID: actionID, Flags: core.SpellFlagAPL, @@ -51,7 +28,3 @@ func (dk *Deathknight) registerHornOfWinterSpell() { }, }) } - -func (dk *Deathknight) ShouldHornOfWinter(sim *core.Simulation) bool { - return dk.Inputs.RefreshHornOfWinter && dk.HornOfWinter.IsReady(sim) && !dk.HornOfWinterAura.IsActive() -} diff --git a/sim/deathknight/summon_gargoyle.go b/sim/deathknight/summon_gargoyle.go index cbcd0016c8..47dcb507be 100644 --- a/sim/deathknight/summon_gargoyle.go +++ b/sim/deathknight/summon_gargoyle.go @@ -72,11 +72,9 @@ type GargoylePet struct { dkOwner *Deathknight GargoyleStrike *core.Spell - - isNerfedGargoyle bool } -func (dk *Deathknight) NewGargoyle(nerfedGargoyle bool) *GargoylePet { +func (dk *Deathknight) NewGargoyle() *GargoylePet { // Remove any hit that would be given by NocS as it does not translate to pets var nocsHit float64 if dk.nervesOfColdSteelActive() { @@ -97,8 +95,7 @@ func (dk *Deathknight) NewGargoyle(nerfedGargoyle bool) *GargoylePet { stats.SpellHaste: ownerStats[stats.MeleeHaste] * PetSpellHasteScale, } }, false, true), - dkOwner: dk, - isNerfedGargoyle: nerfedGargoyle, + dkOwner: dk, } // NightOfTheDead @@ -109,17 +106,15 @@ func (dk *Deathknight) NewGargoyle(nerfedGargoyle bool) *GargoylePet { gargoyle.MultiplyCastSpeed(dk.PseudoStats.MeleeSpeedMultiplier) // "Nerfed Gargoyle" dynamically updates with owner's haste and melee speed - if gargoyle.isNerfedGargoyle { - gargoyle.EnableDynamicMeleeSpeed(func(amount float64) { - gargoyle.MultiplyCastSpeed(amount) - }) - - gargoyle.EnableDynamicStats(func(ownerStats stats.Stats) stats.Stats { - return stats.Stats{ - stats.SpellHaste: ownerStats[stats.MeleeHaste] * PetSpellHasteScale, - } - }) - } + gargoyle.EnableDynamicMeleeSpeed(func(amount float64) { + gargoyle.MultiplyCastSpeed(amount) + }) + + gargoyle.EnableDynamicStats(func(ownerStats stats.Stats) stats.Stats { + return stats.Stats{ + stats.SpellHaste: ownerStats[stats.MeleeHaste] * PetSpellHasteScale, + } + }) } dk.AddPet(gargoyle) diff --git a/sim/deathknight/tank/tank_deathknight.go b/sim/deathknight/tank/tank_deathknight.go index 6ede0bec8e..e4db62df4f 100644 --- a/sim/deathknight/tank/tank_deathknight.go +++ b/sim/deathknight/tank/tank_deathknight.go @@ -38,7 +38,7 @@ func NewTankDeathknight(character *core.Character, options *proto.Player) *TankD Deathknight: deathknight.NewDeathknight(character, deathknight.DeathknightInputs{ IsDps: false, StartingRunicPower: dkOptions.Options.StartingRunicPower, - }, options.TalentsString, false), + }, options.TalentsString), } tankDk.Inputs.UnholyFrenzyTarget = dkOptions.Options.UnholyFrenzyTarget diff --git a/sim/deathknight/tank/tank_deathknight_test.go b/sim/deathknight/tank/tank_deathknight_test.go index 3f308a73e8..70e68f03a6 100644 --- a/sim/deathknight/tank/tank_deathknight_test.go +++ b/sim/deathknight/tank/tank_deathknight_test.go @@ -55,7 +55,6 @@ var PlayerOptionsBloodTank = &proto.Player_TankDeathknight{ Options: &proto.TankDeathknight_Options{ StartingRunicPower: 0, }, - Rotation: &proto.TankDeathknight_Rotation{}, }, } From fd6d8ec9e3923b9c5f86758a6c37bd4249a7cc29 Mon Sep 17 00:00:00 2001 From: James Tanner Date: Sat, 6 Jan 2024 20:11:40 -0800 Subject: [PATCH 17/28] Cleanup dk code --- proto/apl.proto | 2 - proto/common.proto | 4 - proto/deathknight.proto | 3 - sim/deathknight/blood_boil.go | 5 -- sim/deathknight/blood_strike.go | 5 -- sim/deathknight/dancing_rune_weapon.go | 25 ++---- sim/deathknight/death_coil.go | 5 -- sim/deathknight/death_strike.go | 5 -- sim/deathknight/deathknight.go | 3 +- sim/deathknight/diseases.go | 10 --- sim/deathknight/dps/dps_deathknight.go | 1 - sim/deathknight/heart_strike.go | 4 - sim/deathknight/icy_touch.go | 5 -- sim/deathknight/plague_strike.go | 5 -- sim/deathknight/rune_strike.go | 5 -- sim/deathknight/tank/tank_deathknight.go | 7 -- .../individual_sim_ui/rotation_tab.ts | 1 - ui/core/player.ts | 86 +------------------ ui/core/proto_utils/utils.ts | 64 -------------- ui/core/raid.ts | 4 - ui/deathknight/inputs.ts | 29 ------- ui/deathknight/presets.ts | 13 +-- ui/deathknight/sim.ts | 6 +- ui/feral_druid/inputs.ts | 3 +- 24 files changed, 16 insertions(+), 284 deletions(-) diff --git a/proto/apl.proto b/proto/apl.proto index 2f683604b1..f380dcaee9 100644 --- a/proto/apl.proto +++ b/proto/apl.proto @@ -10,8 +10,6 @@ import "druid.proto"; // Rotation options are based heavily on APL. See https://github.com/simulationcraft/simc/wiki/ActionLists. message APLRotation { - bool enabled = 20 [deprecated = true]; // If false, use old rotation options. - enum Type { TypeUnknown = 0; TypeAuto = 1; diff --git a/proto/common.proto b/proto/common.proto index 8d48b909c1..7bba98594d 100644 --- a/proto/common.proto +++ b/proto/common.proto @@ -785,10 +785,6 @@ message UnitReference { // Reference to the owner, only used iff this is a pet. UnitReference owner = 4; - - // Raid index of the player to target. A value of -1 indicates no target. - // TODO: Delete this after 2 months (on or after 9/19/2023) - int32 target_index = 1 [deprecated = true]; } // ID for actions that aren't spells or items. diff --git a/proto/deathknight.proto b/proto/deathknight.proto index feeaa4083c..000d5c784f 100644 --- a/proto/deathknight.proto +++ b/proto/deathknight.proto @@ -144,7 +144,6 @@ enum DeathknightMinorGlyph { message Deathknight { message Rotation { } - Rotation rotation = 1; message Options { double starting_runic_power = 1; @@ -154,8 +153,6 @@ message Deathknight { bool drw_pesti_apply = 6; - bool new_drw = 7; - bool use_ams = 9; double avg_ams_success_rate = 10; double avg_ams_hit = 11; diff --git a/sim/deathknight/blood_boil.go b/sim/deathknight/blood_boil.go index 943aa60057..62f5dcb046 100644 --- a/sim/deathknight/blood_boil.go +++ b/sim/deathknight/blood_boil.go @@ -64,9 +64,4 @@ func (dk *Deathknight) registerDrwBloodBoilSpell() { } }, }) - - if !dk.Inputs.NewDrw { - dk.RuneWeapon.BloodBoil.DamageMultiplier *= 0.5 - dk.RuneWeapon.BloodBoil.Flags |= core.SpellFlagIgnoreAttackerModifiers - } } diff --git a/sim/deathknight/blood_strike.go b/sim/deathknight/blood_strike.go index 96d53a6f16..11eefb5708 100644 --- a/sim/deathknight/blood_strike.go +++ b/sim/deathknight/blood_strike.go @@ -115,9 +115,4 @@ func (dk *Deathknight) registerDrwBloodStrikeSpell() { spell.CalcAndDealDamage(sim, target, baseDamage, spell.OutcomeMeleeWeaponSpecialHitAndCrit) }, }) - - if !dk.Inputs.NewDrw { - dk.RuneWeapon.BloodStrike.DamageMultiplier *= 0.5 - dk.RuneWeapon.BloodStrike.Flags |= core.SpellFlagIgnoreAttackerModifiers - } } diff --git a/sim/deathknight/dancing_rune_weapon.go b/sim/deathknight/dancing_rune_weapon.go index 99f6914817..17a2232610 100644 --- a/sim/deathknight/dancing_rune_weapon.go +++ b/sim/deathknight/dancing_rune_weapon.go @@ -116,13 +116,7 @@ func (runeWeapon *RuneWeaponPet) Initialize() { } func (dk *Deathknight) DrwWeaponDamage(sim *core.Simulation, spell *core.Spell) float64 { - if dk.Inputs.NewDrw { - return spell.Unit.MHWeaponDamage(sim, spell.MeleeAttackPower()) + - spell.BonusWeaponDamage() - } else { - return spell.Unit.MHNormalizedWeaponDamage(sim, spell.MeleeAttackPower()) + - spell.BonusWeaponDamage() - } + return spell.Unit.MHWeaponDamage(sim, spell.MeleeAttackPower()) + spell.BonusWeaponDamage() } func (dk *Deathknight) NewRuneWeapon() *RuneWeaponPet { @@ -163,11 +157,9 @@ func (dk *Deathknight) NewRuneWeapon() *RuneWeaponPet { mhWeapon := dk.WeaponFromMainHand(dk.DefaultMeleeCritMultiplier()) - if dk.Inputs.NewDrw { - baseDamage := mhWeapon.AverageDamage() / mhWeapon.SwingSpeed * 3.5 - mhWeapon.BaseDamageMin = baseDamage - 150 - mhWeapon.BaseDamageMax = baseDamage + 150 - } + baseDamage := mhWeapon.AverageDamage() / mhWeapon.SwingSpeed * 3.5 + mhWeapon.BaseDamageMin = baseDamage - 150 + mhWeapon.BaseDamageMax = baseDamage + 150 mhWeapon.SwingSpeed = 3.5 mhWeapon.NormalizedSwingSpeed = 3.3 @@ -200,13 +192,8 @@ func (runeWeapon *RuneWeaponPet) enable(sim *core.Simulation) { runeWeapon.PseudoStats.MeleeSpeedMultiplier = 1 runeWeapon.MultiplyMeleeSpeed(sim, runeWeapon.dkOwner.PseudoStats.MeleeSpeedMultiplier) - if runeWeapon.dkOwner.Inputs.NewDrw { - runeWeapon.dkOwner.drwDmgSnapshot = runeWeapon.dkOwner.PseudoStats.DamageDealtMultiplier * 0.5 - runeWeapon.dkOwner.RuneWeapon.PseudoStats.DamageDealtMultiplier *= runeWeapon.dkOwner.drwDmgSnapshot - } else { - runeWeapon.dkOwner.drwDmgSnapshot = runeWeapon.dkOwner.PseudoStats.DamageDealtMultiplier - 0.5 - runeWeapon.dkOwner.RuneWeapon.PseudoStats.DamageDealtMultiplier *= runeWeapon.dkOwner.drwDmgSnapshot - } + runeWeapon.dkOwner.drwDmgSnapshot = runeWeapon.dkOwner.PseudoStats.DamageDealtMultiplier * 0.5 + runeWeapon.dkOwner.RuneWeapon.PseudoStats.DamageDealtMultiplier *= runeWeapon.dkOwner.drwDmgSnapshot runeWeapon.dkOwner.drwPhysSnapshot = runeWeapon.dkOwner.PseudoStats.SchoolDamageDealtMultiplier[stats.SchoolIndexPhysical] runeWeapon.PseudoStats.SchoolDamageDealtMultiplier[stats.SchoolIndexPhysical] *= runeWeapon.dkOwner.drwPhysSnapshot diff --git a/sim/deathknight/death_coil.go b/sim/deathknight/death_coil.go index da233c52f5..b2c6b777f9 100644 --- a/sim/deathknight/death_coil.go +++ b/sim/deathknight/death_coil.go @@ -60,9 +60,4 @@ func (dk *Deathknight) registerDrwDeathCoilSpell() { spell.CalcAndDealDamage(sim, target, baseDamage, spell.OutcomeMagicHitAndCrit) }, }) - - if !dk.Inputs.NewDrw { - dk.RuneWeapon.DeathCoil.DamageMultiplier *= 0.5 - dk.RuneWeapon.DeathCoil.Flags |= core.SpellFlagIgnoreAttackerModifiers - } } diff --git a/sim/deathknight/death_strike.go b/sim/deathknight/death_strike.go index de85bd7a11..c26d7811ad 100644 --- a/sim/deathknight/death_strike.go +++ b/sim/deathknight/death_strike.go @@ -120,9 +120,4 @@ func (dk *Deathknight) registerDrwDeathStrikeSpell() { spell.CalcAndDealDamage(sim, target, baseDamage, spell.OutcomeMeleeWeaponSpecialHitAndCrit) }, }) - - if !dk.Inputs.NewDrw { - dk.RuneWeapon.DeathStrike.DamageMultiplier *= 0.5 - dk.RuneWeapon.DeathStrike.Flags |= core.SpellFlagIgnoreAttackerModifiers - } } diff --git a/sim/deathknight/deathknight.go b/sim/deathknight/deathknight.go index 61c53fe706..673004d4df 100644 --- a/sim/deathknight/deathknight.go +++ b/sim/deathknight/deathknight.go @@ -20,8 +20,7 @@ var TalentTreeSizes = [3]int{28, 29, 31} type DeathknightInputs struct { // Option Vars - IsDps bool - NewDrw bool + IsDps bool UnholyFrenzyTarget *proto.UnitReference diff --git a/sim/deathknight/diseases.go b/sim/deathknight/diseases.go index 4006b43011..7a8b02cb5e 100644 --- a/sim/deathknight/diseases.go +++ b/sim/deathknight/diseases.go @@ -224,11 +224,6 @@ func (dk *Deathknight) registerDrwFrostFever() { spell.Dot(target).Apply(sim) }, }) - - if !dk.Inputs.NewDrw { - dk.RuneWeapon.FrostFeverSpell.DamageMultiplier *= 0.5 - dk.RuneWeapon.FrostFeverSpell.Flags |= core.SpellFlagIgnoreAttackerModifiers - } } func (dk *Deathknight) registerDrwBloodPlague() { @@ -276,11 +271,6 @@ func (dk *Deathknight) registerDrwBloodPlague() { spell.Dot(target).Apply(sim) }, }) - - if !dk.Inputs.NewDrw { - dk.RuneWeapon.BloodPlagueSpell.DamageMultiplier *= 0.5 - dk.RuneWeapon.BloodPlagueSpell.Flags |= core.SpellFlagIgnoreAttackerModifiers - } } func (dk *Deathknight) doWanderingPlague(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { diff --git a/sim/deathknight/dps/dps_deathknight.go b/sim/deathknight/dps/dps_deathknight.go index de021426d0..8f0cfbce50 100644 --- a/sim/deathknight/dps/dps_deathknight.go +++ b/sim/deathknight/dps/dps_deathknight.go @@ -36,7 +36,6 @@ func NewDpsDeathknight(character *core.Character, player *proto.Player) *DpsDeat PetUptime: dk.Options.PetUptime, DrwPestiApply: dk.Options.DrwPestiApply, IsDps: true, - NewDrw: true, UseAMS: dk.Options.UseAms, AvgAMSSuccessRate: dk.Options.AvgAmsSuccessRate, diff --git a/sim/deathknight/heart_strike.go b/sim/deathknight/heart_strike.go index 1fa9ebf983..92dbdde6b2 100644 --- a/sim/deathknight/heart_strike.go +++ b/sim/deathknight/heart_strike.go @@ -79,10 +79,6 @@ func (dk *Deathknight) newHeartStrikeSpell(isMainTarget bool, isDrw bool) *core. } if isDrw { - if !dk.Inputs.NewDrw { - conf.DamageMultiplier *= 0.5 - conf.Flags |= core.SpellFlagIgnoreAttackerModifiers - } return dk.RuneWeapon.RegisterSpell(conf) } else { return dk.RegisterSpell(conf) diff --git a/sim/deathknight/icy_touch.go b/sim/deathknight/icy_touch.go index e622ee282b..41a793d5c0 100644 --- a/sim/deathknight/icy_touch.go +++ b/sim/deathknight/icy_touch.go @@ -73,9 +73,4 @@ func (dk *Deathknight) registerDrwIcyTouchSpell() { spell.DealDamage(sim, result) }, }) - - if !dk.Inputs.NewDrw { - dk.RuneWeapon.IcyTouch.DamageMultiplier *= 0.5 - dk.RuneWeapon.IcyTouch.Flags |= core.SpellFlagIgnoreAttackerModifiers - } } diff --git a/sim/deathknight/plague_strike.go b/sim/deathknight/plague_strike.go index d6635013c5..f8d26b25ab 100644 --- a/sim/deathknight/plague_strike.go +++ b/sim/deathknight/plague_strike.go @@ -100,9 +100,4 @@ func (dk *Deathknight) registerDrwPlagueStrikeSpell() { } }, }) - - if !dk.Inputs.NewDrw { - dk.RuneWeapon.PlagueStrike.DamageMultiplier *= 0.5 - dk.RuneWeapon.PlagueStrike.Flags |= core.SpellFlagIgnoreAttackerModifiers - } } diff --git a/sim/deathknight/rune_strike.go b/sim/deathknight/rune_strike.go index 6d22e707cd..d74c270fd2 100644 --- a/sim/deathknight/rune_strike.go +++ b/sim/deathknight/rune_strike.go @@ -137,9 +137,4 @@ func (dk *Deathknight) registerDrwRuneStrikeSpell() { spell.CalcAndDealDamage(sim, target, baseDamage, spell.OutcomeMeleeSpecialNoBlockDodgeParry) }, }) - - if !dk.Inputs.NewDrw { - dk.RuneWeapon.RuneStrike.DamageMultiplier *= 0.5 - dk.RuneWeapon.RuneStrike.Flags |= core.SpellFlagIgnoreAttackerModifiers - } } diff --git a/sim/deathknight/tank/tank_deathknight.go b/sim/deathknight/tank/tank_deathknight.go index e8b35054fa..8a5643e8dc 100644 --- a/sim/deathknight/tank/tank_deathknight.go +++ b/sim/deathknight/tank/tank_deathknight.go @@ -25,10 +25,6 @@ func RegisterTankDeathknight() { type TankDeathknight struct { *deathknight.Deathknight - - switchIT bool - BloodSpell *core.Spell - FuSpell *core.Spell } func NewTankDeathknight(character *core.Character, options *proto.Player) *TankDeathknight { @@ -37,7 +33,6 @@ func NewTankDeathknight(character *core.Character, options *proto.Player) *TankD tankDk := &TankDeathknight{ Deathknight: deathknight.NewDeathknight(character, deathknight.DeathknightInputs{ IsDps: false, - NewDrw: true, StartingRunicPower: dkOptions.Options.StartingRunicPower, }, options.TalentsString), } @@ -78,8 +73,6 @@ func (dk *TankDeathknight) Initialize() { func (dk *TankDeathknight) Reset(sim *core.Simulation) { dk.Deathknight.Reset(sim) - dk.switchIT = false - dk.Presence = deathknight.UnsetPresence dk.Deathknight.PseudoStats.Stunned = false } diff --git a/ui/core/components/individual_sim_ui/rotation_tab.ts b/ui/core/components/individual_sim_ui/rotation_tab.ts index 81742a4f7b..70a09d43f7 100644 --- a/ui/core/components/individual_sim_ui/rotation_tab.ts +++ b/ui/core/components/individual_sim_ui/rotation_tab.ts @@ -100,7 +100,6 @@ export class RotationTab extends SimTab { changedEvent: (player: Player) => player.rotationChangeEmitter, getValue: (player: Player) => player.getRotationType(), setValue: (eventID: EventID, player: Player, newValue: number) => { - player.aplRotation.enabled = false; player.aplRotation.type = newValue; player.rotationChangeEmitter.emit(eventID); }, diff --git a/ui/core/player.ts b/ui/core/player.ts index 7690346209..ee9d44f6fb 100644 --- a/ui/core/player.ts +++ b/ui/core/player.ts @@ -780,10 +780,8 @@ export class Player { } getRotationType(): APLRotationType { - if (this.aplRotation.enabled) { + if (this.aplRotation.type == APLRotationType.TypeUnknown) { return APLRotationType.TypeAPL; - } else if (this.aplRotation.type == APLRotationType.TypeUnknown) { - return APLRotationType.TypeLegacy; } else { return this.aplRotation.type; } @@ -1374,40 +1372,6 @@ export class Player { || includeCategories.length == 0 || includeCategories.includes(cat); - if (proto.rotation) { - proto.rotation.prepullActions.forEach(ppa => { - if (ppa.doAt) { - ppa.doAtValue = APLValue.create({ - value: {oneofKind: 'const', const: { val: ppa.doAt }} - }); - ppa.doAt = ''; - } - }); - if (proto.rotation.enabled) { - proto.rotation.enabled = false; - proto.rotation.type = APLRotationType.TypeAPL; - } - } - - const rot = this.specTypeFunctions.rotationFromPlayer(proto); - if (rot && !this.specTypeFunctions.rotationEquals(rot, this.specTypeFunctions.rotationCreate())) { - if (proto.rotation?.type == APLRotationType.TypeAPL) { - // Do nothing - } else if (this.simpleRotationGenerator) { - proto.rotation = APLRotation.create({ - type: APLRotationType.TypeSimple, - simple: { - specRotationJson: JSON.stringify(this.specTypeFunctions.rotationToJson(rot)), - cooldowns: proto.cooldowns, - }, - }); - } else { - proto.rotation = APLRotation.create({ - type: APLRotationType.TypeAuto, - }); - } - } - TypedEvent.freezeAllAndDo(() => { if (loadCategory(SimSettingCategories.Gear)) { this.setGear(eventID, proto.equipment ? this.sim.db.lookupEquipmentSpec(proto.equipment) : new Gear({})); @@ -1452,50 +1416,6 @@ export class Player { this.setBuffs(eventID, proto.buffs || IndividualBuffs.create()); } - const options = this.getSpecOptions(); - for (let key in options) { - if ((options[key] as any)?.['targetIndex']) { - const targetIndex = (options[key] as any)['targetIndex'] as number; - if (targetIndex == -1) { - (options[key] as any) = UnitReference.create(); - } else { - (options[key] as any) = UnitReference.create({type: UnitReference_Type.Player, index: targetIndex}); - } - this.setSpecOptions(eventID, options); - break; - } - } - - if (this.spec == Spec.SpecBalanceDruid) { - const rot = this.getSimpleRotation() as SpecRotation; - if (rot.okfPpm) { - rot.okfPpm = 0; - this.setSimpleRotation(eventID, rot as SpecRotation); - } - } - - if (this.spec == Spec.SpecHunter) { - const rot = this.getSimpleRotation() as SpecRotation; - if (rot.timeToTrapWeaveMs) { - const options = this.getSpecOptions() as SpecOptions; - options.timeToTrapWeaveMs = rot.timeToTrapWeaveMs; - this.setSpecOptions(eventID, options as SpecOptions); - rot.timeToTrapWeaveMs = 0; - this.setSimpleRotation(eventID, rot as SpecRotation); - } - } - - if (this.spec == Spec.SpecMage) { - const rot = this.getSimpleRotation() as SpecRotation; - if (rot.waterElementalDisobeyChance) { - const options = this.getSpecOptions() as SpecOptions; - options.waterElementalDisobeyChance = rot.waterElementalDisobeyChance; - rot.waterElementalDisobeyChance = 0; - this.setSpecOptions(eventID, options as SpecOptions); - this.setSimpleRotation(eventID, rot as SpecRotation); - } - } - if (this.spec == Spec.SpecShadowPriest) { const options = this.getSpecOptions() as SpecOptions; if (options.latency) { @@ -1546,8 +1466,8 @@ export class Player { } } - if (this.spec == Spec.SpecWarlock || this.spec == Spec.SpecDeathknight) { - const rot = this.getSimpleRotation() as SpecRotation; + if (this.spec == Spec.SpecWarlock) { + const rot = this.getSimpleRotation() as SpecRotation; if (rot.enableWeaponSwap) { this.setEnableItemSwap(eventID, rot.enableWeaponSwap); rot.enableWeaponSwap = false; diff --git a/ui/core/proto_utils/utils.ts b/ui/core/proto_utils/utils.ts index 8a6be3a96a..3e9d8d20c8 100644 --- a/ui/core/proto_utils/utils.ts +++ b/ui/core/proto_utils/utils.ts @@ -548,7 +548,6 @@ export type SpecTypeFunctions = { rotationCopy: (a: SpecRotation) => SpecRotation; rotationToJson: (a: SpecRotation) => any; rotationFromJson: (obj: any) => SpecRotation; - rotationFromPlayer: (player: Player) => SpecRotation; talentsCreate: () => SpecTalents; talentsEquals: (a: SpecTalents, b: SpecTalents) => boolean; @@ -571,9 +570,6 @@ export const specTypeFunctions: Record> = { rotationCopy: (a) => BalanceDruidRotation.clone(a as BalanceDruidRotation), rotationToJson: (a) => BalanceDruidRotation.toJson(a as BalanceDruidRotation), rotationFromJson: (obj) => BalanceDruidRotation.fromJson(obj), - rotationFromPlayer: (player) => player.spec.oneofKind == 'balanceDruid' - ? player.spec.balanceDruid.rotation || BalanceDruidRotation.create() - : BalanceDruidRotation.create(), talentsCreate: () => DruidTalents.create(), talentsEquals: (a, b) => DruidTalents.equals(a as DruidTalents, b as DruidTalents), @@ -596,9 +592,6 @@ export const specTypeFunctions: Record> = { rotationCopy: (a) => FeralDruidRotation.clone(a as FeralDruidRotation), rotationToJson: (a) => FeralDruidRotation.toJson(a as FeralDruidRotation), rotationFromJson: (obj) => FeralDruidRotation.fromJson(obj), - rotationFromPlayer: (player) => player.spec.oneofKind == 'feralDruid' - ? player.spec.feralDruid.rotation || FeralDruidRotation.create() - : FeralDruidRotation.create(), talentsCreate: () => DruidTalents.create(), talentsEquals: (a, b) => DruidTalents.equals(a as DruidTalents, b as DruidTalents), @@ -621,9 +614,6 @@ export const specTypeFunctions: Record> = { rotationCopy: (a) => FeralTankDruidRotation.clone(a as FeralTankDruidRotation), rotationToJson: (a) => FeralTankDruidRotation.toJson(a as FeralTankDruidRotation), rotationFromJson: (obj) => FeralTankDruidRotation.fromJson(obj), - rotationFromPlayer: (player) => player.spec.oneofKind == 'feralTankDruid' - ? player.spec.feralTankDruid.rotation || FeralTankDruidRotation.create() - : FeralTankDruidRotation.create(), talentsCreate: () => DruidTalents.create(), talentsEquals: (a, b) => DruidTalents.equals(a as DruidTalents, b as DruidTalents), @@ -646,9 +636,6 @@ export const specTypeFunctions: Record> = { rotationCopy: (a) => RestorationDruidRotation.clone(a as RestorationDruidRotation), rotationToJson: (a) => RestorationDruidRotation.toJson(a as RestorationDruidRotation), rotationFromJson: (obj) => RestorationDruidRotation.fromJson(obj), - rotationFromPlayer: (player) => player.spec.oneofKind == 'restorationDruid' - ? player.spec.restorationDruid.rotation || RestorationDruidRotation.create() - : RestorationDruidRotation.create(), talentsCreate: () => DruidTalents.create(), talentsEquals: (a, b) => DruidTalents.equals(a as DruidTalents, b as DruidTalents), @@ -671,9 +658,6 @@ export const specTypeFunctions: Record> = { rotationCopy: (a) => ElementalShamanRotation.clone(a as ElementalShamanRotation), rotationToJson: (a) => ElementalShamanRotation.toJson(a as ElementalShamanRotation), rotationFromJson: (obj) => ElementalShamanRotation.fromJson(obj), - rotationFromPlayer: (player) => player.spec.oneofKind == 'elementalShaman' - ? player.spec.elementalShaman.rotation || ElementalShamanRotation.create() - : ElementalShamanRotation.create(), talentsCreate: () => ShamanTalents.create(), talentsEquals: (a, b) => ShamanTalents.equals(a as ShamanTalents, b as ShamanTalents), @@ -696,9 +680,6 @@ export const specTypeFunctions: Record> = { rotationCopy: (a) => EnhancementShamanRotation.clone(a as EnhancementShamanRotation), rotationToJson: (a) => EnhancementShamanRotation.toJson(a as EnhancementShamanRotation), rotationFromJson: (obj) => EnhancementShamanRotation.fromJson(obj), - rotationFromPlayer: (player) => player.spec.oneofKind == 'enhancementShaman' - ? player.spec.enhancementShaman.rotation || EnhancementShamanRotation.create() - : EnhancementShamanRotation.create(), talentsCreate: () => ShamanTalents.create(), talentsEquals: (a, b) => ShamanTalents.equals(a as ShamanTalents, b as ShamanTalents), @@ -721,9 +702,6 @@ export const specTypeFunctions: Record> = { rotationCopy: (a) => RestorationShamanRotation.clone(a as RestorationShamanRotation), rotationToJson: (a) => RestorationShamanRotation.toJson(a as RestorationShamanRotation), rotationFromJson: (obj) => RestorationShamanRotation.fromJson(obj), - rotationFromPlayer: (player) => player.spec.oneofKind == 'restorationShaman' - ? player.spec.restorationShaman.rotation || RestorationShamanRotation.create() - : RestorationShamanRotation.create(), talentsCreate: () => ShamanTalents.create(), talentsEquals: (a, b) => ShamanTalents.equals(a as ShamanTalents, b as ShamanTalents), @@ -746,9 +724,6 @@ export const specTypeFunctions: Record> = { rotationCopy: (a) => HunterRotation.clone(a as HunterRotation), rotationToJson: (a) => HunterRotation.toJson(a as HunterRotation), rotationFromJson: (obj) => HunterRotation.fromJson(obj), - rotationFromPlayer: (player) => player.spec.oneofKind == 'hunter' - ? player.spec.hunter.rotation || HunterRotation.create() - : HunterRotation.create(), talentsCreate: () => HunterTalents.create(), talentsEquals: (a, b) => HunterTalents.equals(a as HunterTalents, b as HunterTalents), @@ -771,9 +746,6 @@ export const specTypeFunctions: Record> = { rotationCopy: (a) => MageRotation.clone(a as MageRotation), rotationToJson: (a) => MageRotation.toJson(a as MageRotation), rotationFromJson: (obj) => MageRotation.fromJson(obj), - rotationFromPlayer: (player) => player.spec.oneofKind == 'mage' - ? player.spec.mage.rotation || MageRotation.create() - : MageRotation.create(), talentsCreate: () => MageTalents.create(), talentsEquals: (a, b) => MageTalents.equals(a as MageTalents, b as MageTalents), @@ -796,9 +768,6 @@ export const specTypeFunctions: Record> = { rotationCopy: (a) => HolyPaladinRotation.clone(a as HolyPaladinRotation), rotationToJson: (a) => HolyPaladinRotation.toJson(a as HolyPaladinRotation), rotationFromJson: (obj) => HolyPaladinRotation.fromJson(obj), - rotationFromPlayer: (player) => player.spec.oneofKind == 'holyPaladin' - ? player.spec.holyPaladin.rotation || HolyPaladinRotation.create() - : HolyPaladinRotation.create(), talentsCreate: () => PaladinTalents.create(), talentsEquals: (a, b) => PaladinTalents.equals(a as PaladinTalents, b as PaladinTalents), @@ -821,9 +790,6 @@ export const specTypeFunctions: Record> = { rotationCopy: (a) => ProtectionPaladinRotation.clone(a as ProtectionPaladinRotation), rotationToJson: (a) => ProtectionPaladinRotation.toJson(a as ProtectionPaladinRotation), rotationFromJson: (obj) => ProtectionPaladinRotation.fromJson(obj), - rotationFromPlayer: (player) => player.spec.oneofKind == 'protectionPaladin' - ? player.spec.protectionPaladin.rotation || ProtectionPaladinRotation.create() - : ProtectionPaladinRotation.create(), talentsCreate: () => PaladinTalents.create(), talentsEquals: (a, b) => PaladinTalents.equals(a as PaladinTalents, b as PaladinTalents), @@ -846,9 +812,6 @@ export const specTypeFunctions: Record> = { rotationCopy: (a) => RetributionPaladinRotation.clone(a as RetributionPaladinRotation), rotationToJson: (a) => RetributionPaladinRotation.toJson(a as RetributionPaladinRotation), rotationFromJson: (obj) => RetributionPaladinRotation.fromJson(obj), - rotationFromPlayer: (player) => player.spec.oneofKind == 'retributionPaladin' - ? player.spec.retributionPaladin.rotation || RetributionPaladinRotation.create() - : RetributionPaladinRotation.create(), talentsCreate: () => PaladinTalents.create(), talentsEquals: (a, b) => PaladinTalents.equals(a as PaladinTalents, b as PaladinTalents), @@ -871,9 +834,6 @@ export const specTypeFunctions: Record> = { rotationCopy: (a) => RogueRotation.clone(a as RogueRotation), rotationToJson: (a) => RogueRotation.toJson(a as RogueRotation), rotationFromJson: (obj) => RogueRotation.fromJson(obj), - rotationFromPlayer: (player) => player.spec.oneofKind == 'rogue' - ? player.spec.rogue.rotation || RogueRotation.create() - : RogueRotation.create(), talentsCreate: () => RogueTalents.create(), talentsEquals: (a, b) => RogueTalents.equals(a as RogueTalents, b as RogueTalents), @@ -896,9 +856,6 @@ export const specTypeFunctions: Record> = { rotationCopy: (a) => HealingPriestRotation.clone(a as HealingPriestRotation), rotationToJson: (a) => HealingPriestRotation.toJson(a as HealingPriestRotation), rotationFromJson: (obj) => HealingPriestRotation.fromJson(obj), - rotationFromPlayer: (player) => player.spec.oneofKind == 'healingPriest' - ? player.spec.healingPriest.rotation || HealingPriestRotation.create() - : HealingPriestRotation.create(), talentsCreate: () => PriestTalents.create(), talentsEquals: (a, b) => PriestTalents.equals(a as PriestTalents, b as PriestTalents), @@ -921,9 +878,6 @@ export const specTypeFunctions: Record> = { rotationCopy: (a) => ShadowPriestRotation.clone(a as ShadowPriestRotation), rotationToJson: (a) => ShadowPriestRotation.toJson(a as ShadowPriestRotation), rotationFromJson: (obj) => ShadowPriestRotation.fromJson(obj), - rotationFromPlayer: (player) => player.spec.oneofKind == 'shadowPriest' - ? player.spec.shadowPriest.rotation || ShadowPriestRotation.create() - : ShadowPriestRotation.create(), talentsCreate: () => PriestTalents.create(), talentsEquals: (a, b) => PriestTalents.equals(a as PriestTalents, b as PriestTalents), @@ -946,9 +900,6 @@ export const specTypeFunctions: Record> = { rotationCopy: (a) => SmitePriestRotation.clone(a as SmitePriestRotation), rotationToJson: (a) => SmitePriestRotation.toJson(a as SmitePriestRotation), rotationFromJson: (obj) => SmitePriestRotation.fromJson(obj), - rotationFromPlayer: (player) => player.spec.oneofKind == 'smitePriest' - ? player.spec.smitePriest.rotation || SmitePriestRotation.create() - : SmitePriestRotation.create(), talentsCreate: () => PriestTalents.create(), talentsEquals: (a, b) => PriestTalents.equals(a as PriestTalents, b as PriestTalents), @@ -971,9 +922,6 @@ export const specTypeFunctions: Record> = { rotationCopy: (a) => WarlockRotation.clone(a as WarlockRotation), rotationToJson: (a) => WarlockRotation.toJson(a as WarlockRotation), rotationFromJson: (obj) => WarlockRotation.fromJson(obj), - rotationFromPlayer: (player) => player.spec.oneofKind == 'warlock' - ? player.spec.warlock.rotation || WarlockRotation.create() - : WarlockRotation.create(), talentsCreate: () => WarlockTalents.create(), talentsEquals: (a, b) => WarlockTalents.equals(a as WarlockTalents, b as WarlockTalents), @@ -996,9 +944,6 @@ export const specTypeFunctions: Record> = { rotationCopy: (a) => WarriorRotation.clone(a as WarriorRotation), rotationToJson: (a) => WarriorRotation.toJson(a as WarriorRotation), rotationFromJson: (obj) => WarriorRotation.fromJson(obj), - rotationFromPlayer: (player) => player.spec.oneofKind == 'warrior' - ? player.spec.warrior.rotation || WarriorRotation.create() - : WarriorRotation.create(), talentsCreate: () => WarriorTalents.create(), talentsEquals: (a, b) => WarriorTalents.equals(a as WarriorTalents, b as WarriorTalents), @@ -1021,9 +966,6 @@ export const specTypeFunctions: Record> = { rotationCopy: (a) => ProtectionWarriorRotation.clone(a as ProtectionWarriorRotation), rotationToJson: (a) => ProtectionWarriorRotation.toJson(a as ProtectionWarriorRotation), rotationFromJson: (obj) => ProtectionWarriorRotation.fromJson(obj), - rotationFromPlayer: (player) => player.spec.oneofKind == 'protectionWarrior' - ? player.spec.protectionWarrior.rotation || ProtectionWarriorRotation.create() - : ProtectionWarriorRotation.create(), talentsCreate: () => WarriorTalents.create(), talentsEquals: (a, b) => WarriorTalents.equals(a as WarriorTalents, b as WarriorTalents), @@ -1046,9 +988,6 @@ export const specTypeFunctions: Record> = { rotationCopy: (a) => DeathknightRotation.clone(a as DeathknightRotation), rotationToJson: (a) => DeathknightRotation.toJson(a as DeathknightRotation), rotationFromJson: (obj) => DeathknightRotation.fromJson(obj), - rotationFromPlayer: (player) => player.spec.oneofKind == 'deathknight' - ? player.spec.deathknight.rotation || DeathknightRotation.create() - : DeathknightRotation.create(), talentsCreate: () => DeathknightTalents.create(), talentsEquals: (a, b) => DeathknightTalents.equals(a as DeathknightTalents, b as DeathknightTalents), @@ -1071,9 +1010,6 @@ export const specTypeFunctions: Record> = { rotationCopy: (a) => TankDeathknightRotation.clone(a as TankDeathknightRotation), rotationToJson: (a) => TankDeathknightRotation.toJson(a as TankDeathknightRotation), rotationFromJson: (obj) => TankDeathknightRotation.fromJson(obj), - rotationFromPlayer: (player) => player.spec.oneofKind == 'tankDeathknight' - ? player.spec.tankDeathknight.rotation || TankDeathknightRotation.create() - : TankDeathknightRotation.create(), talentsCreate: () => DeathknightTalents.create(), talentsEquals: (a, b) => DeathknightTalents.equals(a as DeathknightTalents, b as DeathknightTalents), diff --git a/ui/core/raid.ts b/ui/core/raid.ts index 1dae6e4849..d42215b1ad 100644 --- a/ui/core/raid.ts +++ b/ui/core/raid.ts @@ -234,10 +234,6 @@ export class Raid { fromProto(eventID: EventID, proto: RaidProto) { TypedEvent.freezeAllAndDo(() => { - if (proto.tanks) { - proto.tanks = proto.tanks.map(tank => (tank.type == 0 && tank.targetIndex != -1) ? UnitReference.create({type: UnitType.Player, index: tank.targetIndex}) : tank); - } - if (proto.buffs) { if (proto.buffs.demonicPact > 0 && proto.buffs.demonicPactSp == 0) { proto.buffs.demonicPactSp = proto.buffs.demonicPact; diff --git a/ui/deathknight/inputs.ts b/ui/deathknight/inputs.ts index 94183ef92b..f20dd4c859 100644 --- a/ui/deathknight/inputs.ts +++ b/ui/deathknight/inputs.ts @@ -46,20 +46,6 @@ export const PetUptime = InputHelpers.makeSpecOptionsNumberInput) => player.getTalents().masterOfGhouls, }); -export const PrecastGhoulFrenzy = InputHelpers.makeSpecOptionsBooleanInput({ - fieldName: 'precastGhoulFrenzy', - label: 'Pre-Cast Ghoul Frenzy', - labelTooltip: 'Cast Ghoul Frenzy 10 seconds before combat starts.', - showWhen: (player: Player) => player.getTalents().summonGargoyle && player.getTalents().ghoulFrenzy, - changeEmitter: (player: Player) => TypedEvent.onAny([player.specOptionsChangeEmitter, player.rotationChangeEmitter, player.talentsChangeEmitter]), -}); - -export const PrecastHornOfWinter = InputHelpers.makeSpecOptionsBooleanInput({ - fieldName: 'precastHornOfWinter', - label: 'Pre-Cast Horn of Winter', - labelTooltip: 'Precast Horn of Winter for 10 extra runic power before fight.', -}); - export const DrwPestiApply = InputHelpers.makeSpecOptionsBooleanInput({ fieldName: 'drwPestiApply', label: 'DRW Pestilence Add', @@ -68,21 +54,6 @@ export const DrwPestiApply = InputHelpers.makeSpecOptionsBooleanInput) => TypedEvent.onAny([player.specOptionsChangeEmitter, player.rotationChangeEmitter, player.talentsChangeEmitter]), }); -export const NewDrwInput = InputHelpers.makeSpecOptionsBooleanInput({ - fieldName: 'newDrw', - label: 'PTR DRW Scaling', - showWhen: (player: Player) => player.getTalents().dancingRuneWeapon, - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), -}) - -export const DiseaseDowntime = InputHelpers.makeSpecOptionsNumberInput({ - fieldName: 'diseaseDowntime', - label: 'Disease Downtime', - labelTooltip: 'Maximum allowed downtime between disease applications.', - showWhen: (player: Player) => player.getTalentTree() == 2, - changeEmitter: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.talentsChangeEmitter]), -}); - export const UseAMSInput = InputHelpers.makeSpecOptionsBooleanInput({ fieldName: 'useAms', label: 'Use AMS', diff --git a/ui/deathknight/presets.ts b/ui/deathknight/presets.ts index d73bd8b94d..70f3c6c517 100644 --- a/ui/deathknight/presets.ts +++ b/ui/deathknight/presets.ts @@ -182,31 +182,24 @@ export const BloodTalents = { }; export const DefaultUnholyOptions = DeathKnightOptions.create({ - drwPestiApply: true, startingRunicPower: 0, petUptime: 1, - precastGhoulFrenzy: false, - precastHornOfWinter: true, unholyFrenzyTarget: UnitReference.create(), - diseaseDowntime: 2, + drwPestiApply: true, }); export const DefaultFrostOptions = DeathKnightOptions.create({ - drwPestiApply: true, startingRunicPower: 0, petUptime: 1, - precastHornOfWinter: true, unholyFrenzyTarget: UnitReference.create(), - diseaseDowntime: 0, + drwPestiApply: true, }); export const DefaultBloodOptions = DeathKnightOptions.create({ - drwPestiApply: true, startingRunicPower: 0, petUptime: 1, - precastHornOfWinter: true, unholyFrenzyTarget: UnitReference.create(), - diseaseDowntime: 0, + drwPestiApply: true, }); export const OtherDefaults = { diff --git a/ui/deathknight/sim.ts b/ui/deathknight/sim.ts index 9aa93de575..ee214815e2 100644 --- a/ui/deathknight/sim.ts +++ b/ui/deathknight/sim.ts @@ -182,18 +182,14 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecDeathknight, { // Inputs to include in the 'Other' section on the settings tab. otherInputs: { inputs: [ - DeathKnightInputs.DiseaseDowntime, - DeathKnightInputs.DrwPestiApply, DeathKnightInputs.SelfUnholyFrenzy, DeathKnightInputs.StartingRunicPower, DeathKnightInputs.PetUptime, + DeathKnightInputs.DrwPestiApply, DeathKnightInputs.UseAMSInput, DeathKnightInputs.AvgAMSSuccessRateInput, DeathKnightInputs.AvgAMSHitInput, - DeathKnightInputs.PrecastGhoulFrenzy, - DeathKnightInputs.PrecastHornOfWinter, - OtherInputs.TankAssignment, OtherInputs.InFrontOfTarget, ], diff --git a/ui/feral_druid/inputs.ts b/ui/feral_druid/inputs.ts index 88b482a56a..2f16efda08 100644 --- a/ui/feral_druid/inputs.ts +++ b/ui/feral_druid/inputs.ts @@ -1,5 +1,6 @@ import { UnitReference, UnitReference_Type as UnitType } from '../core/proto/common.js'; import { Spec } from '../core/proto/common.js'; +import { APLRotation_Type } from '../core/proto/apl.js'; import { ActionId } from '../core/proto_utils/action_id.js'; import { Player } from '../core/player.js'; import { EventID, TypedEvent } from '../core/typed_event.js'; @@ -133,7 +134,7 @@ export const FeralDruidRotationConfig = { fieldName: 'raidTargets', label: 'GotW Raid Targets', labelTooltip: 'Raid size to assume for clearcast proc chance (can include pets as well, so 25 man raid potentically can be ~30)', - showWhen: (player: Player) => player.aplRotation.enabled || (ShouldShowAdvParamAoe(player) && player.getSimpleRotation().flowerWeave == true), + showWhen: (player: Player) => player.aplRotation.type != APLRotation_Type.TypeSimple || (ShouldShowAdvParamAoe(player) && player.getSimpleRotation().flowerWeave == true), }), // Can be uncommented if/when analytical bite mode is added //InputHelpers.makeRotationEnumInput({ From e0dc3bcae5fa92c48f44148de38474b29fef2c58 Mon Sep 17 00:00:00 2001 From: James Tanner Date: Sat, 6 Jan 2024 21:32:03 -0800 Subject: [PATCH 18/28] Fix priest test change --- sim/priest/healing/TestHoly.results | 4 ++-- sim/priest/hymn_of_hope.go | 2 +- sim/priest/smite/TestSmite.results | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sim/priest/healing/TestHoly.results b/sim/priest/healing/TestHoly.results index 7de62a4da8..388a12beda 100644 --- a/sim/priest/healing/TestHoly.results +++ b/sim/priest/healing/TestHoly.results @@ -172,8 +172,8 @@ dps_results: { dps_results: { key: "TestHoly-AllItems-DarkmoonCard:Greatness-44255" value: { - tps: 35.9717 - hps: 4983.05245 + tps: 36.04595 + hps: 4986.56935 } } dps_results: { diff --git a/sim/priest/hymn_of_hope.go b/sim/priest/hymn_of_hope.go index f88c6ecafe..995b1a541f 100644 --- a/sim/priest/hymn_of_hope.go +++ b/sim/priest/hymn_of_hope.go @@ -30,7 +30,7 @@ func (priest *Priest) RegisterHymnOfHopeCD() { ApplyEffects: func(sim *core.Simulation, _ *core.Unit, spell *core.Spell) { core.StartPeriodicAction(sim, core.PeriodicActionOptions{ - Period: time.Second * 2, + Period: spell.Unit.ApplyCastSpeedForSpell(time.Second*2, spell), NumTicks: int(numTicks), OnAction: func(sim *core.Simulation) { // This is 3%, but it increases the target's max mana by 20% for the duration diff --git a/sim/priest/smite/TestSmite.results b/sim/priest/smite/TestSmite.results index 110aae8059..ae55fcdfe8 100644 --- a/sim/priest/smite/TestSmite.results +++ b/sim/priest/smite/TestSmite.results @@ -855,7 +855,7 @@ dps_results: { key: "TestSmite-Settings-Undead-p1-Basic-default-NoBuffs-ShortSingleTarget" value: { dps: 2520.9093 - tps: 2126.72097 + tps: 2130.11373 } } dps_results: { From 0938396717aee3aa206c84eed1472b02a420941d Mon Sep 17 00:00:00 2001 From: James Tanner Date: Sat, 6 Jan 2024 22:37:18 -0800 Subject: [PATCH 19/28] Remove unused protos and fields --- proto/druid.proto | 61 +--------- proto/hunter.proto | 25 ----- proto/mage.proto | 4 - proto/paladin.proto | 55 --------- proto/priest.proto | 43 ------- proto/rogue.proto | 65 ----------- proto/shaman.proto | 106 ------------------ proto/warlock.proto | 47 -------- proto/warrior.proto | 105 ----------------- sim/druid/balance/balance_test.go | 1 - sim/druid/restoration/restoration_test.go | 1 - sim/druid/tank/tank_test.go | 1 - sim/mage/mage_test.go | 3 - sim/paladin/avenging_wrath.go | 8 -- sim/paladin/holy/holy.go | 8 +- sim/paladin/holy/holy_test.go | 3 +- sim/paladin/paladin.go | 4 - sim/paladin/protection/protection_test.go | 7 +- sim/paladin/retribution/retribution.go | 4 - sim/paladin/retribution/retribution_test.go | 11 -- sim/priest/healing/healing_priest_test.go | 2 - sim/priest/shadow/shadow_priest_test.go | 11 -- sim/priest/smite/smite_priest_test.go | 1 - sim/raid_bench_test.go | 26 +---- sim/shaman/elemental/elemental.go | 3 +- sim/shaman/elemental/elemental_test.go | 10 +- sim/shaman/enhancement/enhancement.go | 7 +- sim/shaman/enhancement/enhancement_test.go | 27 ++--- sim/shaman/restoration/restoration.go | 3 +- sim/shaman/restoration/restoration_test.go | 5 +- sim/shaman/shaman.go | 7 +- sim/warlock/warlock_test.go | 10 -- .../protection/protection_warrior_test.go | 3 +- sim/web/main_test.go | 3 - ui/core/player.ts | 81 ------------- ui/elemental_shaman/presets.ts | 1 - ui/enhancement_shaman/presets.ts | 1 - ui/raid/raid_stats.ts | 2 +- ui/restoration_shaman/presets.ts | 1 - 39 files changed, 37 insertions(+), 729 deletions(-) diff --git a/proto/druid.proto b/proto/druid.proto index a5e8215341..61429b6059 100644 --- a/proto/druid.proto +++ b/proto/druid.proto @@ -146,64 +146,7 @@ enum DruidMinorGlyph { message BalanceDruid { message Rotation { - enum Type { - Unknown = 0; - Default = 1; - Manual = 2; - } - Type type = 1; - - enum MfUsage { - NoMf = 0; - BeforeLunar = 1; - MaximizeMf = 2; - MultidotMf = 3; - } - MfUsage mf_usage = 2; - - enum IsUsage { - NoIs = 0; - BeforeSolar = 1; - OptimizeIs = 2; - MultidotIs = 3; - } - IsUsage is_usage = 3; - - bool use_battle_res = 4; - enum WrathUsage { - NoWrath = 0; - FishingForLunar= 1; - RegularWrath = 2; - } - WrathUsage wrath_usage = 5; - bool use_starfire = 6; - bool use_typhoon = 7; - bool use_hurricane = 8; - bool use_smart_cooldowns = 9; - bool maintain_faerie_fire = 10; - int32 player_latency = 11; - float okf_ppm = 14 [deprecated = true]; - - enum EclipsePrio { - Lunar = 0; - Solar = 1; - } - EclipsePrio eclipse_prio = 12; - bool eclipse_shuffling = 13; - - enum MfExtension { - ExtendFishingForLunar = 0; - ExtendFishingForSolar = 1; - ExtendDuringLunar = 2; - ExtendDuringSolar = 3; - ExtendAlways = 4; - ExtendOutsideSolar = 5; - DontExtend = 6; - } - MfExtension mf_extension = 15; - bool snapshot_mf = 16; - } - Rotation rotation = 1; + } message Options { UnitReference innervate_target = 1; @@ -269,7 +212,6 @@ message FeralTankDruid { bool maintain_demoralizing_roar = 2; double lacerate_time = 3; } - Rotation rotation = 1; message Options { UnitReference innervate_target = 1; @@ -281,7 +223,6 @@ message FeralTankDruid { message RestorationDruid { message Rotation { } - Rotation rotation = 1; message Options { UnitReference innervate_target = 1; diff --git a/proto/hunter.proto b/proto/hunter.proto index f470dd0c4d..ae3753fa07 100644 --- a/proto/hunter.proto +++ b/proto/hunter.proto @@ -3,8 +3,6 @@ package proto; option go_package = "./proto"; -import "common.proto"; - message HunterTalents { // Beast Mastery int32 improved_aspect_of_the_hawk = 1; @@ -198,27 +196,6 @@ message Hunter { bool trap_weave = 1; - // TODO: Safe to delete after 1 month (after 8/26/2023). - double time_to_trap_weave_ms = 2 [deprecated = true]; - - enum SpellOption { - NoSpell = 0; - SteadyShot = 1; - ArcaneShot = 2; - AimedShot = 3; - MultiShot = 4; - SerpentStingSpell = 5; - ScorpidStingSpell = 6; - KillShot = 7; - BlackArrow = 8; - ChimeraShot = 9; - ExplosiveShot = 10; - ExplosiveShotDownrank = 13; - ExplosiveTrap = 11; - Volley = 12; - } - CustomRotation custom_rotation = 8 [deprecated = true]; - // Switch to Aspect of the Viper when mana goes below this percent. double viper_start_mana_percent = 6; // Switch back to Aspect of the Hawk when mana goes above this percent. @@ -228,9 +205,7 @@ message Hunter { bool allow_explosive_shot_downrank = 10; bool multi_dot_serpent_sting = 11; - double steady_shot_max_delay = 12 [deprecated = true]; } - Rotation rotation = 1; message Options { enum Ammo { diff --git a/proto/mage.proto b/proto/mage.proto index 9cf136b1ac..9c75cb42f3 100644 --- a/proto/mage.proto +++ b/proto/mage.proto @@ -145,8 +145,6 @@ enum MageMinorGlyph { message Mage { message Rotation { // Arcane Options. - int32 extra_blasts_during_first_ap = 10 [deprecated = true]; - int32 missile_barrage_below_arcane_blast_stacks = 14 [deprecated = true]; double missile_barrage_below_mana_percent = 15; double blast_without_missile_barrage_above_mana_percent = 16; double only_3_arcane_blast_stacks_below_mana_percent = 17; @@ -164,9 +162,7 @@ message Mage { // Frost Options. bool use_ice_lance = 18; - double water_elemental_disobey_chance = 6 [deprecated = true]; } - Rotation rotation = 1; message Options { enum ArmorType { diff --git a/proto/paladin.proto b/proto/paladin.proto index 30aab70b4a..27aec34243 100644 --- a/proto/paladin.proto +++ b/proto/paladin.proto @@ -3,8 +3,6 @@ package proto; option go_package = "./proto"; - import "common.proto"; - message PaladinTalents { // Holy int32 spiritual_focus = 1; @@ -163,40 +161,7 @@ enum PaladinJudgement { message RetributionPaladin { message Rotation { - int32 exo_slack = 1; - int32 cons_slack = 2; - double divine_plea_percentage = 3; - int32 holy_wrath_threshold = 4; - int32 sov_targets = 5; - - enum SpellOption { - NoSpell = 0; - JudgementOfWisdom = 1; - DivineStorm = 2; - HammerOfWrath = 3; - Consecration = 4; - HolyWrath = 5; - CrusaderStrike = 6; - Exorcism = 7; - DivinePlea = 8; - } - CustomRotation custom_rotation = 8; - CustomRotation custom_cast_sequence = 10; - - enum RotationType { - UnknownType = 0; - Standard = 1; - Custom = 2; - CastSequence = 3; - } - RotationType type = 9; - - bool use_divine_plea = 11; - bool avoid_clipping_consecration = 12; - bool hold_last_avenging_wrath_until_execution = 13; - bool cancel_chaos_bane = 14; } - Rotation rotation = 1; message Options { PaladinJudgement judgement = 1; @@ -209,26 +174,7 @@ message RetributionPaladin { message ProtectionPaladin { message Rotation { - bool hammer_first = 1; - bool use_custom_prio = 2; - bool squeeze_holy_wrath = 4; - double wait_slack = 5; - - enum SpellOption { - NoSpell = 0; - JudgementOfWisdom = 1; - HammerOfWrath = 2; - Consecration = 3; - HolyWrath = 4; - Exorcism = 5; - ShieldOfRighteousness = 6; - AvengersShield = 7; - HammerOfTheRighteous = 8; - HolyShield = 9; - } - CustomRotation custom_rotation = 3; } - Rotation rotation = 1; message Options { PaladinJudgement judgement = 1; @@ -242,7 +188,6 @@ message ProtectionPaladin { message HolyPaladin { message Rotation { } - Rotation rotation = 1; message Options { PaladinJudgement judgement = 1; diff --git a/proto/priest.proto b/proto/priest.proto index d275e525bd..9aad900732 100644 --- a/proto/priest.proto +++ b/proto/priest.proto @@ -138,23 +138,7 @@ enum PriestMinorGlyph { message ShadowPriest { message Rotation { - enum RotationType { - Unknown = 0; - Basic = 1; - Clipping = 2; - Ideal = 3; - AoE = 4; - } - enum PreCastOption { - Nothing = 0; - PrecastVt = 1; - PrecastMb = 2; - } - RotationType rotation_type = 1; - PreCastOption precast_type = 2; - double latency = 3 [deprecated = true]; // Latency between actions } - Rotation rotation = 1; message Options { enum Armor { @@ -174,13 +158,7 @@ message ShadowPriest { message SmitePriest { message Rotation { - bool use_mind_blast = 2; - bool use_shadow_word_death = 3; - bool use_devouring_plague = 4; - bool meme_dream = 5; - double allowed_holy_fire_delay_ms = 6; } - Rotation rotation = 1; message Options { bool use_inner_fire = 3; @@ -192,28 +170,7 @@ message SmitePriest { message HealingPriest { message Rotation { - enum RotationType { - UnknownType = 0; - Cycle = 1; - Custom = 2; - } - RotationType type = 1; - - enum SpellOption { - NoSpell = 0; - GreaterHeal = 1; - FlashHeal = 2; - Renew = 3; - PowerWordShield = 4; - CircleOfHealing = 5; - PrayerOfHealing = 6; - PrayerOfMending = 7; - Penance = 8; - BindingHeal = 9; - } - CustomRotation custom_rotation = 2; } - Rotation rotation = 1; message Options { bool use_inner_fire = 3; diff --git a/proto/rogue.proto b/proto/rogue.proto index c9661fe73c..3d191bcd50 100644 --- a/proto/rogue.proto +++ b/proto/rogue.proto @@ -140,72 +140,7 @@ enum RogueMinorGlyph { message Rogue { message Rotation { - enum Frequency { - Never = 0; - Once = 1; - Maintain = 2; - FrequencyUnknown = 5; - } - Frequency expose_armor_frequency = 1; - - int32 minimum_combo_points_expose_armor = 2; - - Frequency tricks_of_the_trade_frequency = 3; - - enum CombatPriority { - RuptureEviscerate = 0; - EviscerateRupture = 1; - CombatPriorityUnknown = 2; - } - CombatPriority combat_finisher_priority = 4; - - enum CombatBuilder { - SinisterStrike = 0; - Backstab = 1; - HemorrhageCombat = 2; - } - CombatBuilder combat_builder = 25; - - enum AssassinationPriority { - EnvenomRupture = 0; - RuptureEnvenom = 1; - AssassinationPriorityUnknown = 2; - } - AssassinationPriority assassination_finisher_priority = 5; - - enum SubtletyBuilder { - Hemorrhage = 0; - BackstabSub = 1; - } - SubtletyBuilder subtlety_builder = 26; - - enum SubtletyPriority { - SubtletyEviscerate = 0; - SubtletyEnvenom = 1; - SubtletyPriorityUnknown = 2; - } - SubtletyPriority subtlety_finisher_priority = 6; - - int32 minimum_combo_points_primary_finisher = 7; - int32 minimum_combo_points_secondary_finisher = 8; - - Frequency MultiTargetSliceFrequency = 9; - int32 minimum_combo_points_multi_target_slice = 10; - - reserved 11, 13, 14, 19, 21, 22, 23; // the various envenom pooling parameters - - bool use_feint = 12; - - bool open_with_garrote = 15; - bool open_with_premeditation = 16; - bool open_with_shadowstep = 17; - - bool rupture_for_bleed = 18; - - bool hemo_with_dagger = 20; - bool use_ghostly_strike = 24; } - Rotation rotation = 1; message Options { UnitReference tricks_of_the_trade_target = 1; diff --git a/proto/shaman.proto b/proto/shaman.proto index b5fde9f161..83413a897c 100644 --- a/proto/shaman.proto +++ b/proto/shaman.proto @@ -2,7 +2,6 @@ syntax = "proto3"; package proto; option go_package = "./proto"; -import "common.proto"; message ShamanTalents { // Elemental @@ -210,39 +209,10 @@ enum ShamanSyncType { message ElementalShaman { message Rotation { - // Deprecated as of 2023-08-29 - ShamanTotems totems = 3 [deprecated = true]; - - enum RotationType { - Unknown = 0; - Adaptive = 1; - Manual = 2; - } - RotationType type = 1; - bool in_thunderstorm_range = 2 [deprecated = true]; - - // These options are used for the manual rotation. - bool use_fire_nova = 4; - double fn_min_mana_per = 9; - bool use_chain_lightning = 5; - bool use_cl_only_gap = 11; - double cl_min_mana_per = 10; - bool overwrite_flameshock = 6; - bool always_crit_lvb = 7; - bool use_thunderstorm = 8; - double lvb_fs_wait_ms = 12; - - enum BloodlustUse { - UnsetBloodlust = 0; - UseBloodlust = 1; - NoBloodlust = 2; - } - BloodlustUse bloodlust = 13; } message Options { ShamanShield shield = 1; - bool bloodlust = 2 [deprecated = true]; ShamanTotems totems = 3; enum ThunderstormRange { @@ -253,83 +223,21 @@ message ElementalShaman { ThunderstormRange thunderstormRange = 4; } - Rotation rotation = 1; Options options = 3; } message EnhancementShaman { message Rotation { - // Deprecated as of 2023-08-29 - ShamanTotems totems = 1 [deprecated = true]; - - enum RotationType { - Unknown = 0; - Priority = 1; - Custom = 2; - } - RotationType rotation_type = 2; - - //TODO: add spells here for custom rotation (if necessary?) - enum CustomRotationSpell { - NoSpell = 0; - Stormstrike = 1; - StormstrikeDebuffMissing = 2; //find a way to differentiate tooltips for this, lightning bolt weaves, and downranked flametongue - LightningBolt = 3; - LightningBoltWeave = 4; - FlameShock = 5; - EarthShock = 6; - LavaLash = 7; - LavaBurst = 8; - LightningShield = 9; - FireNova = 10; - ChainLightning = 11; - FrostShock = 12; - MagmaTotem = 13; - LightningBoltDelayedWeave = 14; - } - CustomRotation custom_rotation = 3; - - //weaving options - bool lavaburst_weave = 4; - bool lightningbolt_weave = 5; - int32 maelstromweapon_min_stack = 6; - double auto_weave_delay = 7; - - //other general rotation config options - double firenova_mana_threshold = 8; - double shamanistic_rage_mana_threshold = 9; - - enum PrimaryShock { - None = 0; - Earth = 1; - Frost = 2; - } - - bool weave_flame_shock = 10; - PrimaryShock primary_shock = 11; - int32 flame_shock_clip_ticks = 12; - double delay_gcd_weave = 13; - ItemSwap item_swap = 14; - bool enable_item_swap = 15; - - enum BloodlustUse { - UnsetBloodlust = 0; - UseBloodlust = 1; - NoBloodlust = 2; - } - BloodlustUse bloodlust = 16; } message Options { ShamanShield shield = 1; - bool bloodlust = 2 [deprecated = true]; ShamanSyncType sync_type = 3; ShamanImbue imbue_mh = 4; ShamanImbue imbue_oh = 5; ShamanTotems totems = 6; } - Rotation rotation = 1; Options options = 3; } @@ -342,28 +250,14 @@ enum ShamanHealSpell { message RestorationShaman { message Rotation { - // Deprecated as of 2023-08-29 - ShamanTotems totems = 1 [deprecated = true]; - bool use_earth_shield = 2; - ShamanHealSpell primary_heal = 3; - bool use_riptide = 4; - - enum BloodlustUse { - UnsetBloodlust = 0; - UseBloodlust = 1; - NoBloodlust = 2; - } - BloodlustUse bloodlust = 5; } message Options { ShamanShield shield = 1; - bool bloodlust = 2 [deprecated = true]; ShamanImbue imbue_mh = 4; int32 earth_shield_p_p_m = 5; ShamanTotems totems = 6; } - Rotation rotation = 1; Options options = 3; } diff --git a/proto/warlock.proto b/proto/warlock.proto index 9e387cca6c..21f95aa0f2 100644 --- a/proto/warlock.proto +++ b/proto/warlock.proto @@ -2,7 +2,6 @@ syntax = "proto3"; package proto; option go_package = "./proto"; -import "common.proto"; // WotLK talents message WarlockTalents { @@ -138,53 +137,7 @@ enum WarlockMinorGlyph { message Warlock { message Rotation { - enum Preset { - Manual = 0; - Automatic = 1; - } - enum Type { - Affliction = 0; - Demonology = 1; - Destruction = 2; - } - enum PrimarySpell { - UnknownSpell = 0; - ShadowBolt = 1; - Incinerate = 2; - Seed = 3; - } - enum Curse { - NoCurse = 0; - Elements = 1; - Weakness = 2; - Doom = 3; - Agony = 4; - Tongues = 5; - } - enum SecondaryDot { - NoSecondaryDot = 0; - Immolate = 1; - UnstableAffliction = 2; - } - enum SpecSpell { - NoSpecSpell = 0; - ChaosBolt = 1; - Haunt = 2; - } - Preset preset = 1; - Curse curse = 2; - PrimarySpell primary_spell = 3; - SecondaryDot secondary_dot = 4; - bool corruption = 5; - bool detonate_seed = 6; - SpecSpell spec_spell = 7; - Type type = 8; - bool use_infernal = 9; - - bool enable_weapon_swap = 10; - ItemSwap weapon_swap = 11; } - Rotation rotation = 1; message Options { enum Summon { diff --git a/proto/warrior.proto b/proto/warrior.proto index 8886e52313..51a6cd3e65 100644 --- a/proto/warrior.proto +++ b/proto/warrior.proto @@ -3,8 +3,6 @@ package proto; option go_package = "./proto"; -import "common.proto"; - message WarriorTalents { // Arms int32 improved_heroic_strike = 1; @@ -148,78 +146,7 @@ enum WarriorShout { message Warrior { message Rotation { - bool use_cleave = 1; - bool use_rend = 2; - bool use_ms = 18; - bool use_slam = 3; - - enum MainGcd { - None = 0; - Slam = 1; - Bloodthirst = 2; - Whirlwind = 3; - } - MainGcd main_gcd = 4; - - enum SunderArmor { - SunderArmorNone = 0; - SunderArmorHelpStack = 1; - SunderArmorMaintain = 2; - } - SunderArmor sunderArmor = 5; - bool maintain_demo_shout = 6; - bool maintain_thunder_clap = 7; - - // Queue HS or Cleave when over this threshold. - double hs_rage_threshold = 8; - - // Use Mortal Strike when over this threshold. - double ms_rage_threshold = 9; - - // Use Rend when below this threshold. - double rend_rage_threshold_below = 10; - - // Use Slam when over this threshold. - double slam_rage_threshold = 11; - - // Refresh Rend when remaining duration is less than this threshold. - double rend_cd_threshold = 12; - - bool use_hs_during_execute = 13; - bool use_bt_during_execute = 14; - bool spam_execute = 15; - bool use_ww_during_execute = 16; - bool use_slam_over_execute = 17; - - enum StanceOption { - DefaultStance = 0; - BattleStance = 1; - BerserkerStance = 2; - } - StanceOption stance_option = 19; - double rend_health_threshold_above = 20; - - // Only used for Fury - bool use_overpower = 21; - bool execute_phase_overpower = 22; - double bloodsurge_duration_threshold = 25; - - enum SpellOption { - NoSpell = 0; - BloodthirstCustom = 1; - MortalStrike = 2; - WhirlwindCustom = 3; - SlamCustom = 4; - Rend = 5; - Overpower = 6; - Execute = 7; - ThunderClap = 8; - SlamExpiring = 9; - } - CustomRotation custom_rotation = 23; - bool custom_rotation_option = 24; } - Rotation rotation = 1; message Options { double starting_rage = 1; @@ -234,39 +161,7 @@ message Warrior { message ProtectionWarrior { message Rotation { - enum DemoShoutChoice { - DemoShoutChoiceNone = 0; - DemoShoutChoiceMaintain = 1; - DemoShoutChoiceFiller = 2; - } - DemoShoutChoice demo_shout_choice = 1; - - enum ThunderClapChoice { - ThunderClapChoiceNone = 0; - ThunderClapChoiceMaintain = 1; - ThunderClapChoiceOnCD = 2; - } - ThunderClapChoice thunder_clap_choice = 2; - - enum SpellOption { - NoSpell = 0; - Revenge = 1; - ShieldSlam = 2; - Devastate = 3; - SunderArmor = 4; - Shout = 5; - DemoralizingShout = 6; - ThunderClap = 7; - MortalStrike = 8; - ConcussionBlow = 9; - Shockwave = 10; - } - CustomRotation custom_rotation = 3; - - double hs_rage_threshold = 4; - bool prio_sslam_on_shield_block = 5; } - Rotation rotation = 1; message Options { double starting_rage = 1; diff --git a/sim/druid/balance/balance_test.go b/sim/druid/balance/balance_test.go index 5e5d2d2b2e..6d4faf9b5b 100644 --- a/sim/druid/balance/balance_test.go +++ b/sim/druid/balance/balance_test.go @@ -85,7 +85,6 @@ var PlayerOptionsAdaptive = &proto.Player_BalanceDruid{ Options: &proto.BalanceDruid_Options{ OkfUptime: 0.2, }, - Rotation: &proto.BalanceDruid_Rotation{}, }, } diff --git a/sim/druid/restoration/restoration_test.go b/sim/druid/restoration/restoration_test.go index cd6edfb296..9860678554 100644 --- a/sim/druid/restoration/restoration_test.go +++ b/sim/druid/restoration/restoration_test.go @@ -60,7 +60,6 @@ var PlayerOptionsStandard = &proto.Player_RestorationDruid{ Options: &proto.RestorationDruid_Options{ InnervateTarget: &proto.UnitReference{Type: proto.UnitReference_Player, Index: 0}, // self innervate }, - Rotation: &proto.RestorationDruid_Rotation{}, }, } diff --git a/sim/druid/tank/tank_test.go b/sim/druid/tank/tank_test.go index 1424efb46f..b9788176e7 100644 --- a/sim/druid/tank/tank_test.go +++ b/sim/druid/tank/tank_test.go @@ -83,7 +83,6 @@ var PlayerOptionsDefault = &proto.Player_FeralTankDruid{ InnervateTarget: &proto.UnitReference{}, // no Innervate StartingRage: 20, }, - Rotation: &proto.FeralTankDruid_Rotation{}, }, } diff --git a/sim/mage/mage_test.go b/sim/mage/mage_test.go index 3f9e9b4145..b5e777f68c 100644 --- a/sim/mage/mage_test.go +++ b/sim/mage/mage_test.go @@ -128,7 +128,6 @@ var PlayerOptionsFire = &proto.Player_Mage{ Options: &proto.Mage_Options{ Armor: proto.Mage_Options_MoltenArmor, }, - Rotation: &proto.Mage_Rotation{}, }, } @@ -137,7 +136,6 @@ var PlayerOptionsFrost = &proto.Player_Mage{ Options: &proto.Mage_Options{ Armor: proto.Mage_Options_MageArmor, }, - Rotation: &proto.Mage_Rotation{}, }, } @@ -146,7 +144,6 @@ var PlayerOptionsArcane = &proto.Player_Mage{ Options: &proto.Mage_Options{ Armor: proto.Mage_Options_MoltenArmor, }, - Rotation: &proto.Mage_Rotation{}, }, } diff --git a/sim/paladin/avenging_wrath.go b/sim/paladin/avenging_wrath.go index b853e05f08..018012a8f3 100644 --- a/sim/paladin/avenging_wrath.go +++ b/sim/paladin/avenging_wrath.go @@ -56,14 +56,6 @@ func (paladin *Paladin) RegisterAvengingWrathCD() { Type: core.CooldownTypeDPS, // modify this logic if it should ever not be spammed on CD / maybe should synced with other CDs ShouldActivate: func(sim *core.Simulation, character *core.Character) bool { - if paladin.HoldLastAvengingWrathUntilExecution && float64(sim.CurrentTime+paladin.AvengingWrath.CD.Duration) >= float64(sim.Duration) { - if float64(sim.CurrentTime+paladin.AvengingWrathAura.Duration) >= float64(sim.Duration) { - // If we're cutting it close on iteration end time, pop AW anyways to try and get full duration. - return true - } - return false - } - if paladin.CurrentSeal == paladin.SealOfVengeanceAura { if paladin.SovDotSpell.Dot(paladin.CurrentTarget).GetStacks() < 5 { return false diff --git a/sim/paladin/holy/holy.go b/sim/paladin/holy/holy.go index 7230b32915..535c1484b1 100644 --- a/sim/paladin/holy/holy.go +++ b/sim/paladin/holy/holy.go @@ -27,9 +27,8 @@ func NewHolyPaladin(character *core.Character, options *proto.Player) *HolyPalad holyOptions := options.GetHolyPaladin() holy := &HolyPaladin{ - Paladin: paladin.NewPaladin(character, options.TalentsString), - Rotation: holyOptions.Rotation, - Options: holyOptions.Options, + Paladin: paladin.NewPaladin(character, options.TalentsString), + Options: holyOptions.Options, } holy.PaladinAura = holyOptions.Options.Aura @@ -40,8 +39,7 @@ func NewHolyPaladin(character *core.Character, options *proto.Player) *HolyPalad type HolyPaladin struct { *paladin.Paladin - Rotation *proto.HolyPaladin_Rotation - Options *proto.HolyPaladin_Options + Options *proto.HolyPaladin_Options } func (holy *HolyPaladin) GetPaladin() *paladin.Paladin { diff --git a/sim/paladin/holy/holy_test.go b/sim/paladin/holy/holy_test.go index 81bbcf1835..5550a226a4 100644 --- a/sim/paladin/holy/holy_test.go +++ b/sim/paladin/holy/holy_test.go @@ -87,8 +87,7 @@ var defaultProtOptions = &proto.HolyPaladin_Options{ var BasicOptions = &proto.Player_HolyPaladin{ HolyPaladin: &proto.HolyPaladin{ - Options: defaultProtOptions, - Rotation: &proto.HolyPaladin_Rotation{}, + Options: defaultProtOptions, }, } diff --git a/sim/paladin/paladin.go b/sim/paladin/paladin.go index 8b4c5aa17b..d91ca9bb13 100644 --- a/sim/paladin/paladin.go +++ b/sim/paladin/paladin.go @@ -70,10 +70,6 @@ type Paladin struct { DemonAndUndeadTargetCount int32 - AvoidClippingConsecration bool - HoldLastAvengingWrathUntilExecution bool - CancelChaosBane bool - mutualLockoutDPAW *core.Timer } diff --git a/sim/paladin/protection/protection_test.go b/sim/paladin/protection/protection_test.go index dcfb1f388e..5b38e0bdbb 100644 --- a/sim/paladin/protection/protection_test.go +++ b/sim/paladin/protection/protection_test.go @@ -33,7 +33,6 @@ func TestProtection(t *testing.T) { Seal: proto.PaladinSeal_Command, Aura: proto.PaladinAura_RetributionAura, }, - Rotation: defaultProtRotation, }, }, }, @@ -46,7 +45,6 @@ func TestProtection(t *testing.T) { Seal: proto.PaladinSeal_Righteousness, Aura: proto.PaladinAura_RetributionAura, }, - Rotation: defaultProtRotation, }, }, }, @@ -106,8 +104,6 @@ var StandardGlyphs = &proto.Glyphs{ Minor2: int32(proto.PaladinMinorGlyph_GlyphOfSenseUndead), } -var defaultProtRotation = &proto.ProtectionPaladin_Rotation{} - var defaultProtOptions = &proto.ProtectionPaladin_Options{ Judgement: proto.PaladinJudgement_JudgementOfWisdom, Seal: proto.PaladinSeal_Vengeance, @@ -116,8 +112,7 @@ var defaultProtOptions = &proto.ProtectionPaladin_Options{ var DefaultOptions = &proto.Player_ProtectionPaladin{ ProtectionPaladin: &proto.ProtectionPaladin{ - Options: defaultProtOptions, - Rotation: defaultProtRotation, + Options: defaultProtOptions, }, } diff --git a/sim/paladin/retribution/retribution.go b/sim/paladin/retribution/retribution.go index a21aca2089..0af33a5d40 100644 --- a/sim/paladin/retribution/retribution.go +++ b/sim/paladin/retribution/retribution.go @@ -33,10 +33,6 @@ func NewRetributionPaladin(character *core.Character, options *proto.Player) *Re Seal: retOptions.Options.Seal, } - pal.AvoidClippingConsecration = retOptions.Rotation.AvoidClippingConsecration - pal.HoldLastAvengingWrathUntilExecution = retOptions.Rotation.HoldLastAvengingWrathUntilExecution - pal.CancelChaosBane = retOptions.Rotation.CancelChaosBane - ret.PaladinAura = retOptions.Options.Aura ret.EnableAutoAttacks(ret, core.AutoAttackOptions{ diff --git a/sim/paladin/retribution/retribution_test.go b/sim/paladin/retribution/retribution_test.go index b4eb5a47ce..a0d790ec77 100644 --- a/sim/paladin/retribution/retribution_test.go +++ b/sim/paladin/retribution/retribution_test.go @@ -33,7 +33,6 @@ func TestRetribution(t *testing.T) { Seal: proto.PaladinSeal_Command, Aura: proto.PaladinAura_RetributionAura, }, - Rotation: &proto.RetributionPaladin_Rotation{}, }, }, }, @@ -46,7 +45,6 @@ func TestRetribution(t *testing.T) { Seal: proto.PaladinSeal_Righteousness, Aura: proto.PaladinAura_RetributionAura, }, - Rotation: &proto.RetributionPaladin_Rotation{}, }, }, }, @@ -59,14 +57,6 @@ func TestRetribution(t *testing.T) { Seal: proto.PaladinSeal_Vengeance, Aura: proto.PaladinAura_RetributionAura, }, - Rotation: &proto.RetributionPaladin_Rotation{ - ConsSlack: 500, - ExoSlack: 500, - UseDivinePlea: true, - DivinePleaPercentage: 0.75, - HolyWrathThreshold: 4, - SovTargets: 2, - }, }, }, }, @@ -133,7 +123,6 @@ var DefaultOptions = &proto.Player_RetributionPaladin{ Seal: proto.PaladinSeal_Vengeance, Aura: proto.PaladinAura_RetributionAura, }, - Rotation: &proto.RetributionPaladin_Rotation{}, }, } diff --git a/sim/priest/healing/healing_priest_test.go b/sim/priest/healing/healing_priest_test.go index c283397c98..0ff0f4907e 100644 --- a/sim/priest/healing/healing_priest_test.go +++ b/sim/priest/healing/healing_priest_test.go @@ -106,7 +106,6 @@ var PlayerOptionsDisc = &proto.Player_HealingPriest{ UseShadowfiend: true, RapturesPerMinute: 5, }, - Rotation: &proto.HealingPriest_Rotation{}, }, } @@ -116,6 +115,5 @@ var PlayerOptionsHoly = &proto.Player_HealingPriest{ UseInnerFire: true, UseShadowfiend: true, }, - Rotation: &proto.HealingPriest_Rotation{}, }, } diff --git a/sim/priest/shadow/shadow_priest_test.go b/sim/priest/shadow/shadow_priest_test.go index 3fb8fae729..edd33176d8 100644 --- a/sim/priest/shadow/shadow_priest_test.go +++ b/sim/priest/shadow/shadow_priest_test.go @@ -70,9 +70,6 @@ var PlayerOptionsBasic = &proto.Player_ShadowPriest{ UseMindBlast: true, UseShadowWordDeath: true, }, - Rotation: &proto.ShadowPriest_Rotation{ - RotationType: proto.ShadowPriest_Rotation_Basic, - }, }, } var PlayerOptionsClipping = &proto.Player_ShadowPriest{ @@ -83,10 +80,6 @@ var PlayerOptionsClipping = &proto.Player_ShadowPriest{ UseMindBlast: true, UseShadowWordDeath: true, }, - Rotation: &proto.ShadowPriest_Rotation{ - RotationType: proto.ShadowPriest_Rotation_Clipping, - PrecastType: 1, - }, }, } var PlayerOptionsIdeal = &proto.Player_ShadowPriest{ @@ -97,9 +90,5 @@ var PlayerOptionsIdeal = &proto.Player_ShadowPriest{ UseMindBlast: true, UseShadowWordDeath: true, }, - Rotation: &proto.ShadowPriest_Rotation{ - RotationType: proto.ShadowPriest_Rotation_Ideal, - PrecastType: 1, - }, }, } diff --git a/sim/priest/smite/smite_priest_test.go b/sim/priest/smite/smite_priest_test.go index a4a067f70d..5ed9e42767 100644 --- a/sim/priest/smite/smite_priest_test.go +++ b/sim/priest/smite/smite_priest_test.go @@ -60,6 +60,5 @@ var PlayerOptionsBasic = &proto.Player_SmitePriest{ UseInnerFire: true, UseShadowfiend: true, }, - Rotation: &proto.SmitePriest_Rotation{}, }, } diff --git a/sim/raid_bench_test.go b/sim/raid_bench_test.go index d159a20cc1..41e9ef3411 100644 --- a/sim/raid_bench_test.go +++ b/sim/raid_bench_test.go @@ -18,9 +18,6 @@ var castersWithElemental = &proto.Party{ Equipment: MoonkinEquipment, Spec: &proto.Player_BalanceDruid{ BalanceDruid: &proto.BalanceDruid{ - Rotation: &proto.BalanceDruid_Rotation{ - Type: proto.BalanceDruid_Rotation_Default, - }, Options: &proto.BalanceDruid_Options{ InnervateTarget: &proto.UnitReference{}, }, @@ -41,9 +38,6 @@ var castersWithElemental = &proto.Party{ Equipment: ShadowEquipment, Spec: &proto.Player_ShadowPriest{ ShadowPriest: &proto.ShadowPriest{ - Rotation: &proto.ShadowPriest_Rotation{ - RotationType: proto.ShadowPriest_Rotation_Ideal, - }, Options: &proto.ShadowPriest_Options{ UseShadowfiend: true, }, @@ -64,12 +58,8 @@ var castersWithElemental = &proto.Party{ Equipment: ElementalEquipment, Spec: &proto.Player_ElementalShaman{ ElementalShaman: &proto.ElementalShaman{ - Rotation: &proto.ElementalShaman_Rotation{ - Type: proto.ElementalShaman_Rotation_Adaptive, - }, Options: &proto.ElementalShaman_Options{ - Shield: proto.ShamanShield_WaterShield, - Bloodlust: true, + Shield: proto.ShamanShield_WaterShield, Totems: &proto.ShamanTotems{ Earth: proto.EarthTotem_TremorTotem, Air: proto.AirTotem_WrathOfAirTotem, @@ -97,7 +87,6 @@ var castersWithElemental = &proto.Party{ Options: &proto.Mage_Options{ Armor: proto.Mage_Options_MageArmor, }, - Rotation: &proto.Mage_Rotation{}, }, }, Consumes: &proto.Consumes{ @@ -122,9 +111,6 @@ var castersWithResto = &proto.Party{ Equipment: MoonkinEquipment, Spec: &proto.Player_BalanceDruid{ BalanceDruid: &proto.BalanceDruid{ - Rotation: &proto.BalanceDruid_Rotation{ - Type: proto.BalanceDruid_Rotation_Default, - }, Options: &proto.BalanceDruid_Options{ InnervateTarget: &proto.UnitReference{ Type: proto.UnitReference_Player, @@ -148,9 +134,6 @@ var castersWithResto = &proto.Party{ Equipment: ShadowEquipment, Spec: &proto.Player_ShadowPriest{ ShadowPriest: &proto.ShadowPriest{ - Rotation: &proto.ShadowPriest_Rotation{ - RotationType: proto.ShadowPriest_Rotation_Ideal, - }, Options: &proto.ShadowPriest_Options{ UseShadowfiend: true, }, @@ -174,7 +157,6 @@ var castersWithResto = &proto.Party{ Options: &proto.Mage_Options{ Armor: proto.Mage_Options_MageArmor, }, - Rotation: &proto.Mage_Rotation{}, }, }, Consumes: &proto.Consumes{ @@ -206,11 +188,9 @@ func BenchmarkSimulate(b *testing.B) { Equipment: EnhancementEquipment, Spec: &proto.Player_EnhancementShaman{ EnhancementShaman: &proto.EnhancementShaman{ - Rotation: &proto.EnhancementShaman_Rotation{}, Options: &proto.EnhancementShaman_Options{ - Shield: proto.ShamanShield_LightningShield, - Bloodlust: true, - SyncType: proto.ShamanSyncType_SyncMainhandOffhandSwings, + Shield: proto.ShamanShield_LightningShield, + SyncType: proto.ShamanSyncType_SyncMainhandOffhandSwings, Totems: &proto.ShamanTotems{ Earth: proto.EarthTotem_TremorTotem, Air: proto.AirTotem_WrathOfAirTotem, diff --git a/sim/shaman/elemental/elemental.go b/sim/shaman/elemental/elemental.go index b33058633b..5e63cd3756 100644 --- a/sim/shaman/elemental/elemental.go +++ b/sim/shaman/elemental/elemental.go @@ -28,8 +28,7 @@ func NewElementalShaman(character *core.Character, options *proto.Player) *Eleme eleShamOptions := options.GetElementalShaman() selfBuffs := shaman.SelfBuffs{ - Bloodlust: eleShamOptions.Options.Bloodlust, - Shield: eleShamOptions.Options.Shield, + Shield: eleShamOptions.Options.Shield, } totems := &proto.ShamanTotems{} diff --git a/sim/shaman/elemental/elemental_test.go b/sim/shaman/elemental/elemental_test.go index 5a20559d19..d47892c4a3 100644 --- a/sim/shaman/elemental/elemental_test.go +++ b/sim/shaman/elemental/elemental_test.go @@ -111,9 +111,8 @@ var FireElementalBasicTotems = &proto.ShamanTotems{ var PlayerOptionsAdaptive = &proto.Player_ElementalShaman{ ElementalShaman: &proto.ElementalShaman{ Options: &proto.ElementalShaman_Options{ - Shield: proto.ShamanShield_WaterShield, - Bloodlust: true, - Totems: FireElementalBasicTotems, + Shield: proto.ShamanShield_WaterShield, + Totems: FireElementalBasicTotems, }, }, } @@ -121,9 +120,8 @@ var PlayerOptionsAdaptive = &proto.Player_ElementalShaman{ var PlayerOptionsAdaptiveFireElemental = &proto.Player_ElementalShaman{ ElementalShaman: &proto.ElementalShaman{ Options: &proto.ElementalShaman_Options{ - Shield: proto.ShamanShield_WaterShield, - Bloodlust: true, - Totems: FireElementalBasicTotems, + Shield: proto.ShamanShield_WaterShield, + Totems: FireElementalBasicTotems, }, }, } diff --git a/sim/shaman/enhancement/enhancement.go b/sim/shaman/enhancement/enhancement.go index e1653492f2..5dba89bcda 100644 --- a/sim/shaman/enhancement/enhancement.go +++ b/sim/shaman/enhancement/enhancement.go @@ -29,10 +29,9 @@ func NewEnhancementShaman(character *core.Character, options *proto.Player) *Enh enhOptions := options.GetEnhancementShaman() selfBuffs := shaman.SelfBuffs{ - Bloodlust: enhOptions.Options.Bloodlust, - Shield: enhOptions.Options.Shield, - ImbueMH: enhOptions.Options.ImbueMh, - ImbueOH: enhOptions.Options.ImbueOh, + Shield: enhOptions.Options.Shield, + ImbueMH: enhOptions.Options.ImbueMh, + ImbueOH: enhOptions.Options.ImbueOh, } totems := &proto.ShamanTotems{} diff --git a/sim/shaman/enhancement/enhancement_test.go b/sim/shaman/enhancement/enhancement_test.go index 14da520aef..11be85311a 100644 --- a/sim/shaman/enhancement/enhancement_test.go +++ b/sim/shaman/enhancement/enhancement_test.go @@ -98,19 +98,17 @@ var PlayerOptionsFTFT = &proto.Player_EnhancementShaman{ } var enhShamWFWF = &proto.EnhancementShaman_Options{ - Shield: proto.ShamanShield_WaterShield, - Bloodlust: true, - SyncType: proto.ShamanSyncType_DelayOffhandSwings, - ImbueMh: proto.ShamanImbue_WindfuryWeapon, - ImbueOh: proto.ShamanImbue_WindfuryWeapon, + Shield: proto.ShamanShield_WaterShield, + SyncType: proto.ShamanSyncType_DelayOffhandSwings, + ImbueMh: proto.ShamanImbue_WindfuryWeapon, + ImbueOh: proto.ShamanImbue_WindfuryWeapon, } var enhShamFTFT = &proto.EnhancementShaman_Options{ - Shield: proto.ShamanShield_LightningShield, - Bloodlust: true, - SyncType: proto.ShamanSyncType_Auto, - ImbueMh: proto.ShamanImbue_FlametongueWeaponDownrank, - ImbueOh: proto.ShamanImbue_FlametongueWeapon, + Shield: proto.ShamanShield_LightningShield, + SyncType: proto.ShamanSyncType_Auto, + ImbueMh: proto.ShamanImbue_FlametongueWeaponDownrank, + ImbueOh: proto.ShamanImbue_FlametongueWeapon, Totems: &proto.ShamanTotems{ Earth: proto.EarthTotem_StrengthOfEarthTotem, Air: proto.AirTotem_WindfuryTotem, @@ -121,11 +119,10 @@ var enhShamFTFT = &proto.EnhancementShaman_Options{ } var enhShamWFFT = &proto.EnhancementShaman_Options{ - Shield: proto.ShamanShield_LightningShield, - Bloodlust: true, - SyncType: proto.ShamanSyncType_NoSync, - ImbueMh: proto.ShamanImbue_WindfuryWeapon, - ImbueOh: proto.ShamanImbue_FlametongueWeapon, + Shield: proto.ShamanShield_LightningShield, + SyncType: proto.ShamanSyncType_NoSync, + ImbueMh: proto.ShamanImbue_WindfuryWeapon, + ImbueOh: proto.ShamanImbue_FlametongueWeapon, } var FullConsumes = &proto.Consumes{ diff --git a/sim/shaman/restoration/restoration.go b/sim/shaman/restoration/restoration.go index a4a2d0b706..20bb441821 100644 --- a/sim/shaman/restoration/restoration.go +++ b/sim/shaman/restoration/restoration.go @@ -27,8 +27,7 @@ func NewRestorationShaman(character *core.Character, options *proto.Player) *Res restoShamOptions := options.GetRestorationShaman() selfBuffs := shaman.SelfBuffs{ - Bloodlust: restoShamOptions.Options.Bloodlust, - Shield: restoShamOptions.Options.Shield, + Shield: restoShamOptions.Options.Shield, } totems := &proto.ShamanTotems{} diff --git a/sim/shaman/restoration/restoration_test.go b/sim/shaman/restoration/restoration_test.go index 629b68812a..f39cd5a715 100644 --- a/sim/shaman/restoration/restoration_test.go +++ b/sim/shaman/restoration/restoration_test.go @@ -85,9 +85,8 @@ var BasicTotems = &proto.ShamanTotems{ } var restoShamOptions = &proto.RestorationShaman_Options{ - Shield: proto.ShamanShield_WaterShield, - Bloodlust: true, - Totems: BasicTotems, + Shield: proto.ShamanShield_WaterShield, + Totems: BasicTotems, } var PlayerOptionsStandard = &proto.Player_RestorationShaman{ RestorationShaman: &proto.RestorationShaman{ diff --git a/sim/shaman/shaman.go b/sim/shaman/shaman.go index ca370a75ba..06ae6ea461 100644 --- a/sim/shaman/shaman.go +++ b/sim/shaman/shaman.go @@ -60,10 +60,9 @@ func NewShaman(character *core.Character, talents string, totems *proto.ShamanTo // Which buffs this shaman is using. type SelfBuffs struct { - Bloodlust bool - Shield proto.ShamanShield - ImbueMH proto.ShamanImbue - ImbueOH proto.ShamanImbue + Shield proto.ShamanShield + ImbueMH proto.ShamanImbue + ImbueOH proto.ShamanImbue } // Indexes into NextTotemDrops for self buffs diff --git a/sim/warlock/warlock_test.go b/sim/warlock/warlock_test.go index 1e8e56443e..74cf2555af 100644 --- a/sim/warlock/warlock_test.go +++ b/sim/warlock/warlock_test.go @@ -92,16 +92,6 @@ var DestructionGlyphs = &proto.Glyphs{ Major3: int32(proto.WarlockMajorGlyph_GlyphOfIncinerate), } -var defaultDestroRotation = &proto.Warlock_Rotation{ - Type: proto.Warlock_Rotation_Destruction, - PrimarySpell: proto.Warlock_Rotation_Incinerate, - SecondaryDot: proto.Warlock_Rotation_Immolate, - SpecSpell: proto.Warlock_Rotation_ChaosBolt, - Curse: proto.Warlock_Rotation_Doom, - Corruption: false, - DetonateSeed: true, -} - var defaultDestroOptions = &proto.Warlock_Options{ Armor: proto.Warlock_Options_FelArmor, Summon: proto.Warlock_Options_Imp, diff --git a/sim/warrior/protection/protection_warrior_test.go b/sim/warrior/protection/protection_warrior_test.go index 3d01bba754..e4fad71719 100644 --- a/sim/warrior/protection/protection_warrior_test.go +++ b/sim/warrior/protection/protection_warrior_test.go @@ -91,8 +91,7 @@ var DefaultGlyphs = &proto.Glyphs{ var PlayerOptionsBasic = &proto.Player_ProtectionWarrior{ ProtectionWarrior: &proto.ProtectionWarrior{ - Options: warriorOptions, - Rotation: &proto.ProtectionWarrior_Rotation{}, + Options: warriorOptions, }, } diff --git a/sim/web/main_test.go b/sim/web/main_test.go index 84695ae0f7..53e9d95cea 100644 --- a/sim/web/main_test.go +++ b/sim/web/main_test.go @@ -18,9 +18,6 @@ import ( var basicSpec = &proto.Player_ElementalShaman{ ElementalShaman: &proto.ElementalShaman{ - Rotation: &proto.ElementalShaman_Rotation{ - Type: proto.ElementalShaman_Rotation_Adaptive, - }, Options: &proto.ElementalShaman_Options{ Shield: proto.ShamanShield_WaterShield, }, diff --git a/ui/core/player.ts b/ui/core/player.ts index ee9d44f6fb..7e6fde5a22 100644 --- a/ui/core/player.ts +++ b/ui/core/player.ts @@ -17,7 +17,6 @@ import { Spec, Stat, UnitStats, - UnitReference_Type, } from './proto/common.js'; import { AuraStats as AuraStatsProto, @@ -27,7 +26,6 @@ import { import { APLRotation, APLRotation_Type as APLRotationType, - APLValue, SimpleRotation, } from './proto/apl.js'; import { @@ -78,7 +76,6 @@ import { specToEligibleRaces, specTypeFunctions, withSpecProto, - ShamanSpecs, } from './proto_utils/utils.js'; import * as Mechanics from './constants/mechanics.js'; @@ -88,7 +85,6 @@ import { Party, MAX_PARTY_SIZE } from './party.js'; import { Raid } from './raid.js'; import { Sim, SimSettingCategories } from './sim.js'; import { stringComparator, sum } from './utils.js'; -import { ElementalShaman_Options, ElementalShaman_Options_ThunderstormRange, ElementalShaman_Rotation, ElementalShaman_Rotation_BloodlustUse, EnhancementShaman_Rotation, EnhancementShaman_Rotation_BloodlustUse, RestorationShaman_Rotation, RestorationShaman_Rotation_BloodlustUse } from './proto/shaman.js'; import { Database } from './proto_utils/database.js'; export interface AuraStats { @@ -1415,83 +1411,6 @@ export class Player { if (loadCategory(SimSettingCategories.External)) { this.setBuffs(eventID, proto.buffs || IndividualBuffs.create()); } - - if (this.spec == Spec.SpecShadowPriest) { - const options = this.getSpecOptions() as SpecOptions; - if (options.latency) { - this.setChannelClipDelay(eventID, options.latency); - options.latency = 0; - this.setSpecOptions(eventID, options as SpecOptions) - } - } - - if ([Spec.SpecEnhancementShaman, Spec.SpecRestorationShaman, Spec.SpecElementalShaman].includes(this.spec)) { - const rot = this.getSimpleRotation() as SpecRotation; - if (rot.totems) { - const options = this.getSpecOptions() as SpecOptions; - options.totems = rot.totems; - this.setSpecOptions(eventID, options as SpecOptions); - rot.totems = undefined; - this.setSimpleRotation(eventID, rot as SpecRotation); - } - const opt = this.getSpecOptions() as SpecOptions; - - // Update Bloodlust to be part of rotation instead of options to support APL casting bloodlust. - if (opt.bloodlust) { - opt.bloodlust = false; - - var tRot = this.getSimpleRotation(); - if (this.spec == Spec.SpecElementalShaman) { - (tRot as ElementalShaman_Rotation).bloodlust = ElementalShaman_Rotation_BloodlustUse.UseBloodlust; - } else if (this.spec == Spec.SpecEnhancementShaman) { - (tRot as EnhancementShaman_Rotation).bloodlust = EnhancementShaman_Rotation_BloodlustUse.UseBloodlust; - } else if (this.spec == Spec.SpecRestorationShaman) { - (tRot as RestorationShaman_Rotation).bloodlust = RestorationShaman_Rotation_BloodlustUse.UseBloodlust; - } - - this.setSimpleRotation(eventID, tRot as SpecRotation); - this.setSpecOptions(eventID, opt as SpecOptions); - } - - // Update Ele TS range option. - if (this.spec == Spec.SpecElementalShaman) { - var eleOpt = this.getSpecOptions() as ElementalShaman_Options; - var eleRot = this.getSimpleRotation() as ElementalShaman_Rotation; - if (eleRot.inThunderstormRange) { - eleOpt.thunderstormRange = ElementalShaman_Options_ThunderstormRange.TSInRange; - eleRot.inThunderstormRange = false; - this.setSimpleRotation(eventID, eleRot as SpecRotation); - this.setSpecOptions(eventID, eleOpt as SpecOptions); - } - } - } - - if (this.spec == Spec.SpecWarlock) { - const rot = this.getSimpleRotation() as SpecRotation; - if (rot.enableWeaponSwap) { - this.setEnableItemSwap(eventID, rot.enableWeaponSwap); - rot.enableWeaponSwap = false; - this.setSimpleRotation(eventID, rot as SpecRotation) - } - if (rot.weaponSwap) { - this.setItemSwapGear(eventID, this.sim.db.lookupItemSwap(rot.weaponSwap)); - rot.weaponSwap = undefined; - this.setSimpleRotation(eventID, rot as SpecRotation) - } - } - if (this.spec == Spec.SpecEnhancementShaman) { - const rot = this.getSimpleRotation() as SpecRotation; - if (rot.enableItemSwap) { - this.setEnableItemSwap(eventID, rot.enableItemSwap); - rot.enableItemSwap = false; - this.setSimpleRotation(eventID, rot as SpecRotation) - } - if (rot.itemSwap) { - this.setItemSwapGear(eventID, this.sim.db.lookupItemSwap(rot.itemSwap)); - rot.itemSwap = undefined; - this.setSimpleRotation(eventID, rot as SpecRotation) - } - } }); } diff --git a/ui/elemental_shaman/presets.ts b/ui/elemental_shaman/presets.ts index d41b815709..929f3826d0 100644 --- a/ui/elemental_shaman/presets.ts +++ b/ui/elemental_shaman/presets.ts @@ -64,7 +64,6 @@ export const StandardTalents = { export const DefaultOptions = ElementalShamanOptions.create({ shield: ShamanShield.WaterShield, - bloodlust: true, totems: ShamanTotems.create({ earth: EarthTotem.StrengthOfEarthTotem, air: AirTotem.WrathOfAirTotem, diff --git a/ui/enhancement_shaman/presets.ts b/ui/enhancement_shaman/presets.ts index 1d4174bec1..7069a9ac9f 100644 --- a/ui/enhancement_shaman/presets.ts +++ b/ui/enhancement_shaman/presets.ts @@ -84,7 +84,6 @@ export const Phase3Talents = { export const DefaultOptions = EnhancementShamanOptions.create({ shield: ShamanShield.LightningShield, - bloodlust: true, imbueMh: ShamanImbue.WindfuryWeapon, imbueOh: ShamanImbue.FlametongueWeapon, syncType: ShamanSyncType.Auto, diff --git a/ui/raid/raid_stats.ts b/ui/raid/raid_stats.ts index 516105ffb0..38d4f91dd2 100644 --- a/ui/raid/raid_stats.ts +++ b/ui/raid/raid_stats.ts @@ -295,7 +295,7 @@ const RAID_STATS_OPTIONS: RaidStatsOptions = { { label: 'Bloodlust', actionId: ActionId.fromSpellId(2825), - playerData: playerClass(Class.ClassShaman, player => player.getSpecOptions().bloodlust), + playerData: playerClass(Class.ClassShaman), }, ], }, diff --git a/ui/restoration_shaman/presets.ts b/ui/restoration_shaman/presets.ts index c1b8631e04..bf332e295e 100644 --- a/ui/restoration_shaman/presets.ts +++ b/ui/restoration_shaman/presets.ts @@ -64,7 +64,6 @@ export const RaidHealingTalents = { export const DefaultOptions = RestorationShamanOptions.create({ shield: ShamanShield.WaterShield, - bloodlust: true, earthShieldPPM: 0, }); From 08c7406706be5ce1a0d7bfbec2e43695649f04fc Mon Sep 17 00:00:00 2001 From: James Tanner Date: Sat, 6 Jan 2024 22:40:26 -0800 Subject: [PATCH 20/28] Remove README reference to talents and rotation --- README.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/README.md b/README.md index 8a63d13624..e232c04675 100644 --- a/README.md +++ b/README.md @@ -149,10 +149,7 @@ This project uses [Google Protocol Buffers](https://developers.google.com/protoc For a new sim, make the following changes: - Add a new value to the `Spec` enum in proto/common.proto. __NOTE: The name you give to this enum value is not just a name, it is used in our templating system. This guide will refer to this name as `$SPEC` elsewhere.__ - - Add a 'proto/YOUR_CLASS.proto' file if it doesn't already exist and add data messages containing all the class/spec-specific information needed to run your sim. In general, there will be 3 pieces of information you need: - - Talents - - Rotation (the order in which your sim will use spells/abilities) - - Options (additional choices your sim needs to make) + - Add a 'proto/YOUR_CLASS.proto' file if it doesn't already exist and add data messages containing all the class/spec-specific information needed to run your sim. - Update the `PlayerOptions.spec` field in `proto/api.proto` to include your shiny new message as an option. That's it! Now when you run `make` there will be generated .go and .ts code in `sim/core/proto` and `ui/core/proto` respectively. If you aren't familiar with protos, take a quick look at them to see what's happening. From dd9c6dc0f50e4cfcbd5742a7b78d0480b6ccd77a Mon Sep 17 00:00:00 2001 From: James Tanner Date: Sat, 6 Jan 2024 22:59:59 -0800 Subject: [PATCH 21/28] Tiny cleanups --- sim/shaman/enhancement/enhancement.go | 4 ---- ui/core/components/totem_inputs.ts | 11 +++-------- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/sim/shaman/enhancement/enhancement.go b/sim/shaman/enhancement/enhancement.go index 5dba89bcda..e13e8cffbe 100644 --- a/sim/shaman/enhancement/enhancement.go +++ b/sim/shaman/enhancement/enhancement.go @@ -83,9 +83,6 @@ func (enh *EnhancementShaman) getImbueProcMask(imbue proto.ShamanImbue) core.Pro type EnhancementShaman struct { *shaman.Shaman - - // for weaving Lava Burst or Lightning Bolt - previousSwingAt time.Duration } func (enh *EnhancementShaman) GetShaman() *shaman.Shaman { @@ -112,7 +109,6 @@ func (enh *EnhancementShaman) Initialize() { } func (enh *EnhancementShaman) Reset(sim *core.Simulation) { - enh.previousSwingAt = 0 enh.Shaman.Reset(sim) } diff --git a/ui/core/components/totem_inputs.ts b/ui/core/components/totem_inputs.ts index 3b9f5770b4..db1316d107 100644 --- a/ui/core/components/totem_inputs.ts +++ b/ui/core/components/totem_inputs.ts @@ -1,24 +1,19 @@ -import { BooleanPicker } from '../components/boolean_picker.js'; -import { EnumPicker } from '../components/enum_picker.js'; -import { IconEnumPicker, IconEnumPickerConfig } from '../components/icon_enum_picker.js'; +import { IconEnumPicker } from '../components/icon_enum_picker.js'; import { IconPicker } from '../components/icon_picker.js'; -import { IconPickerConfig } from '../components/icon_picker.js'; import { AirTotem, EarthTotem, FireTotem, WaterTotem, ShamanTotems, - EnhancementShaman, } from '../proto/shaman.js'; import { Spec } from '../proto/common.js'; import { ActionId } from '../proto_utils/action_id.js'; import { Player } from '../player.js'; -import { Sim } from '../sim.js'; import { IndividualSimUI } from '../individual_sim_ui.js'; -import { EventID, TypedEvent } from '../typed_event.js'; +import { EventID } from '../typed_event.js'; import * as InputHelpers from '../components/input_helpers.js'; -import { SpecRotation, ShamanSpecs } from '../proto_utils/utils.js'; +import { ShamanSpecs } from '../proto_utils/utils.js'; import { ContentBlock } from './content_block.js'; import { Input } from './input.js'; From e07657f840fa3bf744d2d388a80b9ceebbaa4a88 Mon Sep 17 00:00:00 2001 From: James Tanner Date: Sat, 6 Jan 2024 23:24:41 -0800 Subject: [PATCH 22/28] Fix ele tests --- sim/shaman/elemental/TestElemental.results | 642 ++++++++++----------- sim/shaman/elemental/elemental_test.go | 2 +- 2 files changed, 322 insertions(+), 322 deletions(-) diff --git a/sim/shaman/elemental/TestElemental.results b/sim/shaman/elemental/TestElemental.results index eb13cce09e..ad70d93501 100644 --- a/sim/shaman/elemental/TestElemental.results +++ b/sim/shaman/elemental/TestElemental.results @@ -49,12 +49,12 @@ stat_weights_results: { weights: 0 weights: 0 weights: 0 - weights: 4.52675 + weights: 4.44299 weights: 0 - weights: 1.60973 + weights: 1.57057 weights: 0 weights: 0 - weights: 1.43945 + weights: 1.63513 weights: 0 weights: 0 weights: 0 @@ -91,1023 +91,1023 @@ stat_weights_results: { dps_results: { key: "TestElemental-AllItems-Althor'sAbacus-50359" value: { - dps: 6863.28823 - tps: 3844.36465 + dps: 6650.62639 + tps: 3908.93838 } } dps_results: { key: "TestElemental-AllItems-Althor'sAbacus-50366" value: { - dps: 6896.84001 - tps: 3863.05201 + dps: 6683.44081 + tps: 3927.92265 } } dps_results: { key: "TestElemental-AllItems-AustereEarthsiegeDiamond" value: { - dps: 6970.06348 - tps: 3869.24998 + dps: 6650.78587 + tps: 3892.51837 } } dps_results: { key: "TestElemental-AllItems-Bandit'sInsignia-40371" value: { - dps: 6590.29876 - tps: 3692.31749 + dps: 6383.63628 + tps: 3754.47542 } } dps_results: { key: "TestElemental-AllItems-BaubleofTrueBlood-50354" value: { - dps: 6590.29876 - tps: 3692.31749 + dps: 6383.63628 + tps: 3754.47542 } } dps_results: { key: "TestElemental-AllItems-BaubleofTrueBlood-50726" value: { - dps: 6590.29876 - tps: 3692.31749 + dps: 6383.63628 + tps: 3754.47542 } } dps_results: { key: "TestElemental-AllItems-BeamingEarthsiegeDiamond" value: { - dps: 7073.31686 - tps: 3931.20584 + dps: 6749.85373 + tps: 3950.83736 } } dps_results: { key: "TestElemental-AllItems-Beast-tamer'sShoulders-30892" value: { - dps: 6637.19889 - tps: 3686.64787 + dps: 6284.7992 + tps: 3692.43192 } } dps_results: { key: "TestElemental-AllItems-Bizuri'sTotemofShatteredIce-50458" value: { - dps: 6957.45214 - tps: 3860.74595 + dps: 6721.95171 + tps: 3946.75474 } } dps_results: { key: "TestElemental-AllItems-BlackBruise-50035" value: { - dps: 5934.84303 - tps: 3289.58182 + dps: 5647.12346 + tps: 3312.02078 } } dps_results: { key: "TestElemental-AllItems-BlackBruise-50692" value: { - dps: 5934.84303 - tps: 3289.58182 + dps: 5647.12346 + tps: 3312.02078 } } dps_results: { key: "TestElemental-AllItems-BlessedGarboftheUndeadSlayer" value: { - dps: 4849.76749 - tps: 2661.84341 + dps: 4621.6797 + tps: 2713.57301 } } dps_results: { key: "TestElemental-AllItems-BlessedRegaliaofUndeadCleansing" value: { - dps: 5087.30576 - tps: 2788.85887 + dps: 4847.11817 + tps: 2844.06021 } } dps_results: { key: "TestElemental-AllItems-BracingEarthsiegeDiamond" value: { - dps: 7008.89733 - tps: 3813.18697 + dps: 6688.4352 + tps: 3836.11596 } } dps_results: { key: "TestElemental-AllItems-Bryntroll,theBoneArbiter-50415" value: { - dps: 7164.80442 - tps: 3989.22636 + dps: 6878.48069 + tps: 4029.20239 } } dps_results: { key: "TestElemental-AllItems-Bryntroll,theBoneArbiter-50709" value: { - dps: 7164.80442 - tps: 3989.22636 + dps: 6878.48069 + tps: 4029.20239 } } dps_results: { key: "TestElemental-AllItems-ChaoticSkyflareDiamond" value: { - dps: 7164.80442 - tps: 3989.22636 + dps: 6878.48069 + tps: 4029.20239 } } dps_results: { key: "TestElemental-AllItems-CorpseTongueCoin-50349" value: { - dps: 6590.29876 - tps: 3692.31749 + dps: 6383.63628 + tps: 3754.47542 } } dps_results: { key: "TestElemental-AllItems-CorpseTongueCoin-50352" value: { - dps: 6590.29876 - tps: 3692.31749 + dps: 6383.63628 + tps: 3754.47542 } } dps_results: { key: "TestElemental-AllItems-CorrodedSkeletonKey-50356" value: { - dps: 6590.29876 - tps: 3692.31749 + dps: 6383.63628 + tps: 3754.47542 } } dps_results: { key: "TestElemental-AllItems-DarkmoonCard:Berserker!-42989" value: { - dps: 6732.02618 - tps: 3773.01076 + dps: 6553.94093 + tps: 3849.61191 } } dps_results: { key: "TestElemental-AllItems-DarkmoonCard:Death-42990" value: { - dps: 6860.7293 - tps: 3880.09818 + dps: 6570.39262 + tps: 3890.05855 } } dps_results: { key: "TestElemental-AllItems-DarkmoonCard:Greatness-44255" value: { - dps: 7040.20523 - tps: 3959.90556 + dps: 6793.15133 + tps: 3996.29522 } } dps_results: { key: "TestElemental-AllItems-DeadlyGladiator'sTotemofSurvival-42602" value: { - dps: 7105.93371 - tps: 3949.85562 + dps: 6815.79901 + tps: 3989.27266 } } dps_results: { key: "TestElemental-AllItems-Death'sChoice-47464" value: { - dps: 6590.29876 - tps: 3692.31749 + dps: 6383.63628 + tps: 3754.47542 } } dps_results: { key: "TestElemental-AllItems-DeathKnight'sAnguish-38212" value: { - dps: 6654.44856 - tps: 3731.08418 + dps: 6424.08497 + tps: 3776.14708 } } dps_results: { key: "TestElemental-AllItems-Deathbringer'sWill-50362" value: { - dps: 6608.92553 - tps: 3701.80012 + dps: 6362.13263 + tps: 3742.1294 } } dps_results: { key: "TestElemental-AllItems-Deathbringer'sWill-50363" value: { - dps: 6615.30831 - tps: 3701.43181 + dps: 6344.09943 + tps: 3729.51539 } } dps_results: { key: "TestElemental-AllItems-Defender'sCode-40257" value: { - dps: 6590.29876 - tps: 3692.31749 + dps: 6383.63628 + tps: 3754.47542 } } dps_results: { key: "TestElemental-AllItems-DestructiveSkyflareDiamond" value: { - dps: 6983.31752 - tps: 3875.81743 + dps: 6690.07926 + tps: 3915.78762 } } dps_results: { key: "TestElemental-AllItems-DislodgedForeignObject-50348" value: { - dps: 6966.64527 - tps: 3900.5792 + dps: 6703.78396 + tps: 3932.26253 } } dps_results: { key: "TestElemental-AllItems-DislodgedForeignObject-50353" value: { - dps: 6942.61816 - tps: 3893.17893 + dps: 6663.50664 + tps: 3914.71277 } } dps_results: { key: "TestElemental-AllItems-EarthshatterBattlegear" value: { - dps: 5240.68746 - tps: 2874.25887 + dps: 5008.10765 + tps: 2942.16728 } } dps_results: { key: "TestElemental-AllItems-EarthshatterGarb" value: { - dps: 6674.94094 - tps: 3717.32881 + dps: 6179.49141 + tps: 3627.02244 } } dps_results: { key: "TestElemental-AllItems-EffulgentSkyflareDiamond" value: { - dps: 6970.06348 - tps: 3869.24998 + dps: 6650.78587 + tps: 3892.51837 } } dps_results: { key: "TestElemental-AllItems-EmberSkyflareDiamond" value: { - dps: 7109.25352 - tps: 3952.04187 + dps: 6780.0939 + tps: 3969.04623 } } dps_results: { key: "TestElemental-AllItems-EnigmaticSkyflareDiamond" value: { - dps: 6981.25486 - tps: 3875.42442 + dps: 6688.54472 + tps: 3915.04084 } } dps_results: { key: "TestElemental-AllItems-EnigmaticStarflareDiamond" value: { - dps: 6978.29223 - tps: 3873.56016 + dps: 6685.93319 + tps: 3913.7067 } } dps_results: { key: "TestElemental-AllItems-EphemeralSnowflake-50260" value: { - dps: 6590.29876 - tps: 3692.31749 + dps: 6383.63628 + tps: 3754.47542 } } dps_results: { key: "TestElemental-AllItems-EssenceofGossamer-37220" value: { - dps: 6590.29876 - tps: 3692.31749 + dps: 6383.63628 + tps: 3754.47542 } } dps_results: { key: "TestElemental-AllItems-EternalEarthsiegeDiamond" value: { - dps: 6970.06348 - tps: 3869.24998 + dps: 6650.78587 + tps: 3892.51837 } } dps_results: { key: "TestElemental-AllItems-ExtractofNecromanticPower-40373" value: { - dps: 6796.89239 - tps: 3823.35342 + dps: 6590.60935 + tps: 3895.85528 } } dps_results: { key: "TestElemental-AllItems-EyeoftheBroodmother-45308" value: { - dps: 6921.47785 - tps: 3875.31782 + dps: 6729.4714 + tps: 3950.89645 } } dps_results: { key: "TestElemental-AllItems-Figurine-SapphireOwl-42413" value: { - dps: 6752.7015 - tps: 3787.08978 + dps: 6575.3696 + tps: 3870.55974 } } dps_results: { key: "TestElemental-AllItems-ForethoughtTalisman-40258" value: { - dps: 6759.58274 - tps: 3786.60372 + dps: 6549.19998 + tps: 3850.25971 } } dps_results: { key: "TestElemental-AllItems-ForgeEmber-37660" value: { - dps: 6857.94549 - tps: 3833.97125 + dps: 6643.77803 + tps: 3900.27038 } } dps_results: { key: "TestElemental-AllItems-ForlornSkyflareDiamond" value: { - dps: 7008.89733 - tps: 3890.80376 + dps: 6688.4352 + tps: 3914.20069 } } dps_results: { key: "TestElemental-AllItems-ForlornStarflareDiamond" value: { - dps: 7001.13056 - tps: 3886.493 + dps: 6680.90533 + tps: 3909.86422 } } dps_results: { key: "TestElemental-AllItems-FrostWitch'sBattlegear" value: { - dps: 6251.22911 - tps: 3478.8872 + dps: 5945.37615 + tps: 3481.78408 } } dps_results: { key: "TestElemental-AllItems-FrostWitch'sRegalia" value: { - dps: 8181.04054 - tps: 4550.42527 + dps: 7844.07938 + tps: 4580.49628 } } dps_results: { key: "TestElemental-AllItems-FuriousGladiator'sTotemofSurvival-42603" value: { - dps: 7120.43152 - tps: 3957.75317 + dps: 6830.00984 + tps: 3997.28389 } } dps_results: { key: "TestElemental-AllItems-FuryoftheFiveFlights-40431" value: { - dps: 6590.29876 - tps: 3692.31749 + dps: 6383.63628 + tps: 3754.47542 } } dps_results: { key: "TestElemental-AllItems-FuturesightRune-38763" value: { - dps: 6684.85377 - tps: 3744.98187 + dps: 6476.1133 + tps: 3807.97655 } } dps_results: { key: "TestElemental-AllItems-Gladiator'sEarthshaker" value: { - dps: 5674.43948 - tps: 3169.07236 + dps: 5335.58213 + tps: 3145.50078 } } dps_results: { key: "TestElemental-AllItems-Gladiator'sWartide" value: { - dps: 6486.91113 - tps: 3600.91125 + dps: 6112.79044 + tps: 3592.17518 } } dps_results: { key: "TestElemental-AllItems-GlowingTwilightScale-54573" value: { - dps: 6880.06412 - tps: 3853.70833 + dps: 6667.0336 + tps: 3918.43051 } } dps_results: { key: "TestElemental-AllItems-GlowingTwilightScale-54589" value: { - dps: 6918.19114 - tps: 3874.94396 + dps: 6704.32272 + tps: 3940.00355 } } dps_results: { key: "TestElemental-AllItems-GnomishLightningGenerator-41121" value: { - dps: 6720.43279 - tps: 3765.32555 + dps: 6521.92552 + tps: 3829.99373 } } dps_results: { key: "TestElemental-AllItems-HatefulGladiator'sTotemofSurvival-42601" value: { - dps: 7068.6805 - tps: 3929.02562 + dps: 6777.4012 + tps: 3967.65244 } } dps_results: { key: "TestElemental-AllItems-Heartpierce-49982" value: { - dps: 7164.80442 - tps: 3989.22636 + dps: 6878.48069 + tps: 4029.20239 } } dps_results: { key: "TestElemental-AllItems-Heartpierce-50641" value: { - dps: 7164.80442 - tps: 3989.22636 + dps: 6878.48069 + tps: 4029.20239 } } dps_results: { key: "TestElemental-AllItems-ImpassiveSkyflareDiamond" value: { - dps: 6981.25486 - tps: 3875.42442 + dps: 6688.54472 + tps: 3915.04084 } } dps_results: { key: "TestElemental-AllItems-ImpassiveStarflareDiamond" value: { - dps: 6978.29223 - tps: 3873.56016 + dps: 6685.93319 + tps: 3913.7067 } } dps_results: { key: "TestElemental-AllItems-IncisorFragment-37723" value: { - dps: 6590.29876 - tps: 3692.31749 + dps: 6383.63628 + tps: 3754.47542 } } dps_results: { key: "TestElemental-AllItems-InsightfulEarthsiegeDiamond" value: { - dps: 7290.49152 - tps: 4066.63225 + dps: 6913.42681 + tps: 4049.97369 } } dps_results: { key: "TestElemental-AllItems-InvigoratingEarthsiegeDiamond" value: { - dps: 6970.06348 - tps: 3869.24998 + dps: 6650.78587 + tps: 3892.51837 } } dps_results: { key: "TestElemental-AllItems-LastWord-50179" value: { - dps: 7164.80442 - tps: 3989.22636 + dps: 6878.48069 + tps: 4029.20239 } } dps_results: { key: "TestElemental-AllItems-LastWord-50708" value: { - dps: 7164.80442 - tps: 3989.22636 + dps: 6878.48069 + tps: 4029.20239 } } dps_results: { key: "TestElemental-AllItems-Lavanthor'sTalisman-37872" value: { - dps: 6590.29876 - tps: 3692.31749 + dps: 6383.63628 + tps: 3754.47542 } } dps_results: { key: "TestElemental-AllItems-MajesticDragonFigurine-40430" value: { - dps: 6590.29876 - tps: 3692.31749 + dps: 6383.63628 + tps: 3754.47542 } } dps_results: { key: "TestElemental-AllItems-MeteoriteWhetstone-37390" value: { - dps: 6703.01641 - tps: 3757.5639 + dps: 6509.07319 + tps: 3823.05387 } } dps_results: { key: "TestElemental-AllItems-NevermeltingIceCrystal-50259" value: { - dps: 6759.58274 - tps: 3786.60372 + dps: 6549.19998 + tps: 3850.25971 } } dps_results: { key: "TestElemental-AllItems-Nibelung-49992" value: { - dps: 7164.80442 - tps: 3989.22636 + dps: 6878.48069 + tps: 4029.20239 } } dps_results: { key: "TestElemental-AllItems-Nibelung-50648" value: { - dps: 7164.80442 - tps: 3989.22636 + dps: 6878.48069 + tps: 4029.20239 } } dps_results: { key: "TestElemental-AllItems-OfferingofSacrifice-37638" value: { - dps: 6590.29876 - tps: 3692.31749 + dps: 6383.63628 + tps: 3754.47542 } } dps_results: { key: "TestElemental-AllItems-PersistentEarthshatterDiamond" value: { - dps: 6970.06348 - tps: 3869.24998 + dps: 6650.78587 + tps: 3892.51837 } } dps_results: { key: "TestElemental-AllItems-PersistentEarthsiegeDiamond" value: { - dps: 6970.06348 - tps: 3869.24998 + dps: 6650.78587 + tps: 3892.51837 } } dps_results: { key: "TestElemental-AllItems-PetrifiedScarab-21685" value: { - dps: 6590.29876 - tps: 3692.31749 + dps: 6383.63628 + tps: 3754.47542 } } dps_results: { key: "TestElemental-AllItems-PetrifiedTwilightScale-54571" value: { - dps: 6590.29876 - tps: 3692.31749 + dps: 6383.63628 + tps: 3754.47542 } } dps_results: { key: "TestElemental-AllItems-PetrifiedTwilightScale-54591" value: { - dps: 6590.29876 - tps: 3692.31749 + dps: 6383.63628 + tps: 3754.47542 } } dps_results: { key: "TestElemental-AllItems-PowerfulEarthshatterDiamond" value: { - dps: 6970.06348 - tps: 3869.24998 + dps: 6650.78587 + tps: 3892.51837 } } dps_results: { key: "TestElemental-AllItems-PowerfulEarthsiegeDiamond" value: { - dps: 6970.06348 - tps: 3869.24998 + dps: 6650.78587 + tps: 3892.51837 } } dps_results: { key: "TestElemental-AllItems-PurifiedShardoftheGods" value: { - dps: 6590.29876 - tps: 3692.31749 + dps: 6383.63628 + tps: 3754.47542 } } dps_results: { key: "TestElemental-AllItems-ReignoftheDead-47316" value: { - dps: 7052.24444 - tps: 4039.06046 + dps: 6785.44036 + tps: 4061.50904 } } dps_results: { key: "TestElemental-AllItems-ReignoftheDead-47477" value: { - dps: 7103.52117 - tps: 4078.12459 + dps: 6835.69769 + tps: 4100.44394 } } dps_results: { key: "TestElemental-AllItems-RelentlessEarthsiegeDiamond" value: { - dps: 7152.70434 - tps: 3982.54241 + dps: 6838.52532 + tps: 4005.44364 } } dps_results: { key: "TestElemental-AllItems-RelentlessGladiator'sTotemofSurvival-42604" value: { - dps: 7138.036 - tps: 3967.34306 + dps: 6847.26584 + tps: 4007.0118 } } dps_results: { key: "TestElemental-AllItems-RevitalizingSkyflareDiamond" value: { - dps: 7046.129 - tps: 3916.29081 + dps: 6732.8001 + tps: 3942.32307 } } dps_results: { key: "TestElemental-AllItems-RuneofRepulsion-40372" value: { - dps: 6590.29876 - tps: 3692.31749 + dps: 6383.63628 + tps: 3754.47542 } } dps_results: { key: "TestElemental-AllItems-SavageGladiator'sTotemofSurvival-42594" value: { - dps: 7062.9973 - tps: 3926.0163 + dps: 6772.13405 + tps: 3964.67891 } } dps_results: { key: "TestElemental-AllItems-SealofthePantheon-36993" value: { - dps: 6590.29876 - tps: 3692.31749 + dps: 6383.63628 + tps: 3754.47542 } } dps_results: { key: "TestElemental-AllItems-Shadowmourne-49623" value: { - dps: 7164.80442 - tps: 3989.22636 + dps: 6878.48069 + tps: 4029.20239 } } dps_results: { key: "TestElemental-AllItems-ShinyShardoftheGods" value: { - dps: 6590.29876 - tps: 3692.31749 + dps: 6383.63628 + tps: 3754.47542 } } dps_results: { key: "TestElemental-AllItems-Sindragosa'sFlawlessFang-50361" value: { - dps: 6590.29876 - tps: 3692.31749 + dps: 6383.63628 + tps: 3754.47542 } } dps_results: { key: "TestElemental-AllItems-SkycallTotem-33506" value: { - dps: 6996.67757 - tps: 3883.18757 + dps: 6682.61033 + tps: 3913.80687 } } dps_results: { key: "TestElemental-AllItems-SkyshatterHarness" value: { - dps: 4242.77008 - tps: 2309.658 + dps: 4002.585 + tps: 2357.7596 } } dps_results: { key: "TestElemental-AllItems-SkyshatterRegalia" value: { - dps: 5207.79808 - tps: 2868.59121 + dps: 4883.58338 + tps: 2859.69339 } } dps_results: { key: "TestElemental-AllItems-SliverofPureIce-50339" value: { - dps: 6831.26153 - tps: 3826.52671 + dps: 6619.30353 + tps: 3890.81702 } } dps_results: { key: "TestElemental-AllItems-SliverofPureIce-50346" value: { - dps: 6861.76315 - tps: 3843.51522 + dps: 6649.13482 + tps: 3908.07545 } } dps_results: { key: "TestElemental-AllItems-SoulPreserver-37111" value: { - dps: 6704.67982 - tps: 3756.0244 + dps: 6495.50364 + tps: 3819.19453 } } dps_results: { key: "TestElemental-AllItems-SouloftheDead-40382" value: { - dps: 7069.54719 - tps: 3985.56698 + dps: 6825.82188 + tps: 4022.98812 } } dps_results: { key: "TestElemental-AllItems-SparkofLife-37657" value: { - dps: 7025.73924 - tps: 3971.04629 + dps: 6650.00647 + tps: 3915.17261 } } dps_results: { key: "TestElemental-AllItems-SphereofRedDragon'sBlood-37166" value: { - dps: 6837.78129 - tps: 3823.43591 + dps: 6623.79551 + tps: 3891.42765 } } dps_results: { key: "TestElemental-AllItems-Stonebreaker'sTotem-33507" value: { - dps: 7033.44467 - tps: 3910.36784 + dps: 6744.74488 + tps: 3949.21654 } } dps_results: { key: "TestElemental-AllItems-StormshroudArmor" value: { - dps: 4709.32376 - tps: 2574.18851 + dps: 4355.70242 + tps: 2550.73391 } } dps_results: { key: "TestElemental-AllItems-SwiftSkyflareDiamond" value: { - dps: 6970.06348 - tps: 3869.24998 + dps: 6650.78587 + tps: 3892.51837 } } dps_results: { key: "TestElemental-AllItems-SwiftStarflareDiamond" value: { - dps: 6970.06348 - tps: 3869.24998 + dps: 6650.78587 + tps: 3892.51837 } } dps_results: { key: "TestElemental-AllItems-SwiftWindfireDiamond" value: { - dps: 6970.06348 - tps: 3869.24998 + dps: 6650.78587 + tps: 3892.51837 } } dps_results: { key: "TestElemental-AllItems-TalismanofTrollDivinity-37734" value: { - dps: 6590.29876 - tps: 3692.31749 + dps: 6383.63628 + tps: 3754.47542 } } dps_results: { key: "TestElemental-AllItems-TearsoftheVanquished-47215" value: { - dps: 6909.61723 - tps: 3881.54719 + dps: 6689.01917 + tps: 3935.29542 } } dps_results: { key: "TestElemental-AllItems-TheFistsofFury" value: { - dps: 5891.32972 - tps: 3249.59732 + dps: 5625.57829 + tps: 3285.97169 } } dps_results: { key: "TestElemental-AllItems-TheGeneral'sHeart-45507" value: { - dps: 6590.29876 - tps: 3692.31749 + dps: 6383.63628 + tps: 3754.47542 } } dps_results: { key: "TestElemental-AllItems-Thrall'sBattlegear" value: { - dps: 5796.83651 - tps: 3216.81418 + dps: 5516.27414 + tps: 3246.61244 } } dps_results: { key: "TestElemental-AllItems-Thrall'sRegalia" value: { - dps: 6929.19955 - tps: 3885.68471 + dps: 6598.34827 + tps: 3909.84157 } } dps_results: { key: "TestElemental-AllItems-ThunderingSkyflareDiamond" value: { - dps: 6970.06348 - tps: 3869.24998 + dps: 6650.78587 + tps: 3892.51837 } } dps_results: { key: "TestElemental-AllItems-TidefuryRaiment" value: { - dps: 4718.56457 - tps: 2574.31116 + dps: 4423.20082 + tps: 2596.84574 } } dps_results: { key: "TestElemental-AllItems-TinyAbominationinaJar-50351" value: { - dps: 6988.22174 - tps: 3926.40867 + dps: 6655.54584 + tps: 3899.95103 } } dps_results: { key: "TestElemental-AllItems-TinyAbominationinaJar-50706" value: { - dps: 6988.22174 - tps: 3926.40867 + dps: 6655.54584 + tps: 3899.95103 } } dps_results: { key: "TestElemental-AllItems-TirelessSkyflareDiamond" value: { - dps: 7008.89733 - tps: 3890.80376 + dps: 6688.4352 + tps: 3914.20069 } } dps_results: { key: "TestElemental-AllItems-TirelessStarflareDiamond" value: { - dps: 7001.13056 - tps: 3886.493 + dps: 6680.90533 + tps: 3909.86422 } } dps_results: { key: "TestElemental-AllItems-TomeofArcanePhenomena-36972" value: { - dps: 6694.00426 - tps: 3750.07842 + dps: 6485.06269 + tps: 3813.15408 } } dps_results: { key: "TestElemental-AllItems-TotemofElectrifyingWind-47666" value: { - dps: 6976.71388 - tps: 3877.7192 + dps: 6736.64674 + tps: 3958.31392 } } dps_results: { key: "TestElemental-AllItems-TotemofQuakingEarth-47667" value: { - dps: 7033.44467 - tps: 3910.36784 + dps: 6744.74488 + tps: 3949.21654 } } dps_results: { key: "TestElemental-AllItems-TotemoftheAvalanche-50463" value: { - dps: 7033.44467 - tps: 3910.36784 + dps: 6744.74488 + tps: 3949.21654 } } dps_results: { key: "TestElemental-AllItems-TotemoftheElementalPlane-40708" value: { - dps: 7016.26152 - tps: 3891.61216 + dps: 6674.7515 + tps: 3911.78201 } } dps_results: { key: "TestElemental-AllItems-TrenchantEarthshatterDiamond" value: { - dps: 7001.13056 - tps: 3886.493 + dps: 6680.90533 + tps: 3909.86422 } } dps_results: { key: "TestElemental-AllItems-TrenchantEarthsiegeDiamond" value: { - dps: 7008.89733 - tps: 3890.80376 + dps: 6688.4352 + tps: 3914.20069 } } dps_results: { key: "TestElemental-AllItems-UndeadSlayer'sBlessedArmor" value: { - dps: 4569.19693 - tps: 2487.70946 + dps: 4323.7801 + tps: 2529.23393 } } dps_results: { key: "TestElemental-AllItems-Val'anyr,HammerofAncientKings-46017" value: { - dps: 7390.12914 - tps: 4115.93764 + dps: 7128.01624 + tps: 4183.98496 } } dps_results: { key: "TestElemental-AllItems-WingedTalisman-37844" value: { - dps: 6590.29876 - tps: 3692.31749 + dps: 6383.63628 + tps: 3754.47542 } } dps_results: { key: "TestElemental-AllItems-WorldbreakerBattlegear" value: { - dps: 5369.52365 - tps: 2952.12673 + dps: 5093.03619 + tps: 2978.14057 } } dps_results: { key: "TestElemental-AllItems-WorldbreakerGarb" value: { - dps: 6993.19748 - tps: 3958.54516 + dps: 6644.51389 + tps: 3953.39731 } } dps_results: { key: "TestElemental-AllItems-WrathfulGladiator'sTotemofSurvival-51513" value: { - dps: 7156.67604 - tps: 3977.49706 + dps: 6865.5369 + tps: 4017.31195 } } dps_results: { key: "TestElemental-Average-Default" value: { - dps: 7276.45932 - tps: 4041.15477 + dps: 6975.13169 + tps: 4083.69205 } } dps_results: { key: "TestElemental-Settings-Orc-p1-Adaptive-advanced-FullBuffs-LongMultiTarget" value: { - dps: 9771.21018 - tps: 4705.22913 + dps: 7158.1636 + tps: 4631.22912 } } dps_results: { key: "TestElemental-Settings-Orc-p1-Adaptive-advanced-FullBuffs-LongSingleTarget" value: { - dps: 7454.50067 - tps: 4140.478 + dps: 7051.59197 + tps: 4152.01262 } } dps_results: { key: "TestElemental-Settings-Orc-p1-Adaptive-advanced-FullBuffs-ShortSingleTarget" value: { - dps: 8964.30154 - tps: 4708.79854 + dps: 8048.02778 + tps: 4774.36143 } } dps_results: { key: "TestElemental-Settings-Orc-p1-Adaptive-advanced-NoBuffs-LongMultiTarget" value: { - dps: 5521.03184 - tps: 2325.24307 + dps: 3548.58923 + tps: 2374.57903 } } dps_results: { key: "TestElemental-Settings-Orc-p1-Adaptive-advanced-NoBuffs-LongSingleTarget" value: { - dps: 3837.05884 - tps: 2026.4407 + dps: 3555.63224 + tps: 2074.92756 } } dps_results: { key: "TestElemental-Settings-Orc-p1-Adaptive-advanced-NoBuffs-ShortSingleTarget" value: { - dps: 6515.97761 - tps: 3373.88626 + dps: 5696.34418 + tps: 3366.5265 } } dps_results: { key: "TestElemental-Settings-Orc-p1-Adaptive-default-FullBuffs-LongMultiTarget" value: { - dps: 8579.99908 - tps: 3796.63806 + dps: 6069.22264 + tps: 3746.61997 } } dps_results: { key: "TestElemental-Settings-Orc-p1-Adaptive-default-FullBuffs-LongSingleTarget" value: { - dps: 7313.94007 - tps: 4056.90464 + dps: 6948.65991 + tps: 4079.46271 } } dps_results: { key: "TestElemental-Settings-Orc-p1-Adaptive-default-FullBuffs-ShortSingleTarget" value: { - dps: 9410.66293 - tps: 4967.07992 + dps: 8298.85912 + tps: 4893.97673 } } dps_results: { key: "TestElemental-Settings-Orc-p1-Adaptive-default-NoBuffs-LongMultiTarget" value: { - dps: 4748.6775 - tps: 1590.44032 + dps: 2796.89148 + tps: 1627.34252 } } dps_results: { key: "TestElemental-Settings-Orc-p1-Adaptive-default-NoBuffs-LongSingleTarget" value: { - dps: 3294.32029 - tps: 1688.70458 + dps: 3020.48753 + tps: 1734.1061 } } dps_results: { key: "TestElemental-Settings-Orc-p1-Adaptive-default-NoBuffs-ShortSingleTarget" value: { - dps: 6610.40307 - tps: 3428.92065 + dps: 5846.9485 + tps: 3464.62776 } } dps_results: { @@ -1197,85 +1197,85 @@ dps_results: { dps_results: { key: "TestElemental-Settings-Troll-p1-Adaptive-advanced-FullBuffs-LongMultiTarget" value: { - dps: 9488.36304 - tps: 4655.75987 + dps: 7188.71322 + tps: 4648.91616 } } dps_results: { key: "TestElemental-Settings-Troll-p1-Adaptive-advanced-FullBuffs-LongSingleTarget" value: { - dps: 7367.11741 - tps: 4114.77864 + dps: 7020.67592 + tps: 4141.24482 } } dps_results: { key: "TestElemental-Settings-Troll-p1-Adaptive-advanced-FullBuffs-ShortSingleTarget" value: { - dps: 9035.33243 - tps: 4858.19017 + dps: 8241.24547 + tps: 4948.94681 } } dps_results: { key: "TestElemental-Settings-Troll-p1-Adaptive-advanced-NoBuffs-LongMultiTarget" value: { - dps: 5368.23343 - tps: 2330.5972 + dps: 3505.62587 + tps: 2350.14464 } } dps_results: { key: "TestElemental-Settings-Troll-p1-Adaptive-advanced-NoBuffs-LongSingleTarget" value: { - dps: 3821.62337 - tps: 2048.21029 + dps: 3509.36245 + tps: 2042.74932 } } dps_results: { key: "TestElemental-Settings-Troll-p1-Adaptive-advanced-NoBuffs-ShortSingleTarget" value: { - dps: 6522.405 - tps: 3434.46393 + dps: 5750.36161 + tps: 3412.18966 } } dps_results: { key: "TestElemental-Settings-Troll-p1-Adaptive-default-FullBuffs-LongMultiTarget" value: { - dps: 8339.91467 - tps: 3764.5368 + dps: 6135.51805 + tps: 3798.17278 } } dps_results: { key: "TestElemental-Settings-Troll-p1-Adaptive-default-FullBuffs-LongSingleTarget" value: { - dps: 7164.80442 - tps: 3989.22636 + dps: 6878.48069 + tps: 4029.20239 } } dps_results: { key: "TestElemental-Settings-Troll-p1-Adaptive-default-FullBuffs-ShortSingleTarget" value: { - dps: 9014.56519 - tps: 4792.02486 + dps: 8150.21209 + tps: 4790.65713 } } dps_results: { key: "TestElemental-Settings-Troll-p1-Adaptive-default-NoBuffs-LongMultiTarget" value: { - dps: 4642.58591 - tps: 1623.02948 + dps: 2815.63936 + tps: 1642.0156 } } dps_results: { key: "TestElemental-Settings-Troll-p1-Adaptive-default-NoBuffs-LongSingleTarget" value: { - dps: 3256.28858 - tps: 1685.78523 + dps: 2959.15746 + tps: 1688.05159 } } dps_results: { key: "TestElemental-Settings-Troll-p1-Adaptive-default-NoBuffs-ShortSingleTarget" value: { - dps: 6403.21606 - tps: 3333.61161 + dps: 5711.12961 + tps: 3354.03045 } } dps_results: { @@ -1365,7 +1365,7 @@ dps_results: { dps_results: { key: "TestElemental-SwitchInFrontOfTarget-Default" value: { - dps: 7144.09519 - tps: 3989.22636 + dps: 6878.48069 + tps: 4029.20239 } } diff --git a/sim/shaman/elemental/elemental_test.go b/sim/shaman/elemental/elemental_test.go index d47892c4a3..469836c68b 100644 --- a/sim/shaman/elemental/elemental_test.go +++ b/sim/shaman/elemental/elemental_test.go @@ -112,7 +112,7 @@ var PlayerOptionsAdaptive = &proto.Player_ElementalShaman{ ElementalShaman: &proto.ElementalShaman{ Options: &proto.ElementalShaman_Options{ Shield: proto.ShamanShield_WaterShield, - Totems: FireElementalBasicTotems, + Totems: BasicTotems, }, }, } From 2cd9e30a729534b6cffa497b5ba524735e8426d0 Mon Sep 17 00:00:00 2001 From: James Tanner Date: Sun, 7 Jan 2024 02:55:05 -0800 Subject: [PATCH 23/28] Add back detonate_seed rotation field, as an option --- proto/warlock.proto | 1 + sim/warlock/seed.go | 6 +++++- sim/warlock/warlock_test.go | 21 ++++++++++++--------- ui/warlock/inputs.ts | 6 ++++++ ui/warlock/sim.ts | 1 + 5 files changed, 25 insertions(+), 10 deletions(-) diff --git a/proto/warlock.proto b/proto/warlock.proto index 21f95aa0f2..b4b778fa9e 100644 --- a/proto/warlock.proto +++ b/proto/warlock.proto @@ -165,6 +165,7 @@ message Warlock { Summon summon = 2; WeaponImbue weaponImbue = 3; bool _oldDPBehaviourOption = 4; + bool detonate_seed = 5; } Options options = 3; } diff --git a/sim/warlock/seed.go b/sim/warlock/seed.go index d404d16861..bf479799d8 100644 --- a/sim/warlock/seed.go +++ b/sim/warlock/seed.go @@ -108,7 +108,11 @@ func (warlock *Warlock) registerSeedSpell() { // seed is mutually exclusive with corruption warlock.Corruption.Dot(target).Deactivate(sim) - spell.Dot(target).Apply(sim) + if warlock.Options.DetonateSeed { + seedExplosion.Cast(sim, target) + } else { + spell.Dot(target).Apply(sim) + } } }) }, diff --git a/sim/warlock/warlock_test.go b/sim/warlock/warlock_test.go index 74cf2555af..288d7cac2a 100644 --- a/sim/warlock/warlock_test.go +++ b/sim/warlock/warlock_test.go @@ -93,9 +93,10 @@ var DestructionGlyphs = &proto.Glyphs{ } var defaultDestroOptions = &proto.Warlock_Options{ - Armor: proto.Warlock_Options_FelArmor, - Summon: proto.Warlock_Options_Imp, - WeaponImbue: proto.Warlock_Options_GrandFirestone, + Armor: proto.Warlock_Options_FelArmor, + Summon: proto.Warlock_Options_Imp, + WeaponImbue: proto.Warlock_Options_GrandFirestone, + DetonateSeed: true, } var DefaultDestroWarlock = &proto.Player_Warlock{ @@ -112,9 +113,10 @@ var DefaultAfflictionWarlock = &proto.Player_Warlock{ } var defaultAfflictionOptions = &proto.Warlock_Options{ - Armor: proto.Warlock_Options_FelArmor, - Summon: proto.Warlock_Options_Felhunter, - WeaponImbue: proto.Warlock_Options_GrandSpellstone, + Armor: proto.Warlock_Options_FelArmor, + Summon: proto.Warlock_Options_Felhunter, + WeaponImbue: proto.Warlock_Options_GrandSpellstone, + DetonateSeed: true, } // --------------------------------------- @@ -125,9 +127,10 @@ var DefaultDemonologyWarlock = &proto.Player_Warlock{ } var defaultDemonologyOptions = &proto.Warlock_Options{ - Armor: proto.Warlock_Options_FelArmor, - Summon: proto.Warlock_Options_Felguard, - WeaponImbue: proto.Warlock_Options_GrandSpellstone, + Armor: proto.Warlock_Options_FelArmor, + Summon: proto.Warlock_Options_Felguard, + WeaponImbue: proto.Warlock_Options_GrandSpellstone, + DetonateSeed: true, } // --------------------------------------------------------- diff --git a/ui/warlock/inputs.ts b/ui/warlock/inputs.ts index f0763c80bc..1c0380f778 100644 --- a/ui/warlock/inputs.ts +++ b/ui/warlock/inputs.ts @@ -45,3 +45,9 @@ export const PetInput = InputHelpers.makeSpecOptionsEnumIconInput) => player.changeEmitter, }); + +export const DetonateSeed = InputHelpers.makeSpecOptionsBooleanInput({ + fieldName: 'detonateSeed', + label: 'Detonate Seed on Cast', + labelTooltip: 'Simulates raid doing damage to targets such that seed detonates immediately on cast.', +}); diff --git a/ui/warlock/sim.ts b/ui/warlock/sim.ts index c35da9c98c..e40c13932e 100644 --- a/ui/warlock/sim.ts +++ b/ui/warlock/sim.ts @@ -116,6 +116,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecWarlock, { // Inputs to include in the 'Other' section on the settings tab. otherInputs: { inputs: [ + WarlockInputs.DetonateSeed, OtherInputs.DistanceFromTarget, OtherInputs.TankAssignment, OtherInputs.ChannelClipDelay, From ff7d01e6045e5354b79b23934da6732615fbf0c9 Mon Sep 17 00:00:00 2001 From: James Tanner Date: Sun, 7 Jan 2024 03:23:45 -0800 Subject: [PATCH 24/28] Update warlock demo tests --- sim/shaman/fire_elemental_totem.go | 2 +- sim/warlock/TestDemonology.results | 424 ++++++++++++++--------------- sim/warlock/inferno.go | 5 - ui/warlock/presets.ts | 3 + 4 files changed, 216 insertions(+), 218 deletions(-) diff --git a/sim/shaman/fire_elemental_totem.go b/sim/shaman/fire_elemental_totem.go index 893fc5ab8c..b9afd73072 100644 --- a/sim/shaman/fire_elemental_totem.go +++ b/sim/shaman/fire_elemental_totem.go @@ -60,6 +60,6 @@ func (shaman *Shaman) registerFireElementalTotem() { shaman.AddMajorCooldown(core.MajorCooldown{ Spell: shaman.FireElementalTotem, - Type: core.CooldownTypeUnknown, + Type: core.CooldownTypeDPS, }) } diff --git a/sim/warlock/TestDemonology.results b/sim/warlock/TestDemonology.results index 536e7e6fb0..8279f7033d 100644 --- a/sim/warlock/TestDemonology.results +++ b/sim/warlock/TestDemonology.results @@ -46,738 +46,738 @@ character_stats_results: { dps_results: { key: "TestDemonology-AllItems-Althor'sAbacus-50359" value: { - dps: 11029.86291 - tps: 10767.28533 + dps: 13362.9926 + tps: 11605.06694 } } dps_results: { key: "TestDemonology-AllItems-Althor'sAbacus-50366" value: { - dps: 11055.04985 - tps: 10791.31034 + dps: 13408.47575 + tps: 11646.08451 } } dps_results: { key: "TestDemonology-AllItems-AshtongueTalismanofShadows-32493" value: { - dps: 10875.72599 - tps: 10616.72071 + dps: 13223.59596 + tps: 11481.52309 } } dps_results: { key: "TestDemonology-AllItems-AustereEarthsiegeDiamond" value: { - dps: 11073.18055 - tps: 10814.91661 + dps: 13573.58115 + tps: 11798.10008 } } dps_results: { key: "TestDemonology-AllItems-Bandit'sInsignia-40371" value: { - dps: 10720.55552 - tps: 10464.17138 + dps: 13001.05853 + tps: 11278.57276 } } dps_results: { key: "TestDemonology-AllItems-BaubleofTrueBlood-50354" value: { - dps: 10722.16856 - tps: 10465.85596 - hps: 101.80272 + dps: 13006.0771 + tps: 11284.03967 + hps: 101.08784 } } dps_results: { key: "TestDemonology-AllItems-BaubleofTrueBlood-50726" value: { - dps: 10722.16856 - tps: 10465.85596 - hps: 101.80272 + dps: 13006.0771 + tps: 11284.03967 + hps: 101.08784 } } dps_results: { key: "TestDemonology-AllItems-BeamingEarthsiegeDiamond" value: { - dps: 11099.41588 - tps: 10841.25543 + dps: 13563.75667 + tps: 11788.03405 } } dps_results: { key: "TestDemonology-AllItems-BlessedRegaliaofUndeadCleansing" value: { - dps: 8005.70237 - tps: 7802.7555 + dps: 9902.89183 + tps: 8440.13945 } } dps_results: { key: "TestDemonology-AllItems-BracingEarthsiegeDiamond" value: { - dps: 11119.66976 - tps: 10645.99435 + dps: 13599.47078 + tps: 11585.96681 } } dps_results: { key: "TestDemonology-AllItems-ChaoticSkyflareDiamond" value: { - dps: 11410.3423 - tps: 11152.09819 + dps: 13937.65732 + tps: 12163.36117 } } dps_results: { key: "TestDemonology-AllItems-CorpseTongueCoin-50349" value: { - dps: 10720.55552 - tps: 10464.17138 + dps: 13001.05853 + tps: 11278.57276 } } dps_results: { key: "TestDemonology-AllItems-CorpseTongueCoin-50352" value: { - dps: 10720.55552 - tps: 10464.17138 + dps: 13001.05853 + tps: 11278.57276 } } dps_results: { key: "TestDemonology-AllItems-CorrodedSkeletonKey-50356" value: { - dps: 10770.42571 - tps: 10513.39859 + dps: 13073.06117 + tps: 11345.1642 hps: 64 } } dps_results: { key: "TestDemonology-AllItems-DarkCoven'sRegalia" value: { - dps: 10425.18922 - tps: 10175.94046 + dps: 12728.43281 + tps: 11034.66574 } } dps_results: { key: "TestDemonology-AllItems-DarkmoonCard:Berserker!-42989" value: { - dps: 10864.3927 - tps: 10608.00856 + dps: 13169.18682 + tps: 11446.70105 } } dps_results: { key: "TestDemonology-AllItems-DarkmoonCard:Death-42990" value: { - dps: 10914.04201 - tps: 10657.69731 + dps: 13205.69172 + tps: 11483.33552 } } dps_results: { key: "TestDemonology-AllItems-DarkmoonCard:Greatness-44255" value: { - dps: 10827.49237 - tps: 10566.12402 + dps: 13123.06301 + tps: 11391.45655 } } dps_results: { key: "TestDemonology-AllItems-Death'sChoice-47464" value: { - dps: 10720.49094 - tps: 10464.1068 + dps: 13001.05853 + tps: 11278.57276 } } dps_results: { key: "TestDemonology-AllItems-DeathKnight'sAnguish-38212" value: { - dps: 10768.14946 - tps: 10511.76532 + dps: 13054.31942 + tps: 11331.83365 } } dps_results: { key: "TestDemonology-AllItems-Deathbringer'sWill-50362" value: { - dps: 10720.55552 - tps: 10464.17138 + dps: 13001.05853 + tps: 11278.57276 } } dps_results: { key: "TestDemonology-AllItems-Deathbringer'sWill-50363" value: { - dps: 10720.55552 - tps: 10464.17138 + dps: 13001.05853 + tps: 11278.57276 } } dps_results: { key: "TestDemonology-AllItems-DeathbringerGarb" value: { - dps: 8750.45172 - tps: 8513.7745 + dps: 10829.58867 + tps: 9256.94195 } } dps_results: { key: "TestDemonology-AllItems-Defender'sCode-40257" value: { - dps: 10720.55552 - tps: 10464.17138 + dps: 13001.09262 + tps: 11278.60685 } } dps_results: { key: "TestDemonology-AllItems-DestructiveSkyflareDiamond" value: { - dps: 11104.72076 - tps: 10846.47665 + dps: 13604.8557 + tps: 11830.55955 } } dps_results: { key: "TestDemonology-AllItems-DislodgedForeignObject-50353" value: { - dps: 11327.35486 - tps: 11069.91946 + dps: 13835.25615 + tps: 12063.59581 } } dps_results: { key: "TestDemonology-AllItems-EffulgentSkyflareDiamond" value: { - dps: 11073.18055 - tps: 10814.91661 + dps: 13573.58115 + tps: 11798.10008 } } dps_results: { key: "TestDemonology-AllItems-EmberSkyflareDiamond" value: { - dps: 11134.3961 - tps: 10875.5855 + dps: 13584.42686 + tps: 11804.01851 } } dps_results: { key: "TestDemonology-AllItems-EnigmaticSkyflareDiamond" value: { - dps: 11100.49894 - tps: 10842.25483 + dps: 13597.95754 + tps: 11823.66138 } } dps_results: { key: "TestDemonology-AllItems-EnigmaticStarflareDiamond" value: { - dps: 11092.43436 - tps: 10834.19025 + dps: 13588.9541 + tps: 11814.65795 } } dps_results: { key: "TestDemonology-AllItems-EphemeralSnowflake-50260" value: { - dps: 10879.10858 - tps: 10625.58514 + dps: 13200.05256 + tps: 11476.85655 } } dps_results: { key: "TestDemonology-AllItems-EssenceofGossamer-37220" value: { - dps: 10742.56294 - tps: 10485.89317 + dps: 13039.12931 + tps: 11313.92687 } } dps_results: { key: "TestDemonology-AllItems-EternalEarthsiegeDiamond" value: { - dps: 11067.81225 - tps: 10809.56813 + dps: 13562.44986 + tps: 11788.1537 } } dps_results: { key: "TestDemonology-AllItems-ExtractofNecromanticPower-40373" value: { - dps: 10953.30393 - tps: 10696.91978 + dps: 13232.58503 + tps: 11510.37767 } } dps_results: { key: "TestDemonology-AllItems-EyeoftheBroodmother-45308" value: { - dps: 11069.28 - tps: 10808.5171 + dps: 13416.73309 + tps: 11669.56719 } } dps_results: { key: "TestDemonology-AllItems-Figurine-SapphireOwl-42413" value: { - dps: 10754.22395 - tps: 10497.0465 + dps: 13041.91339 + tps: 11315.17499 } } dps_results: { key: "TestDemonology-AllItems-ForethoughtTalisman-40258" value: { - dps: 10918.00416 - tps: 10657.22787 + dps: 13211.86872 + tps: 11468.52981 } } dps_results: { key: "TestDemonology-AllItems-ForgeEmber-37660" value: { - dps: 10966.72513 - tps: 10707.20814 + dps: 13362.65503 + tps: 11617.2622 } } dps_results: { key: "TestDemonology-AllItems-ForlornSkyflareDiamond" value: { - dps: 11119.66976 - tps: 10860.98248 + dps: 13599.47078 + tps: 11820.25 } } dps_results: { key: "TestDemonology-AllItems-ForlornStarflareDiamond" value: { - dps: 11105.65831 - tps: 10847.10119 + dps: 13588.30536 + tps: 11809.90411 } } dps_results: { key: "TestDemonology-AllItems-FuryoftheFiveFlights-40431" value: { - dps: 10720.55552 - tps: 10464.17138 + dps: 13001.05853 + tps: 11278.57276 } } dps_results: { key: "TestDemonology-AllItems-FuturesightRune-38763" value: { - dps: 10877.79011 - tps: 10618.64538 + dps: 13205.12887 + tps: 11464.5391 } } dps_results: { key: "TestDemonology-AllItems-Gladiator'sFelshroud" value: { - dps: 8575.50793 - tps: 8343.43479 + dps: 10677.0966 + tps: 9098.70061 } } dps_results: { key: "TestDemonology-AllItems-GlowingTwilightScale-54573" value: { - dps: 11034.67418 - tps: 10771.5057 + dps: 13387.6928 + tps: 11626.99352 } } dps_results: { key: "TestDemonology-AllItems-GlowingTwilightScale-54589" value: { - dps: 11080.46799 - tps: 10816.04753 + dps: 13438.36879 + tps: 11673.25119 } } dps_results: { key: "TestDemonology-AllItems-GnomishLightningGenerator-41121" value: { - dps: 10896.47429 - tps: 10640.15174 + dps: 13184.64163 + tps: 11462.7986 } } dps_results: { key: "TestDemonology-AllItems-Gul'dan'sRegalia" value: { - dps: 8893.35742 - tps: 8648.53034 + dps: 11170.31233 + tps: 9425.53097 } } dps_results: { key: "TestDemonology-AllItems-IllustrationoftheDragonSoul-40432" value: { - dps: 11019.97936 - tps: 10757.4527 + dps: 13395.10575 + tps: 11633.43219 } } dps_results: { key: "TestDemonology-AllItems-ImpassiveSkyflareDiamond" value: { - dps: 11100.49894 - tps: 10842.25483 + dps: 13597.95754 + tps: 11823.66138 } } dps_results: { key: "TestDemonology-AllItems-ImpassiveStarflareDiamond" value: { - dps: 11092.43436 - tps: 10834.19025 + dps: 13588.9541 + tps: 11814.65795 } } dps_results: { key: "TestDemonology-AllItems-IncisorFragment-37723" value: { - dps: 10720.55552 - tps: 10464.17138 + dps: 13001.09262 + tps: 11278.60685 } } dps_results: { key: "TestDemonology-AllItems-InsightfulEarthsiegeDiamond" value: { - dps: 11111.06498 - tps: 10852.30362 + dps: 13576.20154 + tps: 11802.41958 } } dps_results: { key: "TestDemonology-AllItems-InvigoratingEarthsiegeDiamond" value: { - dps: 11067.81225 - tps: 10809.56813 + dps: 13562.44986 + tps: 11788.1537 } } dps_results: { key: "TestDemonology-AllItems-Lavanthor'sTalisman-37872" value: { - dps: 10720.55552 - tps: 10464.17138 + dps: 13001.05853 + tps: 11278.57276 } } dps_results: { key: "TestDemonology-AllItems-MajesticDragonFigurine-40430" value: { - dps: 10912.86436 - tps: 10652.26582 + dps: 13229.87428 + tps: 11485.10666 } } dps_results: { key: "TestDemonology-AllItems-MaleficRaiment" value: { - dps: 6854.13966 - tps: 6659.45182 + dps: 8500.92025 + tps: 7137.00467 } } dps_results: { key: "TestDemonology-AllItems-MeteoriteWhetstone-37390" value: { - dps: 10825.62748 - tps: 10569.24333 + dps: 13121.26418 + tps: 11398.77841 } } dps_results: { key: "TestDemonology-AllItems-NevermeltingIceCrystal-50259" value: { - dps: 10983.322 - tps: 10722.54571 + dps: 13276.44705 + tps: 11533.10814 } } dps_results: { key: "TestDemonology-AllItems-OfferingofSacrifice-37638" value: { - dps: 10720.55552 - tps: 10464.17138 + dps: 13001.05853 + tps: 11278.57276 } } dps_results: { key: "TestDemonology-AllItems-PersistentEarthshatterDiamond" value: { - dps: 11067.81225 - tps: 10809.56813 + dps: 13562.44986 + tps: 11788.1537 } } dps_results: { key: "TestDemonology-AllItems-PersistentEarthsiegeDiamond" value: { - dps: 11067.81225 - tps: 10809.56813 + dps: 13562.44986 + tps: 11788.1537 } } dps_results: { key: "TestDemonology-AllItems-PetrifiedScarab-21685" value: { - dps: 10720.55552 - tps: 10464.17138 + dps: 13001.05853 + tps: 11278.57276 } } dps_results: { key: "TestDemonology-AllItems-PetrifiedTwilightScale-54571" value: { - dps: 10720.55552 - tps: 10464.17138 + dps: 13001.05853 + tps: 11278.57276 } } dps_results: { key: "TestDemonology-AllItems-PetrifiedTwilightScale-54591" value: { - dps: 10720.55552 - tps: 10464.17138 + dps: 13001.05853 + tps: 11278.57276 } } dps_results: { key: "TestDemonology-AllItems-PlagueheartGarb" value: { - dps: 8326.41706 - tps: 8103.48409 + dps: 10353.38967 + tps: 8813.1671 } } dps_results: { key: "TestDemonology-AllItems-PowerfulEarthshatterDiamond" value: { - dps: 11071.97708 - tps: 10813.72807 + dps: 13569.99782 + tps: 11794.76338 } } dps_results: { key: "TestDemonology-AllItems-PowerfulEarthsiegeDiamond" value: { - dps: 11073.18055 - tps: 10814.91661 + dps: 13573.58115 + tps: 11798.10008 } } dps_results: { key: "TestDemonology-AllItems-PurifiedShardoftheGods" value: { - dps: 10720.55552 - tps: 10464.17138 + dps: 13001.05853 + tps: 11278.57276 } } dps_results: { key: "TestDemonology-AllItems-ReignoftheDead-47316" value: { - dps: 11182.591 - tps: 10920.47378 + dps: 13578.66848 + tps: 11826.60815 } } dps_results: { key: "TestDemonology-AllItems-ReignoftheDead-47477" value: { - dps: 11238.80768 - tps: 10976.33941 + dps: 13625.62539 + tps: 11869.82399 } } dps_results: { key: "TestDemonology-AllItems-RelentlessEarthsiegeDiamond" value: { - dps: 11374.7138 - tps: 11116.46969 + dps: 13898.95395 + tps: 12124.6578 } } dps_results: { key: "TestDemonology-AllItems-RevitalizingSkyflareDiamond" value: { - dps: 11055.59429 - tps: 10797.48576 + dps: 13555.88187 + tps: 11780.03817 } } dps_results: { key: "TestDemonology-AllItems-RuneofRepulsion-40372" value: { - dps: 10720.55552 - tps: 10464.17138 + dps: 13001.09262 + tps: 11278.60685 } } dps_results: { key: "TestDemonology-AllItems-SealofthePantheon-36993" value: { - dps: 10720.55552 - tps: 10464.17138 + dps: 13001.09262 + tps: 11278.60685 } } dps_results: { key: "TestDemonology-AllItems-ShinyShardoftheGods" value: { - dps: 10720.55552 - tps: 10464.17138 + dps: 13001.05853 + tps: 11278.57276 } } dps_results: { key: "TestDemonology-AllItems-Sindragosa'sFlawlessFang-50361" value: { - dps: 10770.41707 - tps: 10513.38995 + dps: 13073.04367 + tps: 11345.1467 } } dps_results: { key: "TestDemonology-AllItems-SliverofPureIce-50339" value: { - dps: 11018.87465 - tps: 10759.96064 + dps: 13367.39811 + tps: 11613.85091 } } dps_results: { key: "TestDemonology-AllItems-SliverofPureIce-50346" value: { - dps: 11045.70793 - tps: 10785.47065 + dps: 13358.48994 + tps: 11601.09505 } } dps_results: { key: "TestDemonology-AllItems-SoulPreserver-37111" value: { - dps: 10853.08201 - tps: 10594.90656 + dps: 13163.13832 + tps: 11426.59504 } } dps_results: { key: "TestDemonology-AllItems-SouloftheDead-40382" value: { - dps: 10904.13536 - tps: 10648.91037 + dps: 13196.76389 + tps: 11475.18871 } } dps_results: { key: "TestDemonology-AllItems-SparkofLife-37657" value: { - dps: 10875.52441 - tps: 10614.81598 + dps: 13203.57651 + tps: 11476.11353 } } dps_results: { key: "TestDemonology-AllItems-SphereofRedDragon'sBlood-37166" value: { - dps: 10727.3943 - tps: 10464.17138 + dps: 13025.12425 + tps: 11287.66844 } } dps_results: { key: "TestDemonology-AllItems-SwiftSkyflareDiamond" value: { - dps: 11067.81225 - tps: 10809.56813 + dps: 13562.44986 + tps: 11788.1537 } } dps_results: { key: "TestDemonology-AllItems-SwiftStarflareDiamond" value: { - dps: 11067.81225 - tps: 10809.56813 + dps: 13562.44986 + tps: 11788.1537 } } dps_results: { key: "TestDemonology-AllItems-SwiftWindfireDiamond" value: { - dps: 11067.81225 - tps: 10809.56813 + dps: 13562.44986 + tps: 11788.1537 } } dps_results: { key: "TestDemonology-AllItems-TalismanofTrollDivinity-37734" value: { - dps: 10798.36596 - tps: 10541.0729 + dps: 13117.12603 + tps: 11386.11813 } } dps_results: { key: "TestDemonology-AllItems-TearsoftheVanquished-47215" value: { - dps: 10776.36851 - tps: 10515.78096 + dps: 13083.28612 + tps: 11354.52228 } } dps_results: { key: "TestDemonology-AllItems-TheGeneral'sHeart-45507" value: { - dps: 10720.55552 - tps: 10464.17138 + dps: 13001.05853 + tps: 11278.57276 } } dps_results: { key: "TestDemonology-AllItems-ThunderingSkyflareDiamond" value: { - dps: 11067.81225 - tps: 10809.56813 + dps: 13562.44986 + tps: 11788.1537 } } dps_results: { key: "TestDemonology-AllItems-TinyAbominationinaJar-50351" value: { - dps: 10729.22572 - tps: 10464.17138 + dps: 13036.21327 + tps: 11291.58017 } } dps_results: { key: "TestDemonology-AllItems-TinyAbominationinaJar-50706" value: { - dps: 10729.22572 - tps: 10464.17138 + dps: 13036.21327 + tps: 11291.58017 } } dps_results: { key: "TestDemonology-AllItems-TirelessSkyflareDiamond" value: { - dps: 11119.66976 - tps: 10860.98248 + dps: 13599.47078 + tps: 11820.25 } } dps_results: { key: "TestDemonology-AllItems-TirelessStarflareDiamond" value: { - dps: 11105.65831 - tps: 10847.10119 + dps: 13588.30536 + tps: 11809.90411 } } dps_results: { key: "TestDemonology-AllItems-TomeofArcanePhenomena-36972" value: { - dps: 10917.10386 - tps: 10661.13027 + dps: 13269.52013 + tps: 11535.64917 } } dps_results: { key: "TestDemonology-AllItems-TrenchantEarthshatterDiamond" value: { - dps: 11105.65831 - tps: 10847.10119 + dps: 13588.30536 + tps: 11809.90411 } } dps_results: { key: "TestDemonology-AllItems-TrenchantEarthsiegeDiamond" value: { - dps: 11119.66976 - tps: 10860.98248 + dps: 13599.47078 + tps: 11820.25 } } dps_results: { key: "TestDemonology-AllItems-WingedTalisman-37844" value: { - dps: 10843.78785 - tps: 10585.1107 + dps: 13220.90237 + tps: 11480.34933 } } dps_results: { key: "TestDemonology-Average-Default" value: { - dps: 11508.98797 - tps: 11252.67784 + dps: 14094.85717 + tps: 12300.56245 } } dps_results: { key: "TestDemonology-Settings-Orc-p4_demo-Demonology Warlock-demo-FullBuffs-LongMultiTarget" value: { - dps: 14569.48158 - tps: 16422.33574 + dps: 17327.69771 + tps: 17164.80693 } } dps_results: { key: "TestDemonology-Settings-Orc-p4_demo-Demonology Warlock-demo-FullBuffs-LongSingleTarget" value: { - dps: 11410.3423 - tps: 11152.09819 + dps: 13937.65732 + tps: 12163.36117 } } dps_results: { key: "TestDemonology-Settings-Orc-p4_demo-Demonology Warlock-demo-FullBuffs-ShortSingleTarget" value: { - dps: 14524.59149 - tps: 12818.53577 + dps: 15997.67468 + tps: 13932.25441 } } dps_results: { key: "TestDemonology-Settings-Orc-p4_demo-Demonology Warlock-demo-NoBuffs-LongMultiTarget" value: { - dps: 6562.7132 - tps: 8970.11008 + dps: 10670.49322 + tps: 12397.56516 } } dps_results: { key: "TestDemonology-Settings-Orc-p4_demo-Demonology Warlock-demo-NoBuffs-LongSingleTarget" value: { - dps: 6266.27386 - tps: 6225.81786 + dps: 8066.21241 + tps: 7450.9108 } } dps_results: { key: "TestDemonology-Settings-Orc-p4_demo-Demonology Warlock-demo-NoBuffs-ShortSingleTarget" value: { - dps: 6929.63748 - tps: 6137.98157 + dps: 8263.86975 + tps: 7507.09706 } } dps_results: { key: "TestDemonology-SwitchInFrontOfTarget-Default" value: { - dps: 11359.99577 - tps: 11138.46347 + dps: 13827.77154 + tps: 12196.0304 } } diff --git a/sim/warlock/inferno.go b/sim/warlock/inferno.go index da4b7740f3..f08c271c1e 100644 --- a/sim/warlock/inferno.go +++ b/sim/warlock/inferno.go @@ -56,11 +56,6 @@ func (warlock *Warlock) registerInfernoSpell() { summonInfernalAura.Activate(sim) }, }) - - warlock.AddMajorCooldown(core.MajorCooldown{ - Spell: warlock.Inferno, - Type: core.CooldownTypeUnknown, - }) } type InfernalPet struct { diff --git a/ui/warlock/presets.ts b/ui/warlock/presets.ts index fef9006aa3..e9ca7de51a 100644 --- a/ui/warlock/presets.ts +++ b/ui/warlock/presets.ts @@ -119,18 +119,21 @@ export const AfflictionOptions = WarlockOptions.create({ armor: Armor.FelArmor, summon: Summon.Felhunter, weaponImbue: WeaponImbue.GrandSpellstone, + detonateSeed: true, }); export const DemonologyOptions = WarlockOptions.create({ armor: Armor.FelArmor, summon: Summon.Felguard, weaponImbue: WeaponImbue.GrandSpellstone, + detonateSeed: true, }); export const DestructionOptions = WarlockOptions.create({ armor: Armor.FelArmor, summon: Summon.Imp, weaponImbue: WeaponImbue.GrandFirestone, + detonateSeed: true, }); export const DefaultConsumes = Consumes.create({ From d0910e78d23a872ee48617e7a06b9776feb12a2f Mon Sep 17 00:00:00 2001 From: James Tanner Date: Mon, 8 Jan 2024 17:49:35 -0800 Subject: [PATCH 25/28] Fix hs+cleave bug --- sim/warrior/dps/TestArms.results | 534 ++++++++--------- sim/warrior/dps/TestFury.results | 532 ++++++++--------- sim/warrior/heroic_strike_cleave.go | 2 + .../protection/TestProtectionWarrior.results | 540 +++++++++--------- 4 files changed, 805 insertions(+), 803 deletions(-) diff --git a/sim/warrior/dps/TestArms.results b/sim/warrior/dps/TestArms.results index 8c4f33cd79..8dba53729a 100644 --- a/sim/warrior/dps/TestArms.results +++ b/sim/warrior/dps/TestArms.results @@ -46,935 +46,935 @@ character_stats_results: { dps_results: { key: "TestArms-AllItems-Althor'sAbacus-50359" value: { - dps: 6262.82724 - tps: 5037.96938 + dps: 6396.79762 + tps: 5166.90921 } } dps_results: { key: "TestArms-AllItems-Althor'sAbacus-50366" value: { - dps: 6262.82724 - tps: 5037.96938 + dps: 6396.79762 + tps: 5166.90921 } } dps_results: { key: "TestArms-AllItems-AustereEarthsiegeDiamond" value: { - dps: 6482.41744 - tps: 5220.02072 + dps: 6578.76707 + tps: 5317.04783 } } dps_results: { key: "TestArms-AllItems-Bandit'sInsignia-40371" value: { - dps: 6431.93917 - tps: 5172.33986 + dps: 6602.04105 + tps: 5330.43346 } } dps_results: { key: "TestArms-AllItems-BaubleofTrueBlood-50354" value: { - dps: 6264.67869 - tps: 5039.7388 + dps: 6417.35518 + tps: 5185.5382 hps: 89.11518 } } dps_results: { key: "TestArms-AllItems-BaubleofTrueBlood-50726" value: { - dps: 6264.67869 - tps: 5039.7388 + dps: 6417.35518 + tps: 5185.5382 hps: 89.11518 } } dps_results: { key: "TestArms-AllItems-BeamingEarthsiegeDiamond" value: { - dps: 6495.57286 - tps: 5230.5847 + dps: 6610.9396 + tps: 5341.97634 } } dps_results: { key: "TestArms-AllItems-Beast-tamer'sShoulders-30892" value: { - dps: 6301.65452 - tps: 5073.33708 + dps: 6412.14717 + tps: 5185.57512 } } dps_results: { key: "TestArms-AllItems-BlackBruise-50035" value: { - dps: 4742.24633 - tps: 3856.45854 + dps: 4866.62556 + tps: 3976.19228 } } dps_results: { key: "TestArms-AllItems-BlackBruise-50692" value: { - dps: 4893.49698 - tps: 3974.34796 + dps: 5008.28346 + tps: 4090.87462 } } dps_results: { key: "TestArms-AllItems-BlessedBattlegearofUndeadSlaying" value: { - dps: 5271.93662 - tps: 4227.7173 + dps: 5391.55621 + tps: 4346.35392 } } dps_results: { key: "TestArms-AllItems-BlessedGarboftheUndeadSlayer" value: { - dps: 5222.59026 - tps: 4193.75014 + dps: 5306.16771 + tps: 4274.09658 } } dps_results: { key: "TestArms-AllItems-BlessedRegaliaofUndeadCleansing" value: { - dps: 5026.17849 - tps: 4038.78586 + dps: 5092.62896 + tps: 4104.40432 } } dps_results: { key: "TestArms-AllItems-BracingEarthsiegeDiamond" value: { - dps: 6478.84863 - tps: 5112.88003 + dps: 6588.02377 + tps: 5218.54295 } } dps_results: { key: "TestArms-AllItems-Bryntroll,theBoneArbiter-50415" value: { - dps: 8016.6666 - tps: 6494.27378 + dps: 8625.42745 + tps: 7032.99268 } } dps_results: { key: "TestArms-AllItems-Bryntroll,theBoneArbiter-50709" value: { - dps: 8109.90868 - tps: 6570.52233 + dps: 8730.89242 + tps: 7119.83335 } } dps_results: { key: "TestArms-AllItems-ChaoticSkyflareDiamond" value: { - dps: 6616.85785 - tps: 5325.93338 + dps: 6756.72828 + tps: 5463.2377 } } dps_results: { key: "TestArms-AllItems-CorpseTongueCoin-50349" value: { - dps: 6262.82724 - tps: 5037.96938 + dps: 6396.79762 + tps: 5166.90921 } } dps_results: { key: "TestArms-AllItems-CorpseTongueCoin-50352" value: { - dps: 6262.82724 - tps: 5037.96938 + dps: 6396.79762 + tps: 5166.90921 } } dps_results: { key: "TestArms-AllItems-CorrodedSkeletonKey-50356" value: { - dps: 6262.82724 - tps: 5037.96938 + dps: 6396.79762 + tps: 5166.90921 hps: 64 } } dps_results: { key: "TestArms-AllItems-DarkmoonCard:Berserker!-42989" value: { - dps: 6374.41061 - tps: 5130.23029 + dps: 6537.93935 + tps: 5284.55832 } } dps_results: { key: "TestArms-AllItems-DarkmoonCard:Death-42990" value: { - dps: 6412.14822 - tps: 5159.52149 + dps: 6564.43708 + tps: 5304.84013 } } dps_results: { key: "TestArms-AllItems-DarkmoonCard:Greatness-44255" value: { - dps: 6262.82724 - tps: 5037.96938 + dps: 6396.79762 + tps: 5166.90921 } } dps_results: { key: "TestArms-AllItems-Death'sChoice-47464" value: { - dps: 6726.16041 - tps: 5407.81841 + dps: 6919.08161 + tps: 5580.98556 } } dps_results: { key: "TestArms-AllItems-DeathKnight'sAnguish-38212" value: { - dps: 6335.28796 - tps: 5097.65887 + dps: 6469.76481 + tps: 5227.75503 } } dps_results: { key: "TestArms-AllItems-Deathbringer'sWill-50362" value: { - dps: 6665.69456 - tps: 5361.54303 + dps: 6851.65251 + tps: 5532.825 } } dps_results: { key: "TestArms-AllItems-Deathbringer'sWill-50363" value: { - dps: 6724.67718 - tps: 5407.8647 + dps: 6960.67426 + tps: 5623.80389 } } dps_results: { key: "TestArms-AllItems-Defender'sCode-40257" value: { - dps: 6274.81353 - tps: 5047.61817 + dps: 6422.78999 + tps: 5185.91516 } } dps_results: { key: "TestArms-AllItems-DestructiveSkyflareDiamond" value: { - dps: 6501.0713 - tps: 5235.03075 + dps: 6620.04877 + tps: 5349.00093 } } dps_results: { key: "TestArms-AllItems-DislodgedForeignObject-50348" value: { - dps: 6350.28984 - tps: 5105.87855 + dps: 6541.00488 + tps: 5284.47045 } } dps_results: { key: "TestArms-AllItems-DislodgedForeignObject-50353" value: { - dps: 6346.59736 - tps: 5105.06065 + dps: 6542.30837 + tps: 5288.85649 } } dps_results: { key: "TestArms-AllItems-DreadnaughtBattlegear" value: { - dps: 5920.25992 - tps: 4781.31769 + dps: 6000.16096 + tps: 4864.19104 } } dps_results: { key: "TestArms-AllItems-DreadnaughtPlate" value: { - dps: 5211.25695 - tps: 4187.74189 + dps: 5270.24824 + tps: 4251.82732 } } dps_results: { key: "TestArms-AllItems-EffulgentSkyflareDiamond" value: { - dps: 6478.84863 - tps: 5217.20055 + dps: 6588.02377 + tps: 5324.94752 } } dps_results: { key: "TestArms-AllItems-EmberSkyflareDiamond" value: { - dps: 6478.84863 - tps: 5217.20055 + dps: 6588.02377 + tps: 5324.94752 } } dps_results: { key: "TestArms-AllItems-EnigmaticSkyflareDiamond" value: { - dps: 6495.57286 - tps: 5230.5847 + dps: 6610.9396 + tps: 5341.97634 } } dps_results: { key: "TestArms-AllItems-EnigmaticStarflareDiamond" value: { - dps: 6493.76947 - tps: 5229.12812 + dps: 6604.9531 + tps: 5337.21903 } } dps_results: { key: "TestArms-AllItems-EphemeralSnowflake-50260" value: { - dps: 6306.94826 - tps: 5070.34131 + dps: 6462.73846 + tps: 5216.74118 } } dps_results: { key: "TestArms-AllItems-EssenceofGossamer-37220" value: { - dps: 6262.82724 - tps: 5037.96938 + dps: 6396.79762 + tps: 5166.90921 } } dps_results: { key: "TestArms-AllItems-EternalEarthsiegeDiamond" value: { - dps: 6478.84863 - tps: 5217.20055 + dps: 6588.02377 + tps: 5324.94752 } } dps_results: { key: "TestArms-AllItems-ExtractofNecromanticPower-40373" value: { - dps: 6415.35315 - tps: 5162.44931 + dps: 6572.93669 + tps: 5312.26817 } } dps_results: { key: "TestArms-AllItems-EyeoftheBroodmother-45308" value: { - dps: 6364.14747 - tps: 5121.48477 + dps: 6517.96016 + tps: 5267.85674 } } dps_results: { key: "TestArms-AllItems-Figurine-SapphireOwl-42413" value: { - dps: 6262.82724 - tps: 5037.96938 + dps: 6396.79762 + tps: 5166.90921 } } dps_results: { key: "TestArms-AllItems-ForethoughtTalisman-40258" value: { - dps: 6262.82724 - tps: 5037.96938 + dps: 6396.79762 + tps: 5166.90921 } } dps_results: { key: "TestArms-AllItems-ForgeEmber-37660" value: { - dps: 6348.70584 - tps: 5108.3564 + dps: 6482.47577 + tps: 5238.35676 } } dps_results: { key: "TestArms-AllItems-ForlornSkyflareDiamond" value: { - dps: 6478.84863 - tps: 5217.20055 + dps: 6588.02377 + tps: 5324.94752 } } dps_results: { key: "TestArms-AllItems-ForlornStarflareDiamond" value: { - dps: 6478.84863 - tps: 5217.20055 + dps: 6588.02377 + tps: 5324.94752 } } dps_results: { key: "TestArms-AllItems-FuryoftheFiveFlights-40431" value: { - dps: 6464.14941 - tps: 5197.35269 + dps: 6638.27271 + tps: 5355.17518 } } dps_results: { key: "TestArms-AllItems-FuturesightRune-38763" value: { - dps: 6262.82724 - tps: 5037.96938 + dps: 6396.79762 + tps: 5166.90921 } } dps_results: { key: "TestArms-AllItems-Gladiator'sBattlegear" value: { - dps: 6213.38971 - tps: 4971.99584 + dps: 6400.63471 + tps: 5147.67442 } } dps_results: { key: "TestArms-AllItems-GlowingTwilightScale-54573" value: { - dps: 6262.82724 - tps: 5037.96938 + dps: 6396.79762 + tps: 5166.90921 } } dps_results: { key: "TestArms-AllItems-GlowingTwilightScale-54589" value: { - dps: 6262.82724 - tps: 5037.96938 + dps: 6396.79762 + tps: 5166.90921 } } dps_results: { key: "TestArms-AllItems-GnomishLightningGenerator-41121" value: { - dps: 6390.97801 - tps: 5142.58532 + dps: 6542.31487 + tps: 5287.03693 } } dps_results: { key: "TestArms-AllItems-Heartpierce-49982" value: { - dps: 7444.30414 - tps: 6007.8764 + dps: 7994.21671 + tps: 6504.30258 } } dps_results: { key: "TestArms-AllItems-Heartpierce-50641" value: { - dps: 7475.93535 - tps: 6035.59142 + dps: 8082.17352 + tps: 6572.49427 } } dps_results: { key: "TestArms-AllItems-IllustrationoftheDragonSoul-40432" value: { - dps: 6262.82724 - tps: 5037.96938 + dps: 6396.79762 + tps: 5166.90921 } } dps_results: { key: "TestArms-AllItems-ImpassiveSkyflareDiamond" value: { - dps: 6495.57286 - tps: 5230.5847 + dps: 6610.9396 + tps: 5341.97634 } } dps_results: { key: "TestArms-AllItems-ImpassiveStarflareDiamond" value: { - dps: 6493.76947 - tps: 5229.12812 + dps: 6604.9531 + tps: 5337.21903 } } dps_results: { key: "TestArms-AllItems-IncisorFragment-37723" value: { - dps: 6455.69968 - tps: 5193.01856 + dps: 6619.05428 + tps: 5343.00426 } } dps_results: { key: "TestArms-AllItems-InsightfulEarthsiegeDiamond" value: { - dps: 6478.84863 - tps: 5217.20055 + dps: 6588.02377 + tps: 5324.94752 } } dps_results: { key: "TestArms-AllItems-InvigoratingEarthsiegeDiamond" value: { - dps: 6509.46429 - tps: 5241.50367 - hps: 13.00101 + dps: 6614.63311 + tps: 5350.04895 + hps: 12.91576 } } dps_results: { key: "TestArms-AllItems-LastWord-50179" value: { - dps: 7563.0174 - tps: 6106.2864 + dps: 8087.93558 + tps: 6582.07627 } } dps_results: { key: "TestArms-AllItems-LastWord-50708" value: { - dps: 7618.9608 - tps: 6151.49898 + dps: 8207.14873 + tps: 6678.32817 } } dps_results: { key: "TestArms-AllItems-Lavanthor'sTalisman-37872" value: { - dps: 6262.82724 - tps: 5037.96938 + dps: 6396.79762 + tps: 5166.90921 } } dps_results: { key: "TestArms-AllItems-MajesticDragonFigurine-40430" value: { - dps: 6262.82724 - tps: 5037.96938 + dps: 6396.79762 + tps: 5166.90921 } } dps_results: { key: "TestArms-AllItems-MeteoriteWhetstone-37390" value: { - dps: 6433.64558 - tps: 5170.07371 + dps: 6576.42366 + tps: 5311.90634 } } dps_results: { key: "TestArms-AllItems-NevermeltingIceCrystal-50259" value: { - dps: 6439.79417 - tps: 5187.48571 + dps: 6559.25088 + tps: 5305.75722 } } dps_results: { key: "TestArms-AllItems-OfferingofSacrifice-37638" value: { - dps: 6269.28658 - tps: 5043.25365 + dps: 6427.37465 + tps: 5190.7848 } } dps_results: { key: "TestArms-AllItems-OnslaughtArmor" value: { - dps: 4249.68079 - tps: 3420.45651 + dps: 4291.99379 + tps: 3468.58551 } } dps_results: { key: "TestArms-AllItems-OnslaughtBattlegear" value: { - dps: 4855.76003 - tps: 3906.0545 + dps: 4912.08281 + tps: 3968.95214 } } dps_results: { key: "TestArms-AllItems-PersistentEarthshatterDiamond" value: { - dps: 6502.12946 - tps: 5235.59711 + dps: 6605.13756 + tps: 5339.31511 } } dps_results: { key: "TestArms-AllItems-PersistentEarthsiegeDiamond" value: { - dps: 6507.6073 - tps: 5239.92558 + dps: 6615.60889 + tps: 5348.2666 } } dps_results: { key: "TestArms-AllItems-PetrifiedScarab-21685" value: { - dps: 6262.82724 - tps: 5037.96938 + dps: 6396.79762 + tps: 5166.90921 } } dps_results: { key: "TestArms-AllItems-PetrifiedTwilightScale-54571" value: { - dps: 6301.19551 - tps: 5068.45148 + dps: 6450.7036 + tps: 5211.08658 } } dps_results: { key: "TestArms-AllItems-PetrifiedTwilightScale-54591" value: { - dps: 6306.61193 - tps: 5072.72871 + dps: 6452.11243 + tps: 5210.71614 } } dps_results: { key: "TestArms-AllItems-PowerfulEarthshatterDiamond" value: { - dps: 6478.84863 - tps: 5217.20055 + dps: 6588.02377 + tps: 5324.94752 } } dps_results: { key: "TestArms-AllItems-PowerfulEarthsiegeDiamond" value: { - dps: 6478.84863 - tps: 5217.20055 + dps: 6588.02377 + tps: 5324.94752 } } dps_results: { key: "TestArms-AllItems-PurifiedShardoftheGods" value: { - dps: 6262.82724 - tps: 5037.96938 + dps: 6396.79762 + tps: 5166.90921 } } dps_results: { key: "TestArms-AllItems-ReignoftheDead-47316" value: { - dps: 6262.82724 - tps: 5037.96938 + dps: 6396.79762 + tps: 5166.90921 } } dps_results: { key: "TestArms-AllItems-ReignoftheDead-47477" value: { - dps: 6262.82724 - tps: 5037.96938 + dps: 6396.79762 + tps: 5166.90921 } } dps_results: { key: "TestArms-AllItems-RelentlessEarthsiegeDiamond" value: { - dps: 6615.86001 - tps: 5325.11157 + dps: 6750.31463 + tps: 5459.33646 } } dps_results: { key: "TestArms-AllItems-RevitalizingSkyflareDiamond" value: { - dps: 6478.84863 - tps: 5217.20055 + dps: 6588.02377 + tps: 5324.94752 } } dps_results: { key: "TestArms-AllItems-RuneofRepulsion-40372" value: { - dps: 6262.82724 - tps: 5037.96938 + dps: 6396.79762 + tps: 5166.90921 } } dps_results: { key: "TestArms-AllItems-SealofthePantheon-36993" value: { - dps: 6277.61903 - tps: 5049.92266 + dps: 6428.76892 + tps: 5195.23185 } } dps_results: { key: "TestArms-AllItems-Shadowmourne-49623" value: { - dps: 9038.57363 - tps: 7317.90816 + dps: 9653.04384 + tps: 7861.38457 } } dps_results: { key: "TestArms-AllItems-ShinyShardoftheGods" value: { - dps: 6262.82724 - tps: 5037.96938 + dps: 6396.79762 + tps: 5166.90921 } } dps_results: { key: "TestArms-AllItems-SiegebreakerBattlegear" value: { - dps: 6056.90359 - tps: 4885.56365 + dps: 6186.50477 + tps: 5003.29305 } } dps_results: { key: "TestArms-AllItems-SiegebreakerPlate" value: { - dps: 5354.47251 - tps: 4302.15286 + dps: 5424.27098 + tps: 4379.25955 } } dps_results: { key: "TestArms-AllItems-Sindragosa'sFlawlessFang-50361" value: { - dps: 6262.82724 - tps: 5037.96938 + dps: 6396.79762 + tps: 5166.90921 } } dps_results: { key: "TestArms-AllItems-SliverofPureIce-50339" value: { - dps: 6262.82724 - tps: 5037.96938 + dps: 6396.79762 + tps: 5166.90921 } } dps_results: { key: "TestArms-AllItems-SliverofPureIce-50346" value: { - dps: 6262.82724 - tps: 5037.96938 + dps: 6396.79762 + tps: 5166.90921 } } dps_results: { key: "TestArms-AllItems-SoulPreserver-37111" value: { - dps: 6262.82724 - tps: 5037.96938 + dps: 6396.79762 + tps: 5166.90921 } } dps_results: { key: "TestArms-AllItems-SouloftheDead-40382" value: { - dps: 6366.26913 - tps: 5123.1821 + dps: 6524.77466 + tps: 5273.73855 } } dps_results: { key: "TestArms-AllItems-SparkofLife-37657" value: { - dps: 6317.02843 - tps: 5079.75626 + dps: 6461.52646 + tps: 5219.97511 } } dps_results: { key: "TestArms-AllItems-SphereofRedDragon'sBlood-37166" value: { - dps: 6453.84761 - tps: 5186.09003 + dps: 6581.50708 + tps: 5315.95236 } } dps_results: { key: "TestArms-AllItems-StormshroudArmor" value: { - dps: 5018.15938 - tps: 4030.1328 + dps: 5028.43701 + tps: 4051.08268 } } dps_results: { key: "TestArms-AllItems-SwiftSkyflareDiamond" value: { - dps: 6507.6073 - tps: 5239.92558 + dps: 6615.60889 + tps: 5348.2666 } } dps_results: { key: "TestArms-AllItems-SwiftStarflareDiamond" value: { - dps: 6502.12946 - tps: 5235.59711 + dps: 6605.13756 + tps: 5339.31511 } } dps_results: { key: "TestArms-AllItems-SwiftWindfireDiamond" value: { - dps: 6492.54324 - tps: 5228.02215 + dps: 6591.23359 + tps: 5327.78051 } } dps_results: { key: "TestArms-AllItems-TalismanofTrollDivinity-37734" value: { - dps: 6262.82724 - tps: 5037.96938 + dps: 6396.79762 + tps: 5166.90921 } } dps_results: { key: "TestArms-AllItems-TearsoftheVanquished-47215" value: { - dps: 6262.82724 - tps: 5037.96938 + dps: 6396.79762 + tps: 5166.90921 } } dps_results: { key: "TestArms-AllItems-TheFistsofFury" value: { - dps: 4568.08818 - tps: 3767.77424 + dps: 4805.27477 + tps: 3994.52922 } } dps_results: { key: "TestArms-AllItems-TheGeneral'sHeart-45507" value: { - dps: 6262.82724 - tps: 5037.96938 + dps: 6396.79762 + tps: 5166.90921 } } dps_results: { key: "TestArms-AllItems-TheTwinBladesofAzzinoth" value: { - dps: 4862.05922 - tps: 3989.98278 + dps: 5146.53578 + tps: 4258.94583 } } dps_results: { key: "TestArms-AllItems-ThunderingSkyflareDiamond" value: { - dps: 6508.13877 - tps: 5243.09018 + dps: 6594.14082 + tps: 5330.03796 } } dps_results: { key: "TestArms-AllItems-TinyAbominationinaJar-50351" value: { - dps: 6584.29713 - tps: 5296.3194 + dps: 6726.39326 + tps: 5433.60078 } } dps_results: { key: "TestArms-AllItems-TinyAbominationinaJar-50706" value: { - dps: 6630.29753 - tps: 5335.32952 + dps: 6806.24088 + tps: 5498.45942 } } dps_results: { key: "TestArms-AllItems-TirelessSkyflareDiamond" value: { - dps: 6478.84863 - tps: 5217.20055 + dps: 6588.02377 + tps: 5324.94752 } } dps_results: { key: "TestArms-AllItems-TirelessStarflareDiamond" value: { - dps: 6478.84863 - tps: 5217.20055 + dps: 6588.02377 + tps: 5324.94752 } } dps_results: { key: "TestArms-AllItems-TomeofArcanePhenomena-36972" value: { - dps: 6324.60419 - tps: 5086.9172 + dps: 6423.29498 + tps: 5189.66479 } } dps_results: { key: "TestArms-AllItems-TrenchantEarthshatterDiamond" value: { - dps: 6478.84863 - tps: 5217.20055 + dps: 6588.02377 + tps: 5324.94752 } } dps_results: { key: "TestArms-AllItems-TrenchantEarthsiegeDiamond" value: { - dps: 6478.84863 - tps: 5217.20055 + dps: 6588.02377 + tps: 5324.94752 } } dps_results: { key: "TestArms-AllItems-UndeadSlayer'sBlessedArmor" value: { - dps: 5209.00537 - tps: 4182.56264 + dps: 5334.191 + tps: 4298.58943 } } dps_results: { key: "TestArms-AllItems-Val'anyr,HammerofAncientKings-46017" value: { - dps: 3739.49527 - tps: 3074.84622 + dps: 3822.06397 + tps: 3168.78811 } } dps_results: { key: "TestArms-AllItems-WingedTalisman-37844" value: { - dps: 6262.82724 - tps: 5037.96938 + dps: 6396.79762 + tps: 5166.90921 } } dps_results: { key: "TestArms-AllItems-Wrynn'sBattlegear" value: { - dps: 6714.43279 - tps: 5406.58323 + dps: 6890.70917 + tps: 5566.1016 } } dps_results: { key: "TestArms-AllItems-Wrynn'sPlate" value: { - dps: 5548.49888 - tps: 4454.25 + dps: 5640.39847 + tps: 4546.03583 } } dps_results: { key: "TestArms-AllItems-YmirjarLord'sBattlegear" value: { - dps: 7349.16566 - tps: 5931.73881 + dps: 7494.64482 + tps: 6071.88535 } } dps_results: { key: "TestArms-AllItems-YmirjarLord'sPlate" value: { - dps: 5808.61237 - tps: 4674.27625 + dps: 5937.65653 + tps: 4794.79385 } } dps_results: { key: "TestArms-Average-Default" value: { - dps: 6659.68361 - tps: 5357.47752 + dps: 6831.86673 + tps: 5520.13027 } } dps_results: { key: "TestArms-Settings-Human-p1_arms-Basic-arms-FullBuffs-LongMultiTarget" value: { - dps: 11184.11318 - tps: 10321.38091 + dps: 11927.56542 + tps: 11029.81694 } } dps_results: { key: "TestArms-Settings-Human-p1_arms-Basic-arms-FullBuffs-LongSingleTarget" value: { - dps: 6552.42865 - tps: 5252.94836 + dps: 6744.96972 + tps: 5435.72093 } } dps_results: { key: "TestArms-Settings-Human-p1_arms-Basic-arms-FullBuffs-ShortSingleTarget" value: { - dps: 6969.43738 - tps: 5653.47586 + dps: 7303.9868 + tps: 5943.01221 } } dps_results: { key: "TestArms-Settings-Human-p1_arms-Basic-arms-NoBuffs-LongMultiTarget" value: { - dps: 6170.00187 - tps: 5850.70513 + dps: 6201.566 + tps: 5886.67849 } } dps_results: { key: "TestArms-Settings-Human-p1_arms-Basic-arms-NoBuffs-LongSingleTarget" value: { - dps: 3543.41931 - tps: 2859.62352 + dps: 3507.48553 + tps: 2829.64022 } } dps_results: { key: "TestArms-Settings-Human-p1_arms-Basic-arms-NoBuffs-ShortSingleTarget" value: { - dps: 3711.29059 - tps: 3024.56901 + dps: 3700.71515 + tps: 3012.98824 } } dps_results: { key: "TestArms-Settings-Orc-p1_arms-Basic-arms-FullBuffs-LongMultiTarget" value: { - dps: 11336.28583 - tps: 10480.36946 + dps: 11974.1173 + tps: 11074.57371 } } dps_results: { key: "TestArms-Settings-Orc-p1_arms-Basic-arms-FullBuffs-LongSingleTarget" value: { - dps: 6615.86001 - tps: 5325.11157 + dps: 6750.31463 + tps: 5459.33646 } } dps_results: { key: "TestArms-Settings-Orc-p1_arms-Basic-arms-FullBuffs-ShortSingleTarget" value: { - dps: 7108.58976 - tps: 5787.99086 + dps: 7373.00838 + tps: 6033.37017 } } dps_results: { key: "TestArms-Settings-Orc-p1_arms-Basic-arms-NoBuffs-LongMultiTarget" value: { - dps: 6335.42532 - tps: 6013.61723 + dps: 6352.90441 + tps: 6027.91913 } } dps_results: { key: "TestArms-Settings-Orc-p1_arms-Basic-arms-NoBuffs-LongSingleTarget" value: { - dps: 3576.94646 - tps: 2890.00901 + dps: 3536.91307 + tps: 2857.80735 } } dps_results: { key: "TestArms-Settings-Orc-p1_arms-Basic-arms-NoBuffs-ShortSingleTarget" value: { - dps: 3779.35597 - tps: 3094.87687 + dps: 3767.68859 + tps: 3083.31246 } } dps_results: { key: "TestArms-SwitchInFrontOfTarget-Default" value: { - dps: 6140.51847 - tps: 4918.78951 + dps: 6324.6294 + tps: 5088.14444 } } diff --git a/sim/warrior/dps/TestFury.results b/sim/warrior/dps/TestFury.results index 1288ac4796..2450f6b563 100644 --- a/sim/warrior/dps/TestFury.results +++ b/sim/warrior/dps/TestFury.results @@ -46,935 +46,935 @@ character_stats_results: { dps_results: { key: "TestFury-AllItems-Althor'sAbacus-50359" value: { - dps: 6068.64055 - tps: 4458.98045 + dps: 6559.28013 + tps: 4874.20474 } } dps_results: { key: "TestFury-AllItems-Althor'sAbacus-50366" value: { - dps: 6068.64055 - tps: 4458.98045 + dps: 6559.28013 + tps: 4874.20474 } } dps_results: { key: "TestFury-AllItems-AustereEarthsiegeDiamond" value: { - dps: 6285.39617 - tps: 4617.84989 + dps: 6864.87671 + tps: 5103.38904 } } dps_results: { key: "TestFury-AllItems-Bandit'sInsignia-40371" value: { - dps: 6242.67815 - tps: 4584.7029 + dps: 6776.94205 + tps: 5031.73545 } } dps_results: { key: "TestFury-AllItems-BaubleofTrueBlood-50354" value: { - dps: 6070.00097 - tps: 4459.82625 + dps: 6576.11035 + tps: 4886.41831 hps: 90.47701 } } dps_results: { key: "TestFury-AllItems-BaubleofTrueBlood-50726" value: { - dps: 6070.00097 - tps: 4459.82625 + dps: 6576.11035 + tps: 4886.41831 hps: 90.47701 } } dps_results: { key: "TestFury-AllItems-BeamingEarthsiegeDiamond" value: { - dps: 6308.37895 - tps: 4634.43174 + dps: 6868.88557 + tps: 5105.07983 } } dps_results: { key: "TestFury-AllItems-Beast-tamer'sShoulders-30892" value: { - dps: 6105.97004 - tps: 4489.27971 + dps: 6643.31619 + tps: 4936.52029 } } dps_results: { key: "TestFury-AllItems-BlackBruise-50035" value: { - dps: 5437.88412 - tps: 3997.69695 + dps: 5912.90398 + tps: 4415.24024 } } dps_results: { key: "TestFury-AllItems-BlackBruise-50692" value: { - dps: 5535.51042 - tps: 4067.26735 + dps: 5993.38342 + tps: 4473.93155 } } dps_results: { key: "TestFury-AllItems-BlessedBattlegearofUndeadSlaying" value: { - dps: 5046.84075 - tps: 3707.15469 + dps: 5402.16423 + tps: 4017.57594 } } dps_results: { key: "TestFury-AllItems-BlessedGarboftheUndeadSlayer" value: { - dps: 5022.57195 - tps: 3691.86742 + dps: 5344.32106 + tps: 3981.71498 } } dps_results: { key: "TestFury-AllItems-BlessedRegaliaofUndeadCleansing" value: { - dps: 4729.19706 - tps: 3476.65924 + dps: 5037.55692 + tps: 3754.11053 } } dps_results: { key: "TestFury-AllItems-BracingEarthsiegeDiamond" value: { - dps: 6282.08305 - tps: 4523.20391 + dps: 6885.18545 + tps: 5017.06984 } } dps_results: { key: "TestFury-AllItems-Bryntroll,theBoneArbiter-50415" value: { - dps: 6423.92566 - tps: 4719.63158 + dps: 6964.93261 + tps: 5177.34824 } } dps_results: { key: "TestFury-AllItems-Bryntroll,theBoneArbiter-50709" value: { - dps: 6423.92566 - tps: 4719.63158 + dps: 6964.93261 + tps: 5177.34824 } } dps_results: { key: "TestFury-AllItems-ChaoticSkyflareDiamond" value: { - dps: 6423.92566 - tps: 4719.63158 + dps: 6964.93261 + tps: 5177.34824 } } dps_results: { key: "TestFury-AllItems-CorpseTongueCoin-50349" value: { - dps: 6068.64055 - tps: 4458.98045 + dps: 6559.28013 + tps: 4874.20474 } } dps_results: { key: "TestFury-AllItems-CorpseTongueCoin-50352" value: { - dps: 6068.64055 - tps: 4458.98045 + dps: 6559.28013 + tps: 4874.20474 } } dps_results: { key: "TestFury-AllItems-CorrodedSkeletonKey-50356" value: { - dps: 6068.64055 - tps: 4458.98045 + dps: 6559.28013 + tps: 4874.20474 hps: 64 } } dps_results: { key: "TestFury-AllItems-DarkmoonCard:Berserker!-42989" value: { - dps: 6203.41318 - tps: 4555.80129 + dps: 6772.21685 + tps: 5026.11285 } } dps_results: { key: "TestFury-AllItems-DarkmoonCard:Death-42990" value: { - dps: 6236.15781 - tps: 4578.8361 + dps: 6766.62895 + tps: 5024.21231 } } dps_results: { key: "TestFury-AllItems-DarkmoonCard:Greatness-44255" value: { - dps: 6068.64055 - tps: 4458.98045 + dps: 6559.28013 + tps: 4874.20474 } } dps_results: { key: "TestFury-AllItems-Death'sChoice-47464" value: { - dps: 6602.64112 - tps: 4849.8309 + dps: 7160.83725 + tps: 5311.32515 } } dps_results: { key: "TestFury-AllItems-DeathKnight'sAnguish-38212" value: { - dps: 6195.32949 - tps: 4547.48663 + dps: 6735.37032 + tps: 4998.68447 } } dps_results: { key: "TestFury-AllItems-Deathbringer'sWill-50362" value: { - dps: 6493.06269 - tps: 4766.0526 + dps: 7181.01403 + tps: 5330.98337 } } dps_results: { key: "TestFury-AllItems-Deathbringer'sWill-50363" value: { - dps: 6551.19253 - tps: 4809.30975 + dps: 7248.12327 + tps: 5377.03041 } } dps_results: { key: "TestFury-AllItems-Defender'sCode-40257" value: { - dps: 6084.47406 - tps: 4470.52004 + dps: 6596.66988 + tps: 4898.49101 } } dps_results: { key: "TestFury-AllItems-DestructiveSkyflareDiamond" value: { - dps: 6302.17513 - tps: 4630.51897 + dps: 6874.8921 + tps: 5109.55671 } } dps_results: { key: "TestFury-AllItems-DislodgedForeignObject-50348" value: { - dps: 6224.77452 - tps: 4564.93063 + dps: 6768.86309 + tps: 5020.85517 } } dps_results: { key: "TestFury-AllItems-DislodgedForeignObject-50353" value: { - dps: 6185.24566 - tps: 4539.96506 + dps: 6729.96579 + tps: 4989.43781 } } dps_results: { key: "TestFury-AllItems-DreadnaughtBattlegear" value: { - dps: 5719.89221 - tps: 4210.60192 + dps: 6227.13442 + tps: 4636.21994 } } dps_results: { key: "TestFury-AllItems-DreadnaughtPlate" value: { - dps: 5029.00135 - tps: 3700.982 + dps: 5328.10898 + tps: 3971.17866 } } dps_results: { key: "TestFury-AllItems-EffulgentSkyflareDiamond" value: { - dps: 6282.08305 - tps: 4615.43576 + dps: 6885.18545 + tps: 5119.12412 } } dps_results: { key: "TestFury-AllItems-EmberSkyflareDiamond" value: { - dps: 6282.08305 - tps: 4615.43576 + dps: 6885.18545 + tps: 5119.12412 } } dps_results: { key: "TestFury-AllItems-EnigmaticSkyflareDiamond" value: { - dps: 6308.37895 - tps: 4634.43174 + dps: 6868.88557 + tps: 5105.07983 } } dps_results: { key: "TestFury-AllItems-EnigmaticStarflareDiamond" value: { - dps: 6308.8863 - tps: 4634.79924 + dps: 6874.11509 + tps: 5110.75442 } } dps_results: { key: "TestFury-AllItems-EphemeralSnowflake-50260" value: { - dps: 6198.69096 - tps: 4553.2291 + dps: 6687.25612 + tps: 4967.56472 } } dps_results: { key: "TestFury-AllItems-EssenceofGossamer-37220" value: { - dps: 6068.64055 - tps: 4458.98045 + dps: 6559.28013 + tps: 4874.20474 } } dps_results: { key: "TestFury-AllItems-EternalEarthsiegeDiamond" value: { - dps: 6282.08305 - tps: 4615.43576 + dps: 6885.18545 + tps: 5119.12412 } } dps_results: { key: "TestFury-AllItems-ExtractofNecromanticPower-40373" value: { - dps: 6235.09401 - tps: 4578.01366 + dps: 6760.84201 + tps: 5019.53926 } } dps_results: { key: "TestFury-AllItems-EyeoftheBroodmother-45308" value: { - dps: 6189.43599 - tps: 4545.7705 + dps: 6704.97271 + tps: 4980.45534 } } dps_results: { key: "TestFury-AllItems-Figurine-SapphireOwl-42413" value: { - dps: 6077.42867 - tps: 4464.82713 + dps: 6584.90525 + tps: 4893.12317 } } dps_results: { key: "TestFury-AllItems-ForethoughtTalisman-40258" value: { - dps: 6068.64055 - tps: 4458.98045 + dps: 6559.28013 + tps: 4874.20474 } } dps_results: { key: "TestFury-AllItems-ForgeEmber-37660" value: { - dps: 6167.90206 - tps: 4529.76924 + dps: 6687.15497 + tps: 4970.63554 } } dps_results: { key: "TestFury-AllItems-ForlornSkyflareDiamond" value: { - dps: 6282.08305 - tps: 4615.43576 + dps: 6885.18545 + tps: 5119.12412 } } dps_results: { key: "TestFury-AllItems-ForlornStarflareDiamond" value: { - dps: 6282.08305 - tps: 4615.43576 + dps: 6885.18545 + tps: 5119.12412 } } dps_results: { key: "TestFury-AllItems-FuryoftheFiveFlights-40431" value: { - dps: 6282.77567 - tps: 4614.70076 + dps: 6784.00223 + tps: 5039.12821 } } dps_results: { key: "TestFury-AllItems-FuturesightRune-38763" value: { - dps: 6068.64055 - tps: 4458.98045 + dps: 6559.28013 + tps: 4874.20474 } } dps_results: { key: "TestFury-AllItems-Gladiator'sBattlegear" value: { - dps: 6112.49241 - tps: 4488.96448 + dps: 6570.55313 + tps: 4873.70756 } } dps_results: { key: "TestFury-AllItems-GlowingTwilightScale-54573" value: { - dps: 6068.64055 - tps: 4458.98045 + dps: 6559.28013 + tps: 4874.20474 } } dps_results: { key: "TestFury-AllItems-GlowingTwilightScale-54589" value: { - dps: 6068.64055 - tps: 4458.98045 + dps: 6559.28013 + tps: 4874.20474 } } dps_results: { key: "TestFury-AllItems-GnomishLightningGenerator-41121" value: { - dps: 6214.57201 - tps: 4563.14193 + dps: 6732.63239 + tps: 5001.11317 } } dps_results: { key: "TestFury-AllItems-Heartpierce-49982" value: { - dps: 6423.92566 - tps: 4719.63158 + dps: 6964.93261 + tps: 5177.34824 } } dps_results: { key: "TestFury-AllItems-Heartpierce-50641" value: { - dps: 6423.92566 - tps: 4719.63158 + dps: 6964.93261 + tps: 5177.34824 } } dps_results: { key: "TestFury-AllItems-IllustrationoftheDragonSoul-40432" value: { - dps: 6068.64055 - tps: 4458.98045 + dps: 6559.28013 + tps: 4874.20474 } } dps_results: { key: "TestFury-AllItems-ImpassiveSkyflareDiamond" value: { - dps: 6308.37895 - tps: 4634.43174 + dps: 6868.88557 + tps: 5105.07983 } } dps_results: { key: "TestFury-AllItems-ImpassiveStarflareDiamond" value: { - dps: 6308.8863 - tps: 4634.79924 + dps: 6874.11509 + tps: 5110.75442 } } dps_results: { key: "TestFury-AllItems-IncisorFragment-37723" value: { - dps: 6266.13203 - tps: 4604.24723 + dps: 6823.56239 + tps: 5065.85738 } } dps_results: { key: "TestFury-AllItems-InsightfulEarthsiegeDiamond" value: { - dps: 6282.08305 - tps: 4615.43576 + dps: 6885.18545 + tps: 5119.12412 } } dps_results: { key: "TestFury-AllItems-InvigoratingEarthsiegeDiamond" value: { - dps: 6311.85119 - tps: 4637.13045 + dps: 6901.3274 + tps: 5130.02631 hps: 13.7626 } } dps_results: { key: "TestFury-AllItems-LastWord-50179" value: { - dps: 6423.92566 - tps: 4719.63158 + dps: 6964.93261 + tps: 5177.34824 } } dps_results: { key: "TestFury-AllItems-LastWord-50708" value: { - dps: 6423.92566 - tps: 4719.63158 + dps: 6964.93261 + tps: 5177.34824 } } dps_results: { key: "TestFury-AllItems-Lavanthor'sTalisman-37872" value: { - dps: 6068.64055 - tps: 4458.98045 + dps: 6559.28013 + tps: 4874.20474 } } dps_results: { key: "TestFury-AllItems-MajesticDragonFigurine-40430" value: { - dps: 6068.64055 - tps: 4458.98045 + dps: 6559.28013 + tps: 4874.20474 } } dps_results: { key: "TestFury-AllItems-MeteoriteWhetstone-37390" value: { - dps: 6251.76275 - tps: 4593.72518 + dps: 6806.36961 + tps: 5051.69152 } } dps_results: { key: "TestFury-AllItems-NevermeltingIceCrystal-50259" value: { - dps: 6161.9534 - tps: 4525.70484 + dps: 6792.6766 + tps: 5044.42421 } } dps_results: { key: "TestFury-AllItems-OfferingofSacrifice-37638" value: { - dps: 6078.88576 - tps: 4466.4473 + dps: 6589.2357 + tps: 4893.12034 } } dps_results: { key: "TestFury-AllItems-OnslaughtArmor" value: { - dps: 3940.83335 - tps: 2909.62123 + dps: 4116.35794 + tps: 3078.01119 } } dps_results: { key: "TestFury-AllItems-OnslaughtBattlegear" value: { - dps: 4706.60413 - tps: 3464.23862 + dps: 4936.60791 + tps: 3686.08324 } } dps_results: { key: "TestFury-AllItems-PersistentEarthshatterDiamond" value: { - dps: 6305.68102 - tps: 4632.63106 + dps: 6887.6853 + tps: 5120.31582 } } dps_results: { key: "TestFury-AllItems-PersistentEarthsiegeDiamond" value: { - dps: 6311.23348 - tps: 4636.67698 + dps: 6891.5717 + tps: 5123.87783 } } dps_results: { key: "TestFury-AllItems-PetrifiedScarab-21685" value: { - dps: 6068.64055 - tps: 4458.98045 + dps: 6559.28013 + tps: 4874.20474 } } dps_results: { key: "TestFury-AllItems-PetrifiedTwilightScale-54571" value: { - dps: 6111.91006 - tps: 4490.4593 + dps: 6650.5469 + tps: 4940.36559 } } dps_results: { key: "TestFury-AllItems-PetrifiedTwilightScale-54591" value: { - dps: 6117.38687 - tps: 4494.45067 + dps: 6653.49639 + tps: 4940.1973 } } dps_results: { key: "TestFury-AllItems-PowerfulEarthshatterDiamond" value: { - dps: 6282.08305 - tps: 4615.43576 + dps: 6885.18545 + tps: 5119.12412 } } dps_results: { key: "TestFury-AllItems-PowerfulEarthsiegeDiamond" value: { - dps: 6282.08305 - tps: 4615.43576 + dps: 6885.18545 + tps: 5119.12412 } } dps_results: { key: "TestFury-AllItems-PurifiedShardoftheGods" value: { - dps: 6068.64055 - tps: 4458.98045 + dps: 6559.28013 + tps: 4874.20474 } } dps_results: { key: "TestFury-AllItems-ReignoftheDead-47316" value: { - dps: 6068.64055 - tps: 4458.98045 + dps: 6559.28013 + tps: 4874.20474 } } dps_results: { key: "TestFury-AllItems-ReignoftheDead-47477" value: { - dps: 6068.64055 - tps: 4458.98045 + dps: 6559.28013 + tps: 4874.20474 } } dps_results: { key: "TestFury-AllItems-RelentlessEarthsiegeDiamond" value: { - dps: 6425.2442 - tps: 4720.58779 + dps: 6960.0882 + tps: 5172.83324 } } dps_results: { key: "TestFury-AllItems-RevitalizingSkyflareDiamond" value: { - dps: 6282.08305 - tps: 4615.43576 + dps: 6885.18545 + tps: 5119.12412 } } dps_results: { key: "TestFury-AllItems-RuneofRepulsion-40372" value: { - dps: 6068.64055 - tps: 4458.98045 + dps: 6559.28013 + tps: 4874.20474 } } dps_results: { key: "TestFury-AllItems-SealofthePantheon-36993" value: { - dps: 6085.67296 - tps: 4471.39282 + dps: 6575.61208 + tps: 4885.8321 } } dps_results: { key: "TestFury-AllItems-Shadowmourne-49623" value: { - dps: 6423.92566 - tps: 4719.63158 + dps: 6964.93261 + tps: 5177.34824 } } dps_results: { key: "TestFury-AllItems-ShinyShardoftheGods" value: { - dps: 6068.64055 - tps: 4458.98045 + dps: 6559.28013 + tps: 4874.20474 } } dps_results: { key: "TestFury-AllItems-SiegebreakerBattlegear" value: { - dps: 6011.43514 - tps: 4416.30194 + dps: 6538.17097 + tps: 4855.89342 } } dps_results: { key: "TestFury-AllItems-SiegebreakerPlate" value: { - dps: 5195.06886 - tps: 3822.59421 + dps: 5485.8763 + tps: 4084.22545 } } dps_results: { key: "TestFury-AllItems-Sindragosa'sFlawlessFang-50361" value: { - dps: 6068.64055 - tps: 4458.98045 + dps: 6559.28013 + tps: 4874.20474 } } dps_results: { key: "TestFury-AllItems-SliverofPureIce-50339" value: { - dps: 6068.64055 - tps: 4458.98045 + dps: 6559.28013 + tps: 4874.20474 } } dps_results: { key: "TestFury-AllItems-SliverofPureIce-50346" value: { - dps: 6068.64055 - tps: 4458.98045 + dps: 6559.28013 + tps: 4874.20474 } } dps_results: { key: "TestFury-AllItems-SoulPreserver-37111" value: { - dps: 6068.64055 - tps: 4458.98045 + dps: 6559.28013 + tps: 4874.20474 } } dps_results: { key: "TestFury-AllItems-SouloftheDead-40382" value: { - dps: 6191.58883 - tps: 4547.35385 + dps: 6717.34147 + tps: 4988.78197 } } dps_results: { key: "TestFury-AllItems-SparkofLife-37657" value: { - dps: 6127.85832 - tps: 4496.68067 + dps: 6638.30084 + tps: 4923.44284 } } dps_results: { key: "TestFury-AllItems-SphereofRedDragon'sBlood-37166" value: { - dps: 6325.26769 - tps: 4648.06878 + dps: 6856.62273 + tps: 5088.22252 } } dps_results: { key: "TestFury-AllItems-StormshroudArmor" value: { - dps: 4734.56855 - tps: 3486.58656 + dps: 5041.64657 + tps: 3761.17074 } } dps_results: { key: "TestFury-AllItems-SwiftSkyflareDiamond" value: { - dps: 6311.23348 - tps: 4636.67698 + dps: 6891.5717 + tps: 5123.87783 } } dps_results: { key: "TestFury-AllItems-SwiftStarflareDiamond" value: { - dps: 6305.68102 - tps: 4632.63106 + dps: 6887.6853 + tps: 5120.31582 } } dps_results: { key: "TestFury-AllItems-SwiftWindfireDiamond" value: { - dps: 6295.96421 - tps: 4625.55079 + dps: 6871.46861 + tps: 5109.19871 } } dps_results: { key: "TestFury-AllItems-TalismanofTrollDivinity-37734" value: { - dps: 6068.64055 - tps: 4458.98045 + dps: 6559.28013 + tps: 4874.20474 } } dps_results: { key: "TestFury-AllItems-TearsoftheVanquished-47215" value: { - dps: 6068.64055 - tps: 4458.98045 + dps: 6559.28013 + tps: 4874.20474 } } dps_results: { key: "TestFury-AllItems-TheFistsofFury" value: { - dps: 4701.8964 - tps: 3441.99943 + dps: 4965.9252 + tps: 3701.06728 } } dps_results: { key: "TestFury-AllItems-TheGeneral'sHeart-45507" value: { - dps: 6068.64055 - tps: 4458.98045 + dps: 6559.28013 + tps: 4874.20474 } } dps_results: { key: "TestFury-AllItems-TheTwinBladesofAzzinoth" value: { - dps: 4945.02638 - tps: 3617.54645 + dps: 5099.68017 + tps: 3798.55202 } } dps_results: { key: "TestFury-AllItems-ThunderingSkyflareDiamond" value: { - dps: 6307.79817 - tps: 4632.78041 + dps: 6864.56544 + tps: 5101.01566 } } dps_results: { key: "TestFury-AllItems-TinyAbominationinaJar-50351" value: { - dps: 6419.39976 - tps: 4712.21557 + dps: 6971.6567 + tps: 5171.68032 } } dps_results: { key: "TestFury-AllItems-TinyAbominationinaJar-50706" value: { - dps: 6473.31079 - tps: 4750.92795 + dps: 6969.68545 + tps: 5166.48933 } } dps_results: { key: "TestFury-AllItems-TirelessSkyflareDiamond" value: { - dps: 6282.08305 - tps: 4615.43576 + dps: 6885.18545 + tps: 5119.12412 } } dps_results: { key: "TestFury-AllItems-TirelessStarflareDiamond" value: { - dps: 6282.08305 - tps: 4615.43576 + dps: 6885.18545 + tps: 5119.12412 } } dps_results: { key: "TestFury-AllItems-TomeofArcanePhenomena-36972" value: { - dps: 6202.53723 - tps: 4553.28874 + dps: 6683.01256 + tps: 4964.43213 } } dps_results: { key: "TestFury-AllItems-TrenchantEarthshatterDiamond" value: { - dps: 6282.08305 - tps: 4615.43576 + dps: 6885.18545 + tps: 5119.12412 } } dps_results: { key: "TestFury-AllItems-TrenchantEarthsiegeDiamond" value: { - dps: 6282.08305 - tps: 4615.43576 + dps: 6885.18545 + tps: 5119.12412 } } dps_results: { key: "TestFury-AllItems-UndeadSlayer'sBlessedArmor" value: { - dps: 5013.02305 - tps: 3682.17626 + dps: 5320.23269 + tps: 3960.22988 } } dps_results: { key: "TestFury-AllItems-Val'anyr,HammerofAncientKings-46017" value: { - dps: 4752.73581 - tps: 3499.1314 + dps: 5196.53795 + tps: 3921.70656 } } dps_results: { key: "TestFury-AllItems-WingedTalisman-37844" value: { - dps: 6068.64055 - tps: 4458.98045 + dps: 6559.28013 + tps: 4874.20474 } } dps_results: { key: "TestFury-AllItems-Wrynn'sBattlegear" value: { - dps: 6659.09505 - tps: 4890.56157 + dps: 7357.98622 + tps: 5453.94083 } } dps_results: { key: "TestFury-AllItems-Wrynn'sPlate" value: { - dps: 5451.43473 - tps: 4008.11611 + dps: 5786.67168 + tps: 4305.73513 } } dps_results: { key: "TestFury-AllItems-YmirjarLord'sBattlegear" value: { - dps: 7377.42047 - tps: 5413.47443 + dps: 8067.43407 + tps: 5973.43415 } } dps_results: { key: "TestFury-AllItems-YmirjarLord'sPlate" value: { - dps: 5755.86045 - tps: 4233.42579 + dps: 6174.83894 + tps: 4593.70936 } } dps_results: { key: "TestFury-Average-Default" value: { - dps: 6423.99337 - tps: 4721.09766 + dps: 7015.89861 + tps: 5207.27726 } } dps_results: { key: "TestFury-Settings-Human-p1_fury-Basic-fury-FullBuffs-LongMultiTarget" value: { - dps: 8643.58521 - tps: 6686.76935 + dps: 10294.60824 + tps: 8016.90735 } } dps_results: { key: "TestFury-Settings-Human-p1_fury-Basic-fury-FullBuffs-LongSingleTarget" value: { - dps: 6333.29509 - tps: 4652.58237 + dps: 6955.40821 + tps: 5169.2826 } } dps_results: { key: "TestFury-Settings-Human-p1_fury-Basic-fury-FullBuffs-ShortSingleTarget" value: { - dps: 7404.71574 - tps: 5425.96083 + dps: 8347.45997 + tps: 6188.65399 } } dps_results: { key: "TestFury-Settings-Human-p1_fury-Basic-fury-NoBuffs-LongMultiTarget" value: { - dps: 4307.27459 - tps: 3451.63161 + dps: 4394.68747 + tps: 3569.94332 } } dps_results: { key: "TestFury-Settings-Human-p1_fury-Basic-fury-NoBuffs-LongSingleTarget" value: { - dps: 2871.0366 - tps: 2139.06489 + dps: 2797.06729 + tps: 2107.61812 } } dps_results: { key: "TestFury-Settings-Human-p1_fury-Basic-fury-NoBuffs-ShortSingleTarget" value: { - dps: 3272.65818 - tps: 2447.12949 + dps: 3038.98566 + tps: 2297.15898 } } dps_results: { key: "TestFury-Settings-Orc-p1_fury-Basic-fury-FullBuffs-LongMultiTarget" value: { - dps: 8694.98225 - tps: 6729.1045 + dps: 10435.10341 + tps: 8132.46118 } } dps_results: { key: "TestFury-Settings-Orc-p1_fury-Basic-fury-FullBuffs-LongSingleTarget" value: { - dps: 6423.92566 - tps: 4719.63158 + dps: 6964.93261 + tps: 5177.34824 } } dps_results: { key: "TestFury-Settings-Orc-p1_fury-Basic-fury-FullBuffs-ShortSingleTarget" value: { - dps: 7516.95896 - tps: 5506.71715 + dps: 8385.2664 + tps: 6218.08828 } } dps_results: { key: "TestFury-Settings-Orc-p1_fury-Basic-fury-NoBuffs-LongMultiTarget" value: { - dps: 4334.00204 - tps: 3472.20866 + dps: 4418.12696 + tps: 3589.70524 } } dps_results: { key: "TestFury-Settings-Orc-p1_fury-Basic-fury-NoBuffs-LongSingleTarget" value: { - dps: 2910.72975 - tps: 2168.2564 + dps: 2797.24399 + tps: 2107.99386 } } dps_results: { key: "TestFury-Settings-Orc-p1_fury-Basic-fury-NoBuffs-ShortSingleTarget" value: { - dps: 3338.8731 - tps: 2494.623 + dps: 3131.51163 + tps: 2357.99182 } } dps_results: { key: "TestFury-SwitchInFrontOfTarget-Default" value: { - dps: 5887.98903 - tps: 4330.99525 + dps: 6468.4034 + tps: 4804.77961 } } diff --git a/sim/warrior/heroic_strike_cleave.go b/sim/warrior/heroic_strike_cleave.go index defe4fa625..94e532653c 100644 --- a/sim/warrior/heroic_strike_cleave.go +++ b/sim/warrior/heroic_strike_cleave.go @@ -48,6 +48,7 @@ func (warrior *Warrior) registerHeroicStrikeSpell() { } }, }) + warrior.makeQueueSpellsAndAura(warrior.HeroicStrike) } func (warrior *Warrior) registerCleaveSpell() { @@ -94,6 +95,7 @@ func (warrior *Warrior) registerCleaveSpell() { } }, }) + warrior.makeQueueSpellsAndAura(warrior.Cleave) } func (warrior *Warrior) makeQueueSpellsAndAura(srcSpell *core.Spell) *core.Spell { diff --git a/sim/warrior/protection/TestProtectionWarrior.results b/sim/warrior/protection/TestProtectionWarrior.results index 8f624c145c..c86c6c7975 100644 --- a/sim/warrior/protection/TestProtectionWarrior.results +++ b/sim/warrior/protection/TestProtectionWarrior.results @@ -46,7 +46,7 @@ character_stats_results: { stat_weights_results: { key: "TestProtectionWarrior-StatWeights-Default" value: { - weights: 0.71312 + weights: 0.76367 weights: 0 weights: 0 weights: 0 @@ -57,7 +57,7 @@ stat_weights_results: { weights: 0 weights: 0 weights: 0 - weights: 0.19612 + weights: 0.2638 weights: 0 weights: 0 weights: 0 @@ -66,12 +66,12 @@ stat_weights_results: { weights: 0 weights: 0 weights: 0 - weights: 0.00611 + weights: -3e-05 weights: 0 weights: 0 weights: 0 - weights: 0.43871 - weights: 0.05727 + weights: 0.43043 + weights: 0.09932 weights: 0 weights: 0 weights: 0 @@ -91,874 +91,874 @@ stat_weights_results: { dps_results: { key: "TestProtectionWarrior-AllItems-Althor'sAbacus-50359" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-Althor'sAbacus-50366" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-AustereEarthsiegeDiamond" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-Bandit'sInsignia-40371" value: { - dps: 1349.67155 - tps: 3452.90509 + dps: 1497.4236 + tps: 3865.5531 } } dps_results: { key: "TestProtectionWarrior-AllItems-BaubleofTrueBlood-50354" value: { - dps: 1289.68012 - tps: 3328.53102 - hps: 82.28496 + dps: 1443.61597 + tps: 3757.74334 + hps: 82.16554 } } dps_results: { key: "TestProtectionWarrior-AllItems-BaubleofTrueBlood-50726" value: { - dps: 1289.68012 - tps: 3328.53102 - hps: 82.28496 + dps: 1443.61597 + tps: 3757.74334 + hps: 82.16554 } } dps_results: { key: "TestProtectionWarrior-AllItems-BeamingEarthsiegeDiamond" value: { - dps: 1296.93101 - tps: 3344.72411 + dps: 1436.29269 + tps: 3738.87948 } } dps_results: { key: "TestProtectionWarrior-AllItems-Beast-tamer'sShoulders-30892" value: { - dps: 1268.62008 - tps: 3272.93157 + dps: 1403.06881 + tps: 3652.51629 } } dps_results: { key: "TestProtectionWarrior-AllItems-BlackBruise-50035" value: { - dps: 1366.40693 - tps: 3480.65126 + dps: 1502.62813 + tps: 3840.29252 } } dps_results: { key: "TestProtectionWarrior-AllItems-BlackBruise-50692" value: { - dps: 1393.43275 - tps: 3536.68929 + dps: 1532.82854 + tps: 3902.58233 } } dps_results: { key: "TestProtectionWarrior-AllItems-BlessedBattlegearofUndeadSlaying" value: { - dps: 1095.91679 - tps: 2830.7771 + dps: 1236.90562 + tps: 3226.4392 } } dps_results: { key: "TestProtectionWarrior-AllItems-BlessedGarboftheUndeadSlayer" value: { - dps: 1083.97911 - tps: 2801.35142 + dps: 1213.25286 + tps: 3161.94609 } } dps_results: { key: "TestProtectionWarrior-AllItems-BlessedRegaliaofUndeadCleansing" value: { - dps: 1038.79449 - tps: 2703.60683 + dps: 1149.45808 + tps: 3021.01244 } } dps_results: { key: "TestProtectionWarrior-AllItems-BracingEarthsiegeDiamond" value: { - dps: 1288.48948 - tps: 3259.55894 + dps: 1429.13677 + tps: 3649.22353 } } dps_results: { key: "TestProtectionWarrior-AllItems-Bryntroll,theBoneArbiter-50415" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-Bryntroll,theBoneArbiter-50709" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-ChaoticSkyflareDiamond" value: { - dps: 1312.2867 - tps: 3382.90933 + dps: 1464.89347 + tps: 3806.56276 } } dps_results: { key: "TestProtectionWarrior-AllItems-CorpseTongueCoin-50349" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-CorpseTongueCoin-50352" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-CorrodedSkeletonKey-50356" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 hps: 64 } } dps_results: { key: "TestProtectionWarrior-AllItems-DarkmoonCard:Berserker!-42989" value: { - dps: 1326.14307 - tps: 3412.47151 + dps: 1482.8109 + tps: 3850.33623 } } dps_results: { key: "TestProtectionWarrior-AllItems-DarkmoonCard:Death-42990" value: { - dps: 1370.16223 - tps: 3503.06341 + dps: 1514.2653 + tps: 3906.78831 } } dps_results: { key: "TestProtectionWarrior-AllItems-DarkmoonCard:Greatness-44255" value: { - dps: 1320.20348 - tps: 3397.32538 + dps: 1475.90374 + tps: 3829.1951 } } dps_results: { key: "TestProtectionWarrior-AllItems-Death'sChoice-47464" value: { - dps: 1362.44929 - tps: 3485.44146 + dps: 1516.88738 + tps: 3908.179 } } dps_results: { key: "TestProtectionWarrior-AllItems-DeathKnight'sAnguish-38212" value: { - dps: 1315.30651 - tps: 3386.90955 + dps: 1458.84083 + tps: 3789.00873 } } dps_results: { key: "TestProtectionWarrior-AllItems-Deathbringer'sWill-50362" value: { - dps: 1379.04866 - tps: 3530.54996 + dps: 1550.72349 + tps: 4003.56481 } } dps_results: { key: "TestProtectionWarrior-AllItems-Deathbringer'sWill-50363" value: { - dps: 1402.27748 - tps: 3586.09731 + dps: 1559.26933 + tps: 4021.26044 } } dps_results: { key: "TestProtectionWarrior-AllItems-DestructiveSkyflareDiamond" value: { - dps: 1297.77538 - tps: 3346.47492 + dps: 1438.34767 + tps: 3744.86385 } } dps_results: { key: "TestProtectionWarrior-AllItems-DislodgedForeignObject-50348" value: { - dps: 1332.44248 - tps: 3426.37457 + dps: 1471.50005 + tps: 3813.02114 } } dps_results: { key: "TestProtectionWarrior-AllItems-DislodgedForeignObject-50353" value: { - dps: 1327.12982 - tps: 3414.81696 + dps: 1470.21311 + tps: 3812.0458 } } dps_results: { key: "TestProtectionWarrior-AllItems-DreadnaughtBattlegear" value: { - dps: 1309.91106 - tps: 3337.8708 + dps: 1474.02677 + tps: 3793.84899 } } dps_results: { key: "TestProtectionWarrior-AllItems-DreadnaughtPlate" value: { - dps: 1216.07089 - tps: 3142.58615 + dps: 1354.59803 + tps: 3527.38642 } } dps_results: { key: "TestProtectionWarrior-AllItems-EffulgentSkyflareDiamond" value: { - dps: 1288.48948 - tps: 3326.07038 + dps: 1429.13677 + tps: 3723.6434 } } dps_results: { key: "TestProtectionWarrior-AllItems-EmberSkyflareDiamond" value: { - dps: 1288.48948 - tps: 3326.07038 + dps: 1429.13677 + tps: 3723.6434 } } dps_results: { key: "TestProtectionWarrior-AllItems-EnigmaticSkyflareDiamond" value: { - dps: 1296.93101 - tps: 3344.72411 + dps: 1436.29269 + tps: 3738.87948 } } dps_results: { key: "TestProtectionWarrior-AllItems-EnigmaticStarflareDiamond" value: { - dps: 1295.62188 - tps: 3341.52155 + dps: 1436.28313 + tps: 3739.17223 } } dps_results: { key: "TestProtectionWarrior-AllItems-EphemeralSnowflake-50260" value: { - dps: 1314.10173 - tps: 3386.07585 + dps: 1452.25212 + tps: 3775.3647 } } dps_results: { key: "TestProtectionWarrior-AllItems-EssenceofGossamer-37220" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-EternalEarthsiegeDiamond" value: { - dps: 1302.09935 - tps: 3362.75646 + dps: 1442.7152 + tps: 3760.24472 } } dps_results: { key: "TestProtectionWarrior-AllItems-ExtractofNecromanticPower-40373" value: { - dps: 1359.5275 - tps: 3481.35292 + dps: 1503.39455 + tps: 3880.58924 } } dps_results: { key: "TestProtectionWarrior-AllItems-EyeoftheBroodmother-45308" value: { - dps: 1323.63574 - tps: 3406.9386 + dps: 1466.27182 + tps: 3802.47188 } } dps_results: { key: "TestProtectionWarrior-AllItems-Figurine-SapphireOwl-42413" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-ForethoughtTalisman-40258" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-ForgeEmber-37660" value: { - dps: 1315.49823 - tps: 3387.44624 + dps: 1464.82611 + tps: 3806.06243 } } dps_results: { key: "TestProtectionWarrior-AllItems-ForlornSkyflareDiamond" value: { - dps: 1288.48948 - tps: 3326.07038 + dps: 1429.13677 + tps: 3723.6434 } } dps_results: { key: "TestProtectionWarrior-AllItems-ForlornStarflareDiamond" value: { - dps: 1288.48948 - tps: 3326.07038 + dps: 1429.13677 + tps: 3723.6434 } } dps_results: { key: "TestProtectionWarrior-AllItems-FuryoftheFiveFlights-40431" value: { - dps: 1318.14001 - tps: 3387.55053 + dps: 1473.63265 + tps: 3820.71002 } } dps_results: { key: "TestProtectionWarrior-AllItems-FuturesightRune-38763" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-Gladiator'sBattlegear" value: { - dps: 1390.13929 - tps: 3488.94895 + dps: 1546.55353 + tps: 3917.21448 } } dps_results: { key: "TestProtectionWarrior-AllItems-GlowingTwilightScale-54573" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-GlowingTwilightScale-54589" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-GnomishLightningGenerator-41121" value: { - dps: 1357.44157 - tps: 3476.42661 + dps: 1499.30293 + tps: 3876.2045 } } dps_results: { key: "TestProtectionWarrior-AllItems-Heartpierce-49982" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-Heartpierce-50641" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-IllustrationoftheDragonSoul-40432" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-ImpassiveSkyflareDiamond" value: { - dps: 1296.93101 - tps: 3344.72411 + dps: 1436.29269 + tps: 3738.87948 } } dps_results: { key: "TestProtectionWarrior-AllItems-ImpassiveStarflareDiamond" value: { - dps: 1295.62188 - tps: 3341.52155 + dps: 1436.28313 + tps: 3739.17223 } } dps_results: { key: "TestProtectionWarrior-AllItems-IncisorFragment-37723" value: { - dps: 1325.06872 - tps: 3409.61163 + dps: 1477.31363 + tps: 3830.89904 } } dps_results: { key: "TestProtectionWarrior-AllItems-InsightfulEarthsiegeDiamond" value: { - dps: 1288.48948 - tps: 3326.07038 + dps: 1429.13677 + tps: 3723.6434 } } dps_results: { key: "TestProtectionWarrior-AllItems-InvigoratingEarthsiegeDiamond" value: { - dps: 1292.37353 - tps: 3334.12396 - hps: 15.35543 + dps: 1439.81394 + tps: 3750.17262 + hps: 16.38289 } } dps_results: { key: "TestProtectionWarrior-AllItems-LastWord-50179" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-LastWord-50708" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-Lavanthor'sTalisman-37872" value: { - dps: 1302.08299 - tps: 3361.96359 + dps: 1456.808 + tps: 3793.30312 } } dps_results: { key: "TestProtectionWarrior-AllItems-MajesticDragonFigurine-40430" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-MeteoriteWhetstone-37390" value: { - dps: 1342.00137 - tps: 3451.0587 + dps: 1487.95987 + tps: 3858.19024 } } dps_results: { key: "TestProtectionWarrior-AllItems-NevermeltingIceCrystal-50259" value: { - dps: 1341.11428 - tps: 3446.17637 + dps: 1488.45581 + tps: 3857.26512 } } dps_results: { key: "TestProtectionWarrior-AllItems-OfferingofSacrifice-37638" value: { - dps: 1291.10608 - tps: 3331.4959 + dps: 1439.06283 + tps: 3744.35518 } } dps_results: { key: "TestProtectionWarrior-AllItems-OnslaughtArmor" value: { - dps: 1032.96893 - tps: 2697.01584 + dps: 1143.96277 + tps: 3010.38028 } } dps_results: { key: "TestProtectionWarrior-AllItems-OnslaughtBattlegear" value: { - dps: 1073.2847 - tps: 2744.73876 + dps: 1212.73705 + tps: 3132.14296 } } dps_results: { key: "TestProtectionWarrior-AllItems-PersistentEarthshatterDiamond" value: { - dps: 1291.63371 - tps: 3332.58995 + dps: 1441.44826 + tps: 3755.28496 } } dps_results: { key: "TestProtectionWarrior-AllItems-PersistentEarthsiegeDiamond" value: { - dps: 1292.37353 - tps: 3334.12396 + dps: 1439.81394 + tps: 3750.17262 } } dps_results: { key: "TestProtectionWarrior-AllItems-PetrifiedScarab-21685" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-PetrifiedTwilightScale-54571" value: { - dps: 1295.55527 - tps: 3340.7213 + dps: 1438.52633 + tps: 3741.00002 } } dps_results: { key: "TestProtectionWarrior-AllItems-PetrifiedTwilightScale-54591" value: { - dps: 1296.3105 - tps: 3342.28727 + dps: 1437.28281 + tps: 3735.73938 } } dps_results: { key: "TestProtectionWarrior-AllItems-PowerfulEarthshatterDiamond" value: { - dps: 1288.48948 - tps: 3326.07038 + dps: 1429.13677 + tps: 3723.6434 } } dps_results: { key: "TestProtectionWarrior-AllItems-PowerfulEarthsiegeDiamond" value: { - dps: 1288.48948 - tps: 3326.07038 + dps: 1429.13677 + tps: 3723.6434 } } dps_results: { key: "TestProtectionWarrior-AllItems-PurifiedShardoftheGods" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-ReignoftheDead-47316" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-ReignoftheDead-47477" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-RelentlessEarthsiegeDiamond" value: { - dps: 1311.03851 - tps: 3379.80384 + dps: 1464.99517 + tps: 3809.20556 } } dps_results: { key: "TestProtectionWarrior-AllItems-RevitalizingSkyflareDiamond" value: { - dps: 1288.48948 - tps: 3326.07038 + dps: 1429.13677 + tps: 3723.6434 } } dps_results: { key: "TestProtectionWarrior-AllItems-RuneofRepulsion-40372" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-SealofthePantheon-36993" value: { - dps: 1291.56894 - tps: 3332.45565 + dps: 1432.85618 + tps: 3727.67586 } } dps_results: { key: "TestProtectionWarrior-AllItems-Shadowmourne-49623" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-ShinyShardoftheGods" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-SiegebreakerBattlegear" value: { - dps: 1348.66714 - tps: 3431.43035 + dps: 1528.60272 + tps: 3922.80255 } } dps_results: { key: "TestProtectionWarrior-AllItems-SiegebreakerPlate" value: { - dps: 1226.35732 - tps: 3155.63414 + dps: 1362.18488 + tps: 3534.24554 } } dps_results: { key: "TestProtectionWarrior-AllItems-Sindragosa'sFlawlessFang-50361" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-SliverofPureIce-50339" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-SliverofPureIce-50346" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-SoulPreserver-37111" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-SouloftheDead-40382" value: { - dps: 1324.25226 - tps: 3408.21696 + dps: 1468.61799 + tps: 3808.46535 } } dps_results: { key: "TestProtectionWarrior-AllItems-SparkofLife-37657" value: { - dps: 1309.36532 - tps: 3376.66033 + dps: 1440.66133 + tps: 3742.16595 } } dps_results: { key: "TestProtectionWarrior-AllItems-SphereofRedDragon'sBlood-37166" value: { - dps: 1322.14884 - tps: 3404.71972 + dps: 1478.71065 + tps: 3846.54338 } } dps_results: { key: "TestProtectionWarrior-AllItems-StormshroudArmor" value: { - dps: 1027.97703 - tps: 2682.10178 + dps: 1131.41118 + tps: 2973.77697 } } dps_results: { key: "TestProtectionWarrior-AllItems-SwiftSkyflareDiamond" value: { - dps: 1292.37353 - tps: 3334.12396 + dps: 1439.81394 + tps: 3750.17262 } } dps_results: { key: "TestProtectionWarrior-AllItems-SwiftStarflareDiamond" value: { - dps: 1291.63371 - tps: 3332.58995 + dps: 1441.44826 + tps: 3755.28496 } } dps_results: { key: "TestProtectionWarrior-AllItems-SwiftWindfireDiamond" value: { - dps: 1290.33903 - tps: 3329.90542 + dps: 1434.21835 + tps: 3734.84239 } } dps_results: { key: "TestProtectionWarrior-AllItems-TalismanofTrollDivinity-37734" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-TearsoftheVanquished-47215" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-TheFistsofFury" value: { - dps: 638.3805 - tps: 1332.04643 + dps: 1002.18698 + tps: 2269.92269 } } dps_results: { key: "TestProtectionWarrior-AllItems-TheGeneral'sHeart-45507" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-TheTwinBladesofAzzinoth" value: { - dps: 672.48703 - tps: 1402.91131 + dps: 1067.10265 + tps: 2408.07406 } } dps_results: { key: "TestProtectionWarrior-AllItems-ThunderingSkyflareDiamond" value: { - dps: 1295.25946 - tps: 3338.84336 + dps: 1433.77973 + tps: 3730.22067 } } dps_results: { key: "TestProtectionWarrior-AllItems-TinyAbominationinaJar-50351" value: { - dps: 1336.15076 - tps: 3441.80734 + dps: 1478.24422 + tps: 3833.2328 } } dps_results: { key: "TestProtectionWarrior-AllItems-TinyAbominationinaJar-50706" value: { - dps: 1350.48168 - tps: 3475.99802 + dps: 1467.27925 + tps: 3802.76201 } } dps_results: { key: "TestProtectionWarrior-AllItems-TirelessSkyflareDiamond" value: { - dps: 1288.48948 - tps: 3326.07038 + dps: 1429.13677 + tps: 3723.6434 } } dps_results: { key: "TestProtectionWarrior-AllItems-TirelessStarflareDiamond" value: { - dps: 1288.48948 - tps: 3326.07038 + dps: 1429.13677 + tps: 3723.6434 } } dps_results: { key: "TestProtectionWarrior-AllItems-TomeofArcanePhenomena-36972" value: { - dps: 1308.92313 - tps: 3378.26678 + dps: 1436.78984 + tps: 3728.88041 } } dps_results: { key: "TestProtectionWarrior-AllItems-TrenchantEarthshatterDiamond" value: { - dps: 1288.48948 - tps: 3326.07038 + dps: 1429.13677 + tps: 3723.6434 } } dps_results: { key: "TestProtectionWarrior-AllItems-TrenchantEarthsiegeDiamond" value: { - dps: 1288.48948 - tps: 3326.07038 + dps: 1429.13677 + tps: 3723.6434 } } dps_results: { key: "TestProtectionWarrior-AllItems-UndeadSlayer'sBlessedArmor" value: { - dps: 1086.63762 - tps: 2805.44607 + dps: 1207.40792 + tps: 3148.8019 } } dps_results: { key: "TestProtectionWarrior-AllItems-Val'anyr,HammerofAncientKings-46017" value: { - dps: 1216.28045 - tps: 3164.34375 + dps: 1320.86781 + tps: 3455.68965 } } dps_results: { key: "TestProtectionWarrior-AllItems-WingedTalisman-37844" value: { - dps: 1289.69323 - tps: 3328.56635 + dps: 1443.50947 + tps: 3757.45627 } } dps_results: { key: "TestProtectionWarrior-AllItems-Wrynn'sBattlegear" value: { - dps: 1501.65236 - tps: 3779.411 + dps: 1715.22713 + tps: 4343.02026 } } dps_results: { key: "TestProtectionWarrior-AllItems-Wrynn'sPlate" value: { - dps: 1310.8597 - tps: 3363.59082 + dps: 1438.9139 + tps: 3715.52095 } } dps_results: { key: "TestProtectionWarrior-AllItems-YmirjarLord'sBattlegear" value: { - dps: 1681.60003 - tps: 4188.20074 + dps: 1915.35055 + tps: 4811.31977 } } dps_results: { key: "TestProtectionWarrior-AllItems-YmirjarLord'sPlate" value: { - dps: 1425.09691 - tps: 3644.74776 + dps: 1565.56182 + tps: 4034.16559 } } dps_results: { key: "TestProtectionWarrior-Average-Default" value: { - dps: 2540.72733 - tps: 6095.0764 - dtps: 127.44615 + dps: 2771.65176 + tps: 6733.04173 + dtps: 127.4897 } } dps_results: { key: "TestProtectionWarrior-Settings-Human-p1_balanced-Basic-default-FullBuffs-LongMultiTarget" value: { - dps: 1353.97589 - tps: 3511.30182 + dps: 1476.36368 + tps: 3891.49394 } } dps_results: { key: "TestProtectionWarrior-Settings-Human-p1_balanced-Basic-default-FullBuffs-LongSingleTarget" value: { - dps: 1353.97589 - tps: 3501.81765 + dps: 1476.36368 + tps: 3840.82728 } } dps_results: { key: "TestProtectionWarrior-Settings-Human-p1_balanced-Basic-default-FullBuffs-ShortSingleTarget" value: { - dps: 1561.83404 - tps: 4024.60825 + dps: 1639.76544 + tps: 4236.26058 } } dps_results: { key: "TestProtectionWarrior-Settings-Human-p1_balanced-Basic-default-NoBuffs-LongMultiTarget" value: { - dps: 1094.86734 - tps: 3435.07618 + dps: 1084.94322 + tps: 3407.20547 } } dps_results: { key: "TestProtectionWarrior-Settings-Human-p1_balanced-Basic-default-NoBuffs-LongSingleTarget" value: { - dps: 882.0064 - tps: 2533.03893 + dps: 866.97075 + tps: 2487.10038 } } dps_results: { @@ -971,36 +971,36 @@ dps_results: { dps_results: { key: "TestProtectionWarrior-Settings-Orc-p1_balanced-Basic-default-FullBuffs-LongMultiTarget" value: { - dps: 1360.20142 - tps: 3524.55292 + dps: 1493.10216 + tps: 3930.30504 } } dps_results: { key: "TestProtectionWarrior-Settings-Orc-p1_balanced-Basic-default-FullBuffs-LongSingleTarget" value: { - dps: 1360.20142 - tps: 3515.09003 + dps: 1493.10216 + tps: 3879.63837 } } dps_results: { key: "TestProtectionWarrior-Settings-Orc-p1_balanced-Basic-default-FullBuffs-ShortSingleTarget" value: { - dps: 1573.75672 - tps: 4049.75167 + dps: 1681.29892 + tps: 4344.50046 } } dps_results: { key: "TestProtectionWarrior-Settings-Orc-p1_balanced-Basic-default-NoBuffs-LongMultiTarget" value: { - dps: 1104.93219 - tps: 3468.9695 + dps: 1097.36592 + tps: 3443.56821 } } dps_results: { key: "TestProtectionWarrior-Settings-Orc-p1_balanced-Basic-default-NoBuffs-LongSingleTarget" value: { - dps: 885.75406 - tps: 2542.0882 + dps: 881.93425 + tps: 2531.41294 } } dps_results: { @@ -1013,8 +1013,8 @@ dps_results: { dps_results: { key: "TestProtectionWarrior-SwitchInFrontOfTarget-Default" value: { - dps: 2658.90648 - tps: 6391.54637 - dtps: 120.61498 + dps: 2890.35455 + tps: 7022.68811 + dtps: 120.81343 } } From e138207915a7dff4917bc36e2226035ee9b25a63 Mon Sep 17 00:00:00 2001 From: James Tanner Date: Tue, 9 Jan 2024 02:09:41 -0800 Subject: [PATCH 26/28] Fix small shaman bug --- .../enhancement/TestEnhancement.results | 144 +++++++++--------- sim/shaman/totems.go | 7 +- 2 files changed, 78 insertions(+), 73 deletions(-) diff --git a/sim/shaman/enhancement/TestEnhancement.results b/sim/shaman/enhancement/TestEnhancement.results index c72deb447e..e1003be241 100644 --- a/sim/shaman/enhancement/TestEnhancement.results +++ b/sim/shaman/enhancement/TestEnhancement.results @@ -1114,127 +1114,127 @@ dps_results: { dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-default_ft-FullBuffs-LongMultiTarget" value: { - dps: 4944.24822 - tps: 4008.12786 + dps: 22232.41084 + tps: 14032.63156 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-default_ft-FullBuffs-LongSingleTarget" value: { - dps: 4944.24822 - tps: 3210.89845 + dps: 6310.29822 + tps: 3894.21075 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-default_ft-FullBuffs-ShortSingleTarget" value: { - dps: 6208.66309 - tps: 3584.79758 + dps: 7625.09438 + tps: 4292.73614 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-default_ft-NoBuffs-LongMultiTarget" value: { - dps: 2440.10311 - tps: 2574.46437 + dps: 10601.75571 + tps: 7528.77421 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-default_ft-NoBuffs-LongSingleTarget" value: { - dps: 2440.10311 - tps: 1639.91575 + dps: 2818.31739 + tps: 1776.97179 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-default_ft-NoBuffs-ShortSingleTarget" value: { - dps: 2708.33712 - tps: 1602.97462 + dps: 3477.88715 + tps: 2033.81312 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-default_wf-FullBuffs-LongMultiTarget" value: { - dps: 5091.26951 - tps: 4166.23495 + dps: 21690.21929 + tps: 13696.7373 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-default_wf-FullBuffs-LongSingleTarget" value: { - dps: 5091.26951 - tps: 3317.31698 + dps: 6407.59639 + tps: 3963.37725 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-default_wf-FullBuffs-ShortSingleTarget" value: { - dps: 6396.28053 - tps: 3720.37032 + dps: 7688.0309 + tps: 4341.98635 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-default_wf-NoBuffs-LongMultiTarget" value: { - dps: 2568.28624 - tps: 2810.23722 + dps: 9884.6133 + tps: 7003.63947 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-default_wf-NoBuffs-LongSingleTarget" value: { - dps: 2568.28624 - tps: 1736.89243 + dps: 2854.92489 + tps: 1807.16084 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-default_wf-NoBuffs-ShortSingleTarget" value: { - dps: 2834.49133 - tps: 1691.14902 + dps: 3553.21327 + tps: 2087.56986 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-phase_3-FullBuffs-LongMultiTarget" value: { - dps: 4866.76982 - tps: 3900.96896 + dps: 22332.92499 + tps: 14053.10037 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-phase_3-FullBuffs-LongSingleTarget" value: { - dps: 4866.76982 - tps: 3154.8846 + dps: 6333.04736 + tps: 3909.91624 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-phase_3-FullBuffs-ShortSingleTarget" value: { - dps: 6155.11998 - tps: 3552.33946 + dps: 7565.25151 + tps: 4246.92698 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-phase_3-NoBuffs-LongMultiTarget" value: { - dps: 2357.03434 - tps: 2371.87381 + dps: 10577.713 + tps: 7462.8381 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-phase_3-NoBuffs-LongSingleTarget" value: { - dps: 2357.03434 - tps: 1574.49498 + dps: 2829.31347 + tps: 1783.88363 } } dps_results: { key: "TestEnhancement-Settings-Orc-p1-WF-phase_3-NoBuffs-ShortSingleTarget" value: { - dps: 2620.98068 - tps: 1541.92994 + dps: 3469.99663 + tps: 2009.30926 } } dps_results: { @@ -1366,127 +1366,127 @@ dps_results: { dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-default_ft-FullBuffs-LongMultiTarget" value: { - dps: 4987.1598 - tps: 4061.9771 + dps: 22214.34484 + tps: 14071.30753 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-default_ft-FullBuffs-LongSingleTarget" value: { - dps: 4987.1598 - tps: 3258.62378 + dps: 6317.56193 + tps: 3916.88417 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-default_ft-FullBuffs-ShortSingleTarget" value: { - dps: 6308.24779 - tps: 3709.32128 + dps: 7607.20836 + tps: 4327.10898 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-default_ft-NoBuffs-LongMultiTarget" value: { - dps: 2444.83649 - tps: 2561.92902 + dps: 10508.5794 + tps: 7459.33318 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-default_ft-NoBuffs-LongSingleTarget" value: { - dps: 2444.83649 - tps: 1648.29155 + dps: 2822.54419 + tps: 1786.97077 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-default_ft-NoBuffs-ShortSingleTarget" value: { - dps: 2711.86435 - tps: 1621.83785 + dps: 3538.91671 + tps: 2092.00848 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-default_wf-FullBuffs-LongMultiTarget" value: { - dps: 5115.23319 - tps: 4209.88967 + dps: 21464.69877 + tps: 13553.35701 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-default_wf-FullBuffs-LongSingleTarget" value: { - dps: 5115.23319 - tps: 3351.39836 + dps: 6374.41933 + tps: 3951.79147 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-default_wf-FullBuffs-ShortSingleTarget" value: { - dps: 6447.86216 - tps: 3809.26534 + dps: 7722.14196 + tps: 4403.68463 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-default_wf-NoBuffs-LongMultiTarget" value: { - dps: 2558.15125 - tps: 2852.05761 + dps: 9866.63739 + tps: 7014.52359 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-default_wf-NoBuffs-LongSingleTarget" value: { - dps: 2558.15125 - tps: 1737.43083 + dps: 2853.62154 + tps: 1813.24619 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-default_wf-NoBuffs-ShortSingleTarget" value: { - dps: 2841.24541 - tps: 1712.38615 + dps: 3567.55283 + tps: 2111.33287 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-phase_3-FullBuffs-LongMultiTarget" value: { - dps: 4868.01714 - tps: 3921.40877 + dps: 22209.29686 + tps: 14032.30074 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-phase_3-FullBuffs-LongSingleTarget" value: { - dps: 4868.01714 - tps: 3172.16547 + dps: 6316.60001 + tps: 3912.07724 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-phase_3-FullBuffs-ShortSingleTarget" value: { - dps: 6181.81733 - tps: 3618.34966 + dps: 7562.8648 + tps: 4284.24708 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-phase_3-NoBuffs-LongMultiTarget" value: { - dps: 2362.5928 - tps: 2365.21563 + dps: 10640.8485 + tps: 7505.58378 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-phase_3-NoBuffs-LongSingleTarget" value: { - dps: 2362.5928 - tps: 1583.3199 + dps: 2817.18144 + tps: 1783.40572 } } dps_results: { key: "TestEnhancement-Settings-Troll-p1-WF-phase_3-NoBuffs-ShortSingleTarget" value: { - dps: 2633.31988 - tps: 1567.36545 + dps: 3543.74483 + tps: 2079.12484 } } dps_results: { diff --git a/sim/shaman/totems.go b/sim/shaman/totems.go index 9b7e51ed6e..7e9b08550d 100644 --- a/sim/shaman/totems.go +++ b/sim/shaman/totems.go @@ -135,17 +135,22 @@ func (shaman *Shaman) registerCallOfTheElements() { waterTotem := shaman.getWaterTotemSpell(shaman.Totems.Water) totalManaCost := 0.0 + anyTotems := false if airTotem != nil { totalManaCost += airTotem.DefaultCast.Cost + anyTotems = true } if earthTotem != nil { totalManaCost += earthTotem.DefaultCast.Cost + anyTotems = true } if fireTotem != nil { totalManaCost += fireTotem.DefaultCast.Cost + anyTotems = true } if waterTotem != nil { totalManaCost += waterTotem.DefaultCast.Cost + anyTotems = true } shaman.RegisterSpell(core.SpellConfig{ @@ -158,7 +163,7 @@ func (shaman *Shaman) registerCallOfTheElements() { }, }, ExtraCastCondition: func(sim *core.Simulation, target *core.Unit) bool { - return shaman.CurrentMana() >= totalManaCost + return anyTotems && shaman.CurrentMana() >= totalManaCost }, ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { From 9b8987bd4e72edb30fa90d17f8b77fee39213dbb Mon Sep 17 00:00:00 2001 From: James Tanner Date: Tue, 9 Jan 2024 03:40:44 -0800 Subject: [PATCH 27/28] Remove deprecated protos --- proto/apl.proto | 3 -- proto/common.proto | 6 ---- proto/priest.proto | 4 --- proto/ui.proto | 8 ----- sim/core/buffs.go | 10 +------ sim/core/test_utils.go | 2 +- sim/priest/shadow/shadow_priest.go | 2 +- sim/priest/shadow/shadow_priest_test.go | 15 ++-------- sim/raid_bench_test.go | 8 ++--- ui/balance_druid/presets.ts | 2 +- ui/core/components/icon_inputs.ts | 5 ++-- .../components/individual_sim_ui/gear_tab.ts | 6 +--- .../individual_sim_ui/rotation_tab.ts | 5 ---- ui/core/individual_sim_ui.ts | 4 +-- ui/core/preset_utils.ts | 8 ----- ui/core/raid.ts | 29 ------------------- ui/elemental_shaman/sim.ts | 2 +- ui/enhancement_shaman/presets.ts | 2 +- ui/healing_priest/presets.ts | 2 +- ui/holy_paladin/sim.ts | 2 +- ui/mage/sim.ts | 2 +- ui/protection_paladin/sim.ts | 2 +- ui/retribution_paladin/sim.ts | 2 +- ui/shadow_priest/presets.ts | 5 +--- ui/warlock/presets.ts | 2 +- 25 files changed, 22 insertions(+), 116 deletions(-) diff --git a/proto/apl.proto b/proto/apl.proto index f380dcaee9..072ead59fa 100644 --- a/proto/apl.proto +++ b/proto/apl.proto @@ -34,9 +34,6 @@ message APLPrepullAction { APLAction action = 1; APLValue do_at_value = 4; // When to perform this prepull action. Should be a negative value. bool hide = 3; // Causes this item to be ignored. - - // TODO: Remove after 1 month (on or after 8/30/2023). - string do_at = 2 [deprecated = true]; } message APLListItem { diff --git a/proto/common.proto b/proto/common.proto index 7bba98594d..a41176b01e 100644 --- a/proto/common.proto +++ b/proto/common.proto @@ -431,8 +431,6 @@ message RaidBuffs { // +Spell Power bool totem_of_wrath = 18; bool flametongue_totem = 19; - int32 demonic_pact_old = 20; // old demo SP - int32 demonic_pact = 43; // SP buff -- deprecated. int32 demonic_pact_sp = 44; // SP buff NEW CORRECT // +5% Spell Crit and/or +3% Haste @@ -658,7 +656,6 @@ message Target { bool dual_wield = 9; bool dual_wield_penalty = 10; bool parry_haste = 12; - bool tight_enemy_damage = 17; // deprecated as of 07/12/23 bool suppress_dodge = 16; // Sunwell Radiance SpellSchool spell_school = 13; // Allows elemental attacks. @@ -848,9 +845,6 @@ message Cooldowns { // % HP threshold, below which defensive cooldowns can be used. double hp_percent_for_defensives = 2; - - int32 desync_proc_trinket1_seconds = 3 [deprecated = true]; - int32 desync_proc_trinket2_seconds = 4 [deprecated = true]; } message HealingModel { diff --git a/proto/priest.proto b/proto/priest.proto index 9aad900732..3066bda4f1 100644 --- a/proto/priest.proto +++ b/proto/priest.proto @@ -146,12 +146,8 @@ message ShadowPriest { InnerFire = 1; } - bool use_shadowfiend = 1 [deprecated = true]; Armor armor = 2; - bool use_mind_blast = 4 [deprecated = true]; - bool use_shadow_word_death = 5 [deprecated = true]; UnitReference power_infusion_target = 6; - double latency = 7 [deprecated = true]; // Latency between actions } Options options = 3; } diff --git a/proto/ui.proto b/proto/ui.proto index ae1b928691..343ba90593 100644 --- a/proto/ui.proto +++ b/proto/ui.proto @@ -265,8 +265,6 @@ message IndividualSimSettings { Player player = 3; Encounter encounter = 4; int32 target_dummies = 9; - // Deprecate after 2 months (on 2023/02/13) - repeated double ep_weights = 6; UnitStats ep_weights_stats = 10; repeated double ep_ratios = 11; Stat dps_ref_stat = 12; @@ -277,8 +275,6 @@ message IndividualSimSettings { // Local storage data for gear settings. message SavedGearSet { EquipmentSpec gear = 1; - // Deprecate after 2 months (on 2023/02/13) - repeated double bonus_stats = 2; UnitStats bonus_stats_stats = 3; } @@ -290,8 +286,6 @@ message SavedSettings { IndividualBuffs player_buffs = 3; Consumes consumes = 4; Race race = 5; - Cooldowns cooldowns = 6 [deprecated = true]; - string rotation_json = 8 [deprecated = true]; repeated Profession professions = 9; bool enable_item_swap = 18; ItemSwap item_swap = 17; @@ -313,8 +307,6 @@ message SavedTalents { message SavedRotation { APLRotation rotation = 1; - string spec_rotation_options_json = 2 [deprecated = true]; - Cooldowns cooldowns = 3 [deprecated = true]; } message BlessingsAssignment { diff --git a/sim/core/buffs.go b/sim/core/buffs.go index 36107457d5..66d59134fd 100644 --- a/sim/core/buffs.go +++ b/sim/core/buffs.go @@ -224,16 +224,8 @@ func applyBuffEffects(agent Agent, raidBuffs *proto.RaidBuffs, partyBuffs *proto if raidBuffs.TotemOfWrath { MakePermanent(TotemOfWrathAura(character)) } - if raidBuffs.DemonicPactOld > 0 || raidBuffs.DemonicPact > 0 || raidBuffs.DemonicPactSp > 0 { - // Use DemonicPactSp if set. + if raidBuffs.DemonicPactSp > 0 { power := raidBuffs.DemonicPactSp - if power == 0 { - power = raidBuffs.DemonicPact // fallback to old setting. - } - if power == 0 { - power = raidBuffs.DemonicPactOld - } - dpAura := DemonicPactAura(character) dpAura.ExclusiveEffects[0].Priority = float64(power) MakePermanent(dpAura) diff --git a/sim/core/test_utils.go b/sim/core/test_utils.go index 1c0c2cbced..f37983362a 100644 --- a/sim/core/test_utils.go +++ b/sim/core/test_utils.go @@ -53,7 +53,7 @@ var FullRaidBuffs = &proto.RaidBuffs{ ArcaneEmpowerment: true, BattleShout: proto.TristateEffect_TristateEffectImproved, Bloodlust: true, - DemonicPact: 500, + DemonicPactSp: 500, DevotionAura: proto.TristateEffect_TristateEffectImproved, DivineSpirit: true, ElementalOath: true, diff --git a/sim/priest/shadow/shadow_priest.go b/sim/priest/shadow/shadow_priest.go index 36a2ae9c6e..735f84f1bb 100644 --- a/sim/priest/shadow/shadow_priest.go +++ b/sim/priest/shadow/shadow_priest.go @@ -28,7 +28,7 @@ func NewShadowPriest(character *core.Character, options *proto.Player) *ShadowPr shadowOptions := options.GetShadowPriest() selfBuffs := priest.SelfBuffs{ - UseShadowfiend: shadowOptions.Options.UseShadowfiend, + UseShadowfiend: true, UseInnerFire: shadowOptions.Options.Armor == proto.ShadowPriest_Options_InnerFire, } diff --git a/sim/priest/shadow/shadow_priest_test.go b/sim/priest/shadow/shadow_priest_test.go index edd33176d8..ac5003879b 100644 --- a/sim/priest/shadow/shadow_priest_test.go +++ b/sim/priest/shadow/shadow_priest_test.go @@ -65,30 +65,21 @@ var FullConsumes = &proto.Consumes{ var PlayerOptionsBasic = &proto.Player_ShadowPriest{ ShadowPriest: &proto.ShadowPriest{ Options: &proto.ShadowPriest_Options{ - Armor: proto.ShadowPriest_Options_InnerFire, - UseShadowfiend: true, - UseMindBlast: true, - UseShadowWordDeath: true, + Armor: proto.ShadowPriest_Options_InnerFire, }, }, } var PlayerOptionsClipping = &proto.Player_ShadowPriest{ ShadowPriest: &proto.ShadowPriest{ Options: &proto.ShadowPriest_Options{ - Armor: proto.ShadowPriest_Options_InnerFire, - UseShadowfiend: true, - UseMindBlast: true, - UseShadowWordDeath: true, + Armor: proto.ShadowPriest_Options_InnerFire, }, }, } var PlayerOptionsIdeal = &proto.Player_ShadowPriest{ ShadowPriest: &proto.ShadowPriest{ Options: &proto.ShadowPriest_Options{ - Armor: proto.ShadowPriest_Options_InnerFire, - UseShadowfiend: true, - UseMindBlast: true, - UseShadowWordDeath: true, + Armor: proto.ShadowPriest_Options_InnerFire, }, }, } diff --git a/sim/raid_bench_test.go b/sim/raid_bench_test.go index 41e9ef3411..01026d3438 100644 --- a/sim/raid_bench_test.go +++ b/sim/raid_bench_test.go @@ -38,9 +38,7 @@ var castersWithElemental = &proto.Party{ Equipment: ShadowEquipment, Spec: &proto.Player_ShadowPriest{ ShadowPriest: &proto.ShadowPriest{ - Options: &proto.ShadowPriest_Options{ - UseShadowfiend: true, - }, + Options: &proto.ShadowPriest_Options{}, }, }, Consumes: &proto.Consumes{ @@ -134,9 +132,7 @@ var castersWithResto = &proto.Party{ Equipment: ShadowEquipment, Spec: &proto.Player_ShadowPriest{ ShadowPriest: &proto.ShadowPriest{ - Options: &proto.ShadowPriest_Options{ - UseShadowfiend: true, - }, + Options: &proto.ShadowPriest_Options{}, }, }, Consumes: &proto.Consumes{ diff --git a/ui/balance_druid/presets.ts b/ui/balance_druid/presets.ts index b11e50dd42..b4ca4b6aaa 100644 --- a/ui/balance_druid/presets.ts +++ b/ui/balance_druid/presets.ts @@ -137,7 +137,7 @@ export const DefaultRaidBuffs = RaidBuffs.create({ strengthOfEarthTotem: TristateEffect.TristateEffectImproved, trueshotAura: true, wrathOfAirTotem: true, - demonicPact: 500, + demonicPactSp: 500, }); export const DefaultIndividualBuffs = IndividualBuffs.create({ diff --git a/ui/core/components/icon_inputs.ts b/ui/core/components/icon_inputs.ts index 0182abd75f..f2fcf70fe8 100644 --- a/ui/core/components/icon_inputs.ts +++ b/ui/core/components/icon_inputs.ts @@ -20,11 +20,10 @@ import { Player } from '../player.js'; import { Raid } from '../raid.js'; import { EventID, TypedEvent } from '../typed_event.js'; -import { IconPicker, IconPickerConfig } from './icon_picker.js'; -import { IconEnumPicker, IconEnumPickerConfig, IconEnumValueConfig } from './icon_enum_picker.js'; +import { IconPicker, } from './icon_picker.js'; +import { IconEnumPicker, IconEnumValueConfig } from './icon_enum_picker.js'; import * as InputHelpers from './input_helpers.js'; -import { Tooltip } from 'bootstrap'; // Component Functions diff --git a/ui/core/components/individual_sim_ui/gear_tab.ts b/ui/core/components/individual_sim_ui/gear_tab.ts index db11ae7f7c..8698b3582b 100644 --- a/ui/core/components/individual_sim_ui/gear_tab.ts +++ b/ui/core/components/individual_sim_ui/gear_tab.ts @@ -61,11 +61,7 @@ export class GearTab extends SimTab { setData: (eventID: EventID, player: Player, newSavedGear: SavedGearSet) => { TypedEvent.freezeAllAndDo(() => { player.setGear(eventID, this.simUI.sim.db.lookupEquipmentSpec(newSavedGear.gear || EquipmentSpec.create())); - if (newSavedGear.bonusStats && newSavedGear.bonusStats.some(s => s != 0)) { - player.setBonusStats(eventID, new Stats(newSavedGear.bonusStats)); - } else { - player.setBonusStats(eventID, Stats.fromProto(newSavedGear.bonusStatsStats || UnitStats.create())); - } + player.setBonusStats(eventID, Stats.fromProto(newSavedGear.bonusStatsStats || UnitStats.create())); }); }, changeEmitters: [this.simUI.player.changeEmitter], diff --git a/ui/core/components/individual_sim_ui/rotation_tab.ts b/ui/core/components/individual_sim_ui/rotation_tab.ts index 70a09d43f7..2bfe14199a 100644 --- a/ui/core/components/individual_sim_ui/rotation_tab.ts +++ b/ui/core/components/individual_sim_ui/rotation_tab.ts @@ -1,6 +1,5 @@ import { IndividualSimUI, InputSection } from "../../individual_sim_ui"; import { - Cooldowns, Spec, } from "../../proto/common"; import { @@ -188,8 +187,6 @@ export class RotationTab extends SimTab { storageKey: this.simUI.getSavedRotationStorageKey(), getData: (player: Player) => SavedRotation.create({ rotation: APLRotation.clone(player.aplRotation), - specRotationOptionsJson: '{}', - cooldowns: Cooldowns.create(), }), setData: (eventID: EventID, player: Player, newRotation: SavedRotation) => { TypedEvent.freezeAllAndDo(() => { @@ -211,8 +208,6 @@ export class RotationTab extends SimTab { (this.simUI.individualConfig.presets.rotations || []).forEach(presetRotation => { const rotData = presetRotation.rotation; // Fill default values so the equality checks always work. - if (!rotData.cooldowns) rotData.cooldowns = Cooldowns.create(); - if (!rotData.specRotationOptionsJson) rotData.specRotationOptionsJson = '{}'; if (!rotData.rotation) rotData.rotation = APLRotation.create(); savedRotationsManager.addSavedData({ diff --git a/ui/core/individual_sim_ui.ts b/ui/core/individual_sim_ui.ts index 08502d6d36..32c1ed0fe9 100644 --- a/ui/core/individual_sim_ui.ts +++ b/ui/core/individual_sim_ui.ts @@ -542,9 +542,7 @@ export abstract class IndividualSimUI extends SimUI { this.sim.encounter.fromProto(eventID, settings.encounter || EncounterProto.create()); } if (loadCategory(SimSettingCategories.UISettings)) { - if (settings.epWeights?.length > 0) { - this.player.setEpWeights(eventID, new Stats(settings.epWeights)); - } else if (settings.epWeightsStats) { + if (settings.epWeightsStats) { this.player.setEpWeights(eventID, Stats.fromProto(settings.epWeightsStats)); } else { this.player.setEpWeights(eventID, this.individualConfig.defaults.epWeights); diff --git a/ui/core/preset_utils.ts b/ui/core/preset_utils.ts index a62bb11136..f9d2689d99 100644 --- a/ui/core/preset_utils.ts +++ b/ui/core/preset_utils.ts @@ -78,7 +78,6 @@ function makePresetGearHelper(name: string, gear: EquipmentSpec, options: Preset export function makePresetAPLRotation(name: string, rotationJson: any, options?: PresetRotationOptions): PresetRotation { const rotation = SavedRotation.create({ - specRotationOptionsJson: '{}', rotation: APLRotation.fromJson(rotationJson), }); return makePresetRotationHelper(name, rotation, options); @@ -96,13 +95,6 @@ export function makePresetSimpleRotation(name: string, sp return makePresetRotationHelper(name, rotation, options); } -export function makePresetLegacyRotation(name: string, spec: SpecType, simpleRotation: SpecRotation, options?: PresetRotationOptions): PresetRotation { - const rotation = SavedRotation.create({ - specRotationOptionsJson: JSON.stringify(specTypeFunctions[spec].rotationToJson(simpleRotation)), - }); - return makePresetRotationHelper(name, rotation, options); -} - function makePresetRotationHelper(name: string, rotation: SavedRotation, options?: PresetRotationOptions): PresetRotation { let conditions: Array<(player: Player) => boolean> = []; if (options?.talentTree != undefined) { diff --git a/ui/core/raid.ts b/ui/core/raid.ts index d42215b1ad..6079d3398a 100644 --- a/ui/core/raid.ts +++ b/ui/core/raid.ts @@ -131,20 +131,6 @@ export class Raid { // Make a defensive copy this.buffs = RaidBuffs.clone(newBuffs); - if (newBuffs.demonicPact > 0 && newBuffs.demonicPactSp == 0) { - this.buffs.demonicPactSp = this.buffs.demonicPact; - if (this.buffs.demonicPactSp > 1000) { - this.buffs.demonicPactSp /= 10; - } - this.buffs.demonicPact = 0; - } else if (newBuffs.demonicPactOld > 0 && newBuffs.demonicPactSp == 0) { - this.buffs.demonicPactSp = this.buffs.demonicPactOld; - if (this.buffs.demonicPactSp > 1000) { - this.buffs.demonicPactSp /= 10; - } - this.buffs.demonicPactOld = 0; - } - // Special handle ToW since it crosses buffs/debuffs. if (this.debuffs.totemOfWrath != this.buffs.totemOfWrath) { var newDebuff = Debuffs.clone(this.debuffs); @@ -234,21 +220,6 @@ export class Raid { fromProto(eventID: EventID, proto: RaidProto) { TypedEvent.freezeAllAndDo(() => { - if (proto.buffs) { - if (proto.buffs.demonicPact > 0 && proto.buffs.demonicPactSp == 0) { - proto.buffs.demonicPactSp = proto.buffs.demonicPact; - if (proto.buffs.demonicPactSp > 1000) { - proto.buffs.demonicPactSp /= 10; - } - proto.buffs.demonicPact = 0; - } else if (proto.buffs.demonicPactOld > 0 && proto.buffs.demonicPactSp == 0) { - proto.buffs.demonicPactSp = proto.buffs.demonicPactOld; - if (proto.buffs.demonicPactSp > 1000) { - proto.buffs.demonicPactSp /= 10; - } - proto.buffs.demonicPactOld = 0; - } - } this.setBuffs(eventID, proto.buffs || RaidBuffs.create()); this.setDebuffs(eventID, proto.debuffs || Debuffs.create()); this.setTanks(eventID, proto.tanks); diff --git a/ui/elemental_shaman/sim.ts b/ui/elemental_shaman/sim.ts index 6bbaf3bef6..46e36502e2 100644 --- a/ui/elemental_shaman/sim.ts +++ b/ui/elemental_shaman/sim.ts @@ -107,7 +107,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecElementalShaman, { giftOfTheWild: TristateEffect.TristateEffectImproved, moonkinAura: TristateEffect.TristateEffectImproved, sanctifiedRetribution: true, - demonicPact: 500, + demonicPactSp: 500, wrathOfAirTotem: true, }), partyBuffs: PartyBuffs.create({ diff --git a/ui/enhancement_shaman/presets.ts b/ui/enhancement_shaman/presets.ts index 7069a9ac9f..4a1cda843f 100644 --- a/ui/enhancement_shaman/presets.ts +++ b/ui/enhancement_shaman/presets.ts @@ -111,7 +111,7 @@ export const DefaultRaidBuffs = RaidBuffs.create({ sanctifiedRetribution: true, divineSpirit: true, battleShout: TristateEffect.TristateEffectImproved, - demonicPact: 500, + demonicPactSp: 500, }); export const DefaultDebuffs = Debuffs.create({ diff --git a/ui/healing_priest/presets.ts b/ui/healing_priest/presets.ts index 8bb3ab74bc..e634974fdb 100644 --- a/ui/healing_priest/presets.ts +++ b/ui/healing_priest/presets.ts @@ -110,7 +110,7 @@ export const DefaultRaidBuffs = RaidBuffs.create({ wrathOfAirTotem: true, sanctifiedRetribution: true, bloodlust: true, - demonicPact: 500, + demonicPactSp: 500, }); export const DefaultIndividualBuffs = IndividualBuffs.create({ diff --git a/ui/holy_paladin/sim.ts b/ui/holy_paladin/sim.ts index 726cf95491..d73dc75409 100644 --- a/ui/holy_paladin/sim.ts +++ b/ui/holy_paladin/sim.ts @@ -81,7 +81,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecHolyPaladin, { leaderOfThePack: TristateEffect.TristateEffectRegular, icyTalons: true, totemOfWrath: true, - demonicPact: 500, + demonicPactSp: 500, swiftRetribution: true, moonkinAura: TristateEffect.TristateEffectRegular, sanctifiedRetribution: true, diff --git a/ui/mage/sim.ts b/ui/mage/sim.ts index ff702df22d..fff37fb5f0 100644 --- a/ui/mage/sim.ts +++ b/ui/mage/sim.ts @@ -89,7 +89,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecMage, { divineSpirit: true, swiftRetribution: true, sanctifiedRetribution: true, - demonicPact: 500, + demonicPactSp: 500, moonkinAura: TristateEffect.TristateEffectImproved, arcaneBrilliance: true, }), diff --git a/ui/protection_paladin/sim.ts b/ui/protection_paladin/sim.ts index 89161b19f3..11b8ae3b70 100644 --- a/ui/protection_paladin/sim.ts +++ b/ui/protection_paladin/sim.ts @@ -150,7 +150,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecProtectionPaladin, { leaderOfThePack: TristateEffect.TristateEffectRegular, icyTalons: true, totemOfWrath: true, - demonicPact: 500, + demonicPactSp: 500, swiftRetribution: true, moonkinAura: TristateEffect.TristateEffectRegular, sanctifiedRetribution: true, diff --git a/ui/retribution_paladin/sim.ts b/ui/retribution_paladin/sim.ts index d70127cba4..1959bc5061 100644 --- a/ui/retribution_paladin/sim.ts +++ b/ui/retribution_paladin/sim.ts @@ -135,7 +135,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecRetributionPaladin, { icyTalons: true, totemOfWrath: true, wrathOfAirTotem: true, - demonicPact: 500, + demonicPactSp: 500, }), partyBuffs: PartyBuffs.create({ }), diff --git a/ui/shadow_priest/presets.ts b/ui/shadow_priest/presets.ts index f58b46cb1e..fa2cf145b8 100644 --- a/ui/shadow_priest/presets.ts +++ b/ui/shadow_priest/presets.ts @@ -76,9 +76,6 @@ export const EnlightenmentTalents = { }; export const DefaultOptions = Options.create({ - useShadowfiend: true, - useMindBlast: true, - useShadowWordDeath: true, armor: Armor.InnerFire, }); @@ -103,7 +100,7 @@ export const DefaultRaidBuffs = RaidBuffs.create({ wrathOfAirTotem: true, sanctifiedRetribution: true, bloodlust: true, - demonicPact: 500, + demonicPactSp: 500, }); export const DefaultIndividualBuffs = IndividualBuffs.create({ diff --git a/ui/warlock/presets.ts b/ui/warlock/presets.ts index e9ca7de51a..ac09cc6229 100644 --- a/ui/warlock/presets.ts +++ b/ui/warlock/presets.ts @@ -158,7 +158,7 @@ export const DefaultRaidBuffs = RaidBuffs.create({ wrathOfAirTotem: true, sanctifiedRetribution: true, bloodlust: true, - demonicPact: 500, + demonicPactSp: 500, }); export const DefaultIndividualBuffs = IndividualBuffs.create({ From d8bd035d651b85eebd9ac48253856abb2852580f Mon Sep 17 00:00:00 2001 From: James Tanner Date: Mon, 15 Jan 2024 08:32:06 -0800 Subject: [PATCH 28/28] Add comment for potential proto refactoring --- proto/api.proto | 3 +++ ui/core/player.ts | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/proto/api.proto b/proto/api.proto index 3b4e9b3e05..21e5536bfc 100644 --- a/proto/api.proto +++ b/proto/api.proto @@ -65,6 +65,9 @@ message Player { APLRotation rotation = 40; + // TODO: Move most of the remaining fields into a 'MiscellaneousPlayerOptions' message. + // This will remove a lot of the boilerplate code in the UI for each new field. + int32 reaction_time_ms = 41; int32 channel_clip_delay_ms = 42; bool in_front_of_target = 23; diff --git a/ui/core/player.ts b/ui/core/player.ts index 7e6fde5a22..b9e1b95c02 100644 --- a/ui/core/player.ts +++ b/ui/core/player.ts @@ -1368,6 +1368,11 @@ export class Player { || includeCategories.length == 0 || includeCategories.includes(cat); + // For backwards compatibility with legacy rotations (removed on 2024/01/15). + if (proto.rotation?.type == APLRotationType.TypeLegacy) { + proto.rotation.type = APLRotationType.TypeAuto; + } + TypedEvent.freezeAllAndDo(() => { if (loadCategory(SimSettingCategories.Gear)) { this.setGear(eventID, proto.equipment ? this.sim.db.lookupEquipmentSpec(proto.equipment) : new Gear({}));