diff --git a/sim/common/cata/other_effects.go b/sim/common/cata/other_effects.go index 34a748cb5e..15fbbeef68 100644 --- a/sim/common/cata/other_effects.go +++ b/sim/common/cata/other_effects.go @@ -525,154 +525,17 @@ func init() { }) }) - core.NewItemEffect(68972, func(agent core.Agent) { - character := agent.GetCharacter() - - dummyAura := character.RegisterAura(core.Aura{ - Label: "Titanic Power", - ActionID: core.ActionID{SpellID: 96923}, - Duration: time.Second * 30, - MaxStacks: 5, - }) - - core.MakePermanent(core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - Name: "Titanic Power Aura", - ActionID: core.ActionID{ItemID: 68972}, - Callback: core.CallbackOnSpellHitDealt, - ProcMask: core.ProcMaskMelee, - ProcChance: 1, - Outcome: core.OutcomeCrit, - Handler: func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - dummyAura.Activate(sim) - dummyAura.AddStack(sim) - }, - })) - - statBonus := float64(508 * dummyAura.MaxStacks) - buffAuraCrit := character.NewTemporaryStatsAura("Blessing of the Shaper Crit", core.ActionID{SpellID: 96928}, stats.Stats{stats.CritRating: statBonus}, time.Second*15) - buffAuraHaste := character.NewTemporaryStatsAura("Blessing of the Shaper Haste", core.ActionID{SpellID: 96927}, stats.Stats{stats.HasteRating: statBonus}, time.Second*15) - buffAuraMastery := character.NewTemporaryStatsAura("Blessing of the Shaper Mastery", core.ActionID{SpellID: 96929}, stats.Stats{stats.MasteryRating: statBonus}, time.Second*15) - - sharedCD := character.GetOffensiveTrinketCD() - trinketSpell := character.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{ItemID: 68972}, - SpellSchool: core.SpellSchoolPhysical, - ProcMask: core.ProcMaskEmpty, - Flags: core.SpellFlagNoOnCastComplete, - Cast: core.CastConfig{ - SharedCD: core.Cooldown{ - Timer: sharedCD, - Duration: time.Second * 15, - }, - CD: core.Cooldown{ - Timer: character.NewTimer(), - Duration: time.Minute * 2, - }, - }, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - statType := character.GetHighestStatType([]stats.Stat{stats.CritRating, stats.HasteRating, stats.MasteryRating}) - switch statType { - case stats.CritRating: - buffAuraCrit.Activate(sim) - case stats.HasteRating: - buffAuraHaste.Activate(sim) - case stats.MasteryRating: - buffAuraMastery.Activate(sim) - default: - panic("unexpected statType") - } - dummyAura.Deactivate(sim) - }, - ExtraCastCondition: func(sim *core.Simulation, target *core.Unit) bool { - return dummyAura.GetStacks() == 5 - }, - }) - - character.AddMajorCooldown(core.MajorCooldown{ - Spell: trinketSpell, - Priority: core.CooldownPriorityDefault, - Type: core.CooldownTypeDPS, - ShouldActivate: func(s *core.Simulation, c *core.Character) bool { - return dummyAura.GetStacks() == 5 - }, - }) + // Normal + registerApparatusOfKhazGoroth(apparatusConfig{ + ItemID: 68972, + BonusPerStack: 508, }) - core.NewItemEffect(69113, func(agent core.Agent) { - character := agent.GetCharacter() - - dummyAura := character.RegisterAura(core.Aura{ - Label: "Titanic Power (Heroic)", - ActionID: core.ActionID{SpellID: 96923}, - Duration: time.Second * 30, - MaxStacks: 5, - }) - - core.MakePermanent(core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - Name: "Titanic Power Aura (Heroic)", - ActionID: core.ActionID{ItemID: 69113}, - Callback: core.CallbackOnSpellHitDealt, - ProcMask: core.ProcMaskMelee, - ProcChance: 1, - Outcome: core.OutcomeCrit, - Handler: func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - dummyAura.Activate(sim) - dummyAura.AddStack(sim) - }, - })) - - // TODO: discuss the following scenario: - // the trinket should allow to activate at any number of stacks, should we allow this behaviour at all to the users? - // would also mean that we need the temporary aura to be created on the fly after an environment is finalized - statBonus := float64(575 * dummyAura.MaxStacks) - buffAuraCrit := character.NewTemporaryStatsAura("Blessing of the Shaper Crit (Heroic)", core.ActionID{SpellID: 96928}, stats.Stats{stats.CritRating: statBonus}, time.Second*15) - buffAuraHaste := character.NewTemporaryStatsAura("Blessing of the Shaper Haste (Heroic)", core.ActionID{SpellID: 96927}, stats.Stats{stats.HasteRating: statBonus}, time.Second*15) - buffAuraMastery := character.NewTemporaryStatsAura("Blessing of the Shaper Mastery (Heroic)", core.ActionID{SpellID: 96929}, stats.Stats{stats.MasteryRating: statBonus}, time.Second*15) - - sharedCD := character.GetOffensiveTrinketCD() - trinketSpell := character.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{ItemID: 69113}, - SpellSchool: core.SpellSchoolPhysical, - ProcMask: core.ProcMaskEmpty, - Flags: core.SpellFlagNoOnCastComplete, - Cast: core.CastConfig{ - SharedCD: core.Cooldown{ - Timer: sharedCD, - Duration: time.Second * 15, - }, - CD: core.Cooldown{ - Timer: character.NewTimer(), - Duration: time.Minute * 2, - }, - }, - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - statType := character.GetHighestStatType([]stats.Stat{stats.CritRating, stats.HasteRating, stats.MasteryRating}) - switch statType { - case stats.CritRating: - buffAuraCrit.Activate(sim) - case stats.HasteRating: - buffAuraHaste.Activate(sim) - case stats.MasteryRating: - buffAuraMastery.Activate(sim) - default: - panic("unexpected statType") - } - dummyAura.Deactivate(sim) - }, - ExtraCastCondition: func(sim *core.Simulation, target *core.Unit) bool { - return dummyAura.GetStacks() == 5 - }, - }) - - character.AddMajorCooldown(core.MajorCooldown{ - Spell: trinketSpell, - Priority: core.CooldownPriorityDefault, - Type: core.CooldownTypeDPS, - ShouldActivate: func(s *core.Simulation, c *core.Character) bool { - return dummyAura.GetStacks() == 5 - }, - }) + // Heroic + registerApparatusOfKhazGoroth(apparatusConfig{ + ItemID: 69113, + BonusPerStack: 575, + Heroic: true, }) core.NewItemEffect(68994, func(agent core.Agent) { @@ -761,3 +624,111 @@ func init() { }) }) } + +type apparatusConfig struct { + ItemID int32 + BonusPerStack float64 + Heroic bool +} + +func registerApparatusOfKhazGoroth(config apparatusConfig) { + core.NewItemEffect(config.ItemID, func(agent core.Agent) { + character := agent.GetCharacter() + + labelSuffix := core.Ternary(config.Heroic, " (Heroic)", "") + buffDuration := time.Second * 15 + + buffAuraCrit := character.NewTemporaryStatBuffWithStacks( + "Blessing of the Shaper Crit"+labelSuffix, + core.ActionID{SpellID: 96928}, + stats.Stats{stats.CritRating: config.BonusPerStack}, + 5, + buffDuration) + + buffAuraHaste := character.NewTemporaryStatBuffWithStacks( + "Blessing of the Shaper Haste"+labelSuffix, + core.ActionID{SpellID: 96927}, + stats.Stats{stats.HasteRating: config.BonusPerStack}, + 5, + buffDuration) + + buffAuraMastery := character.NewTemporaryStatBuffWithStacks( + "Blessing of the Shaper Mastery"+labelSuffix, + core.ActionID{SpellID: 96929}, + stats.Stats{stats.MasteryRating: config.BonusPerStack}, + 5, + buffDuration) + + titanicPower := character.RegisterAura(core.Aura{ + Label: "Titanic Power" + labelSuffix, + ActionID: core.ActionID{SpellID: 96923}, + Duration: time.Second * 30, + MaxStacks: 5, + }) + + core.MakePermanent(core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ + Name: "Titanic Power Aura" + labelSuffix, + ActionID: core.ActionID{SpellID: 96924}, + Callback: core.CallbackOnSpellHitDealt, + ProcMask: core.ProcMaskMelee, + ProcChance: 1, + Outcome: core.OutcomeCrit, + Handler: func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { + if buffAuraCrit.IsActive() || buffAuraHaste.IsActive() || buffAuraMastery.IsActive() { + return + } + + titanicPower.Activate(sim) + titanicPower.AddStack(sim) + }, + })) + + trinketSpell := character.RegisterSpell(core.SpellConfig{ + ActionID: core.ActionID{ItemID: config.ItemID}, + SpellSchool: core.SpellSchoolPhysical, + ProcMask: core.ProcMaskEmpty, + Flags: core.SpellFlagNoOnCastComplete, + Cast: core.CastConfig{ + SharedCD: core.Cooldown{ + Timer: character.GetOffensiveTrinketCD(), + Duration: time.Second * 15, + }, + CD: core.Cooldown{ + Timer: character.NewTimer(), + Duration: time.Minute * 2, + }, + }, + ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { + statType := character.GetHighestStatType([]stats.Stat{stats.CritRating, stats.HasteRating, stats.MasteryRating}) + + switch statType { + case stats.CritRating: + buffAuraCrit.Activate(sim) + buffAuraCrit.SetStacks(sim, titanicPower.GetStacks()) + case stats.HasteRating: + buffAuraHaste.Activate(sim) + buffAuraHaste.SetStacks(sim, titanicPower.GetStacks()) + case stats.MasteryRating: + buffAuraMastery.Activate(sim) + buffAuraMastery.SetStacks(sim, titanicPower.GetStacks()) + default: + panic("unexpected statType") + } + + titanicPower.Deactivate(sim) + }, + ExtraCastCondition: func(sim *core.Simulation, target *core.Unit) bool { + return titanicPower.IsActive() + }, + }) + + character.AddMajorCooldown(core.MajorCooldown{ + Spell: trinketSpell, + Priority: core.CooldownPriorityDefault, + Type: core.CooldownTypeDPS, + ShouldActivate: func(sim *core.Simulation, character *core.Character) bool { + return titanicPower.IsActive() + }, + }) + }) +} diff --git a/sim/core/aura_helpers.go b/sim/core/aura_helpers.go index d0af3fd5e0..8017cf1ca2 100644 --- a/sim/core/aura_helpers.go +++ b/sim/core/aura_helpers.go @@ -224,6 +224,18 @@ func MakePermanent(aura *Aura) *Aura { return aura } +func (character *Character) NewTemporaryStatBuffWithStacks(auraLabel string, actionID ActionID, bonusPerStack stats.Stats, maxStacks int32, duration time.Duration) *Aura { + return MakeStackingAura(character, StackingStatAura{ + Aura: Aura{ + Label: auraLabel, + ActionID: actionID, + Duration: duration, + MaxStacks: maxStacks, + }, + BonusPerStack: bonusPerStack, + }) +} + // Helper for the common case of making an aura that adds stats. func (character *Character) NewTemporaryStatsAura(auraLabel string, actionID ActionID, tempStats stats.Stats, duration time.Duration) *Aura { return character.NewTemporaryStatsAuraWrapped(auraLabel, actionID, tempStats, duration, nil) diff --git a/sim/death_knight/frost/TestFrost.results b/sim/death_knight/frost/TestFrost.results index e64481986d..b3f5f992ea 100644 --- a/sim/death_knight/frost/TestFrost.results +++ b/sim/death_knight/frost/TestFrost.results @@ -78,16 +78,16 @@ dps_results: { dps_results: { key: "TestFrost-AllItems-ApparatusofKhaz'goroth-68972" value: { - dps: 22067.2198 - tps: 20055.76419 - hps: 218.63072 + dps: 21920.68689 + tps: 19962.48269 + hps: 217.92998 } } dps_results: { key: "TestFrost-AllItems-ApparatusofKhaz'goroth-69113" value: { - dps: 22238.03054 - tps: 20224.97843 + dps: 22121.41929 + tps: 20106.73742 hps: 217.92998 } } diff --git a/sim/death_knight/unholy/TestUnholy.results b/sim/death_knight/unholy/TestUnholy.results index 465de57b22..3a1870c756 100644 --- a/sim/death_knight/unholy/TestUnholy.results +++ b/sim/death_knight/unholy/TestUnholy.results @@ -78,17 +78,17 @@ dps_results: { dps_results: { key: "TestUnholy-AllItems-ApparatusofKhaz'goroth-68972" value: { - dps: 31540.40851 - tps: 23371.35894 - hps: 490.05478 + dps: 31461.98752 + tps: 23327.34034 + hps: 485.83623 } } dps_results: { key: "TestUnholy-AllItems-ApparatusofKhaz'goroth-69113" value: { - dps: 31877.07432 - tps: 23648.34593 - hps: 494.27332 + dps: 31713.08283 + tps: 23495.50639 + hps: 485.83623 } } dps_results: { diff --git a/sim/druid/feral/TestFeral.results b/sim/druid/feral/TestFeral.results index 950f38b98a..5e9efda389 100644 --- a/sim/druid/feral/TestFeral.results +++ b/sim/druid/feral/TestFeral.results @@ -73,15 +73,15 @@ dps_results: { dps_results: { key: "TestFeral-AllItems-ApparatusofKhaz'goroth-68972" value: { - dps: 26010.16289 - tps: 36366.3166 + dps: 25884.26602 + tps: 36625.42619 } } dps_results: { key: "TestFeral-AllItems-ApparatusofKhaz'goroth-69113" value: { - dps: 26164.81755 - tps: 36466.50053 + dps: 25984.84193 + tps: 36758.48515 } } dps_results: { diff --git a/sim/druid/guardian/TestGuardian.results b/sim/druid/guardian/TestGuardian.results index de08b85e3e..840883f50b 100644 --- a/sim/druid/guardian/TestGuardian.results +++ b/sim/druid/guardian/TestGuardian.results @@ -73,15 +73,15 @@ dps_results: { dps_results: { key: "TestGuardian-AllItems-ApparatusofKhaz'goroth-68972" value: { - dps: 7800.83542 - tps: 39070.13604 + dps: 7843.78516 + tps: 39285.30684 } } dps_results: { key: "TestGuardian-AllItems-ApparatusofKhaz'goroth-69113" value: { - dps: 7833.11618 - tps: 39231.31568 + dps: 7887.29914 + tps: 39502.63676 } } dps_results: { diff --git a/sim/hunter/beast_mastery/TestBM.results b/sim/hunter/beast_mastery/TestBM.results index 1810022ea7..28e273c320 100644 --- a/sim/hunter/beast_mastery/TestBM.results +++ b/sim/hunter/beast_mastery/TestBM.results @@ -87,15 +87,15 @@ dps_results: { dps_results: { key: "TestBM-AllItems-ApparatusofKhaz'goroth-68972" value: { - dps: 21087.82523 - tps: 17814.40527 + dps: 21097.03318 + tps: 17811.53822 } } dps_results: { key: "TestBM-AllItems-ApparatusofKhaz'goroth-69113" value: { - dps: 21164.59151 - tps: 17896.62613 + dps: 21145.32226 + tps: 17859.07559 } } dps_results: { diff --git a/sim/hunter/survival/TestSV.results b/sim/hunter/survival/TestSV.results index fa22df5ca6..ca6b3533f7 100644 --- a/sim/hunter/survival/TestSV.results +++ b/sim/hunter/survival/TestSV.results @@ -87,15 +87,15 @@ dps_results: { dps_results: { key: "TestSV-AllItems-ApparatusofKhaz'goroth-68972" value: { - dps: 24461.81628 - tps: 22098.30071 + dps: 24475.60132 + tps: 22111.63781 } } dps_results: { key: "TestSV-AllItems-ApparatusofKhaz'goroth-69113" value: { - dps: 24461.81628 - tps: 22098.30071 + dps: 24478.64407 + tps: 22114.68056 } } dps_results: { diff --git a/sim/paladin/retribution/TestRetribution.results b/sim/paladin/retribution/TestRetribution.results index 65303fd8e6..badf45d29b 100644 --- a/sim/paladin/retribution/TestRetribution.results +++ b/sim/paladin/retribution/TestRetribution.results @@ -73,15 +73,15 @@ dps_results: { dps_results: { key: "TestRetribution-AllItems-ApparatusofKhaz'goroth-68972" value: { - dps: 31683.20496 - tps: 31696.73115 + dps: 31671.11248 + tps: 31684.63868 } } dps_results: { key: "TestRetribution-AllItems-ApparatusofKhaz'goroth-69113" value: { - dps: 31965.28338 - tps: 31978.80958 + dps: 31951.35763 + tps: 31964.88383 } } dps_results: { diff --git a/sim/rogue/assassination/TestAssassination.results b/sim/rogue/assassination/TestAssassination.results index 69fe255f3d..de2afb6c77 100644 --- a/sim/rogue/assassination/TestAssassination.results +++ b/sim/rogue/assassination/TestAssassination.results @@ -110,15 +110,15 @@ dps_results: { dps_results: { key: "TestAssassination-AllItems-ApparatusofKhaz'goroth-68972" value: { - dps: 29320.60438 - tps: 20817.62911 + dps: 28995.90198 + tps: 20587.0904 } } dps_results: { key: "TestAssassination-AllItems-ApparatusofKhaz'goroth-69113" value: { - dps: 29386.21451 - tps: 20864.2123 + dps: 29116.68993 + tps: 20672.84985 } } dps_results: { diff --git a/sim/rogue/combat/TestCombat.results b/sim/rogue/combat/TestCombat.results index d1739cf523..b3746dc738 100644 --- a/sim/rogue/combat/TestCombat.results +++ b/sim/rogue/combat/TestCombat.results @@ -80,15 +80,15 @@ dps_results: { dps_results: { key: "TestCombat-AllItems-ApparatusofKhaz'goroth-68972" value: { - dps: 28367.77298 - tps: 20141.11881 + dps: 28223.2451 + tps: 20038.50402 } } dps_results: { key: "TestCombat-AllItems-ApparatusofKhaz'goroth-69113" value: { - dps: 28461.46596 - tps: 20207.64083 + dps: 28347.85357 + tps: 20126.97603 } } dps_results: { diff --git a/sim/rogue/subtlety/TestSubtlety.results b/sim/rogue/subtlety/TestSubtlety.results index 945d108f61..24bfe4751b 100644 --- a/sim/rogue/subtlety/TestSubtlety.results +++ b/sim/rogue/subtlety/TestSubtlety.results @@ -74,15 +74,15 @@ dps_results: { dps_results: { key: "TestSubtlety-AllItems-ApparatusofKhaz'goroth-68972" value: { - dps: 22888.03892 - tps: 16250.50763 + dps: 22725.42258 + tps: 16135.05003 } } dps_results: { key: "TestSubtlety-AllItems-ApparatusofKhaz'goroth-69113" value: { - dps: 22980.73498 - tps: 16316.32184 + dps: 22911.41058 + tps: 16267.10151 } } dps_results: { diff --git a/sim/shaman/enhancement/TestEnhancement.results b/sim/shaman/enhancement/TestEnhancement.results index 2446647cad..5416a0605b 100644 --- a/sim/shaman/enhancement/TestEnhancement.results +++ b/sim/shaman/enhancement/TestEnhancement.results @@ -80,15 +80,15 @@ dps_results: { dps_results: { key: "TestEnhancement-AllItems-ApparatusofKhaz'goroth-68972" value: { - dps: 28971.28387 - tps: 19222.26788 + dps: 28867.12808 + tps: 19152.4189 } } dps_results: { key: "TestEnhancement-AllItems-ApparatusofKhaz'goroth-69113" value: { - dps: 29123.27112 - tps: 19310.80071 + dps: 29008.30684 + tps: 19235.05295 } } dps_results: { diff --git a/sim/warrior/arms/TestArms.results b/sim/warrior/arms/TestArms.results index 2b835b8235..2aadecf5df 100644 --- a/sim/warrior/arms/TestArms.results +++ b/sim/warrior/arms/TestArms.results @@ -73,15 +73,15 @@ dps_results: { dps_results: { key: "TestArms-AllItems-ApparatusofKhaz'goroth-68972" value: { - dps: 33915.64794 - tps: 22723.80573 + dps: 33902.42086 + tps: 22710.57865 } } dps_results: { key: "TestArms-AllItems-ApparatusofKhaz'goroth-69113" value: { - dps: 34198.92908 - tps: 22918.66312 + dps: 34196.35596 + tps: 22916.09 } } dps_results: {