diff --git a/sim/mage/fire/TestFire.results b/sim/mage/fire/TestFire.results index 6163d11bfa..13fd0406a6 100644 --- a/sim/mage/fire/TestFire.results +++ b/sim/mage/fire/TestFire.results @@ -1692,8 +1692,8 @@ dps_results: { dps_results: { key: "TestFire-AllItems-RegaliaoftheChromaticHydra" value: { - dps: 142343.07242 - tps: 138829.67592 + dps: 142225.27308 + tps: 138708.57938 } } dps_results: { diff --git a/sim/mage/fire/critical_mass.go b/sim/mage/fire/critical_mass.go index 1b08054e9a..a5bef82c5f 100644 --- a/sim/mage/fire/critical_mass.go +++ b/sim/mage/fire/critical_mass.go @@ -8,13 +8,22 @@ import ( func (fire *FireMage) registerCriticalMass() { - getCritPercent := func() float64 { - return fire.GetStat(stats.SpellCritPercent) * fire.criticalMassMultiplier + getCritPercent := func(isPyroblast bool) float64 { + pyroblastCritChance := core.TernaryFloat64(isPyroblast && fire.T15_4pc != nil && fire.T15_4pc.IsActive(), 5, 0) + return pyroblastCritChance + ((fire.GetStat(stats.SpellCritPercent) + pyroblastCritChance) * fire.criticalMassMultiplier) } criticalMassCritBuffMod := fire.AddDynamicMod(core.SpellModConfig{ - FloatValue: getCritPercent(), - ClassMask: mage.MageSpellFireball | mage.MageSpellFrostfireBolt | mage.MageSpellScorch | mage.MageSpellPyroblast | mage.MageSpellPyroblastDot, + FloatValue: getCritPercent(false), + ClassMask: mage.MageSpellFireball | mage.MageSpellFrostfireBolt | mage.MageSpellScorch, + Kind: core.SpellMod_BonusCrit_Percent, + }) + + // Separate mod for Pyroblast since it has a different crit bonus from T15 4-piece + // which is additive and Critical Mass is multiplicative. + criticalMassPyroCritBuffMod := fire.AddDynamicMod(core.SpellModConfig{ + FloatValue: getCritPercent(true), + ClassMask: mage.MageSpellPyroblast | mage.MageSpellPyroblastDot, Kind: core.SpellMod_BonusCrit_Percent, }) @@ -22,18 +31,21 @@ func (fire *FireMage) registerCriticalMass() { Label: "Critical Mass", OnGain: func(aura *core.Aura, sim *core.Simulation) { criticalMassCritBuffMod.Activate() + criticalMassPyroCritBuffMod.Activate() }, OnExpire: func(aura *core.Aura, sim *core.Simulation) { criticalMassCritBuffMod.Deactivate() + criticalMassPyroCritBuffMod.Deactivate() }, })) fire.AddOnTemporaryStatsChange(func(sim *core.Simulation, buffAura *core.Aura, statsChangeWithoutDeps stats.Stats) { - criticalMassCritBuffMod.UpdateFloatValue(getCritPercent()) + criticalMassCritBuffMod.UpdateFloatValue(getCritPercent(false)) + criticalMassPyroCritBuffMod.UpdateFloatValue(getCritPercent(true)) }) fire.RegisterResetEffect(func(sim *core.Simulation) { - criticalMassCritBuffMod.UpdateFloatValue(getCritPercent()) + criticalMassCritBuffMod.UpdateFloatValue(getCritPercent(false)) + criticalMassPyroCritBuffMod.UpdateFloatValue(getCritPercent(true)) }) - } diff --git a/sim/mage/items.go b/sim/mage/items.go index 9606524fa9..02fe76297b 100644 --- a/sim/mage/items.go +++ b/sim/mage/items.go @@ -98,17 +98,13 @@ var ItemSetRegaliaOfTheChromaticHydra = core.NewItemSet(core.ItemSet{ 4: func(agent core.Agent, setBonusAura *core.Aura) { mage := agent.(MageAgent).GetMage() - setBonusAura.AttachSpellMod(core.SpellModConfig{ - Kind: core.SpellMod_BonusCrit_Percent, - ClassMask: MageSpellPyroblast | MageSpellPyroblastDot, - FloatValue: 5, - }) + // Pyroblast is handled in critical_mass.go + // Frostbolt is handled in mage.go#ProcFingersOfFrost + mage.T15_4pc = setBonusAura setBonusAura.ApplyOnGain(func(_ *core.Aura, _ *core.Simulation) { mage.T15_4PC_ArcaneChargeEffect += 0.05 - mage.T15_4PC_FrostboltProcChance += 0.06 }).ApplyOnExpire(func(_ *core.Aura, _ *core.Simulation) { mage.T15_4PC_ArcaneChargeEffect -= 0.05 - mage.T15_4PC_FrostboltProcChance -= 0.06 }) setBonusAura.ExposeToAPL(138376) diff --git a/sim/mage/mage.go b/sim/mage/mage.go index e9f7eeba0e..a92d8a9756 100644 --- a/sim/mage/mage.go +++ b/sim/mage/mage.go @@ -52,11 +52,11 @@ type Mage struct { ArcanePowerDamageMod *core.SpellMod - T15_4PC_FrostboltProcChance float64 - T15_4PC_ArcaneChargeEffect float64 - Icicles []float64 + T15_4PC_ArcaneChargeEffect float64 + Icicles []float64 // Item sets + T15_4pc *core.Aura T16_4pc *core.Aura } @@ -91,7 +91,7 @@ func (mage *Mage) ProcFingersOfFrost(sim *core.Simulation, spell *core.Spell) { return } if spell.Matches(MageSpellFrostbolt | MageSpellFrostfireBolt) { - if sim.Proc(0.15+core.TernaryFloat64(spell.Matches(MageSpellFrostbolt), mage.T15_4PC_FrostboltProcChance, 0), "FingersOfFrostProc") { + if sim.Proc(0.15+core.TernaryFloat64(spell.Matches(MageSpellFrostbolt) && mage.T15_4pc != nil && mage.T15_4pc.IsActive(), 0.06, 0), "FingersOfFrostProc") { mage.FingersOfFrostAura.Activate(sim) mage.FingersOfFrostAura.AddStack(sim) } @@ -166,7 +166,6 @@ func NewMage(character *core.Character, options *proto.Player, mageOptions *prot mage.HasteEffectsManaRegen() mage.Icicles = make([]float64, 0) - mage.T15_4PC_FrostboltProcChance = 0 mage.T15_4PC_ArcaneChargeEffect = 1.0 return mage