Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix bug where auto and simple rotations would not be registered #4075

Merged
merged 1 commit into from
Dec 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
245 changes: 122 additions & 123 deletions ui/balance_druid/sim.ts
Original file line number Diff line number Diff line change
@@ -1,144 +1,143 @@
import { Spec } from '../core/proto/common.js';
import { Stat } from '../core/proto/common.js';
import {
APLAction,
APLListItem,
APLRotation,
} from '../core/proto/apl.js';
import { Stats } from '../core/proto_utils/stats.js';
import { Player } from '../core/player.js';
import { IndividualSimUI } from '../core/individual_sim_ui.js';
import { IndividualSimUI, registerSpecConfig } from '../core/individual_sim_ui.js';

import * as IconInputs from '../core/components/icon_inputs.js';
import * as OtherInputs from '../core/components/other_inputs.js';

import * as DruidInputs from './inputs.js';
import * as Presets from './presets.js';

// noinspection TypeScriptValidateTypes
export class BalanceDruidSimUI extends IndividualSimUI<Spec.SpecBalanceDruid> {
constructor(parentElem: HTMLElement, player: Player<Spec.SpecBalanceDruid>) {
super(parentElem, player, {
cssClass: 'balance-druid-sim-ui',
cssScheme: 'druid',
// List any known bugs / issues here, and they'll be shown on the site.
knownIssues: [
],
const SPEC_CONFIG = registerSpecConfig(Spec.SpecBalanceDruid, {
cssClass: 'balance-druid-sim-ui',
cssScheme: 'druid',
// List any known bugs / issues here, and they'll be shown on the site.
knownIssues: [
],

// All stats for which EP should be calculated.
epStats: [
Stat.StatIntellect,
Stat.StatSpirit,
Stat.StatSpellPower,
Stat.StatSpellHit,
Stat.StatSpellCrit,
Stat.StatSpellHaste,
Stat.StatMP5,
],
// Reference stat against which to calculate EP. I think all classes use either spell power or attack power.
epReferenceStat: Stat.StatSpellPower,
// Which stats to display in the Character Stats section, at the bottom of the left-hand sidebar.
displayStats: [
Stat.StatHealth,
Stat.StatStamina,
Stat.StatIntellect,
Stat.StatSpirit,
Stat.StatSpellPower,
Stat.StatSpellHit,
Stat.StatSpellCrit,
Stat.StatSpellHaste,
Stat.StatMP5,
],

// All stats for which EP should be calculated.
epStats: [
Stat.StatIntellect,
Stat.StatSpirit,
Stat.StatSpellPower,
Stat.StatSpellHit,
Stat.StatSpellCrit,
Stat.StatSpellHaste,
Stat.StatMP5,
],
// Reference stat against which to calculate EP. I think all classes use either spell power or attack power.
epReferenceStat: Stat.StatSpellPower,
// Which stats to display in the Character Stats section, at the bottom of the left-hand sidebar.
displayStats: [
Stat.StatHealth,
Stat.StatStamina,
Stat.StatIntellect,
Stat.StatSpirit,
Stat.StatSpellPower,
Stat.StatSpellHit,
Stat.StatSpellCrit,
Stat.StatSpellHaste,
Stat.StatMP5,
],
defaults: {
// Default equipped gear.
gear: Presets.P3_PRESET_HORDE.gear,
// Default EP weights for sorting gear in the gear picker.
epWeights: Stats.fromMap({
[Stat.StatIntellect]: 0.43,
[Stat.StatSpirit]: 0.34,
[Stat.StatSpellPower]: 1,
[Stat.StatSpellCrit]: 0.82,
[Stat.StatSpellHaste]: 0.80,
[Stat.StatMP5]: 0.00,
}),
// Default consumes settings.
consumes: Presets.DefaultConsumes,
// Default rotation settings.
rotation: Presets.DefaultRotation,
// Default talents.
talents: Presets.Phase3Talents.data,
// Default spec-specific settings.
specOptions: Presets.DefaultOptions,
// Default raid/party buffs settings.
raidBuffs: Presets.DefaultRaidBuffs,
partyBuffs: Presets.DefaultPartyBuffs,
individualBuffs: Presets.DefaultIndividualBuffs,
debuffs: Presets.DefaultDebuffs,
other: Presets.OtherDefaults,
},

defaults: {
// Default equipped gear.
gear: Presets.P3_PRESET_HORDE.gear,
// Default EP weights for sorting gear in the gear picker.
epWeights: Stats.fromMap({
[Stat.StatIntellect]: 0.43,
[Stat.StatSpirit]: 0.34,
[Stat.StatSpellPower]: 1,
[Stat.StatSpellCrit]: 0.82,
[Stat.StatSpellHaste]: 0.80,
[Stat.StatMP5]: 0.00,
}),
// Default consumes settings.
consumes: Presets.DefaultConsumes,
// Default rotation settings.
rotation: Presets.DefaultRotation,
// Default talents.
talents: Presets.Phase3Talents.data,
// Default spec-specific settings.
specOptions: Presets.DefaultOptions,
// Default raid/party buffs settings.
raidBuffs: Presets.DefaultRaidBuffs,
partyBuffs: Presets.DefaultPartyBuffs,
individualBuffs: Presets.DefaultIndividualBuffs,
debuffs: Presets.DefaultDebuffs,
other: Presets.OtherDefaults,
},
// IconInputs to include in the 'Player' section on the settings tab.
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,
IconInputs.MeleeCritBuff,
IconInputs.AttackPowerPercentBuff,
IconInputs.AttackPowerBuff,
IconInputs.MajorArmorDebuff,
IconInputs.MinorArmorDebuff,
IconInputs.PhysicalDamageDebuff,
],
excludeBuffDebuffInputs: [
],
// Inputs to include in the 'Other' section on the settings tab.
otherInputs: {
inputs: [
DruidInputs.OkfUptime,
OtherInputs.TankAssignment,
OtherInputs.ReactionTime,
OtherInputs.DistanceFromTarget,
OtherInputs.nibelungAverageCasts,
],
},
encounterPicker: {
// Whether to include 'Execute Duration (%)' in the 'Encounter' section of the settings tab.
showExecuteProportion: false,
},

// IconInputs to include in the 'Player' section on the settings tab.
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,
IconInputs.MeleeCritBuff,
IconInputs.AttackPowerPercentBuff,
IconInputs.AttackPowerBuff,
IconInputs.MajorArmorDebuff,
IconInputs.MinorArmorDebuff,
IconInputs.PhysicalDamageDebuff,
],
excludeBuffDebuffInputs: [
],
// Inputs to include in the 'Other' section on the settings tab.
otherInputs: {
inputs: [
DruidInputs.OkfUptime,
OtherInputs.TankAssignment,
OtherInputs.ReactionTime,
OtherInputs.DistanceFromTarget,
OtherInputs.nibelungAverageCasts,
],
},
encounterPicker: {
// Whether to include 'Execute Duration (%)' in the 'Encounter' section of the settings tab.
showExecuteProportion: false,
},
presets: {
// Preset talents that the user can quickly select.
talents: [
Presets.Phase1Talents,
Presets.Phase2Talents,
Presets.Phase3Talents,
Presets.Phase4Talents,
],
rotations: [
Presets.ROTATION_PRESET_P3_APL,
Presets.ROTATION_PRESET_P4_FOCUS_APL,
Presets.ROTATION_PRESET_P4_STARFIRE_APL,
],
// Preset gear configurations that the user can quickly select.
gear: [
Presets.PRERAID_PRESET,
Presets.P1_PRESET,
Presets.P2_PRESET,
Presets.P3_PRESET_HORDE,
Presets.P3_PRESET_ALLI,
Presets.P4_PRESET_HORDE,
Presets.P4_PRESET_ALLI,
],
},

presets: {
// Preset talents that the user can quickly select.
talents: [
Presets.Phase1Talents,
Presets.Phase2Talents,
Presets.Phase3Talents,
Presets.Phase4Talents,
],
rotations: [
Presets.ROTATION_PRESET_P3_APL,
Presets.ROTATION_PRESET_P4_FOCUS_APL,
Presets.ROTATION_PRESET_P4_STARFIRE_APL,
],
// Preset gear configurations that the user can quickly select.
gear: [
Presets.PRERAID_PRESET,
Presets.P1_PRESET,
Presets.P2_PRESET,
Presets.P3_PRESET_HORDE,
Presets.P3_PRESET_ALLI,
Presets.P4_PRESET_HORDE,
Presets.P4_PRESET_ALLI,
],
},
autoRotation: (_player: Player<Spec.SpecBalanceDruid>): APLRotation => {
return Presets.ROTATION_PRESET_P3_APL.rotation.rotation!;
},
});

autoRotation: (player: Player<Spec.SpecBalanceDruid>): APLRotation => {
return Presets.ROTATION_PRESET_P3_APL.rotation.rotation!;
},
});
export class BalanceDruidSimUI extends IndividualSimUI<Spec.SpecBalanceDruid> {
constructor(parentElem: HTMLElement, player: Player<Spec.SpecBalanceDruid>) {
super(parentElem, player, SPEC_CONFIG);
}
}
17 changes: 7 additions & 10 deletions ui/core/individual_sim_ui.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { aplLaunchStatuses, LaunchStatus, simLaunchStatuses } from './launched_sims';
import { Player, AutoRotationGenerator, SimpleRotationGenerator } from './player';
import { Player, PlayerConfig, registerSpecConfig as registerPlayerConfig } from './player';
import { SimUI, SimWarning } from './sim_ui';
import { EventID, TypedEvent } from './typed_event';

