diff --git a/proto/api.proto b/proto/api.proto index c77049cef..5d994e1e8 100644 --- a/proto/api.proto +++ b/proto/api.proto @@ -122,6 +122,7 @@ message SimOptions { bool save_all_values = 7; // Only used internally. bool interactive = 8; // Enables interactive mode. bool use_labeled_rands = 9; // Use test level RNG. + bool use_aq_spell_ranks = 10; } // The aggregated results from all uses of a particular action. diff --git a/proto/ui.proto b/proto/ui.proto index 72f84e00d..03de398ac 100644 --- a/proto/ui.proto +++ b/proto/ui.proto @@ -282,6 +282,8 @@ message SimSettings { string language = 9; Faction faction = 6; DatabaseFilters filters = 10; + bool use_aq_spell_ranks = 12; + } // Contains all information that is imported/exported from an individual sim. diff --git a/sim/core/buffs.go b/sim/core/buffs.go index 63223c35f..b28359d02 100644 --- a/sim/core/buffs.go +++ b/sim/core/buffs.go @@ -61,19 +61,6 @@ var BuffSpellValues = map[BuffName]stats.Stats{ AspectOfTheWild: { stats.NatureResistance: 60, }, - BattleShout: { - stats.AttackPower: TernaryFloat64(IncludeAQ, 232, 193), - }, - BlessingOfMight: { - stats.AttackPower: TernaryFloat64(IncludeAQ, 185, 155), - }, - BlessingOfWisdom: { - stats.MP5: TernaryFloat64(IncludeAQ, 33, 30), - }, - HornOfLordaeron: { - stats.Strength: TernaryFloat64(IncludeAQ, 89, 70.15), - stats.Agility: TernaryFloat64(IncludeAQ, 89, 70.15), - }, BloodPact: { stats.Stamina: 42, }, @@ -83,9 +70,6 @@ var BuffSpellValues = map[BuffName]stats.Stats{ DevotionAura: { stats.BonusArmor: 735, }, - GraceOfAir: { - stats.Agility: TernaryFloat64(IncludeAQ, 77, 67), - }, FireResistanceAura: { stats.FireResistance: 60, }, @@ -126,9 +110,6 @@ var BuffSpellValues = map[BuffName]stats.Stats{ ShadowResistanceAura: { stats.ShadowResistance: 60, }, - StrengthOfEarth: { - stats.Strength: TernaryFloat64(IncludeAQ, 77, 61), - }, ScrollOfAgility: { stats.Agility: 17, }, @@ -379,11 +360,7 @@ func applyBuffEffects(agent Agent, playerFaction proto.Faction, raidBuffs *proto } if individualBuffs.BlessingOfWisdom > 0 && isAlliance { - updateStats := BuffSpellValues[BlessingOfWisdom] - if individualBuffs.BlessingOfWisdom == proto.TristateEffect_TristateEffectImproved { - updateStats = updateStats.Multiply(1.2) - } - character.AddStats(updateStats) + MakePermanent(BlessingOfWisdomAura(&character.Unit, GetTristateValueInt32(individualBuffs.BlessingOfWisdom, 0, 2))) } else if raidBuffs.ManaSpringTotem > 0 && isHorde { updateStats := BuffSpellValues[ManaSpring] if raidBuffs.ManaSpringTotem == proto.TristateEffect_TristateEffectImproved { @@ -1334,11 +1311,14 @@ const ReplenishmentAuraDuration = time.Second * 15 }) } */ +const StrengthOfEarthTotemRanks = 5 +var StrengthOfEarthTotemSpellId = [StrengthOfEarthTotemRanks + 1]int32{0, 8075, 8160, 8161, 10442, 25361} +var StrengthOfEarthStrength = [StrengthOfEarthTotemRanks + 1]float64{0, 10, 20, 36, 61, 77} + func StrengthOfEarthTotemAura(unit *Unit, multiplier float64) *Aura { - rank := TernaryInt32(IncludeAQ, 5, 4) - spellID := []int32{0, 8075, 8160, 8161, 10442, 25361}[rank] + spellID := TernaryInt32(unit.Env.UseAQSpellRanks, 25361, 10442) duration := time.Minute * 2 - updateStats := BuffSpellValues[StrengthOfEarth].Multiply(multiplier).Floor() + bonusStrength := math.Floor(TernaryFloat64(unit.Env.UseAQSpellRanks, 77, 61) * multiplier) aura := unit.GetOrRegisterAura(Aura{ Label: "Strength of Earth Totem", @@ -1347,27 +1327,30 @@ func StrengthOfEarthTotemAura(unit *Unit, multiplier float64) *Aura { BuildPhase: CharacterBuildPhaseBuffs, OnGain: func(aura *Aura, sim *Simulation) { if aura.Unit.Env.MeasuringStats && aura.Unit.Env.State != Finalized { - unit.AddStats(updateStats) + unit.AddStat(stats.Strength, bonusStrength) } else { - unit.AddStatsDynamic(sim, updateStats) + unit.AddStatDynamic(sim, stats.Strength, bonusStrength) } }, OnExpire: func(aura *Aura, sim *Simulation) { if aura.Unit.Env.MeasuringStats && aura.Unit.Env.State != Finalized { - unit.AddStats(updateStats.Multiply(-1)) + unit.AddStat(stats.Strength, -bonusStrength) } else { - unit.AddStatsDynamic(sim, updateStats.Multiply(-1)) + unit.AddStatDynamic(sim, stats.Strength, -bonusStrength) } }, }) return aura } +const GraceOfAirTotemRanks = 3 +var GraceOfAirTotemSpellId = [GraceOfAirTotemRanks + 1]int32{0, 8835, 10627, 25359} +var GraceOfAirTotemAgility = [GraceOfAirTotemRanks + 1]float64{0, 43, 67, 77} + func GraceOfAirTotemAura(unit *Unit, multiplier float64) *Aura { - rank := TernaryInt32(IncludeAQ, 3, 2) - spellID := []int32{0, 8835, 10627, 25359}[rank] duration := time.Minute * 2 - updateStats := BuffSpellValues[GraceOfAir].Multiply(multiplier).Floor() + bonusAgi := math.Floor(TernaryFloat64(unit.Env.UseAQSpellRanks, 77, 67) * multiplier) + spellID := TernaryInt32(unit.Env.UseAQSpellRanks, 25359, 10627) aura := unit.GetOrRegisterAura(Aura{ Label: "Grace of Air Totem", @@ -1376,16 +1359,16 @@ func GraceOfAirTotemAura(unit *Unit, multiplier float64) *Aura { BuildPhase: CharacterBuildPhaseBuffs, OnGain: func(aura *Aura, sim *Simulation) { if aura.Unit.Env.MeasuringStats && aura.Unit.Env.State != Finalized { - unit.AddStats(updateStats) + unit.AddStat(stats.Agility, bonusAgi) } else { - unit.AddStatsDynamic(sim, updateStats) + unit.AddStatDynamic(sim, stats.Agility, bonusAgi) } }, OnExpire: func(aura *Aura, sim *Simulation) { if aura.Unit.Env.MeasuringStats && aura.Unit.Env.State != Finalized { - unit.AddStats(updateStats.Multiply(-1)) + unit.AddStat(stats.Agility, -bonusAgi) } else { - unit.AddStatsDynamic(sim, updateStats.Multiply(-1)) + unit.AddStatDynamic(sim, stats.Agility, -bonusAgi) } }, }) @@ -1399,9 +1382,9 @@ var BattleShoutBaseAP = [BattleShoutRanks + 1]float64{0, 20, 40, 57, 93, 138, 19 var BattleShoutLevel = [BattleShoutRanks + 1]int{0, 1, 12, 22, 32, 42, 52, 60} func BattleShoutAura(unit *Unit, impBattleShout int32, boomingVoicePts int32) *Aura { - rank := TernaryInt32(IncludeAQ, 7, 6) + rank := TernaryInt32(unit.Env.UseAQSpellRanks, 7, 6) spellId := BattleShoutSpellId[rank] - baseAP := BattleShoutBaseAP[rank] + bshoutAP := math.Floor(BattleShoutBaseAP[rank] * (1 + 0.05*float64(impBattleShout))) return unit.GetOrRegisterAura(Aura{ Label: "Battle Shout", @@ -1409,14 +1392,18 @@ func BattleShoutAura(unit *Unit, impBattleShout int32, boomingVoicePts int32) *A Duration: time.Duration(float64(time.Minute*2) * (1 + 0.1*float64(boomingVoicePts))), BuildPhase: CharacterBuildPhaseBuffs, OnGain: func(aura *Aura, sim *Simulation) { - aura.Unit.AddStatsDynamic(sim, stats.Stats{ - stats.AttackPower: math.Floor(baseAP * (1 + 0.05*float64(impBattleShout))), - }) + if aura.Unit.Env.MeasuringStats && aura.Unit.Env.State != Finalized { + aura.Unit.AddStat(stats.AttackPower, bshoutAP) + } else { + aura.Unit.AddStatDynamic(sim, stats.AttackPower, bshoutAP) + } }, OnExpire: func(aura *Aura, sim *Simulation) { - aura.Unit.AddStatsDynamic(sim, stats.Stats{ - stats.AttackPower: -1 * math.Floor(baseAP*(1+0.05*float64(impBattleShout))), - }) + if aura.Unit.Env.MeasuringStats && aura.Unit.Env.State != Finalized { + aura.Unit.AddStat(stats.AttackPower, -bshoutAP) + } else { + aura.Unit.AddStatDynamic(sim, stats.AttackPower, -bshoutAP) + } }, }) } @@ -1442,9 +1429,9 @@ func TrueshotAura(unit *Unit) *Aura { } func BlessingOfMightAura(unit *Unit, impBomPts int32) *Aura { - spellID := TernaryInt32(IncludeAQ, 25291, 19838) + spellID := TernaryInt32(unit.Env.UseAQSpellRanks, 25291, 19838) - bonusAP := math.Floor(BuffSpellValues[BlessingOfMight][stats.AttackPower] * (1 + 0.04*float64(impBomPts))) + bonusAP := math.Floor(TernaryFloat64(unit.Env.UseAQSpellRanks, 185, 155) * (1 + 0.04*float64(impBomPts))) aura := MakePermanent(unit.GetOrRegisterAura(Aura{ Label: "Blessing of Might", @@ -1463,6 +1450,35 @@ func BlessingOfMightAura(unit *Unit, impBomPts int32) *Aura { return aura } +func BlessingOfWisdomAura(unit *Unit, impBowPts int32) *Aura { + spellID := TernaryInt32(unit.Env.UseAQSpellRanks, 25290, 19854) + + bonusMP5 := math.Floor(TernaryFloat64(unit.Env.UseAQSpellRanks, 33, 30) * (1 + 0.10*float64(impBowPts))) + + aura := MakePermanent(unit.GetOrRegisterAura(Aura{ + Label: "Blessing of Wisdom", + ActionID: ActionID{SpellID: spellID}, + Duration: NeverExpires, + BuildPhase: CharacterBuildPhaseBuffs, + OnGain: func(aura *Aura, sim *Simulation) { + if aura.Unit.Env.MeasuringStats && aura.Unit.Env.State != Finalized { + aura.Unit.AddStat(stats.MP5, bonusMP5) + } else { + aura.Unit.AddStatDynamic(sim, stats.MP5, bonusMP5) + } + }, + OnExpire: func(aura *Aura, sim *Simulation) { + if aura.Unit.Env.MeasuringStats && aura.Unit.Env.State != Finalized { + aura.Unit.AddStat(stats.MP5, -bonusMP5) + } else { + aura.Unit.AddStatDynamic(sim, stats.MP5, -bonusMP5) + } + }, + })) + + return aura +} + // TODO: Are there exclusive AP buffs in SoD? // func attackPowerBonusEffect(aura *Aura, apBonus float64) *ExclusiveEffect { // return aura.NewExclusiveEffect("AttackPowerBonus", false, ExclusiveEffect{ diff --git a/sim/core/config.go b/sim/core/config.go deleted file mode 100644 index 94c51ebe7..000000000 --- a/sim/core/config.go +++ /dev/null @@ -1,7 +0,0 @@ -package core - -// Global configuration settings - -// Whether to include spell ranks only accessible after the release of Ahn'Qiraj -// TODO: add phase switch instead of hardcoded const later? -const IncludeAQ = true diff --git a/sim/core/environment.go b/sim/core/environment.go index 3d31cc521..758f0c339 100644 --- a/sim/core/environment.go +++ b/sim/core/environment.go @@ -32,6 +32,7 @@ type Environment struct { // Whether stats are currently being measured. Used to disable some validation // checks which are otherwise helpful. MeasuringStats bool + UseAQSpellRanks bool Raid *Raid Encounter Encounter diff --git a/sim/core/sim.go b/sim/core/sim.go index a2be0989f..e23ecfb0a 100644 --- a/sim/core/sim.go +++ b/sim/core/sim.go @@ -184,6 +184,7 @@ func runSim(rsr *proto.RaidSimRequest, progress chan *proto.ProgressMetrics, ski func NewSim(rsr *proto.RaidSimRequest, signals simsignals.Signals) *Simulation { env, _, _ := NewEnvironment(rsr.Raid, rsr.Encounter, false) + env.UseAQSpellRanks = rsr.SimOptions.UseAqSpellRanks return newSimWithEnv(env, rsr.SimOptions, signals) } diff --git a/sim/druid/starfire.go b/sim/druid/starfire.go index 6b511f7ee..937726e98 100644 --- a/sim/druid/starfire.go +++ b/sim/druid/starfire.go @@ -16,7 +16,11 @@ var StarfireLevel = [StarfireRanks + 1]int{0, 20, 26, 34, 42, 50, 58, 60} func (druid *Druid) registerStarfireSpell() { druid.Starfire = make([]*DruidSpell, StarfireRanks+1) - maxRank := core.TernaryInt(core.IncludeAQ, StarfireRanks, StarfireRanks-1) + maxRank := StarfireRanks + if !druid.Env.UseAQSpellRanks { + maxRank -= 1 + } + for rank := 1; rank <= maxRank; rank++ { config := druid.newStarfireSpellConfig(rank) diff --git a/sim/hunter/aspects.go b/sim/hunter/aspects.go index 04fe22b10..25d6b7e4c 100644 --- a/sim/hunter/aspects.go +++ b/sim/hunter/aspects.go @@ -44,7 +44,10 @@ func (hunter *Hunter) getMaxAspectOfTheHawkAttackPower(rank int) float64 { } func (hunter *Hunter) getMaxHawkRank() int { - maxRank := core.TernaryInt(core.IncludeAQ, 7, 6) + maxRank := 7 + if !hunter.Env.UseAQSpellRanks { + maxRank -= 1 + } for i := maxRank; i > 0; i-- { config := hunter.getAspectOfTheHawkSpellConfig(i) diff --git a/sim/hunter/multi_shot.go b/sim/hunter/multi_shot.go index a3a62a2ae..d739ca9a6 100644 --- a/sim/hunter/multi_shot.go +++ b/sim/hunter/multi_shot.go @@ -101,7 +101,10 @@ func (hunter *Hunter) getMultiShotConfig(rank int, timer *core.Timer) core.Spell } func (hunter *Hunter) registerMultiShotSpell(timer *core.Timer) { - maxRank := core.TernaryInt(core.IncludeAQ, 5, 4) + maxRank := 5 + if !hunter.Env.UseAQSpellRanks { + maxRank -= 1 + } for rank := 1; rank <= maxRank; rank++ { config := hunter.getMultiShotConfig(rank, timer) diff --git a/sim/hunter/serpent_sting.go b/sim/hunter/serpent_sting.go index f2034b34c..f824ac6f2 100644 --- a/sim/hunter/serpent_sting.go +++ b/sim/hunter/serpent_sting.go @@ -112,7 +112,10 @@ func (hunter *Hunter) chimeraShotSerpentStingSpell(rank int) *core.Spell { func (hunter *Hunter) registerSerpentStingSpell() { hunter.SerpentStingAPCoeff = 0 - maxRank := core.TernaryInt(core.IncludeAQ, 9, 8) + maxRank := 9 + if !hunter.Env.UseAQSpellRanks { + maxRank -= 1 + } for rank := maxRank; rank >= 0; rank-- { config := hunter.getSerpentStingConfig(rank) diff --git a/sim/mage/arcane_missiles.go b/sim/mage/arcane_missiles.go index 9e97f5f50..94ef989d2 100644 --- a/sim/mage/arcane_missiles.go +++ b/sim/mage/arcane_missiles.go @@ -20,7 +20,11 @@ func (mage *Mage) registerArcaneMissilesSpell() { mage.ArcaneMissiles = make([]*core.Spell, ArcaneMissilesRanks+1) mage.ArcaneMissilesTickSpell = make([]*core.Spell, ArcaneMissilesRanks+1) - // TODO AQ <= + maxRank := ArcaneMissilesRanks + if !mage.Env.UseAQSpellRanks { + maxRank -= 1 + } + for rank := 1; rank < ArcaneMissilesRanks; rank++ { config := mage.getArcaneMissilesSpellConfig(rank) diff --git a/sim/mage/fireball.go b/sim/mage/fireball.go index 42ef8da50..618c8228f 100644 --- a/sim/mage/fireball.go +++ b/sim/mage/fireball.go @@ -20,7 +20,10 @@ var FireballLevel = [FireballRanks + 1]int{0, 1, 6, 12, 18, 24, 30, 36, 42, 48, func (mage *Mage) registerFireballSpell() { mage.Fireball = make([]*core.Spell, FireballRanks+1) - maxRank := core.TernaryInt(core.IncludeAQ, FireballRanks, FireballRanks-1) + maxRank := FireballRanks + if !mage.Env.UseAQSpellRanks { + maxRank -= 1 + } for rank := 1; rank <= maxRank; rank++ { config := mage.newFireballSpellConfig(rank) diff --git a/sim/mage/frostbolt.go b/sim/mage/frostbolt.go index aaf898c5b..8ad580006 100644 --- a/sim/mage/frostbolt.go +++ b/sim/mage/frostbolt.go @@ -18,7 +18,10 @@ var FrostboltLevel = [FrostboltRanks + 1]int{0, 4, 8, 14, 20, 26, 32, 38, 44, 50 func (mage *Mage) registerFrostboltSpell() { mage.Frostbolt = make([]*core.Spell, FrostboltRanks+1) - maxRank := core.TernaryInt(core.IncludeAQ, FrostboltRanks, FrostboltRanks-1) + maxRank := FrostboltRanks + if !mage.Env.UseAQSpellRanks { + maxRank -= 1 + } for rank := 1; rank <= maxRank; rank++ { config := mage.getFrostboltConfig(rank) diff --git a/sim/rogue/backstab.go b/sim/rogue/backstab.go index f2258c6df..5ab8d786b 100644 --- a/sim/rogue/backstab.go +++ b/sim/rogue/backstab.go @@ -11,14 +11,14 @@ func (rogue *Rogue) registerBackstabSpell() { 25: 32, 40: 60, 50: 90, - 60: core.TernaryFloat64(core.IncludeAQ, 150, 140), + 60: core.TernaryFloat64(rogue.Env.UseAQSpellRanks, 210, 225), }[rogue.Level] spellID := map[int32]int32{ 25: 2590, 40: 8721, 50: 11279, - 60: core.TernaryInt32(core.IncludeAQ, 25300, 11281), + 60: core.TernaryInt32(rogue.Env.UseAQSpellRanks, 25300, 11281), }[rogue.Level] damageMultiplier := 1.5 * []float64{1, 1.04, 1.08, 1.12, 1.16, 1.2}[rogue.Talents.Opportunity] diff --git a/sim/rogue/poisons.go b/sim/rogue/poisons.go index 43a2b930e..f2b967f5f 100644 --- a/sim/rogue/poisons.go +++ b/sim/rogue/poisons.go @@ -152,13 +152,13 @@ func (rogue *Rogue) registerDeadlyPoisonSpell() { 25: 9, 40: 13, 50: 20, - 60: 27, + 60: core.TernaryFloat64(rogue.Env.UseAQSpellRanks, 34, 27), }[rogue.Level] spellID := map[int32]int32{ 25: 2823, 40: 2824, 50: 11355, - 60: 11356, + 60: core.TernaryInt32(rogue.Env.UseAQSpellRanks, 25351, 11356), }[rogue.Level] rogue.deadlyPoisonTick = rogue.RegisterSpell(core.SpellConfig{ diff --git a/sim/shaman/air_totems.go b/sim/shaman/air_totems.go index 46755f28a..7db483d18 100644 --- a/sim/shaman/air_totems.go +++ b/sim/shaman/air_totems.go @@ -50,16 +50,13 @@ func (shaman *Shaman) newWindfuryTotemSpellConfig(rank int) core.SpellConfig { return spell } -const GraceOfAirTotemRanks = 3 - -var GraceOfAirTotemSpellId = [GraceOfAirTotemRanks + 1]int32{0, 8835, 10627, 25359} -var GraceOfAirTotemManaCost = [GraceOfAirTotemRanks + 1]float64{0, 155, 250, 310} -var GraceOfAirTotemLevel = [GraceOfAirTotemRanks + 1]int{0, 42, 56, 60} +var GraceOfAirTotemManaCost = [core.GraceOfAirTotemRanks + 1]float64{0, 155, 250, 310} +var GraceOfAirTotemLevel = [core.GraceOfAirTotemRanks + 1]int{0, 42, 56, 60} func (shaman *Shaman) registerGraceOfAirTotemSpell() { - shaman.GraceOfAirTotem = make([]*core.Spell, GraceOfAirTotemRanks+1) + shaman.GraceOfAirTotem = make([]*core.Spell, core.GraceOfAirTotemRanks+1) - for rank := 1; rank <= GraceOfAirTotemRanks; rank++ { + for rank := 1; rank <= core.GraceOfAirTotemRanks; rank++ { config := shaman.newGraceOfAirTotemSpellConfig(rank) if config.RequiredLevel <= int(shaman.Level) { @@ -74,7 +71,7 @@ func (shaman *Shaman) registerGraceOfAirTotemSpell() { } func (shaman *Shaman) newGraceOfAirTotemSpellConfig(rank int) core.SpellConfig { - spellId := GraceOfAirTotemSpellId[rank] + spellId := core.GraceOfAirTotemSpellId[rank] manaCost := GraceOfAirTotemManaCost[rank] level := GraceOfAirTotemLevel[rank] diff --git a/sim/shaman/earth_totems.go b/sim/shaman/earth_totems.go index 4dc02577d..6edd10c16 100644 --- a/sim/shaman/earth_totems.go +++ b/sim/shaman/earth_totems.go @@ -7,16 +7,13 @@ import ( "github.com/wowsims/classic/sim/core/proto" ) -const StrengthOfEarthTotemRanks = 5 - -var StrengthOfEarthTotemSpellId = [StrengthOfEarthTotemRanks + 1]int32{0, 8075, 8160, 8161, 10442, 25361} -var StrengthOfEarthTotemManaCost = [StrengthOfEarthTotemRanks + 1]float64{0, 25, 65, 125, 225, 275} -var StrengthOfEarthTotemLevel = [StrengthOfEarthTotemRanks + 1]int{0, 10, 24, 38, 52, 60} +var StrengthOfEarthTotemManaCost = [core.StrengthOfEarthTotemRanks + 1]float64{0, 25, 65, 125, 225, 275} +var StrengthOfEarthTotemLevel = [core.StrengthOfEarthTotemRanks + 1]int{0, 10, 24, 38, 52, 60} func (shaman *Shaman) registerStrengthOfEarthTotemSpell() { - shaman.StrengthOfEarthTotem = make([]*core.Spell, StrengthOfEarthTotemRanks+1) + shaman.StrengthOfEarthTotem = make([]*core.Spell, core.StrengthOfEarthTotemRanks+1) - for rank := 1; rank <= StrengthOfEarthTotemRanks; rank++ { + for rank := 1; rank <= core.StrengthOfEarthTotemRanks; rank++ { config := shaman.newStrengthOfEarthTotemSpellConfig(rank) if config.RequiredLevel <= int(shaman.Level) { @@ -31,7 +28,7 @@ func (shaman *Shaman) registerStrengthOfEarthTotemSpell() { } func (shaman *Shaman) newStrengthOfEarthTotemSpellConfig(rank int) core.SpellConfig { - spellId := StrengthOfEarthTotemSpellId[rank] + spellId := core.StrengthOfEarthTotemSpellId[rank] manaCost := StrengthOfEarthTotemManaCost[rank] level := StrengthOfEarthTotemLevel[rank] diff --git a/sim/shaman/flame_shock.go b/sim/shaman/flame_shock.go index 67b393f9c..43aeee360 100644 --- a/sim/shaman/flame_shock.go +++ b/sim/shaman/flame_shock.go @@ -20,8 +20,12 @@ var FlameShockLevel = [FlameShockRanks + 1]int{0, 10, 18, 28, 40, 52, 60} func (shaman *Shaman) registerFlameShockSpell(shockTimer *core.Timer) { shaman.FlameShock = make([]*core.Spell, FlameShockRanks+1) + maxRank := FlameShockRanks + if !shaman.Env.UseAQSpellRanks { + maxRank -= 1 + } - for rank := 1; rank <= FlameShockRanks; rank++ { + for rank := 1; rank <= maxRank; rank++ { if FlameShockLevel[rank] <= int(shaman.Level) { shaman.FlameShock[rank] = shaman.RegisterSpell(shaman.newFlameShockSpell(rank, shockTimer)) } diff --git a/sim/warlock/corruption.go b/sim/warlock/corruption.go index cb6f21d06..7152f5b60 100644 --- a/sim/warlock/corruption.go +++ b/sim/warlock/corruption.go @@ -84,7 +84,10 @@ func (warlock *Warlock) getCorruptionConfig(rank int) core.SpellConfig { func (warlock *Warlock) registerCorruptionSpell() { warlock.Corruption = make([]*core.Spell, 0) - maxRank := core.TernaryInt(core.IncludeAQ, CorruptionRanks, CorruptionRanks-1) + maxRank := CorruptionRanks + if !warlock.Env.UseAQSpellRanks { + maxRank -= 1 + } for rank := 1; rank <= maxRank; rank++ { config := warlock.getCorruptionConfig(rank) diff --git a/sim/warlock/immolate.go b/sim/warlock/immolate.go index 971c22b65..d4aa663d4 100644 --- a/sim/warlock/immolate.go +++ b/sim/warlock/immolate.go @@ -106,7 +106,10 @@ func (warlock *Warlock) getActiveImmolateSpell(target *core.Unit) *core.Spell { func (warlock *Warlock) registerImmolateSpell() { warlock.Immolate = make([]*core.Spell, 0) - maxRank := core.TernaryInt(core.IncludeAQ, ImmolateRanks, ImmolateRanks-1) + maxRank := ImmolateRanks + if !warlock.Env.UseAQSpellRanks { + maxRank -= 1 + } for rank := 1; rank <= maxRank; rank++ { config := warlock.getImmolateConfig(rank) diff --git a/sim/warlock/shadowbolt.go b/sim/warlock/shadowbolt.go index c8f6d2cb8..e8a324ebe 100644 --- a/sim/warlock/shadowbolt.go +++ b/sim/warlock/shadowbolt.go @@ -81,7 +81,10 @@ func (warlock *Warlock) getShadowBoltBaseConfig(rank int) core.SpellConfig { func (warlock *Warlock) registerShadowBoltSpell() { warlock.ShadowBolt = make([]*core.Spell, 0) - maxRank := core.TernaryInt(core.IncludeAQ, ShadowBoltRanks, ShadowBoltRanks-1) + maxRank := ShadowBoltRanks + if !warlock.Env.UseAQSpellRanks { + maxRank -= 1 + } for rank := 1; rank <= maxRank; rank++ { config := warlock.getShadowBoltBaseConfig(rank) diff --git a/sim/warrior/heroic_strike_cleave.go b/sim/warrior/heroic_strike_cleave.go index 1d23cb9b4..86febd5fe 100644 --- a/sim/warrior/heroic_strike_cleave.go +++ b/sim/warrior/heroic_strike_cleave.go @@ -9,14 +9,14 @@ func (warrior *Warrior) registerHeroicStrikeSpell(realismICD *core.Cooldown) { 25: 44, 40: 80, 50: 111, - 60: core.TernaryFloat64(core.IncludeAQ, 157, 138), + 60: core.TernaryFloat64(warrior.Env.UseAQSpellRanks, 157, 138), }[warrior.Level] spellID := map[int32]int32{ 25: 1608, 40: 11565, 50: 11566, - 60: core.TernaryInt32(core.IncludeAQ, 25286, 11567), + 60: core.TernaryInt32(warrior.Env.UseAQSpellRanks, 25286, 11567), }[warrior.Level] // No known equation @@ -24,7 +24,7 @@ func (warrior *Warrior) registerHeroicStrikeSpell(realismICD *core.Cooldown) { 25: 68, //guess 40: 103, //guess 50: 120, - 60: core.TernaryFloat64(core.IncludeAQ, 173, 145), + 60: core.TernaryFloat64(warrior.Env.UseAQSpellRanks, 173, 145), }[warrior.Level] warrior.HeroicStrike = warrior.RegisterSpell(AnyStance, core.SpellConfig{ diff --git a/sim/warrior/revenge.go b/sim/warrior/revenge.go index 1209a83ca..f02d9033f 100644 --- a/sim/warrior/revenge.go +++ b/sim/warrior/revenge.go @@ -17,7 +17,7 @@ func (warrior *Warrior) registerRevengeSpell(cdTimer *core.Timer) { 25: 2, 40: 3, 50: 4, - 60: core.TernaryInt(core.IncludeAQ, 6, 5), + 60: core.TernaryInt(warrior.Env.UseAQSpellRanks, 6, 5), }[warrior.Level] actionID := core.ActionID{SpellID: RevengeSpellId[rank]} basedamageLow := RevengeBaseDamage[rank][0] diff --git a/sim/warrior/shouts.go b/sim/warrior/shouts.go index a356f4c20..0d52e1a93 100644 --- a/sim/warrior/shouts.go +++ b/sim/warrior/shouts.go @@ -38,7 +38,7 @@ func (warrior *Warrior) newShoutSpellConfig(actionID core.ActionID, rank int32, } func (warrior *Warrior) registerBattleShout() { - rank := core.TernaryInt32(core.IncludeAQ, 7, 6) + rank := core.TernaryInt32(warrior.Env.UseAQSpellRanks, 7, 6) actionId := core.BattleShoutSpellId[rank] warrior.BattleShout = warrior.newShoutSpellConfig(core.ActionID{SpellID: actionId}, rank, warrior.NewPartyAuraArray(func(unit *core.Unit) *core.Aura { diff --git a/ui/balance_druid/sim.ts b/ui/balance_druid/sim.ts index 8297a4662..ad8c426cc 100644 --- a/ui/balance_druid/sim.ts +++ b/ui/balance_druid/sim.ts @@ -51,7 +51,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecBalanceDruid, { Stat.StatMP5, ], displayPseudoStats: [], - + defaults: { // Default equipped gear. gear: Presets.DefaultGear.gear, @@ -99,7 +99,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecBalanceDruid, { ], // Inputs to include in the 'Other' section on the settings tab. otherInputs: { - inputs: [OtherInputs.ReactionTime, OtherInputs.DistanceFromTarget], + inputs: [OtherInputs.UseAQSpellRanks, OtherInputs.ReactionTime, OtherInputs.DistanceFromTarget], }, itemSwapConfig: { itemSlots: [ItemSlot.ItemSlotMainHand, ItemSlot.ItemSlotOffHand, ItemSlot.ItemSlotRanged], @@ -110,15 +110,9 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecBalanceDruid, { }, presets: { - talents: [ - ...Presets.TalentPresets[Phase.Phase1], - ], - rotations: [ - ...Presets.APLPresets[Phase.Phase1], - ], - gear: [ - ...Presets.GearPresets[Phase.Phase1], - ], + talents: [...Presets.TalentPresets[Phase.Phase1]], + rotations: [...Presets.APLPresets[Phase.Phase1]], + gear: [...Presets.GearPresets[Phase.Phase1]], }, autoRotation: player => { diff --git a/ui/core/components/individual_sim_ui/apl_rotation_picker.ts b/ui/core/components/individual_sim_ui/apl_rotation_picker.ts index f3892c945..8d0cfa9f1 100644 --- a/ui/core/components/individual_sim_ui/apl_rotation_picker.ts +++ b/ui/core/components/individual_sim_ui/apl_rotation_picker.ts @@ -22,7 +22,7 @@ export class APLRotationPicker extends Component { title: 'Prepull Actions', titleTooltip: 'Actions to perform before the pull.', itemLabel: 'Prepull Action', - changedEvent: (player: Player) => player.rotationChangeEmitter, + changedEvent: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.sim.useAQSpellsChangeEmitter]), getValue: (player: Player) => player.aplRotation.prepullActions, setValue: (eventID: EventID, player: Player, newValue: Array) => { player.aplRotation.prepullActions = newValue; @@ -50,7 +50,7 @@ export class APLRotationPicker extends Component { title: 'Priority List', titleTooltip: 'At each decision point, the simulation will perform the first valid action from this list.', itemLabel: 'Action', - changedEvent: (player: Player) => player.rotationChangeEmitter, + changedEvent: (player: Player) => TypedEvent.onAny([player.rotationChangeEmitter, player.sim.useAQSpellsChangeEmitter]), getValue: (player: Player) => player.aplRotation.priorityList, setValue: (eventID: EventID, player: Player, newValue: Array) => { player.aplRotation.priorityList = newValue; diff --git a/ui/core/components/other_inputs.ts b/ui/core/components/other_inputs.ts index eb9d41dc4..ccd478067 100644 --- a/ui/core/components/other_inputs.ts +++ b/ui/core/components/other_inputs.ts @@ -124,6 +124,18 @@ export const DistanceFromTarget = { }, }; +export const UseAQSpellRanks = { + id: 'use-aq-spell-ranks', + type: 'boolean' as const, + label: 'Use AQ Spell Ranks', + labelTooltip: "Include ranks of spells that were added in the Ahn'Qiraj patch.", + changedEvent: (player: Player) => player.sim.useAQSpellsChangeEmitter, + getValue: (player: Player) => player.sim.getUseAQSpellRanks(), + setValue: (eventID: EventID, player: Player, newValue: boolean) => { + player.sim.setUseAQSpellRanks(eventID, newValue); + }, +}; + export const IsbUsingShadowflame = { id: 'isb-using-shadowflame', type: 'boolean' as const, diff --git a/ui/core/sim.ts b/ui/core/sim.ts index ccba4ff9b..fb8808f32 100644 --- a/ui/core/sim.ts +++ b/ui/core/sim.ts @@ -59,12 +59,13 @@ export enum SimSettingCategories { } const WASM_CONCURRENCY_STORAGE_KEY = `classic_wasmconcurrency`; +const DEFAULT_ITERATIONS = 10_000; // Core Sim module which deals only with api types, no UI-related stuff. export class Sim { private readonly workerPool: WorkerPool; - private iterations = 3000; + private iterations = DEFAULT_ITERATIONS; private phase: number = OtherConstants.CURRENT_PHASE; private faction: Faction = Faction.Alliance; private fixedRngSeed = 0; @@ -76,6 +77,7 @@ export class Sim { private wasmConcurrency = 0; private showEPValues = false; private language = ''; + private useAQSpellRanks = true; readonly raid: Raid; readonly encounter: Encounter; @@ -95,6 +97,7 @@ export class Sim { readonly wasmConcurrencyChangeEmitter = new TypedEvent(); readonly showEPValuesChangeEmitter = new TypedEvent(); readonly languageChangeEmitter = new TypedEvent(); + readonly useAQSpellsChangeEmitter = new TypedEvent(); readonly crashEmitter = new TypedEvent(); // Emits when any of the settings change (but not the raid / encounter). @@ -163,6 +166,7 @@ export class Sim { this.showExperimentalChangeEmitter, this.showEPValuesChangeEmitter, this.languageChangeEmitter, + this.useAQSpellsChangeEmitter, ]); this.changeEmitter = TypedEvent.onAny([this.settingsChangeEmitter, this.raid.changeEmitter, this.encounter.changeEmitter]); @@ -407,7 +411,7 @@ export class Sim { epStats: Array, epPseudoStats: Array, epReferenceStat: Stat, - onProgress: WorkerProgressCallback + onProgress: WorkerProgressCallback, ): Promise { if (this.raid.isEmpty()) { throw new Error('Raid is empty! Try adding some players first.'); @@ -444,7 +448,7 @@ export class Sim { pseudoStatsToWeigh: epPseudoStats, epReferenceStat: epReferenceStat, }); - + const signals = this.signalManager.registerRunning(RequestTypes.StatWeights); try { let result: StatWeightsResult; @@ -635,6 +639,16 @@ export class Sim { } } + getUseAQSpellRanks(): boolean { + return this.useAQSpellRanks; + } + setUseAQSpellRanks(eventID: EventID, newVal: boolean) { + if (newVal != this.useAQSpellRanks) { + this.useAQSpellRanks = newVal; + this.useAQSpellsChangeEmitter.emit(eventID); + } + } + static readonly ALL_ARMOR_TYPES = (getEnumValues(ArmorType) as Array).filter(v => v != 0); static readonly ALL_WEAPON_TYPES = (getEnumValues(WeaponType) as Array).filter(v => v != 0); static readonly ALL_RANGED_WEAPON_TYPES = (getEnumValues(RangedWeaponType) as Array).filter(v => v != 0); @@ -669,6 +683,7 @@ export class Sim { showExperimental: this.getShowExperimental(), showEpValues: this.getShowEPValues(), language: this.getLanguage(), + useAqSpellRanks: this.getUseAQSpellRanks(), faction: this.getFaction(), filters: filters, }); @@ -676,7 +691,7 @@ export class Sim { fromProto(eventID: EventID, proto: SimSettingsProto) { TypedEvent.freezeAllAndDo(() => { - this.setIterations(eventID, proto.iterations || 3000); + this.setIterations(eventID, proto.iterations || DEFAULT_ITERATIONS); this.setPhase(eventID, proto.phase || OtherConstants.CURRENT_PHASE); this.setFixedRngSeed(eventID, Number(proto.fixedRngSeed)); this.setShowDamageMetrics(eventID, proto.showDamageMetrics); @@ -685,6 +700,7 @@ export class Sim { this.setShowExperimental(eventID, proto.showExperimental); this.setShowEPValues(eventID, proto.showEpValues); this.setLanguage(eventID, proto.language); + this.setUseAQSpellRanks(eventID, proto.useAqSpellRanks); this.setFaction(eventID, proto.faction || Faction.Alliance); const filters = proto.filters || Sim.defaultFilters(); @@ -711,7 +727,7 @@ export class Sim { this.fromProto( eventID, SimSettingsProto.create({ - iterations: 3000, + iterations: DEFAULT_ITERATIONS, phase: OtherConstants.CURRENT_PHASE, faction: Faction.Alliance, showDamageMetrics: !isHealingSim, diff --git a/ui/elemental_shaman/sim.ts b/ui/elemental_shaman/sim.ts index e1d43060d..f09e0267a 100644 --- a/ui/elemental_shaman/sim.ts +++ b/ui/elemental_shaman/sim.ts @@ -30,9 +30,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecElementalShaman, { Stat.StatSpellHaste, Stat.StatMP5, ], - epPseudoStats: [ - - ], + epPseudoStats: [], // 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. @@ -93,7 +91,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecElementalShaman, { excludeBuffDebuffInputs: [], // Inputs to include in the 'Other' section on the settings tab. otherInputs: { - inputs: [OtherInputs.DistanceFromTarget], + inputs: [OtherInputs.UseAQSpellRanks, OtherInputs.DistanceFromTarget], }, itemSwapConfig: { itemSlots: [ItemSlot.ItemSlotMainHand, ItemSlot.ItemSlotOffHand], @@ -124,9 +122,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecElementalShaman, { ...Presets.APLPresets[Phase.Phase1], ], // Preset gear configurations that the user can quickly select. - gear: [ - Presets.DefaultGear, - ], + gear: [Presets.DefaultGear], }, autoRotation: player => { diff --git a/ui/enhancement_shaman/sim.ts b/ui/enhancement_shaman/sim.ts index 67acd37d4..b580a44f4 100644 --- a/ui/enhancement_shaman/sim.ts +++ b/ui/enhancement_shaman/sim.ts @@ -37,11 +37,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecEnhancementShaman, { Stat.StatSpellHaste, Stat.StatMP5, ], - epPseudoStats: [ - PseudoStat.PseudoStatMainHandDps, - PseudoStat.PseudoStatOffHandDps, - PseudoStat.PseudoStatMeleeSpeedMultiplier, - ], + epPseudoStats: [PseudoStat.PseudoStatMainHandDps, PseudoStat.PseudoStatOffHandDps, PseudoStat.PseudoStatMeleeSpeedMultiplier], // Reference stat against which to calculate EP. I think all classes use either spell power or attack power. epReferenceStat: Stat.StatAttackPower, // Which stats to display in the Character Stats section, at the bottom of the left-hand sidebar. @@ -67,7 +63,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecEnhancementShaman, { Stat.StatMP5, ], displayPseudoStats: [], - + defaults: { race: Race.RaceTroll, // Default equipped gear. @@ -118,7 +114,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecEnhancementShaman, { excludeBuffDebuffInputs: [], // Inputs to include in the 'Other' section on the settings tab. otherInputs: { - inputs: [ShamanInputs.SyncTypeInput, OtherInputs.TankAssignment, OtherInputs.InFrontOfTarget], + inputs: [OtherInputs.UseAQSpellRanks, ShamanInputs.SyncTypeInput, OtherInputs.TankAssignment, OtherInputs.InFrontOfTarget], }, itemSwapConfig: { itemSlots: [ItemSlot.ItemSlotMainHand, ItemSlot.ItemSlotOffHand], @@ -144,9 +140,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecEnhancementShaman, { ...Presets.APLPresets[Phase.Phase2], ...Presets.APLPresets[Phase.Phase1], ], - gear: [ - Presets.DefaultGear, - ], + gear: [Presets.DefaultGear], }, autoRotation: (player): APLRotation => { diff --git a/ui/feral_druid/sim.ts b/ui/feral_druid/sim.ts index fd15f682c..a028a35e7 100644 --- a/ui/feral_druid/sim.ts +++ b/ui/feral_druid/sim.ts @@ -38,9 +38,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecFeralDruid, { // Spell Stat.StatMP5, ], - epPseudoStats: [ - PseudoStat.BonusPhysicalDamage, - ], + epPseudoStats: [PseudoStat.BonusPhysicalDamage], // Reference stat against which to calculate EP. I think all classes use either spell power or attack power. epReferenceStat: Stat.StatAttackPower, // Which stats to display in the Character Stats section, at the bottom of the left-hand sidebar. @@ -61,9 +59,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecFeralDruid, { // Spell Stat.StatMP5, ], - displayPseudoStats: [ - PseudoStat.BonusPhysicalDamage, - ], + displayPseudoStats: [PseudoStat.BonusPhysicalDamage], defaults: { // Default equipped gear. @@ -118,6 +114,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecFeralDruid, { // Inputs to include in the 'Other' section on the settings tab. otherInputs: { inputs: [ + OtherInputs.UseAQSpellRanks, OtherInputs.ReactionTime, // DruidInputs.AssumeBleedActive, OtherInputs.TankAssignment, @@ -134,16 +131,10 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecFeralDruid, { presets: { // Preset talents that the user can quickly select. - talents: [ - ...Presets.TalentPresets[Phase.Phase1], - ], - rotations: [ - ...Presets.APLPresets[Phase.Phase1], - ], + talents: [...Presets.TalentPresets[Phase.Phase1]], + rotations: [...Presets.APLPresets[Phase.Phase1]], // Preset gear configurations that the user can quickly select. - gear: [ - ...Presets.GearPresets[Phase.Phase1], - ], + gear: [...Presets.GearPresets[Phase.Phase1]], }, autoRotation: player => { diff --git a/ui/feral_tank_druid/sim.ts b/ui/feral_tank_druid/sim.ts index 52426e12a..fa229299e 100644 --- a/ui/feral_tank_druid/sim.ts +++ b/ui/feral_tank_druid/sim.ts @@ -54,7 +54,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecFeralTankDruid, { Stat.StatShadowResistance, ], displayPseudoStats: [], - + defaults: { // Default equipped gear. gear: Presets.DefaultGear.gear, @@ -116,6 +116,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecFeralTankDruid, { // Inputs to include in the 'Other' section on the settings tab. otherInputs: { inputs: [ + OtherInputs.UseAQSpellRanks, OtherInputs.TankAssignment, OtherInputs.IncomingHps, OtherInputs.HealingCadence, diff --git a/ui/hunter/sim.ts b/ui/hunter/sim.ts index c440b5ca6..da280a747 100644 --- a/ui/hunter/sim.ts +++ b/ui/hunter/sim.ts @@ -70,7 +70,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecHunter, { Stat.StatMP5, ], displayPseudoStats: [], - + defaults: { race: Presets.OtherDefaults.race, // Default equipped gear. @@ -125,6 +125,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecHunter, { // Inputs to include in the 'Other' section on the settings tab. otherInputs: { inputs: [ + OtherInputs.UseAQSpellRanks, //HunterInputs.NewRaptorStrike, HunterInputs.PetAttackSpeedInput, HunterInputs.PetUptime, @@ -140,27 +141,21 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecHunter, { presets: { // Preset talents that the user can quickly select. - talents: [ - ...Presets.TalentPresets[Phase.Phase1], - ], + talents: [...Presets.TalentPresets[Phase.Phase1]], // Preset rotations that the user can quickly select. - rotations: [ - ...Presets.APLPresets[Phase.Phase1], - ], + rotations: [...Presets.APLPresets[Phase.Phase1]], // Preset gear configurations that the user can quickly select. - gear: [ - ...Presets.GearPresets[Phase.Phase1], - ], + gear: [...Presets.GearPresets[Phase.Phase1]], }, autoRotation: player => { const isMelee = false; - //player.hasRune(ItemSlot.ItemSlotWaist, HunterRune.RuneBeltMeleeSpecialist) || - //player.hasRune(ItemSlot.ItemSlotFeet, HunterRune.RuneBootsDualWieldSpecialization) || - //player.hasRune(ItemSlot.ItemSlotFeet, HunterRune.RuneBootsWyvernStrike); - + //player.hasRune(ItemSlot.ItemSlotWaist, HunterRune.RuneBeltMeleeSpecialist) || + //player.hasRune(ItemSlot.ItemSlotFeet, HunterRune.RuneBootsDualWieldSpecialization) || + //player.hasRune(ItemSlot.ItemSlotFeet, HunterRune.RuneBootsWyvernStrike); + return Presets.DefaultAPL.rotation.rotation!; - + // COMMENTING OUT TO SAVE FOR FUTURE IMPLEMENTATION. // if (isMelee) { // switch (level) { diff --git a/ui/mage/sim.ts b/ui/mage/sim.ts index 7a235dc01..841b1b8d7 100644 --- a/ui/mage/sim.ts +++ b/ui/mage/sim.ts @@ -52,7 +52,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecMage, { Stat.StatMP5, ], displayPseudoStats: [], - + defaults: { // Default equipped gear. gear: Presets.DefaultGear.gear, @@ -105,7 +105,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecMage, { excludeBuffDebuffInputs: [], // Inputs to include in the 'Other' section on the settings tab. otherInputs: { - inputs: [OtherInputs.DistanceFromTarget, OtherInputs.TankAssignment], + inputs: [OtherInputs.DistanceFromTarget, OtherInputs.TankAssignment, OtherInputs.UseAQSpellRanks], }, encounterPicker: { // Whether to include 'Execute Duration (%)' in the 'Encounter' section of the settings tab. @@ -113,15 +113,9 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecMage, { }, presets: { - rotations: [ - ...Presets.APLPresets[Phase.Phase1], - ], - talents: [ - ...Presets.TalentPresets[Phase.Phase1], - ], - gear: [ - ...Presets.GearPresets[Phase.Phase1], - ], + rotations: [...Presets.APLPresets[Phase.Phase1]], + talents: [...Presets.TalentPresets[Phase.Phase1]], + gear: [...Presets.GearPresets[Phase.Phase1]], }, autoRotation: player => { diff --git a/ui/protection_paladin/sim.ts b/ui/protection_paladin/sim.ts index d3b84e129..862a7e502 100644 --- a/ui/protection_paladin/sim.ts +++ b/ui/protection_paladin/sim.ts @@ -104,7 +104,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecProtectionPaladin, { Stat.StatArcaneResistance, ], displayPseudoStats: [], - + defaults: { // Default equipped gear. gear: Presets.DefaultGear.gear, @@ -180,6 +180,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecProtectionPaladin, { OtherInputs.HpPercentForDefensives, OtherInputs.InspirationUptime, OtherInputs.InFrontOfTarget, + OtherInputs.UseAQSpellRanks, //OtherInputs.DistanceFromTarget, ], }, diff --git a/ui/retribution_paladin/sim.ts b/ui/retribution_paladin/sim.ts index db3b5b585..c59358bf8 100644 --- a/ui/retribution_paladin/sim.ts +++ b/ui/retribution_paladin/sim.ts @@ -53,10 +53,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecRetributionPaladin, { Stat.StatSpellHaste, Stat.StatMP5, ], - epPseudoStats: [ - PseudoStat.PseudoStatMainHandDps, - PseudoStat.PseudoStatMeleeSpeedMultiplier, - ], + epPseudoStats: [PseudoStat.PseudoStatMainHandDps, PseudoStat.PseudoStatMeleeSpeedMultiplier], // Reference stat against which to calculate EP. I think all classes use either spell power or attack power. epReferenceStat: Stat.StatAttackPower, // Which stats to display in the Character Stats section, at the bottom of the left-hand sidebar. @@ -82,7 +79,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecRetributionPaladin, { Stat.StatMP5, ], displayPseudoStats: [], - + defaults: { // Default equipped gear. gear: Presets.DefaultGear.gear, @@ -129,7 +126,14 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecRetributionPaladin, { excludeBuffDebuffInputs: [], // Inputs to include in the 'Other' section on the settings tab. otherInputs: { - inputs: [OtherInputs.TankAssignment, OtherInputs.InFrontOfTarget, RetributionPaladinInputs.CrusaderStrikeStopAttack, RetributionPaladinInputs.JudgementStopAttack, RetributionPaladinInputs.DivineStormStopAttack], + inputs: [ + OtherInputs.TankAssignment, + OtherInputs.InFrontOfTarget, + RetributionPaladinInputs.CrusaderStrikeStopAttack, + RetributionPaladinInputs.JudgementStopAttack, + RetributionPaladinInputs.DivineStormStopAttack, + OtherInputs.UseAQSpellRanks, + ], }, encounterPicker: { // Whether to include 'Execute Duration (%)' in the 'Encounter' section of the settings tab. @@ -153,9 +157,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecRetributionPaladin, { ...Presets.TalentPresets[Phase.Phase1], ], // Preset gear configurations that the user can quickly select. - gear: [ - Presets.DefaultGear, - ], + gear: [Presets.DefaultGear], }, autoRotation: player => { diff --git a/ui/rogue/sim.ts b/ui/rogue/sim.ts index 18ce921a8..f40d161eb 100644 --- a/ui/rogue/sim.ts +++ b/ui/rogue/sim.ts @@ -129,7 +129,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecRogue, { excludeBuffDebuffInputs: [], // Inputs to include in the 'Other' section on the settings tab. otherInputs: { - inputs: [OtherInputs.TankAssignment, OtherInputs.InFrontOfTarget], + inputs: [OtherInputs.TankAssignment, OtherInputs.InFrontOfTarget, OtherInputs.UseAQSpellRanks], }, encounterPicker: { // Whether to include 'Execute Duration (%)' in the 'Encounter' section of the settings tab. @@ -138,22 +138,12 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecRogue, { presets: { // Preset talents that the user can quickly select. - talents: [ - ...Presets.TalentPresets[Phase.Phase1], - ], + talents: [...Presets.TalentPresets[Phase.Phase1]], // Preset rotations that the user can quickly select. - rotations: [ - ...Presets.APLPresets[Phase.Phase1], - ], + rotations: [...Presets.APLPresets[Phase.Phase1]], // Preset gear configurations that the user can quickly select. - gear: [ - ...Presets.GearPresets[Phase.Phase1], - ], - builds: [ - Presets.PresetBuildBackstab, - Presets.PresetBuildSinisterStrike, - Presets.PresetBuildIEA, - ], + gear: [...Presets.GearPresets[Phase.Phase1]], + builds: [Presets.PresetBuildBackstab, Presets.PresetBuildSinisterStrike, Presets.PresetBuildIEA], }, autoRotation: player => { diff --git a/ui/shadow_priest/sim.ts b/ui/shadow_priest/sim.ts index 4875baa5f..a225489b1 100644 --- a/ui/shadow_priest/sim.ts +++ b/ui/shadow_priest/sim.ts @@ -50,7 +50,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecShadowPriest, { Stat.StatMP5, ], displayPseudoStats: [], - + modifyDisplayStats: (player: Player) => { let stats = new Stats(); stats = stats.addPseudoStat(PseudoStat.PseudoStatSchoolHitShadow, player.getTalents().shadowFocus * 2 * Mechanics.SPELL_HIT_RATING_PER_HIT_CHANCE); @@ -106,7 +106,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecShadowPriest, { excludeBuffDebuffInputs: [], // Inputs to include in the 'Other' section on the settings tab. otherInputs: { - inputs: [OtherInputs.TankAssignment, OtherInputs.ChannelClipDelay, OtherInputs.DistanceFromTarget], + inputs: [OtherInputs.TankAssignment, OtherInputs.ChannelClipDelay, OtherInputs.DistanceFromTarget, OtherInputs.UseAQSpellRanks], }, encounterPicker: { // Whether to include 'Execute Duration (%)' in the 'Encounter' section of the settings tab. @@ -114,15 +114,9 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecShadowPriest, { }, presets: { - talents: [ - ...Presets.TalentPresets[Phase.Phase1], - ], - rotations: [ - ...Presets.APLPresets[Phase.Phase1], - ], - gear: [ - ...Presets.GearPresets[Phase.Phase1], - ], + talents: [...Presets.TalentPresets[Phase.Phase1]], + rotations: [...Presets.APLPresets[Phase.Phase1]], + gear: [...Presets.GearPresets[Phase.Phase1]], }, autoRotation: player => { diff --git a/ui/tank_warrior/sim.ts b/ui/tank_warrior/sim.ts index 36abadcdd..7c8da3bcd 100644 --- a/ui/tank_warrior/sim.ts +++ b/ui/tank_warrior/sim.ts @@ -65,7 +65,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecTankWarrior, { Stat.StatShadowResistance, ], displayPseudoStats: [], - + defaults: { // Default equipped gear. gear: Presets.DefaultGear.gear, @@ -124,6 +124,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecTankWarrior, { OtherInputs.BurstWindow, OtherInputs.HpPercentForDefensives, OtherInputs.InspirationUptime, + OtherInputs.UseAQSpellRanks, ], }, encounterPicker: { @@ -133,17 +134,11 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecTankWarrior, { presets: { // Preset talents that the user can quickly select. - talents: [ - ...Presets.TalentPresets[Phase.Phase1], - ], + talents: [...Presets.TalentPresets[Phase.Phase1]], // Preset rotations that the user can quickly select. - rotations: [ - ...Presets.APLPresets[Phase.Phase1], - ], + rotations: [...Presets.APLPresets[Phase.Phase1]], // Preset gear configurations that the user can quickly select. - gear: [ - ...Presets.GearPresets[Phase.Phase1], - ], + gear: [...Presets.GearPresets[Phase.Phase1]], // Preset builds that the user can quickly select. builds: [Presets.PresetBuildTanky], }, diff --git a/ui/warlock/sim.ts b/ui/warlock/sim.ts index b35616a81..c6be68652 100644 --- a/ui/warlock/sim.ts +++ b/ui/warlock/sim.ts @@ -131,7 +131,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecWarlock, { petConsumeInputs: [ConsumablesInputs.PetAttackPowerConsumable, ConsumablesInputs.PetAgilityConsumable, ConsumablesInputs.PetStrengthConsumable], // Inputs to include in the 'Other' section on the settings tab. otherInputs: { - inputs: [WarlockInputs.PetPoolManaInput(), OtherInputs.DistanceFromTarget, OtherInputs.ChannelClipDelay], + inputs: [WarlockInputs.PetPoolManaInput(), OtherInputs.DistanceFromTarget, OtherInputs.ChannelClipDelay, OtherInputs.UseAQSpellRanks], }, itemSwapConfig: { itemSlots: [ItemSlot.ItemSlotMainHand, ItemSlot.ItemSlotOffHand, ItemSlot.ItemSlotRanged], diff --git a/ui/warrior/sim.ts b/ui/warrior/sim.ts index 6368e830b..64d5b0f60 100644 --- a/ui/warrior/sim.ts +++ b/ui/warrior/sim.ts @@ -27,11 +27,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecWarrior, { Stat.StatExpertise, Stat.StatMeleeCrit, ], - epPseudoStats: [ - PseudoStat.PseudoStatMainHandDps, - PseudoStat.PseudoStatOffHandDps, - PseudoStat.PseudoStatMeleeSpeedMultiplier, - ], + epPseudoStats: [PseudoStat.PseudoStatMainHandDps, PseudoStat.PseudoStatOffHandDps, PseudoStat.PseudoStatMeleeSpeedMultiplier], // Reference stat against which to calculate EP. I think all classes use either spell power or attack power. epReferenceStat: Stat.StatAttackPower, // Which stats to display in the Character Stats section, at the bottom of the left-hand sidebar. @@ -101,7 +97,12 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecWarrior, { excludeBuffDebuffInputs: [], // Inputs to include in the 'Other' section on the settings tab. otherInputs: { - inputs: [WarriorInputs.StartingRage(), WarriorInputs.StanceSnapshot(), OtherInputs.InFrontOfTarget], + inputs: [ + WarriorInputs.StartingRage(), + WarriorInputs.StanceSnapshot(), + OtherInputs.InFrontOfTarget, + OtherInputs.UseAQSpellRanks, + ], }, encounterPicker: { // Whether to include 'Execute Duration (%)' in the 'Encounter' section of the settings tab. @@ -110,17 +111,11 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecWarrior, { presets: { // Preset talents that the user can quickly select. - talents: [ - ...Presets.TalentPresets[Phase.Phase1], - ], + talents: [...Presets.TalentPresets[Phase.Phase1]], // Preset rotations that the user can quickly select. - rotations: [ - ...Presets.APLPresets[Phase.Phase1], - ], + rotations: [...Presets.APLPresets[Phase.Phase1]], // Preset gear configurations that the user can quickly select. - gear: [ - ...Presets.GearPresets[Phase.Phase1], - ], + gear: [...Presets.GearPresets[Phase.Phase1]], // Preset builds that the user can quickly select. builds: [], },