Expand Down Expand Up @@ -88,7 +88,7 @@ export interface OtherDefaults {
nibelungAverageCasts?: number,
}

export interface IndividualSimUIConfig<SpecType extends Spec> {
export interface IndividualSimUIConfig<SpecType extends Spec> extends PlayerConfig<SpecType> {
// Additional css class to add to the root element.
cssClass: string,
// Used to generate schemed components. E.g. 'shaman', 'druid', 'raid'
Expand Down Expand Up @@ -137,11 +137,13 @@ export interface IndividualSimUIConfig<SpecType extends Spec> {
presets: {
gear: Array<PresetGear>,
talents: Array<SavedDataConfig<Player<any>, SavedTalents>>,
rotations?: Array<PresetRotation>,
rotations: Array<PresetRotation>,
},
}

autoRotation: AutoRotationGenerator<SpecType>,
simpleRotation?: SimpleRotationGenerator<SpecType>,
export function registerSpecConfig<SpecType extends Spec>(spec: SpecType, config: IndividualSimUIConfig<SpecType>): IndividualSimUIConfig<SpecType> {
registerPlayerConfig(spec, config);
return config;
}

export interface Settings {
Expand Down Expand Up @@ -184,11 +186,6 @@ export abstract class IndividualSimUI<SpecType extends Spec> extends SimUI {
this.prevEpIterations = 0;
this.prevEpSimResult = null;

player.setAutoRotationGenerator(config.autoRotation);
if (aplLaunchStatuses[player.spec] == LaunchStatus.Launched && config.simpleRotation) {
player.setSimpleRotationGenerator(config.simpleRotation);
}

this.addWarning({
updateOn: this.player.gearChangeEmitter,
getContent: () => {
Expand Down
34 changes: 24 additions & 10 deletions ui/core/player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,17 @@ export interface MeleeCritCapInfo {
export type AutoRotationGenerator<SpecType extends Spec> = (player: Player<SpecType>) => APLRotation;
export type SimpleRotationGenerator<SpecType extends Spec> = (player: Player<SpecType>, simpleRotation: SpecRotation<SpecType>, cooldowns: Cooldowns) => APLRotation;

export interface PlayerConfig<SpecType extends Spec> {
autoRotation: AutoRotationGenerator<SpecType>,
simpleRotation?: SimpleRotationGenerator<SpecType>,
}

const SPEC_CONFIGS: Partial<Record<Spec, PlayerConfig<any>>> = {};

export function registerSpecConfig(spec: Spec, config: PlayerConfig<any>) {
SPEC_CONFIGS[spec] = config;
}

// Manages all the gear / consumes / other settings for a single Player.
export class Player<SpecType extends Spec> {
readonly sim: Sim;
Expand Down Expand Up @@ -241,8 +252,8 @@ export class Player<SpecType extends Spec> {
private healingModel: HealingModel = HealingModel.create();
private healingEnabled: boolean = false;

private autoRotationGenerator: AutoRotationGenerator<SpecType> | null = null;
private simpleRotationGenerator: SimpleRotationGenerator<SpecType> | null = null;
private readonly autoRotationGenerator: AutoRotationGenerator<SpecType> | null = null;
private readonly simpleRotationGenerator: SimpleRotationGenerator<SpecType> | null = null;

private itemEPCache = new Array<Map<number, number>>();
private gemEPCache = new Map<number, number>();
Expand Down Expand Up @@ -294,6 +305,17 @@ export class Player<SpecType extends Spec> {
this.rotation = this.specTypeFunctions.rotationCreate();
this.specOptions = this.specTypeFunctions.optionsCreate();

const specConfig = SPEC_CONFIGS[this.spec] as PlayerConfig<SpecType>;
if (!specConfig) {
throw new Error('Could not find spec config for spec: ' + this.spec);
}
this.autoRotationGenerator = specConfig.autoRotation;
if (aplLaunchStatuses[this.spec] == LaunchStatus.Launched && specConfig.simpleRotation) {
this.simpleRotationGenerator = specConfig.simpleRotation;
} else {
this.simpleRotationGenerator = null;
}

for(let i = 0; i < ItemSlot.ItemSlotRanged+1; ++i) {
this.itemEPCache[i] = new Map();
}
Expand Down Expand Up @@ -789,14 +811,6 @@ export class Player<SpecType extends Spec> {
}
}

setAutoRotationGenerator(generator: AutoRotationGenerator<SpecType>) {
this.autoRotationGenerator = generator;
}

setSimpleRotationGenerator(generator: SimpleRotationGenerator<SpecType>) {
this.simpleRotationGenerator = generator;
}

hasSimpleRotationGenerator(): boolean {
return this.simpleRotationGenerator != null;
}
Expand Down
Loading
Loading