From f2e078b47a347ef22423992c1c6aa78ed3d26e48 Mon Sep 17 00:00:00 2001 From: sanguinerarogue Date: Wed, 18 Dec 2024 22:13:12 -0700 Subject: [PATCH] mage and item set updates --- sim/common/sod/crafted/phase_1.go | 175 ----- sim/common/sod/crafted/phase_2.go | 344 ---------- sim/common/sod/crafted/phase_3.go | 250 -------- sim/common/sod/crafted/phase_4.go | 126 ---- sim/common/sod/enchant_effects.go | 91 --- sim/common/sod/item_effects.go | 108 ---- sim/common/sod/item_effects/phase_2.go | 384 ----------- sim/common/sod/item_effects/phase_3.go | 597 ------------------ sim/common/sod/item_effects/phase_4.go | 185 ------ sim/common/sod/item_effects/phase_5.go | 431 ------------- sim/common/sod/item_effects/phase_6.go | 533 ---------------- sim/common/sod/items_sets/phase_1.go | 78 --- sim/common/sod/items_sets/phase_2.go | 187 ------ sim/common/sod/items_sets/phase_3.go | 384 ----------- sim/common/sod/items_sets/phase_5.go | 152 ----- .../item_sets/item_sets_pve.go} | 394 ++++-------- sim/common/vanilla/item_sets/item_sets_pvp.go | 231 +++++++ sim/mage/TestP1Mage.results | 11 +- sim/mage/ignite.go | 24 +- sim/mage/item_sets_pve.go | 11 +- sim/mage/mage.go | 1 + sim/priest/shadow/TestP1Shadow.results | 7 + sim/warlock/dps/TestWarlockDSRuin.results | 7 + sim/warlock/dps/TestWarlockSMRuin.results | 7 + 24 files changed, 395 insertions(+), 4323 deletions(-) delete mode 100644 sim/common/sod/crafted/phase_1.go delete mode 100644 sim/common/sod/crafted/phase_2.go delete mode 100644 sim/common/sod/crafted/phase_3.go delete mode 100644 sim/common/sod/crafted/phase_4.go delete mode 100644 sim/common/sod/enchant_effects.go delete mode 100644 sim/common/sod/item_effects.go delete mode 100644 sim/common/sod/item_effects/phase_2.go delete mode 100644 sim/common/sod/item_effects/phase_3.go delete mode 100644 sim/common/sod/item_effects/phase_4.go delete mode 100644 sim/common/sod/item_effects/phase_5.go delete mode 100644 sim/common/sod/item_effects/phase_6.go delete mode 100644 sim/common/sod/items_sets/phase_1.go delete mode 100644 sim/common/sod/items_sets/phase_2.go delete mode 100644 sim/common/sod/items_sets/phase_3.go delete mode 100644 sim/common/sod/items_sets/phase_5.go rename sim/common/{sod/items_sets/phase_4.go => vanilla/item_sets/item_sets_pve.go} (53%) create mode 100644 sim/common/vanilla/item_sets/item_sets_pvp.go diff --git a/sim/common/sod/crafted/phase_1.go b/sim/common/sod/crafted/phase_1.go deleted file mode 100644 index 1a46dd06a..000000000 --- a/sim/common/sod/crafted/phase_1.go +++ /dev/null @@ -1,175 +0,0 @@ -package crafted - -import ( - "time" - - "github.com/wowsims/classic/sim/core" -) - -func init() { - core.AddEffectsToTest = false - - /////////////////////////////////////////////////////////////////////////// - // Cloth - /////////////////////////////////////////////////////////////////////////// - - // Extraplanar Spidersilk Boots - core.NewItemEffect(210795, func(agent core.Agent) { - character := agent.GetCharacter() - actionID := core.ActionID{SpellID: 428489} - - buffAura := character.GetOrRegisterAura(core.Aura{ - Label: "Planar Shift", - ActionID: actionID, - Duration: time.Second * 6, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - character.PseudoStats.DamageDealtMultiplier *= .7 - character.PseudoStats.DamageTakenMultiplier *= .7 - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - character.PseudoStats.DamageDealtMultiplier /= .7 - character.PseudoStats.DamageTakenMultiplier /= .7 - }, - }) - - activationSpell := character.GetOrRegisterSpell(core.SpellConfig{ - ActionID: actionID, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagDefensiveEquipment, - - Cast: core.CastConfig{ - CD: core.Cooldown{ - Timer: character.NewTimer(), - Duration: time.Minute * 10, - }, - }, - - ApplyEffects: func(sim *core.Simulation, _ *core.Unit, _ *core.Spell) { - buffAura.Activate(sim) - }, - }) - - character.AddMajorCooldown(core.MajorCooldown{ - Spell: activationSpell, - Priority: core.CooldownPriorityLow, - Type: core.CooldownTypeSurvival, - ShouldActivate: func(s *core.Simulation, c *core.Character) bool { - return character.IsTanking() - }, - }) - }) - - /////////////////////////////////////////////////////////////////////////// - // Leather - /////////////////////////////////////////////////////////////////////////// - - // Void-Touched Leather Gloves - core.NewItemEffect(211423, func(agent core.Agent) { - character := agent.GetCharacter() - actionID := core.ActionID{SpellID: 429867} - - buffAura := character.GetOrRegisterAura(core.Aura{ - Label: "Void Madness", - ActionID: actionID, - Duration: time.Second * 10, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - character.PseudoStats.ThreatMultiplier *= 1.2 - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - character.PseudoStats.ThreatMultiplier /= 1.2 - }, - }) - - ee := NewSodCraftedAttackSpeedEffect(buffAura, 1.1) - - activationSpell := character.GetOrRegisterSpell(core.SpellConfig{ - ActionID: actionID, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagOffensiveEquipment, - - Cast: core.CastConfig{ - CD: core.Cooldown{ - Timer: character.NewTimer(), - Duration: time.Minute * 10, - }, - }, - - ApplyEffects: func(sim *core.Simulation, _ *core.Unit, _ *core.Spell) { - buffAura.Activate(sim) - }, - - ExtraCastCondition: func(sim *core.Simulation, target *core.Unit) bool { - return !ee.Category.AnyActive() - }, - }) - - character.AddMajorCooldown(core.MajorCooldown{ - Spell: activationSpell, - Priority: core.CooldownPriorityLow, - Type: core.CooldownTypeDPS, - }) - }) - - // Void-Touched Leather Gauntlets - core.NewItemEffect(211502, func(agent core.Agent) { - character := agent.GetCharacter() - actionID := core.ActionID{SpellID: 429868} - - buffAura := character.GetOrRegisterAura(core.Aura{ - Label: "Void Madness", - ActionID: actionID, - Duration: time.Second * 10, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - character.PseudoStats.SchoolDamageDealtMultiplier.MultiplyMagicSchools(1.1) - character.PseudoStats.ThreatMultiplier *= 1.2 - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - character.PseudoStats.SchoolDamageDealtMultiplier.MultiplyMagicSchools(1 / 1.1) - character.PseudoStats.ThreatMultiplier /= 1.2 - }, - }) - - activationSpell := character.GetOrRegisterSpell(core.SpellConfig{ - ActionID: actionID, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagOffensiveEquipment, - - Cast: core.CastConfig{ - CD: core.Cooldown{ - Timer: character.NewTimer(), - Duration: time.Minute * 10, - }, - }, - - ApplyEffects: func(sim *core.Simulation, _ *core.Unit, _ *core.Spell) { - buffAura.Activate(sim) - }, - }) - - character.AddMajorCooldown(core.MajorCooldown{ - Spell: activationSpell, - Priority: core.CooldownPriorityLow, - Type: core.CooldownTypeDPS, - }) - }) - - /////////////////////////////////////////////////////////////////////////// - // Mail - /////////////////////////////////////////////////////////////////////////// - - // Shifting Silver Breastplate - // core.NewItemEffect(210794, func(agent core.Agent) { - // // Nothing to do - // }) - - core.AddEffectsToTest = true -} - -func NewSodCraftedAttackSpeedEffect(aura *core.Aura, attackSpeedBonus float64) *core.ExclusiveEffect { - return aura.NewExclusiveEffect("SoD Crafted Attack Speed", false, core.ExclusiveEffect{ - Priority: attackSpeedBonus, - OnGain: func(ee *core.ExclusiveEffect, sim *core.Simulation) { - ee.Aura.Unit.MultiplyAttackSpeed(sim, ee.Priority) - }, - OnExpire: func(ee *core.ExclusiveEffect, sim *core.Simulation) { - ee.Aura.Unit.MultiplyAttackSpeed(sim, 1/ee.Priority) - }, - }) -} diff --git a/sim/common/sod/crafted/phase_2.go b/sim/common/sod/crafted/phase_2.go deleted file mode 100644 index 7bdd73517..000000000 --- a/sim/common/sod/crafted/phase_2.go +++ /dev/null @@ -1,344 +0,0 @@ -package crafted - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/stats" -) - -func init() { - core.AddEffectsToTest = false - - /////////////////////////////////////////////////////////////////////////// - // Cloth - /////////////////////////////////////////////////////////////////////////// - - // Gneuro-Linked Arcano-Filament Monocle - core.NewItemEffect(215111, func(agent core.Agent) { - character := agent.GetCharacter() - actionId := core.ActionID{SpellID: 437327} - - buffAura := character.GetOrRegisterAura(core.Aura{ - Label: "Charged Inspiration", - ActionID: actionId, - Duration: time.Second * 12, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - character.AddStatDynamic(sim, stats.SpellPower, 50) - character.PseudoStats.SchoolCostMultiplier.AddToMagicSchools(-50) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - character.AddStatDynamic(sim, stats.SpellPower, -50) - character.PseudoStats.SchoolCostMultiplier.AddToMagicSchools(50) - }, - }) - - activationSpell := character.GetOrRegisterSpell(core.SpellConfig{ - ActionID: actionId, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagOffensiveEquipment, - - Cast: core.CastConfig{ - CD: core.Cooldown{ - Timer: character.NewTimer(), - Duration: time.Minute * 10, - }, - }, - - ApplyEffects: func(sim *core.Simulation, _ *core.Unit, _ *core.Spell) { - buffAura.Activate(sim) - }, - }) - - character.AddMajorCooldown(core.MajorCooldown{ - Spell: activationSpell, - Priority: core.CooldownPriorityLow, - Type: core.CooldownTypeDPS, - }) - }) - - // Hyperconductive Goldwrap - core.NewItemEffect(215115, func(agent core.Agent) { - character := agent.GetCharacter() - buffAuraCrit := character.GetOrRegisterAura(core.Aura{ - Label: "Coin Flip: Crit", - ActionID: core.ActionID{SpellID: 437698}, - Duration: time.Second * 30, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - character.AddStatDynamic(sim, stats.MeleeCrit, 3) - character.AddStatDynamic(sim, stats.SpellCrit, 3) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - character.AddStatDynamic(sim, stats.MeleeCrit, -3) - character.AddStatDynamic(sim, stats.SpellCrit, -3) - }, - }) - - buffAuraMs := character.GetOrRegisterAura(core.Aura{ - Label: "Coin Flip: Movement Speed", - ActionID: core.ActionID{SpellID: 437699}, - Duration: time.Second * 30, - }) - - activationSpell := character.GetOrRegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 437368}, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagOffensiveEquipment, - - Cast: core.CastConfig{ - CD: core.Cooldown{ - Timer: character.NewTimer(), - Duration: time.Minute * 15, - }, - }, - - ApplyEffects: func(sim *core.Simulation, _ *core.Unit, _ *core.Spell) { - if sim.RandomFloat("Coin Flip") > 0.5 { - buffAuraCrit.Activate(sim) - } else { - buffAuraMs.Activate(sim) - } - }, - }) - - character.AddMajorCooldown(core.MajorCooldown{ - Spell: activationSpell, - Priority: core.CooldownPriorityLow, - Type: core.CooldownTypeDPS, - }) - }) - - /////////////////////////////////////////////////////////////////////////// - // Leather - /////////////////////////////////////////////////////////////////////////// - - // Glowing Gneuro-Linked Cowl - core.NewItemEffect(215166, func(agent core.Agent) { - character := agent.GetCharacter() - - actionId := core.ActionID{SpellID: 437349} - - buffAura := character.GetOrRegisterAura(core.Aura{ - Label: "Gneuro-Logical Shock", - ActionID: actionId, - Duration: time.Second * 10, - }) - - ee := NewSodCraftedAttackSpeedEffect(buffAura, 1.2) - - spell := character.RegisterSpell(core.SpellConfig{ - ActionID: actionId, - SpellSchool: core.SpellSchoolArcane, - ProcMask: core.ProcMaskEmpty, - // TODO: Verify if SP affects the damage - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagNoMetrics | core.SpellFlagIgnoreAttackerModifiers, - - Cast: core.CastConfig{ - CD: core.Cooldown{ - Timer: character.NewTimer(), - Duration: time.Minute * 10, - }, - }, - - DamageMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - result := spell.CalcDamage(sim, &character.Unit, sim.Roll(343, 757), spell.OutcomeAlwaysHit) - if sim.Log != nil { - character.Log(sim, "Took %.1f damage from Gneuro-Logical Shock.", result.Damage) - } - character.RemoveHealth(sim, result.Damage) - buffAura.Activate(sim) - }, - - ExtraCastCondition: func(sim *core.Simulation, target *core.Unit) bool { - return !ee.Category.AnyActive() - }, - }) - - activationSpell := character.GetOrRegisterSpell(core.SpellConfig{ - ActionID: actionId, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagOffensiveEquipment, - - Cast: core.CastConfig{ - CD: core.Cooldown{ - Timer: character.NewTimer(), - Duration: time.Minute * 10, - }, - }, - - ApplyEffects: func(sim *core.Simulation, _ *core.Unit, _ *core.Spell) { - spell.Cast(sim, &character.Unit) - }, - }) - - character.AddMajorCooldown(core.MajorCooldown{ - Spell: activationSpell, - Priority: core.CooldownPriorityLow, - Type: core.CooldownTypeDPS, - }) - }) - - // Gneuro-Conductive Channeler's Hood - core.NewItemEffect(215381, func(agent core.Agent) { - character := agent.GetCharacter() - actionId := core.ActionID{SpellID: 437357} - - buffAura := character.GetOrRegisterAura(core.Aura{ - Label: "Gneuromantic Meditation", - ActionID: actionId, - Duration: time.Second * 20, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - character.AddStatDynamic(sim, stats.SpellPower, 50) - character.PseudoStats.ForceFullSpiritRegen = true - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - character.AddStatDynamic(sim, stats.SpellPower, -50) - character.PseudoStats.ForceFullSpiritRegen = false - }, - }) - - activationSpell := character.GetOrRegisterSpell(core.SpellConfig{ - ActionID: actionId, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagOffensiveEquipment, - - Cast: core.CastConfig{ - CD: core.Cooldown{ - Timer: character.NewTimer(), - Duration: time.Minute * 10, - }, - }, - - ApplyEffects: func(sim *core.Simulation, _ *core.Unit, _ *core.Spell) { - buffAura.Activate(sim) - }, - }) - - character.AddMajorCooldown(core.MajorCooldown{ - Spell: activationSpell, - Priority: core.CooldownPriorityLow, - Type: core.CooldownTypeDPS, - }) - }) - - /////////////////////////////////////////////////////////////////////////// - // Mail - /////////////////////////////////////////////////////////////////////////// - - // Rad-Resistant Scale Hood - // core.NewItemEffect(215114, func(agent core.Agent) { - // // Nothing to do - // }) - - // Glowing Hyperconductive Scale Coif - core.NewItemEffect(215114, func(agent core.Agent) { - character := agent.GetCharacter() - actionId := core.ActionID{SpellID: 437362} - - buffAura := character.GetOrRegisterAura(core.Aura{ - Label: "Hyperconductive Shock", - ActionID: actionId, - Duration: time.Second * 10, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - character.MultiplyCastSpeed(1.2) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - character.MultiplyCastSpeed(1 / 1.2) - }, - }) - - spell := character.RegisterSpell(core.SpellConfig{ - ActionID: actionId, - SpellSchool: core.SpellSchoolArcane, - ProcMask: core.ProcMaskEmpty, - // TODO: Verify if SP affects the damage - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagPassiveSpell | core.SpellFlagNoMetrics | core.SpellFlagIgnoreAttackerModifiers, - - Cast: core.CastConfig{ - CD: core.Cooldown{ - Timer: character.NewTimer(), - Duration: time.Minute * 10, - }, - }, - - DamageMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - result := spell.CalcDamage(sim, &character.Unit, sim.Roll(312, 668), spell.OutcomeAlwaysHit) - character.RemoveHealth(sim, result.Damage) - buffAura.Activate(sim) - }, - }) - - activationSpell := character.GetOrRegisterSpell(core.SpellConfig{ - ActionID: actionId, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagOffensiveEquipment, - - Cast: core.CastConfig{ - CD: core.Cooldown{ - Timer: character.NewTimer(), - Duration: time.Minute * 10, - }, - }, - - ApplyEffects: func(sim *core.Simulation, _ *core.Unit, _ *core.Spell) { - spell.Cast(sim, &character.Unit) - }, - }) - - character.AddMajorCooldown(core.MajorCooldown{ - Spell: activationSpell, - Priority: core.CooldownPriorityLow, - Type: core.CooldownTypeDPS, - }) - }) - - /////////////////////////////////////////////////////////////////////////// - // Plate - /////////////////////////////////////////////////////////////////////////// - - // Tempered Interference-Negating Helmet - core.NewItemEffect(215161, func(agent core.Agent) { - character := agent.GetCharacter() - actionId := core.ActionID{SpellID: 437377} - - buffAura := character.GetOrRegisterAura(core.Aura{ - Label: "Intense Concentration", - ActionID: actionId, - Duration: time.Second * 10, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - character.MultiplyAttackSpeed(sim, 1.2) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - character.MultiplyAttackSpeed(sim, 1.0/1.2) - }, - }) - - activationSpell := character.GetOrRegisterSpell(core.SpellConfig{ - ActionID: actionId, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagOffensiveEquipment, - - Cast: core.CastConfig{ - CD: core.Cooldown{ - Timer: character.NewTimer(), - Duration: time.Minute * 10, - }, - }, - - ApplyEffects: func(sim *core.Simulation, _ *core.Unit, _ *core.Spell) { - buffAura.Activate(sim) - }, - }) - - character.AddMajorCooldown(core.MajorCooldown{ - Spell: activationSpell, - Priority: core.CooldownPriorityLow, - Type: core.CooldownTypeDPS, - }) - }) - - // Reflective Truesilver Braincage - // core.NewItemEffect(215167, func(agent core.Agent) { - // // Nothing to do - // }) - - core.AddEffectsToTest = true -} diff --git a/sim/common/sod/crafted/phase_3.go b/sim/common/sod/crafted/phase_3.go deleted file mode 100644 index 604bebc65..000000000 --- a/sim/common/sod/crafted/phase_3.go +++ /dev/null @@ -1,250 +0,0 @@ -package crafted - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/stats" -) - -const ( - ShoulderplatesOfDread = 220738 - BalefulPauldrons = 220739 - FearmongersShoulderguards = 220740 - ScreamingChainPauldrons = 220741 - ShriekingSpaulders = 220742 - CacophonousChainShoulderguards = 220743 - WailingChainMantle = 220744 - MembraneOfDarkNeurosis = 220745 - ParanoiaMantle = 220747 - ShoulderpadsOfObsession = 220748 - MantleOfInsanity = 220749 - FracturedMindPauldrons = 220750 - ShoulderpadsOfTheDeranged = 220751 -) - -func init() { - core.AddEffectsToTest = false - - /////////////////////////////////////////////////////////////////////////// - // Cloth - /////////////////////////////////////////////////////////////////////////// - - // Mantle of Insanity - core.NewItemEffect(MantleOfInsanity, echoesOfInsanityEffect) - - // Fractured Mind Pauldrons - core.NewItemEffect(FracturedMindPauldrons, echoesOfMadnessEffect) - - // Shoulderpads of the Deranged - core.NewItemEffect(ShoulderpadsOfTheDeranged, func(agent core.Agent) { - character := agent.GetCharacter() - - if character.Level != 50 { - return - } - - procAura := character.NewTemporaryStatsAura("Echoes of the Depraved Proc", core.ActionID{SpellID: 446572}, stats.Stats{stats.SpellDamage: 30, stats.Dodge: 2}, time.Second*10) - - handler := func(sim *core.Simulation, _ *core.Spell, _ *core.SpellResult) { - procAura.Activate(sim) - } - - core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - ActionID: core.ActionID{SpellID: 446570}, - Name: "Echoes of the Depraved", - Callback: core.CallbackOnCastComplete, - ProcMask: core.ProcMaskSpellDamage, - ProcChance: 0.3, - ICD: time.Second * 40, - Handler: handler, - }) - }) - - /////////////////////////////////////////////////////////////////////////// - // Leather - /////////////////////////////////////////////////////////////////////////// - - // Membrane of Dark Neurosis - core.NewItemEffect(MembraneOfDarkNeurosis, echoesOfFearEffect) - - // Paranoia Mantle - core.NewItemEffect(ParanoiaMantle, echoesOfDreadEffect) - - // Shoulderpads of Obsession - core.NewItemEffect(ShoulderpadsOfObsession, echoesOfInsanityEffect) - - /////////////////////////////////////////////////////////////////////////// - // Mail - /////////////////////////////////////////////////////////////////////////// - - // Screaming Chain Pauldrons - core.NewItemEffect(ScreamingChainPauldrons, echoesOfMadnessEffect) - - // Shrieking Spaulders - core.NewItemEffect(ShriekingSpaulders, func(agent core.Agent) { - character := agent.GetCharacter() - - if character.Level != 50 { - return - } - - procAura := character.NewTemporaryStatsAura("Echoes of the Damned Proc", core.ActionID{SpellID: 446618}, stats.Stats{stats.AttackPower: 60}, time.Second*10) - - handler := func(sim *core.Simulation, _ *core.Spell, _ *core.SpellResult) { - procAura.Activate(sim) - } - - core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - ActionID: core.ActionID{SpellID: 446620}, - Name: "Echoes of the Damned", - Callback: core.CallbackOnCastComplete, - ProcMask: core.ProcMaskMeleeOrRanged, - ProcChance: 0.3, - ICD: time.Second * 40, - Handler: handler, - }) - }) - - // Cacophonous Chain Shoulderguards - core.NewItemEffect(CacophonousChainShoulderguards, echoesOfDreadEffect) - - // Wailing Chain Mantle - core.NewItemEffect(WailingChainMantle, echoesOfInsanityEffect) - - /////////////////////////////////////////////////////////////////////////// - // Plate - /////////////////////////////////////////////////////////////////////////// - - // Shoulderplates of Dread - core.NewItemEffect(ShoulderplatesOfDread, echoesOfDreadEffect) - - // Baleful Pauldrons - core.NewItemEffect(BalefulPauldrons, echoesOfInsanityEffect) - - // Fearmonger's Shoulderguards - core.NewItemEffect(FearmongersShoulderguards, echoesOfFearEffect) - - core.AddEffectsToTest = true -} - -func echoesOfFearEffect(agent core.Agent) { - character := agent.GetCharacter() - - if character.Level != 50 { - return - } - - procAura := character.NewTemporaryStatsAura("Echoes of Fear Proc", core.ActionID{SpellID: 446597}, stats.Stats{stats.SpellDamage: 50}, time.Second*10) - - handler := func(sim *core.Simulation, spell *core.Spell, _ *core.SpellResult) { - if core.ProcMaskRanged.Matches(spell.ProcMask) { - return - } - procAura.Activate(sim) - } - - core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - ActionID: core.ActionID{SpellID: 446592}, - Name: "Echoes of Fear", - Callback: core.CallbackOnCastComplete, - ProcMask: core.ProcMaskDirect, - ProcChance: 0.3, - ICD: time.Second * 40, - Handler: handler, - }) -} - -func echoesOfInsanityEffect(agent core.Agent) { - character := agent.GetCharacter() - - if character.Level != 50 { - return - } - - procAura := character.NewTemporaryStatsAura("Echoes of Insanity Proc", core.ActionID{SpellID: 446541}, stats.Stats{stats.HealingPower: 50}, time.Second*10) - - handler := func(sim *core.Simulation, _ *core.Spell, _ *core.SpellResult) { - procAura.Activate(sim) - } - - core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - ActionID: core.ActionID{SpellID: 446545}, - Name: "Echoes of Insanity", - Callback: core.CallbackOnHealDealt, - ProcMask: core.ProcMaskSpellHealing, - ProcChance: 0.3, - ICD: time.Second * 40, - Handler: handler, - }) -} - -func echoesOfMadnessEffect(agent core.Agent) { - character := agent.GetCharacter() - - if character.Level != 50 { - return - } - - procAura := character.GetOrRegisterAura(core.Aura{ - Label: "Echoes of Madness Proc", - ActionID: core.ActionID{SpellID: 446528}, - Duration: time.Second * 10, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - character.MultiplyCastSpeed(1.1) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - character.MultiplyCastSpeed(1 / 1.1) - }, - }) - - handler := func(sim *core.Simulation, _ *core.Spell, _ *core.SpellResult) { - procAura.Activate(sim) - } - - core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - ActionID: core.ActionID{SpellID: 446518}, - Name: "Echoes of Madness", - Callback: core.CallbackOnCastComplete, - ProcMask: core.ProcMaskSpellDamage, - ProcChance: 0.3, - ICD: time.Second * 40, - Handler: handler, - }) -} - -func echoesOfDreadEffect(agent core.Agent) { - character := agent.GetCharacter() - - if character.Level != 50 { - return - } - - procAura := character.GetOrRegisterAura(core.Aura{ - Label: "Echoes of Dread Proc", - ActionID: core.ActionID{SpellID: 446577}, - Duration: time.Second * 10, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - character.MultiplyAttackSpeed(sim, 1.05) - character.AddStatDynamic(sim, stats.AttackPower, 50) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - character.MultiplyAttackSpeed(sim, 1/1.05) - character.AddStatDynamic(sim, stats.AttackPower, -50) - }, - }) - - handler := func(sim *core.Simulation, _ *core.Spell, _ *core.SpellResult) { - procAura.Activate(sim) - } - - core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - ActionID: core.ActionID{SpellID: 446579}, - Name: "Echoes of Dread", - Callback: core.CallbackOnCastComplete, - ProcMask: core.ProcMaskMelee, - ProcChance: 0.3, - ICD: time.Second * 40, - Handler: handler, - }) -} diff --git a/sim/common/sod/crafted/phase_4.go b/sim/common/sod/crafted/phase_4.go deleted file mode 100644 index 98613dee2..000000000 --- a/sim/common/sod/crafted/phase_4.go +++ /dev/null @@ -1,126 +0,0 @@ -package crafted - -import ( - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/stats" -) - -// Keep these in alphabetical order. - -// https://www.wowhead.com/classic/item-set=1792/black-dragon-mail -var ItemSetBlackDragonMail = core.NewItemSet(core.ItemSet{ - Name: "Black Dragon Mail", - ID: 1792, - Bonuses: map[int32]core.ApplyEffect{ - // Improves your chance to hit with all spells and attacks by 1%. - 2: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.MeleeHit, 1) - character.AddStat(stats.SpellHit, 1) - }, - // Improves your chance to get a critical strike with all spells and attacks by 2%. - 3: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.MeleeCrit, 2*core.CritRatingPerCritChance) - character.AddStat(stats.SpellCrit, 2*core.SpellCritRatingPerCritChance) - }, - // +10 Fire Resistance. - 4: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.FireResistance, 10) - }, - }, -}) - -// https://www.wowhead.com/classic/item-set=1790/blue-dragon-mail -var ItemSetBlueDragonMail = core.NewItemSet(core.ItemSet{ - Name: "Blue Dragon Mail", - ID: 1790, - Bonuses: map[int32]core.ApplyEffect{ - // +4 All Resistances. - 2: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddResistances(4) - }, - // Increases damage and healing done by magical spells and effects by up to 28. - 3: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.SpellPower, 28) - }, - }, -}) - -// https://www.wowhead.com/classic/item-set=1793/devilsaur-armor -var ItemSetDevilsaurArmor = core.NewItemSet(core.ItemSet{ - Name: "Devilsaur Armor", - ID: 1793, - Bonuses: map[int32]core.ApplyEffect{ - // +10 Fire Resistance. - // Improves your chance to hit with all spells and attacks by 2%. - 2: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.FireResistance, 10) - character.AddStat(stats.MeleeHit, 2*core.MeleeHitRatingPerHitChance) - character.AddStat(stats.SpellHit, 2*core.SpellHitRatingPerHitChance) - }, - }, -}) - -// https://www.wowhead.com/classic/item-set=1791/green-dragon-mail -var ItemSetGreenDragonMail = core.NewItemSet(core.ItemSet{ - Name: "Green Dragon Mail", - ID: 1791, - Bonuses: map[int32]core.ApplyEffect{ - // Restores 3 mana per 5 sec. - 2: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.MP5, 3) - }, - // Allows 15% of your Mana regeneration to continue while casting. - 3: func(agent core.Agent) { - character := agent.GetCharacter() - character.PseudoStats.SpiritRegenRateCasting += .15 - }, - }, -}) - -// https://www.wowhead.com/classic/item-set=1789/volcanic-armor -var ItemSetVolcanicArmor = core.NewItemSet(core.ItemSet{ - Name: "Volcanic Armor", - ID: 1789, - Bonuses: map[int32]core.ApplyEffect{ - // +10 Fire Resistance. - 2: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.FireResistance, 10) - }, - // 5% chance of dealing 15 to 25 Fire damage on a successful melee attack. - 3: func(agent core.Agent) { - character := agent.GetCharacter() - procSpell := character.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 9057}, - SpellSchool: core.SpellSchoolFire, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskEmpty, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - spell.CalcAndDealDamage(sim, target, sim.Roll(15, 25), spell.OutcomeMagicHitAndCrit) - }, - }) - - core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - Name: "Firebolt Trigger (Volcanic Armor)", - Callback: core.CallbackOnSpellHitDealt, - Outcome: core.OutcomeLanded, - ProcMask: core.ProcMaskMelee, - ProcChance: .05, - Handler: func(sim *core.Simulation, _ *core.Spell, result *core.SpellResult) { - procSpell.Cast(sim, result.Target) - }, - }) - }, - }, -}) diff --git a/sim/common/sod/enchant_effects.go b/sim/common/sod/enchant_effects.go deleted file mode 100644 index 07b2ed8f5..000000000 --- a/sim/common/sod/enchant_effects.go +++ /dev/null @@ -1,91 +0,0 @@ -package sod - -import ( - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -const ( - WolfsheadTrophy = 7124 -) - -func init() { - core.AddEffectsToTest = false - - // Weapon - Dismantle - core.NewEnchantEffect(7210, func(agent core.Agent) { - character := agent.GetCharacter() - - procSpell := character.GetOrRegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 439164}, - SpellSchool: core.SpellSchoolNature, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskSpellDamage, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - spell.CalcAndDealDamage(sim, target, sim.Roll(60, 90), spell.OutcomeMagicHitAndCrit) - }, - }) - - aura := character.GetOrRegisterAura(core.Aura{ - Label: "Enchant Weapon - Dismantle", - Duration: core.NeverExpires, - OnReset: func(aura *core.Aura, sim *core.Simulation) { - aura.Activate(sim) - }, - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - // Dismantle only procs on hits that land - if !result.Landed() { - return - } - - // Dismantle only procs on Mechanical units - if result.Target.MobType != proto.MobType_MobTypeMechanical { - return - } - - // Dismantle only procs on direct attacks, not proc effects or DoT ticks - if !spell.Flags.Matches(core.SpellFlagNotAProc) && spell.ProcMask.Matches(core.ProcMaskProc|core.ProcMaskSpellDamageProc) { - return - } - - // TODO: Confirm: Dismantle can not proc itself - if spell == procSpell { - return - } - - // Main-Hand hits only trigger Dismantle if the MH weapon is enchanted with Dismantle - if core.ProcMaskMeleeMH.Matches(spell.ProcMask) && (character.GetMHWeapon() == nil || character.GetMHWeapon().Enchant.EffectID != 7210) { - return - } - - // Off-Hand hits only trigger Dismantle if the MH weapon is enchanted with Dismantle - if core.ProcMaskMeleeOH.Matches(spell.ProcMask) && (character.GetOHWeapon() == nil || character.GetOHWeapon().Enchant.EffectID != 7210) { - return - } - - if spell.ProcMask.Matches(core.ProcMaskSpellDamage) { - if sim.RandomFloat("Dismantle") < 0.10 { - // Spells proc both Main-Hand and Off-Hand if both are enchanted - if character.GetMHWeapon() != nil && character.GetMHWeapon().Enchant.EffectID == 7210 { - procSpell.Cast(sim, result.Target) - } - if character.GetOHWeapon() != nil && character.GetOHWeapon().Enchant.EffectID == 7210 { - procSpell.Cast(sim, result.Target) - } - } - } else if sim.RandomFloat("Dismantle") < 0.10 { - // Physical hits only proc on the hand that was hit with - procSpell.Cast(sim, result.Target) - } - }, - }) - - character.ItemSwap.RegisterOnSwapItemForEffect(7210, aura) - }) - - core.AddEffectsToTest = true -} diff --git a/sim/common/sod/item_effects.go b/sim/common/sod/item_effects.go deleted file mode 100644 index aaae8cc8a..000000000 --- a/sim/common/sod/item_effects.go +++ /dev/null @@ -1,108 +0,0 @@ -package sod - -import ( - "time" - - "github.com/wowsims/classic/sim/core" -) - -// Ordered by ID -const () - -func init() { - core.AddEffectsToTest = false - - // ! Please keep items ordered alphabetically within a given category ! - - core.AddEffectsToTest = true -} - -// For Automatic Crowd Pummeler and Druid's Catnip -func RegisterFiftyPercentHasteBuffCD(character *core.Character, actionID core.ActionID) { - aura := character.GetOrRegisterAura(core.Aura{ - Label: "Haste", - ActionID: core.ActionID{SpellID: 13494}, - Duration: time.Second * 30, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - character.MultiplyAttackSpeed(sim, 1.5) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - character.MultiplyAttackSpeed(sim, 1.0/1.5) - }, - }) - - spell := character.GetOrRegisterSpell(core.SpellConfig{ - ActionID: actionID, - Flags: core.SpellFlagNoOnCastComplete, - - Cast: core.CastConfig{ - CD: core.Cooldown{ - Timer: character.GetFiftyPercentHasteBuffCD(), - Duration: time.Minute * 3, - }, - }, - - ApplyEffects: func(sim *core.Simulation, _ *core.Unit, _ *core.Spell) { - aura.Activate(sim) - }, - }) - - character.AddMajorCooldown(core.MajorCooldown{ - Spell: spell, - Priority: core.CooldownPriorityDefault, - Type: core.CooldownTypeDPS, - }) -} - -func StormhammerChainLightningProcAura(agent core.Agent) { - character := agent.GetCharacter() - - maxHits := int(min(3, character.Env.GetNumTargets())) - procSpell := character.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 463946}, - SpellSchool: core.SpellSchoolNature, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskEmpty, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagPassiveSpell, - BonusCoefficient: 0.1, - DamageMultiplier: 1, - ThreatMultiplier: 1, - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - for numHits := 0; numHits < maxHits; numHits++ { - spell.CalcAndDealDamage(sim, target, sim.Roll(105, 145), spell.OutcomeMagicHitAndCrit) - target = character.Env.NextTargetUnit(target) - } - }, - }) - - core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - Name: "Chain Lightning (Skyrider's Masterwork Stormhammer Melee)", - Callback: core.CallbackOnSpellHitDealt, - Outcome: core.OutcomeLanded, - ProcMask: core.ProcMaskMelee, - SpellFlagsExclude: core.SpellFlagSuppressWeaponProcs, - PPM: 4, // Someone in the armemnts Discord tested it out to 4 PPM - Handler: func(sim *core.Simulation, _ *core.Spell, result *core.SpellResult) { - procSpell.Cast(sim, result.Target) - }, - }) - - icd := core.Cooldown{ - Timer: character.NewTimer(), - Duration: time.Millisecond * 100, - } - core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - Name: "Chain Lightning (Skyrider's Masterwork Stormhammer Spell)", - Callback: core.CallbackOnSpellHitDealt, - Outcome: core.OutcomeLanded, - ProcMask: core.ProcMaskSpellDamage, - ProcChance: .1, - Handler: func(sim *core.Simulation, _ *core.Spell, result *core.SpellResult) { - if !icd.IsReady(sim) { - return - } - procSpell.Cast(sim, result.Target) - icd.Use(sim) - }, - }) -} diff --git a/sim/common/sod/item_effects/phase_2.go b/sim/common/sod/item_effects/phase_2.go deleted file mode 100644 index 23385c0ea..000000000 --- a/sim/common/sod/item_effects/phase_2.go +++ /dev/null @@ -1,384 +0,0 @@ -package item_effects - -import ( - "time" - - "github.com/wowsims/classic/sim/common/itemhelpers" - "github.com/wowsims/classic/sim/common/sod" - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -const ( - AutomaticCrowdPummeler = 210741 - ElectromagneticHyperfluxReactivator = 213281 - ElectrocutionersNeedle = 213286 - ToxicRevengerTwo = 213291 - SuperchargedHeadchopper = 213296 - MachinistsGloves = 213319 - MiniaturizedCombustionChamber = 213347 - Shawarmageddon = 213105 - MekkatorquesArcanoShredder = 213409 - GyromaticExperiment420b = 213348 -) - -func init() { - core.AddEffectsToTest = false - - /////////////////////////////////////////////////////////////////////////// - // Cloth - /////////////////////////////////////////////////////////////////////////// - - // Electromagnetic Hyperflux Reactivator - core.NewItemEffect(ElectromagneticHyperfluxReactivator, func(agent core.Agent) { - character := agent.GetCharacter() - - forkedLightning := character.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 11828}, - SpellSchool: core.SpellSchoolNature, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskEmpty, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagPassiveSpell, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, _ *core.Unit, spell *core.Spell) { - for _, aoeTarget := range sim.Encounter.TargetUnits { - baseDamage := sim.Roll(153, 173) - spell.CalcAndDealDamage(sim, aoeTarget, baseDamage, spell.OutcomeMagicHitAndCrit) - } - }, - }) - - dmgShieldActionID := core.ActionID{SpellID: 11841} - - dmgShieldProc := character.RegisterSpell(core.SpellConfig{ - ActionID: dmgShieldActionID, - SpellSchool: core.SpellSchoolNature, - ProcMask: core.ProcMaskEmpty, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - spell.CalcAndDealDamage(sim, target, 5, spell.OutcomeMagicHit) - }, - }) - - dmgShieldAura := character.RegisterAura(core.Aura{ - Label: "Static Barrier", - ActionID: dmgShieldActionID, - Duration: time.Minute * 10, - OnSpellHitTaken: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if result.Landed() && spell.ProcMask.Matches(core.ProcMaskMelee) { - dmgShieldProc.Cast(sim, spell.Unit) - } - }, - }) - - activationSpell := character.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 11826}, - SpellSchool: core.SpellSchoolPhysical, - ProcMask: core.ProcMaskEmpty, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagOffensiveEquipment, - - Cast: core.CastConfig{ - CD: core.Cooldown{ - Timer: character.NewTimer(), - Duration: time.Minute * 30, - }, - }, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - dmgShieldAura.Activate(sim) - core.StartDelayedAction(sim, core.DelayedActionOptions{ - DoAt: sim.CurrentTime + 3*time.Second, - OnAction: func(s *core.Simulation) { - forkedLightning.Cast(sim, target) - }, - }) - }, - }) - - character.AddMajorCooldown(core.MajorCooldown{ - Spell: activationSpell, - Priority: core.CooldownPriorityDefault, - Type: core.CooldownTypeDPS, - ShouldActivate: func(_ *core.Simulation, _ *core.Character) bool { - // Only castable with manual APL Action - return false - }, - }) - }) - - /////////////////////////////////////////////////////////////////////////// - // Leather - /////////////////////////////////////////////////////////////////////////// - - // Machinist's Gloves - core.NewItemEffect(MachinistsGloves, func(agent core.Agent) { - character := agent.GetCharacter() - if character.CurrentTarget.MobType == proto.MobType_MobTypeMechanical { - character.PseudoStats.MobTypeAttackPower += 30 - } - }) - - /////////////////////////////////////////////////////////////////////////// - // Mail - /////////////////////////////////////////////////////////////////////////// - - /////////////////////////////////////////////////////////////////////////// - // Plate - /////////////////////////////////////////////////////////////////////////// - - /////////////////////////////////////////////////////////////////////////// - // Trinkets - /////////////////////////////////////////////////////////////////////////// - - // Miniaturized Combustion Chamber - core.NewItemEffect(MiniaturizedCombustionChamber, func(agent core.Agent) { - character := agent.GetCharacter() - actionID := core.ActionID{SpellID: 435167} - manaMetrics := character.NewManaMetrics(actionID) - - manaRoll := 0.0 - dmgRoll := 0.0 - - regChannel := character.GetOrRegisterSpell(core.SpellConfig{ - ActionID: actionID, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagPassiveSpell | core.SpellFlagChanneled, - - Cast: core.CastConfig{ - CD: core.Cooldown{ - Timer: character.NewTimer(), - Duration: time.Minute * 30, - }, - }, - - Dot: core.DotConfig{ - Aura: core.Aura{ - Label: "Miniaturized Combustion Chamber", - OnGain: func(aura *core.Aura, sim *core.Simulation) { - character.AutoAttacks.CancelAutoSwing(sim) - manaRoll = sim.RollWithLabel(1, 150, "Miniaturized Combustion Chamber") - dmgRoll = sim.RollWithLabel(1, 150, "Miniaturized Combustion Chamber") - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - character.AutoAttacks.EnableAutoSwing(sim) - }, - }, - SelfOnly: true, - NumberOfTicks: 10, - TickLength: time.Second, - - OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) { - character.AddMana(sim, manaRoll, manaMetrics) - character.RemoveHealth(sim, dmgRoll) - }, - }, - - ApplyEffects: func(sim *core.Simulation, _ *core.Unit, spell *core.Spell) { - spell.SelfHot().Apply(sim) - }, - }) - - character.AddMajorCooldown(core.MajorCooldown{ - Spell: regChannel, - Priority: core.CooldownPriorityDefault, - Type: core.CooldownTypeMana, - ShouldActivate: func(_ *core.Simulation, _ *core.Character) bool { - // Only castable with manual APL Action - return false - }, - }) - }) - - core.NewItemEffect(GyromaticExperiment420b, func(agent core.Agent) { - character := agent.GetCharacter() - - hasteAura := character.GetOrRegisterAura(core.Aura{ - Label: "Gyromatic Experiment 420b", - ActionID: core.ActionID{SpellID: 435899}, - Duration: time.Second * 20, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - character.MultiplyAttackSpeed(sim, 1.05) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - character.MultiplyAttackSpeed(sim, 1.0/1.05) - }, - }) - - chickenAura := character.GetOrRegisterAura(core.Aura{ - Label: "Cluck Cluck??", - ActionID: core.ActionID{SpellID: 435896}, - Duration: time.Second * 5, - }) - - activationSpell := character.GetOrRegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 435899}, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagOffensiveEquipment, - - Cast: core.CastConfig{ - CD: core.Cooldown{ - Timer: character.NewTimer(), - Duration: time.Minute * 30, - }, - }, - - ApplyEffects: func(sim *core.Simulation, _ *core.Unit, _ *core.Spell) { - if sim.RandomFloat("Gyromatic Experiment 420b") > 0.95 { - chickenAura.Activate(sim) - character.WaitUntil(sim, chickenAura.ExpiresAt()) - character.AutoAttacks.DelayMeleeBy(sim, time.Second*5) - } else { - hasteAura.Activate(sim) - } - }, - }) - - character.AddMajorCooldown(core.MajorCooldown{ - Spell: activationSpell, - Priority: core.CooldownPriorityDefault, - Type: core.CooldownTypeDPS, - }) - }) - - /////////////////////////////////////////////////////////////////////////// - // Weapons - /////////////////////////////////////////////////////////////////////////// - - // Automatic Crowd Pummeler - core.NewItemEffect(AutomaticCrowdPummeler, func(agent core.Agent) { - character := agent.GetCharacter() - sod.RegisterFiftyPercentHasteBuffCD(character, core.ActionID{ItemID: AutomaticCrowdPummeler}) - }) - - itemhelpers.CreateWeaponCoHProcDamage(ElectrocutionersNeedle, "Electrocutioner's Needle", 6.5, 434839, core.SpellSchoolNature, 25, 10, 0.05, core.DefenseTypeMagic) - - itemhelpers.CreateWeaponCoHProcDamage(SuperchargedHeadchopper, "Supercharged Headchopper", 1.5, 434842, core.SpellSchoolNature, 80, 20, 0.1, core.DefenseTypeMagic) - - itemhelpers.CreateWeaponProcSpell(ToxicRevengerTwo, "Toxic Revenger II", 3.0, func(character *core.Character) *core.Spell { - return character.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 435169}, - SpellSchool: core.SpellSchoolNature, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskEmpty, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - - Dot: core.DotConfig{ - Aura: core.Aura{ - Label: "Toxic Revenger II Poison Cloud", - }, - TickLength: 5 * time.Second, - NumberOfTicks: 3, - - OnSnapshot: func(sim *core.Simulation, target *core.Unit, dot *core.Dot, isRollover bool) { - dot.Snapshot(target, 30, isRollover) - }, - - OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) { - dot.CalcAndDealPeriodicSnapshotDamage(sim, target, dot.OutcomeTick) - }, - }, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - for _, aoeTarget := range sim.Encounter.TargetUnits { - result := spell.CalcOutcome(sim, aoeTarget, spell.OutcomeMagicHit) - if result.Landed() { - spell.Dot(aoeTarget).Apply(sim) - } - } - }, - }) - }) - - core.NewItemEffect(Shawarmageddon, func(agent core.Agent) { - character := agent.GetCharacter() - - actionID := core.ActionID{SpellID: 434488} - - fireStrike := character.GetOrRegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 434488}, - SpellSchool: core.SpellSchoolFire, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskSpellDamage, - - DamageMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - spell.CalcAndDealDamage(sim, target, 7.0, spell.OutcomeMagicHitAndCrit) - }, - }) - - spicyAura := character.RegisterAura(core.Aura{ - Label: "Spicy!", - ActionID: actionID, - Duration: time.Second * 30, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - character.MultiplyAttackSpeed(sim, 1.04) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - character.MultiplyAttackSpeed(sim, 1/1.04) - }, - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if !spell.ProcMask.Matches(core.ProcMaskMelee) { - return - } - - if result.Landed() { - fireStrike.Cast(sim, spell.Unit.CurrentTarget) - } - }, - }) - - spicy := character.RegisterSpell(core.SpellConfig{ - ActionID: actionID, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagOffensiveEquipment, - - Cast: core.CastConfig{ - IgnoreHaste: true, - CD: core.Cooldown{ - Timer: character.NewTimer(), - Duration: time.Minute * 2, - }, - }, - - ApplyEffects: func(sim *core.Simulation, _ *core.Unit, spell *core.Spell) { - spicyAura.Activate(sim) - }, - }) - - character.AddMajorCooldown(core.MajorCooldown{ - Spell: spicy, - Type: core.CooldownTypeDPS, - }) - }) - - // Mekkatorque's Arcano-Shredder - itemhelpers.CreateWeaponProcSpell(MekkatorquesArcanoShredder, "Mekkatorque", 5.0, func(character *core.Character) *core.Spell { - //procAuras := character.NewEnemyAuraArray(core.MekkatorqueFistDebuffAura) - - return character.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 434841}, - SpellSchool: core.SpellSchoolArcane, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskEmpty, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - BonusCoefficient: 0.05, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - if target.Level <= 45 { - spell.CalcAndDealDamage(sim, target, 30, spell.OutcomeMagicHitAndCrit) - //procAuras.Get(target).Activate(sim) - } - }, - }) - }) - - core.AddEffectsToTest = true -} diff --git a/sim/common/sod/item_effects/phase_3.go b/sim/common/sod/item_effects/phase_3.go deleted file mode 100644 index ff438f6a8..000000000 --- a/sim/common/sod/item_effects/phase_3.go +++ /dev/null @@ -1,597 +0,0 @@ -package item_effects - -import ( - "time" - - "github.com/wowsims/classic/sim/common/guardians" - "github.com/wowsims/classic/sim/common/itemhelpers" - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" - "github.com/wowsims/classic/sim/core/stats" -) - -const ( - // Ordered by ID - FistOfTheForsaken = 220578 - DragonsCry = 220582 - CobraFangClaw = 220588 - SerpentsStriker = 220589 - AtalaiBloodRitualMedallion = 220632 - AtalaiBloodRitualBadge = 220633 - AtalaiBloodRitualCharm = 220634 - ScalebaneGreataxe = 220965 - DarkmoonCardDecay = 221307 - DarkmoonCardOvergrowth = 221308 - DarkmoonCardSandstorm = 221309 - RoarOfTheDream = 221440 - RoarOfTheGuardian = 221442 - BloodthirstCrossbow = 221451 - FistOfStone = 223524 - BladeOfEternalDarkness = 223964 - SerpentsStrikerSlow = 224409 -) - -func init() { - core.AddEffectsToTest = false - - /////////////////////////////////////////////////////////////////////////// - // Cloth - /////////////////////////////////////////////////////////////////////////// - - /////////////////////////////////////////////////////////////////////////// - // Leather - /////////////////////////////////////////////////////////////////////////// - - /////////////////////////////////////////////////////////////////////////// - // Mail - /////////////////////////////////////////////////////////////////////////// - - /////////////////////////////////////////////////////////////////////////// - // Plate - /////////////////////////////////////////////////////////////////////////// - - /////////////////////////////////////////////////////////////////////////// - // Rings - /////////////////////////////////////////////////////////////////////////// - - core.NewItemEffect(RoarOfTheDream, func(agent core.Agent) { - character := agent.GetCharacter() - - procAura := character.NewTemporaryStatsAura("Roar of the Dream", core.ActionID{SpellID: 446706}, stats.Stats{stats.SpellDamage: 66}, time.Second*10) - core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - ActionID: core.ActionID{SpellID: 446705}, - Name: "Roar of the Dream Trigger", - Callback: core.CallbackOnCastComplete, - ProcMask: core.ProcMaskSpellOrSpellProc, - ProcChance: 0.05, - Handler: func(sim *core.Simulation, spell *core.Spell, _ *core.SpellResult) { - procAura.Activate(sim) - }, - }) - }) - - /////////////////////////////////////////////////////////////////////////// - // Trinkets - /////////////////////////////////////////////////////////////////////////// - - // https://www.wowhead.com/classic/item=220632/atalai-blood-ritual-medallion - // Increases your melee and ranged damage by 20 for 20 sec. Every time you hit a target, this bonus is reduced by 1. - core.NewItemEffect(AtalaiBloodRitualMedallion, func(agent core.Agent) { - character := agent.GetCharacter() - - actionID := core.ActionID{ItemID: AtalaiBloodRitualMedallion} - - buffAura := character.GetOrRegisterAura(core.Aura{ - Label: "Relentless Strength", - ActionID: actionID, - Duration: time.Second * 20, - MaxStacks: 20, - - OnGain: func(aura *core.Aura, sim *core.Simulation) { - aura.SetStacks(sim, aura.MaxStacks) - }, - OnStacksChange: func(aura *core.Aura, sim *core.Simulation, oldStacks, newStacks int32) { - character.PseudoStats.BonusPhysicalDamage += float64(newStacks - oldStacks) - }, - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if result.Landed() && spell.ProcMask.Matches(core.ProcMaskMeleeOrRanged) { - aura.RemoveStack(sim) - } - }, - }) - - triggerSpell := character.GetOrRegisterSpell(core.SpellConfig{ - ActionID: actionID, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagOffensiveEquipment, - - Cast: core.CastConfig{ - CD: core.Cooldown{ - Timer: character.NewTimer(), - Duration: time.Minute * 2, - }, - }, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - buffAura.Activate(sim) - }, - }) - - character.AddMajorCooldown(core.MajorCooldown{ - Spell: triggerSpell, - Type: core.CooldownTypeDPS, - }) - }) - - // https://www.wowhead.com/classic/item=220633/atalai-blood-ritual-badge - // Increases your armor by 1000 and defense skill by 20 for 20 sec. - // Every time you take melee or ranged damage, this bonus is reduced by 100 armor and 2 defense. - core.NewItemEffect(AtalaiBloodRitualBadge, func(agent core.Agent) { - character := agent.GetCharacter() - - actionID := core.ActionID{ItemID: AtalaiBloodRitualBadge} - bonusPerStack := stats.Stats{ - stats.Armor: 100, - stats.Defense: 2, - } - - buffAura := character.GetOrRegisterAura(core.Aura{ - Label: "Fragile Armor", - ActionID: actionID, - Duration: time.Second * 20, - MaxStacks: 10, - - OnGain: func(aura *core.Aura, sim *core.Simulation) { - aura.SetStacks(sim, aura.MaxStacks) - }, - OnStacksChange: func(aura *core.Aura, sim *core.Simulation, oldStacks, newStacks int32) { - bonusStats := bonusPerStack.Multiply(float64(newStacks - oldStacks)) - character.AddStatsDynamic(sim, bonusStats) - }, - OnSpellHitTaken: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if !spell.ProcMask.Matches(core.ProcMaskMeleeOrRanged) { - return - } - aura.RemoveStack(sim) - }, - }) - - triggerSpell := character.GetOrRegisterSpell(core.SpellConfig{ - ActionID: actionID, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagOffensiveEquipment, - - Cast: core.CastConfig{ - CD: core.Cooldown{ - Timer: character.NewTimer(), - Duration: time.Minute * 2, - }, - }, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - buffAura.Activate(sim) - }, - }) - - character.AddMajorCooldown(core.MajorCooldown{ - Spell: triggerSpell, - Type: core.CooldownTypeSurvival, - }) - }) - - // https://www.wowhead.com/classic/item=220634/atalai-blood-ritual-charm - // Increases your spell damage by up to 96 and your healing by up to 192 for 20 sec. - // Every time you cast a spell, the bonus is reduced by 8 spell damage and 16 healing. - core.NewItemEffect(AtalaiBloodRitualCharm, func(agent core.Agent) { - character := agent.GetCharacter() - - actionID := core.ActionID{ItemID: AtalaiBloodRitualCharm} - bonusPerStack := stats.Stats{ - stats.SpellDamage: 8, - stats.HealingPower: 16, - } - - buffAura := character.GetOrRegisterAura(core.Aura{ - Label: "Unrestrained Power", - ActionID: actionID, - Duration: time.Second * 20, - MaxStacks: 12, - - OnGain: func(aura *core.Aura, sim *core.Simulation) { - aura.SetStacks(sim, aura.MaxStacks) - }, - OnStacksChange: func(aura *core.Aura, sim *core.Simulation, oldStacks, newStacks int32) { - bonusStats := bonusPerStack.Multiply(float64(newStacks - oldStacks)) - character.AddStatsDynamic(sim, bonusStats) - }, - OnCastComplete: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell) { - if !spell.ProcMask.Matches(core.ProcMaskSpellDamage) { - return - } - aura.RemoveStack(sim) - }, - }) - - triggerSpell := character.GetOrRegisterSpell(core.SpellConfig{ - ActionID: actionID, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagOffensiveEquipment, - - Cast: core.CastConfig{ - CD: core.Cooldown{ - Timer: character.NewTimer(), - Duration: time.Minute * 2, - }, - }, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - buffAura.Activate(sim) - }, - }) - - character.AddMajorCooldown(core.MajorCooldown{ - Spell: triggerSpell, - Priority: core.CooldownPriorityDefault, - Type: core.CooldownTypeDPS, - }) - }) - - core.NewItemEffect(DarkmoonCardDecay, func(agent core.Agent) { - character := agent.GetCharacter() - - decayAura := character.GetOrRegisterAura(core.Aura{ - Label: "DMC Decay", - ActionID: core.ActionID{SpellID: 446393}, - Duration: core.NeverExpires, - MaxStacks: 5, - }) - - decayStackedSpell := character.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 446810}, - SpellSchool: core.SpellSchoolShadow, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskEmpty, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagPassiveSpell, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - spell.CalcAndDealDamage(sim, target, sim.Roll(225, 375), spell.OutcomeMagicHitAndCrit) - }, - }) - - decayProcSpell := character.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 446393}, - SpellSchool: core.SpellSchoolShadow, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskEmpty, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagPassiveSpell | core.SpellFlagBinary, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - result := spell.CalcAndDealDamage(sim, target, 40, spell.OutcomeMagicHit) - if result.Landed() { - spell.CalcAndDealHealing(sim, &character.Unit, result.Damage, spell.OutcomeHealing) - decayAura.Activate(sim) - decayAura.AddStack(sim) - } - if decayAura.GetStacks() == 5 { - decayStackedSpell.Cast(sim, target) - decayAura.Deactivate(sim) - } - }, - }) - - // Custom ICD so it can be shared by both proc triggers - icd := core.Cooldown{ - Timer: character.NewTimer(), - Duration: time.Second * 3, - } - - handler := func(sim *core.Simulation, spell *core.Spell, _ *core.SpellResult) { - if !icd.IsReady(sim) { - return - } - - icd.Use(sim) - decayProcSpell.Cast(sim, character.CurrentTarget) - } - - hitAura := core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - ActionID: core.ActionID{SpellID: 446392}, - Name: "DMC Decay Spell Hit", - Callback: core.CallbackOnSpellHitDealt, - Outcome: core.OutcomeLanded, - ProcMask: core.ProcMaskMelee | core.ProcMaskRanged, - PPM: 7.0, // Estimate from log - Handler: handler, - }) - hitAura.Icd = &icd - - castAura := core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - ActionID: core.ActionID{SpellID: 450110}, - Name: "DMC Decay Spell Cast", - Callback: core.CallbackOnCastComplete, - ProcMask: core.ProcMaskSpellDamage, - ProcChance: 0.35, - Handler: handler, - }) - castAura.Icd = &icd - }) - - core.NewItemEffect(DarkmoonCardSandstorm, func(agent core.Agent) { - character := agent.GetCharacter() - - tickSpell := character.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 449288}, - SpellSchool: core.SpellSchoolNature, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskEmpty, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagPassiveSpell, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - spell.CalcAndDealDamage(sim, target, sim.Roll(50, 100), spell.OutcomeMagicCrit) - }, - }) - - // Sandstorm lasts for 10 seconds and moves in an outward spiral. It seems to be able to hit the same boss target - // multiple times during this duration, especially depending on size and positioning. - // On Hakkar seems to on average hit anywhere from 1-3 times - procSpell := character.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 446388}, - SpellSchool: core.SpellSchoolNature, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskEmpty, - - Dot: core.DotConfig{ - IsAOE: true, - Aura: core.Aura{ - Label: "Sandstorm Hit", - }, - NumberOfTicks: 1, - TickLength: time.Second * 1, - - OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) { - for _, aoeTarget := range sim.Encounter.TargetUnits { - tickSpell.Cast(sim, aoeTarget) - } - }, - }, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - dot := spell.AOEDot() - dot.NumberOfTicks = int32(sim.Roll(1, 3)) - dot.Apply(sim) - dot.TickOnce(sim) - }, - }) - - // Custom ICD so it can be shared by both proc triggers - icd := core.Cooldown{ - Timer: character.NewTimer(), - Duration: time.Second * 8, - } - - handler := func(sim *core.Simulation, spell *core.Spell, _ *core.SpellResult) { - if !icd.IsReady(sim) { - return - } - - icd.Use(sim) - procSpell.Cast(sim, character.CurrentTarget) - } - - hitAura := core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - ActionID: core.ActionID{SpellID: 446389}, - Name: "Sandstorm Spell Hit", - Callback: core.CallbackOnSpellHitDealt, - Outcome: core.OutcomeLanded, - ProcMask: core.ProcMaskMelee | core.ProcMaskRanged, - PPM: 10.0, // Estimate from log - Handler: handler, - }) - hitAura.Icd = &icd - - core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - ActionID: core.ActionID{SpellID: 446389}, - Name: "Sandstorm Spell Cast", - Callback: core.CallbackOnCastComplete, - ProcMask: core.ProcMaskSpellDamage, - ProcChance: 0.30, - Handler: handler, - }) - }) - - core.NewSimpleStatOffensiveTrinketEffect(RoarOfTheGuardian, stats.Stats{stats.AttackPower: 70, stats.RangedAttackPower: 70}, time.Second*20, time.Minute*5) - - /////////////////////////////////////////////////////////////////////////// - // Weapons - /////////////////////////////////////////////////////////////////////////// - - itemhelpers.CreateWeaponProcSpell(FistOfTheForsaken, "Fist of the Forsaken", 7.0, func(character *core.Character) *core.Spell { - actionID := core.ActionID{SpellID: 446317} - healthMetrics := character.NewHealthMetrics(actionID) - - return character.RegisterSpell(core.SpellConfig{ - ActionID: actionID, - SpellSchool: core.SpellSchoolShadow, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskEmpty, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - BonusCoefficient: .20, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - result := spell.CalcAndDealDamage(sim, target, 39, spell.OutcomeAlwaysHit) - character.GainHealth(sim, result.Damage, healthMetrics) - }, - }) - }) - - core.NewItemEffect(DragonsCry, func(agent core.Agent) { - character := agent.GetCharacter() - - procMask := character.GetProcMaskForItem(DragonsCry) - - core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - Name: "Emerald Dragon Whelp Proc", - Callback: core.CallbackOnSpellHitDealt, - Outcome: core.OutcomeLanded, - ProcMask: procMask, - PPM: 1.0, // Reported by armaments discord - ICD: time.Minute * 1, - Handler: func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - for _, petAgent := range character.PetAgents { - if whelp, ok := petAgent.(*guardians.EmeraldDragonWhelp); ok { - whelp.EnableWithTimeout(sim, whelp, time.Second*15) - break - } - } - }, - }) - }) - - core.NewItemEffect(CobraFangClaw, func(agent core.Agent) { - character := agent.GetCharacter() - - procMask := character.GetProcMaskForItem(CobraFangClaw) - ppmm := character.AutoAttacks.NewPPMManager(1.0, procMask) - - character.RegisterAura(core.Aura{ - Label: "Cobra Fang Claw Thrash", - Duration: core.NeverExpires, - OnReset: func(aura *core.Aura, sim *core.Simulation) { - aura.Activate(sim) - }, - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if !result.Landed() { - return - } - if !spell.ProcMask.Matches(procMask) { - return - } - - if ppmm.Proc(sim, procMask, "Cobra Fang Claw Extra Attack") { - character.AutoAttacks.ExtraMHAttackProc(sim, 1, core.ActionID{SpellID: 220588}, spell) - } - }, - }) - }) - - serpentsStrikerEffect := func(character *core.Character) *core.Spell { - //procAuras := character.NewEnemyAuraArray(core.SerpentsStrikerFistDebuffAura) - - return character.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 447894}, - SpellSchool: core.SpellSchoolNature, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskEmpty, - Flags: core.SpellFlagPoison | core.SpellFlagNoOnCastComplete | core.SpellFlagPassiveSpell, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - BonusCoefficient: 0.05, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - if target.Level <= 55 { - spell.CalcAndDealDamage(sim, target, 50, spell.OutcomeMagicHitAndCrit) - - //procAuras.Get(target).Activate(sim) - } - }, - }) - } - itemhelpers.CreateWeaponProcSpell(SerpentsStriker, "Serpent's Striker", 5.0, serpentsStrikerEffect) - itemhelpers.CreateWeaponProcSpell(SerpentsStrikerSlow, "Serpent's Striker", 5.0, serpentsStrikerEffect) - - core.NewItemEffect(BloodthirstCrossbow, func(agent core.Agent) { - character := agent.GetCharacter() - - healthMetrics := character.NewHealthMetrics(core.ActionID{SpellID: 446725}) - - thirstForBlood := character.GetOrRegisterSpell(core.SpellConfig{ - ActionID: healthMetrics.ActionID, - SpellSchool: core.SpellSchoolShadow, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskEmpty, - DamageMultiplier: 1, - ThreatMultiplier: 1, - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - // TODO this has a "HEALTH_LEECH" and a "HEAL" effect, so maybe it heals for leeched amount + heal? - spell.CalcAndDealDamage(sim, target, 5, spell.OutcomeMagicHit) - character.GainHealth(sim, 5, healthMetrics) - }, - }) - - core.MakePermanent(character.GetOrRegisterAura(core.Aura{ - Label: "Bloodthirst Crossbow Proc Aura", - OnSpellHitDealt: func(_ *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if result.Landed() && spell.ProcMask.Matches(core.ProcMaskRanged) { - thirstForBlood.Cast(sim, result.Target) - } - }, - })) - }) - - itemhelpers.CreateWeaponProcSpell(FistOfStone, "Fist of Stone", 1.0, func(character *core.Character) *core.Spell { - manaMetrics := character.NewManaMetrics(core.ActionID{SpellID: 21951}) - - return character.RegisterSpell(core.SpellConfig{ - ActionID: manaMetrics.ActionID, - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - character.AddMana(sim, 50, manaMetrics) - }, - }) - }) - - core.NewItemEffect(BladeOfEternalDarkness, func(agent core.Agent) { - character := agent.GetCharacter() - - actionID := core.ActionID{SpellID: 27860} - manaMetrics := character.NewManaMetrics(actionID) - - procSpell := character.RegisterSpell(core.SpellConfig{ - ActionID: actionID, - SpellSchool: core.SpellSchoolShadow, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskEmpty, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - spell.CalcAndDealDamage(sim, target, 100, spell.OutcomeAlwaysHit) - character.AddMana(sim, 100, manaMetrics) - }, - }) - - handler := func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if result.Damage > 0 { - procSpell.Cast(sim, character.CurrentTarget) - } - } - - core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - ActionID: core.ActionID{SpellID: 21978}, - Name: "Engulfing Shadows", - Callback: core.CallbackOnSpellHitDealt, - ProcMask: core.ProcMaskSpellDamage, - ProcChance: .10, - Handler: handler, - }) - }) - - core.NewItemEffect(ScalebaneGreataxe, func(agent core.Agent) { - character := agent.GetCharacter() - - if character.CurrentTarget.MobType == proto.MobType_MobTypeDragonkin { - character.PseudoStats.MobTypeAttackPower += 117 - } - }) - - core.AddEffectsToTest = true -} diff --git a/sim/common/sod/item_effects/phase_4.go b/sim/common/sod/item_effects/phase_4.go deleted file mode 100644 index a5e9c9e87..000000000 --- a/sim/common/sod/item_effects/phase_4.go +++ /dev/null @@ -1,185 +0,0 @@ -package item_effects - -import ( - "time" - - "github.com/wowsims/classic/sim/common/itemhelpers" - "github.com/wowsims/classic/sim/common/sod" - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" - "github.com/wowsims/classic/sim/core/stats" -) - -const ( - CraftOfTheShadows = 227280 - SkyridersMasterworkStormhammer = 227886 - DukesDomain = 227915 - AccursedChalice = 228078 - GerminatingPoisonseed = 228081 - GloamingTreeheart = 228083 - WoodcarvedMoonstalker = 228089 - TheMoltenCore = 228122 - FistOfTheFiresworn = 228139 - BroodmothersBrooch = 228163 - TreantsBane = 228486 - FistOfTheFireswornMolten = 229374 -) - -func init() { - core.AddEffectsToTest = false - - /////////////////////////////////////////////////////////////////////////// - // Weapons - /////////////////////////////////////////////////////////////////////////// - - // https://www.wowhead.com/classic/item=228139/fist-of-the-firesworn - // Chance on hit: Blasts the enemy for 70 Fire damage. - // TODO: Proc rate assumed and needs testing - itemhelpers.CreateWeaponCoHProcDamage(FistOfTheFiresworn, "Fist of the Firesworn", 1.0, 461896, core.SpellSchoolFire, 70, 0, 0.15, core.DefenseTypeMagic) - itemhelpers.CreateWeaponCoHProcDamage(FistOfTheFireswornMolten, "Fist of the Firesworn", 1.0, 461896, core.SpellSchoolFire, 70, 0, 0.15, core.DefenseTypeMagic) - - // https://www.wowhead.com/classic/item=227886/skyriders-masterwork-stormhammer - // Chance on hit: Blasts up to 3 targets for 105 to 145 Nature damage. - // Estimated based on data from WoW Armaments Discord - core.NewItemEffect(SkyridersMasterworkStormhammer, sod.StormhammerChainLightningProcAura) - - // https://www.wowhead.com/classic/item=228486/treants-bane - // Equip: +75 Attack Power when fighting Elementals. - core.NewItemEffect(TreantsBane, func(agent core.Agent) { - character := agent.GetCharacter() - if character.CurrentTarget.MobType == proto.MobType_MobTypeElemental { - character.PseudoStats.MobTypeAttackPower += 75 - } - }) - - /////////////////////////////////////////////////////////////////////////// - // Trinkets - /////////////////////////////////////////////////////////////////////////// - - // https://www.wowhead.com/classic/item=228078/accursed-chalice - // Use: Increases your Strength by 80. Effect lasts for 20 sec. (2 Min Cooldown) - core.NewSimpleStatOffensiveTrinketEffect(AccursedChalice, stats.Stats{stats.Strength: 80}, time.Second*20, time.Minute*2) - - // https://www.wowhead.com/classic/item=228163/broodmothers-brooch - // Use: Increases the block value of your shield by 128 for 20 sec. (2 Min Cooldown) - core.NewSimpleStatDefensiveTrinketEffect(BroodmothersBrooch, stats.Stats{stats.BlockValue: 128}, time.Second*20, time.Minute*2) - - // https://www.wowhead.com/classic/item=227915/dukes-domain - // Use: Expand the Duke's Domain, increasing the Fire Resistance of those who reside within by 50. Lasts for 15 sec. (1 Min, 30 Sec Cooldown) - // TODO: Raid-wide effect if we ever do raid sim - core.NewSimpleStatOffensiveTrinketEffect(DukesDomain, stats.Stats{stats.BlockValue: 128}, time.Second*20, time.Second*90) - - // https://www.wowhead.com/classic/item=228081/germinating-poisonseed - // Use: Increases your Nature Damage by up to 115. Effect lasts for 20 sec. (2 Min Cooldown) - core.NewSimpleStatOffensiveTrinketEffect(GerminatingPoisonseed, stats.Stats{stats.NaturePower: 115}, time.Second*20, time.Minute*2) - - // https://www.wowhead.com/classic/item=228083/gloaming-treeheart - // Use: Increases your Nature Resistance by 90. Effect lasts for 30 sec. (3 Min Cooldown) - core.NewSimpleStatDefensiveTrinketEffect(GloamingTreeheart, stats.Stats{stats.NatureResistance: 90}, time.Second*30, time.Minute*3) - - // https://www.wowhead.com/classic/item=228089/woodcarved-moonstalker - // Use: Increases your Strength by 60. Effect lasts for 15 sec. (1 Min, 30 Sec Cooldown) - core.NewItemEffect(WoodcarvedMoonstalker, func(agent core.Agent) { - character := agent.GetCharacter() - - // Woodcarved Moonstalker isn't unique, but presumably the on-use has a shared CD - if character.HasAura("Woodcarved Moonstalker") { - return - } - - duration := time.Second * 15 - - aura := character.RegisterAura(core.Aura{ - ActionID: core.ActionID{ItemID: WoodcarvedMoonstalker}, - Label: "Woodcarved Moonstalker", - Duration: duration, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - character.AddStatDynamic(sim, stats.Strength, 60) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - character.AddStatDynamic(sim, stats.Strength, -60) - }, - }) - - spell := character.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{ItemID: WoodcarvedMoonstalker}, - ProcMask: core.ProcMaskEmpty, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagOffensiveEquipment, - - Cast: core.CastConfig{ - CD: core.Cooldown{ - Timer: character.NewTimer(), - Duration: time.Second * 90, - }, - SharedCD: core.Cooldown{ - Timer: character.GetOffensiveTrinketCD(), - Duration: duration, - }, - }, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - aura.Activate(sim) - }, - }) - - character.AddMajorCooldown(core.MajorCooldown{ - Type: core.CooldownTypeDPS, - Spell: spell, - }) - }) - - // https://www.wowhead.com/classic/item=228122/the-molten-core - // Equip: Inflicts 20 Fire damage to nearby enemies every 2 sec. - core.NewItemEffect(TheMoltenCore, func(agent core.Agent) { - character := agent.GetCharacter() - - actionID := core.ActionID{SpellID: 461228} - - spell := character.RegisterSpell(core.SpellConfig{ - ActionID: actionID, - SpellSchool: core.SpellSchoolFire, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskEmpty, - - BonusCoefficient: .045, - DamageMultiplier: 1, - ThreatMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - spell.CalcAndDealDamage(sim, target, 20, spell.OutcomeAlwaysHit) - }, - }) - - character.RegisterAura(core.Aura{ - Label: "The Molten Core Trigger", - Duration: core.NeverExpires, - OnReset: func(aura *core.Aura, sim *core.Simulation) { - core.StartPeriodicAction(sim, core.PeriodicActionOptions{ - Period: time.Second * 2, - Priority: core.ActionPriorityDOT, // High prio - OnAction: func(sim *core.Simulation) { - for _, aoeTarget := range sim.Encounter.TargetUnits { - spell.Cast(sim, aoeTarget) - } - }, - }) - }, - }) - }) - - /////////////////////////////////////////////////////////////////////////// - // Other - /////////////////////////////////////////////////////////////////////////// - - // https://www.wowhead.com/classic/item=227280/craft-of-the-shadows - // Equip: Increases your maximum Energy by 10. - core.NewItemEffect(CraftOfTheShadows, func(agent core.Agent) { - character := agent.GetCharacter() - - if character.HasEnergyBar() { - character.EnableEnergyBar(character.MaxEnergy() + 10) - } - }) - - core.AddEffectsToTest = true -} diff --git a/sim/common/sod/item_effects/phase_5.go b/sim/common/sod/item_effects/phase_5.go deleted file mode 100644 index cea2000dc..000000000 --- a/sim/common/sod/item_effects/phase_5.go +++ /dev/null @@ -1,431 +0,0 @@ -package item_effects - -import ( - "time" - - "github.com/wowsims/classic/sim/common/vanilla" - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" - "github.com/wowsims/classic/sim/core/stats" -) - -const ( - Heartstriker = 230253 - ClawOfChromaggus = 230794 - WillOfArlokk = 230939 - NatPaglesFishTerminator = 231016 - BlazefuryRetributer = 231275 - Stormwrath = 231387 - WrathOfWray = 231779 - LightningsCell = 231784 - Windstriker = 231817 - NatPaglesFishTerminatorBloodied = 231848 - WillOfArlokkBloodied = 231850 - BlazefuryRetributerBloodied = 231862 - ClawOfChromaggusShadowflame = 232557 -) - -func init() { - core.AddEffectsToTest = false - - /////////////////////////////////////////////////////////////////////////// - // Weapons - /////////////////////////////////////////////////////////////////////////// - - // https://www.wowhead.com/classic/item=231275/blazefury-retributer - // Adds 2 fire damage to your melee attacks. - core.NewItemEffect(BlazefuryRetributer, func(agent core.Agent) { - vanilla.BlazefuryTriggerAura(agent.GetCharacter(), 468169, core.SpellSchoolFire, 2) - }) - // https://www.wowhead.com/classic/item=231862/blazefury-retributer - core.NewItemEffect(BlazefuryRetributerBloodied, func(agent core.Agent) { - vanilla.BlazefuryTriggerAura(agent.GetCharacter(), 468169, core.SpellSchoolFire, 2) - }) - - // https://www.wowhead.com/classic/item=230794/claw-of-chromaggus - // Your offensive spellcasts increase the spell damage of a random school of magic by 50 for 10 sec. (9.5s cooldown) - core.NewItemEffect(ClawOfChromaggus, func(agent core.Agent) { - ClawOfChromaggusEffect(agent.GetCharacter()) - }) - // https://www.wowhead.com/classic/item=232557/claw-of-chromaggus - core.NewItemEffect(ClawOfChromaggusShadowflame, func(agent core.Agent) { - ClawOfChromaggusEffect(agent.GetCharacter()) - }) - - // https://www.wowhead.com/classic/item=231016/nat-pagles-fish-terminator - // Chance on hit: Zap nearby enemies dealing 175 to 225 damage to them. Will affect up to 4 targets. - core.NewItemEffect(NatPaglesFishTerminator, fishTerminatorEffect) - // https://www.wowhead.com/classic/item=231848/nat-pagles-fish-terminator - core.NewItemEffect(NatPaglesFishTerminatorBloodied, fishTerminatorEffect) - - // https://www.wowhead.com/classic/item=231387/stormwrath-sanctified-shortblade-of-the-galefinder - // Equip: Damaging non-periodic spells have a chance to blast up to 3 targets for 181 to 229. - // (Proc chance: 10%, 100ms cooldown) - core.NewItemEffect(Stormwrath, func(agent core.Agent) { - character := agent.GetCharacter() - - maxHits := int(min(3, character.Env.GetNumTargets())) - procSpell := character.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 468670}, - SpellSchool: core.SpellSchoolNature, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskEmpty, - BonusCoefficient: 0.15, - DamageMultiplier: 1, - ThreatMultiplier: 1, - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - for numHits := 0; numHits < maxHits; numHits++ { - spell.CalcAndDealDamage(sim, target, sim.Roll(180, 230), spell.OutcomeMagicHitAndCrit) - target = character.Env.NextTargetUnit(target) - } - }, - }) - - icd := core.Cooldown{ - Timer: character.NewTimer(), - Duration: time.Millisecond * 100, - } - core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - Name: "Chain Lightning (Stormwrath)", - Callback: core.CallbackOnSpellHitDealt, - Outcome: core.OutcomeLanded, - ProcMask: core.ProcMaskSpellDamage, - ProcChance: .10, - Handler: func(sim *core.Simulation, _ *core.Spell, result *core.SpellResult) { - if !icd.IsReady(sim) { - return - } - procSpell.Cast(sim, result.Target) - icd.Use(sim) - }, - }) - }) - - // https://www.wowhead.com/classic/item=230939/will-of-arlokk - // Use: Calls forth a charmed snake to worship you, increasing your Spirit by 200 for 20 sec. (2 Min Cooldown) - core.NewItemEffect(WillOfArlokk, func(agent core.Agent) { - character := agent.GetCharacter() - makeWillOfWarlookOnUseEffect(character, WillOfArlokk) - }) - core.NewItemEffect(WillOfArlokkBloodied, func(agent core.Agent) { - character := agent.GetCharacter() - makeWillOfWarlookOnUseEffect(character, WillOfArlokkBloodied) - }) - - // https://www.wowhead.com/classic/item=231817/windstriker - // Chance on hit: All attacks are guaranteed to land and will be critical strikes for the next 3 sec. - core.NewItemEffect(Windstriker, func(agent core.Agent) { - character := agent.GetCharacter() - - effectAura := character.NewTemporaryStatsAura("Felstriker", core.ActionID{SpellID: 16551}, stats.Stats{stats.MeleeCrit: 100 * core.CritRatingPerCritChance, stats.MeleeHit: 100 * core.MeleeHitRatingPerHitChance}, time.Second*3) - procMask := character.GetProcMaskForItem(Windstriker) - core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - Name: "Felstriker Trigger", - Callback: core.CallbackOnSpellHitDealt, - Outcome: core.OutcomeLanded, - ProcMask: procMask, - SpellFlagsExclude: core.SpellFlagSuppressWeaponProcs, - PPM: 0.6, - Handler: func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - effectAura.Activate(sim) - }, - }) - }) - - /////////////////////////////////////////////////////////////////////////// - // Trinkets - /////////////////////////////////////////////////////////////////////////// - - // https://www.wowhead.com/classic/item=231784/lightnings-cell - // You gain a charge of Gathering Storm each time you cause a damaging spell critical strike. - // When you reach 3 charges of Gathering Storm, they will release, firing an Unleashed Storm for 277 to 323 damage. - // Gathering Storm cannot be gained more often than once every 2 sec. (2s cooldown) - core.NewItemEffect(LightningsCell, func(agent core.Agent) { - character := agent.GetCharacter() - - unleashedStormSpell := character.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 468782}, - SpellSchool: core.SpellSchoolNature, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskEmpty, - Flags: core.SpellFlagNoOnCastComplete, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - spell.CalcAndDealDamage(sim, target, sim.Roll(277, 323), spell.OutcomeMagicHitAndCrit) - }, - }) - - chargeAura := character.RegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 468780}, - Label: "Lightning's Cell", - Duration: core.NeverExpires, - MaxStacks: 3, - OnStacksChange: func(aura *core.Aura, sim *core.Simulation, oldStacks, newStacks int32) { - if aura.GetStacks() == aura.MaxStacks { - unleashedStormSpell.Cast(sim, aura.Unit.CurrentTarget) - aura.Deactivate(sim) - } - }, - }) - - core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - Name: "Lightning's Cell Trigger", - Callback: core.CallbackOnSpellHitDealt, - Outcome: core.OutcomeCrit, - ProcMask: core.ProcMaskSpellDamage | core.ProcMaskSpellDamageProc, // Procs on procs - ICD: time.Millisecond * 2000, - Handler: func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - chargeAura.Activate(sim) - chargeAura.AddStack(sim) - }, - }) - }) - - // https://www.wowhead.com/classic/item=230253/hearstriker - // Equip: 2% chance on ranged hit to gain 1 extra attack. (Proc chance: 1%, 1s cooldown) // obviously something wrong here lol - core.NewItemEffect(Heartstriker, func(agent core.Agent) { - character := agent.GetCharacter() - if !character.AutoAttacks.AutoSwingRanged { - return - } - - core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - Name: "Heartstrike", - Callback: core.CallbackOnSpellHitDealt, - Outcome: core.OutcomeLanded, - ProcMask: core.ProcMaskRanged, - ProcChance: 0.02, - ICD: time.Second * 1, - SpellFlagsExclude: core.SpellFlagSuppressEquipProcs, - - Handler: func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - spell.Unit.AutoAttacks.ExtraRangedAttack(sim, 1, core.ActionID{SpellID: 461164}, spell.ActionID) - }, - }) - }) - - core.NewSimpleStatOffensiveTrinketEffect(WrathOfWray, stats.Stats{stats.Strength: 92}, time.Second*20, time.Minute*2) - - core.AddEffectsToTest = true -} - -func makeWillOfWarlookOnUseEffect(character *core.Character, itemID int32) { - actionID := core.ActionID{ItemID: itemID} - - buffAura := character.RegisterAura(core.Aura{ - ActionID: actionID, - Label: "Serpentine Spirit", - Duration: time.Second * 20, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - character.AddStatDynamic(sim, stats.Spirit, 200) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - character.AddStatDynamic(sim, stats.Spirit, -200) - }, - }) - - spell := character.RegisterSpell(core.SpellConfig{ - ActionID: actionID, - SpellSchool: core.SpellSchoolPhysical, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagOffensiveEquipment, - Cast: core.CastConfig{ - CD: core.Cooldown{ - Timer: character.NewTimer(), - Duration: time.Minute * 2, - }, - }, - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - buffAura.Activate(sim) - }, - }) - - character.AddMajorCooldown(core.MajorCooldown{ - Spell: spell, - Type: core.CooldownTypeDPS, - }) -} - -/* -Your offensive spellcasts increase the spell damage of a random school of magic by 50 for 10 sec. -(9.5s cooldown) -The in-game implementation is different for every class based on what schools are considered useful. -Each class has a set of "good" schools based on certain parameters. These "good" schools have a higher chance to be procced. -For each proc the game rolls to determine which school buff will be given. -There's no buff for the Holy school, so there are 5 total schools that can be procced. - -schoolChances should be a map of school indexes with the relative proc chance of that school for the given class -*/ -func ClawOfChromaggusEffect(character *core.Character) { - arcaneChance, fireChance, frostChance, natureChance, shadowChance := 0.20, 0.20, 0.20, 0.20, 0.20 - - switch character.Class { - case proto.Class_ClassDruid: - // Assuming 25% Arcane, 25% Nature, 50% divided among the other 3 - arcaneChance, natureChance = 0.25, 0.25 - fireChance, frostChance, shadowChance = 0.50/3, 0.50/3, 0.50/3 - case proto.Class_ClassMage: - // The weapon's effect for mage is specialized, based off of selected runes - /* if character.HasRuneById(int32(proto.MageRune_RuneBeltFrostfireBolt)) { - fireChance, frostChance = 0.25, 0.25 - arcaneChance, natureChance, shadowChance = 0.50/3, 0.50/3, 0.50/3 - } else if character.HasRuneById(int32(proto.MageRune_RuneBeltSpellfrostBolt)) { - arcaneChance, frostChance = 0.25, 0.25 - fireChance, natureChance, shadowChance = 0.50/3, 0.50/3, 0.50/3 - } else if character.HasRuneById(int32(proto.MageRune_RuneBeltMissileBarrage)) { - arcaneChance = 0.50 - fireChance, frostChance, natureChance, shadowChance = 0.125, 0.125, 0.125, 0.125 - } */ - case proto.Class_ClassPriest: - // Confirmed 50% proc chance for Shadow and the other 50% divided among the other 4 schools - shadowChance = 0.50 - arcaneChance, fireChance, frostChance, natureChance = 0.125, 0.125, 0.125, 0.125 - case proto.Class_ClassShaman: - // Assuming 25% Fire, 25% Nature, 50% divided among the other 3 - fireChance, natureChance = 0.25, 0.25 - arcaneChance, frostChance, shadowChance = 0.50/3, 0.50/3, 0.50/3 - case proto.Class_ClassWarlock: - /* if character.HasRuneById(int32(proto.WarlockRune_RuneBracerIncinerate)) { - // Confirmed 50% Fire, 50% divided among the other 4 - fireChance = 0.50 - arcaneChance, frostChance, natureChance, shadowChance = 0.125, 0.125, 0.125, 0.125 - } else */{ - // Confirmed 50% Shadow, 50% divided among the other 4 - shadowChance = 0.50 - arcaneChance, fireChance, frostChance, natureChance = 0.125, 0.125, 0.125, 0.125 - } - } - - duration := time.Second * 10 - - arcaneAura := character.RegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 467410}, - Label: "Brood Boon: Bronze", - Duration: duration, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - aura.Unit.AddStatDynamic(sim, stats.ArcanePower, 50) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - aura.Unit.AddStatDynamic(sim, stats.ArcanePower, -50) - }, - }) - - fireAura := character.RegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 467414}, - Label: "Brood Boon: Red", - Duration: duration, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - aura.Unit.AddStatDynamic(sim, stats.FirePower, 50) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - aura.Unit.AddStatDynamic(sim, stats.FirePower, -50) - }, - }) - - frostAura := character.RegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 467412}, - Label: "Brood Boon: Blue", - Duration: duration, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - aura.Unit.AddStatDynamic(sim, stats.FrostPower, 50) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - aura.Unit.AddStatDynamic(sim, stats.FrostPower, -50) - }, - }) - - natureAura := character.RegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 467413}, - Label: "Brood Boon: Green", - Duration: duration, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - aura.Unit.AddStatDynamic(sim, stats.NaturePower, 50) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - aura.Unit.AddStatDynamic(sim, stats.NaturePower, -50) - }, - }) - - shadowAura := character.RegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 467411}, - Label: "Brood Boon: Black", - Duration: duration, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - aura.Unit.AddStatDynamic(sim, stats.ShadowPower, 50) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - aura.Unit.AddStatDynamic(sim, stats.ShadowPower, -50) - }, - }) - - arcaneRangeMax := 0.0 + arcaneChance - fireRangeMax := arcaneRangeMax + fireChance - frostRangeMax := fireRangeMax + frostChance - natureRangeMax := frostRangeMax + natureChance - shadowRangeMax := natureRangeMax + shadowChance - - if shadowRangeMax > 1.0 { - panic("Invalid school chances provided to Claw of Chromaggus effect.") - } - - core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - Name: "Claw of the Chromatic Trigger", - Callback: core.CallbackOnCastComplete, - ProcMask: core.ProcMaskSpellDamage, - ICD: time.Millisecond * 9500, - Handler: func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - roll := sim.RandomFloat("Claw of Chromaggus") - if roll < arcaneRangeMax { - arcaneAura.Activate(sim) - } else if roll < fireRangeMax { - fireAura.Activate(sim) - } else if roll < frostRangeMax { - frostAura.Activate(sim) - } else if roll < natureRangeMax { - natureAura.Activate(sim) - } else if roll < shadowRangeMax { - shadowAura.Activate(sim) - } - }, - }) -} - -func fishTerminatorEffect(agent core.Agent) { - character := agent.GetCharacter() - - results := make([]*core.SpellResult, min(4, character.Env.GetNumTargets())) - - procSpell := character.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 467836}, - // Same school and defense type as Thunder Clap - SpellSchool: core.SpellSchoolPhysical, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskSpellProc | core.ProcMaskSpellDamageProc, - DamageMultiplier: 1, - ThreatMultiplier: 1, - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - for idx := range results { - results[idx] = spell.CalcDamage(sim, target, sim.Roll(175, 225), spell.OutcomeMagicHitAndCrit) - target = character.Env.NextTargetUnit(target) - } - - for _, result := range results { - spell.DealDamage(sim, result) - } - }, - }) - - core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - Name: "Fish Terminator Trigger", - Callback: core.CallbackOnSpellHitDealt, - Outcome: core.OutcomeLanded, - ProcMask: core.ProcMaskMeleeMH, - SpellFlagsExclude: core.SpellFlagSuppressWeaponProcs, - PPM: 1.50, // 1.50 PPM tested on PTR - Handler: func(sim *core.Simulation, _ *core.Spell, result *core.SpellResult) { - procSpell.Cast(sim, result.Target) - }, - }) -} diff --git a/sim/common/sod/item_effects/phase_6.go b/sim/common/sod/item_effects/phase_6.go deleted file mode 100644 index 175bacf9d..000000000 --- a/sim/common/sod/item_effects/phase_6.go +++ /dev/null @@ -1,533 +0,0 @@ -package item_effects - -import ( - "time" - - "github.com/wowsims/classic/sim/common/sod" - "github.com/wowsims/classic/sim/common/vanilla" - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/stats" -) - -const ( - LeggingsOfImmersion = 233505 - RingOfSwarmingThought = 233507 - RobesOfTheBattleguard = 233575 - - // Obsidian Weapons - ObsidianChampion = 233490 - ObsidianReaver = 233491 - ObsidianDestroyer = 233796 - ObsidianStormhammer = 233797 - ObsidianSageblade = 233798 - ObsidianDefender = 233801 - ObsidianHeartseeker = 234428 - - // Brood of Nozdormu Reputations Rings - SignetRingBronzeDominatorR5 = 234034 - SignetRingBronzeDominatorR4 = 234030 - SignetRingBronzeDominatorR3 = 234026 - SignetRingBronzeDominatorR2 = 234021 - SignetRingBronzeDominatorR1 = 234017 - SignetRingBronzeInvokerR5 = 234032 - SignetRingBronzeInvokerR4 = 234028 - SignetRingBronzeInvokerR3 = 234024 - SignetRingBronzeInvokerR2 = 234020 - SignetRingBronzeInvokerR1 = 234016 - SignetRingBronzeFlamekeeperR5 = 234964 - SignetRingBronzeFlamekeeperR4 = 234965 - SignetRingBronzeFlamekeeperR3 = 234966 - SignetRingBronzeFlamekeeperR2 = 234967 - SignetRingBronzeFlamekeeperR1 = 234968 - SignetRingBronzePreserverR5 = 234033 - SignetRingBronzePreserverR4 = 234029 - SignetRingBronzePreserverR3 = 234025 - SignetRingBronzePreserverR2 = 234023 - SignetRingBronzePreserverR1 = 234019 - SignetRingBronzeProtectorR5 = 234035 - SignetRingBronzeProtectorR4 = 234031 - SignetRingBronzeProtectorR3 = 234027 - SignetRingBronzeProtectorR2 = 234022 - SignetRingBronzeProtectorR1 = 234018 - SignetRingBronzeSubjugatorR5 = 234436 - SignetRingBronzeSubjugatorR4 = 234437 - SignetRingBronzeSubjugatorR3 = 234438 - SignetRingBronzeSubjugatorR2 = 234439 - SignetRingBronzeSubjugatorR1 = 234440 - SignetRingBronzeConquerorR5 = 234202 - SignetRingBronzeConquerorR4 = 234201 - SignetRingBronzeConquerorR3 = 234200 - SignetRingBronzeConquerorR2 = 234199 - SignetRingBronzeConquerorR1 = 234198 -) - -func init() { - core.AddEffectsToTest = false - - /////////////////////////////////////////////////////////////////////////// - // Weapons - /////////////////////////////////////////////////////////////////////////// - - // https://www.wowhead.com/classic/item=233490/obsidian-champion - // Chance on hit: Heal self for 270 to 450 and Increases Strength by 120 for 30 sec. - // Chance on hit: Increases damage done by 20 and attack speed by 5% for 15 sec. - // Equip: Chance on direct spell damage or melee attack to deal 325 to 500 Fire damage to your target. - // Deals extra damage to Silithid creatures in Silithus on almost every hit. - // (2.1s cooldown) - core.NewItemEffect(ObsidianChampion, func(agent core.Agent) { - character := agent.GetCharacter() - vanilla.StrengthOfTheChampionAura(character) - //vanilla.EnrageAura446327(character) - ObsidianEdgedAura(ObsidianChampion, agent) - }) - - // https://www.wowhead.com/classic/item=233801/obsidian-defender - // Equip: Chance on direct spell damage or melee attack to deal 325 to 500 Fire damage to your target. - // Deals extra damage to Silithid creatures in Silithus on almost every hit. - // (2.1s cooldown) - core.NewItemEffect(ObsidianDefender, func(agent core.Agent) { - ObsidianEdgedAura(ObsidianDefender, agent) - }) - - // https://www.wowhead.com/classic/item=233796/obsidian-destroyer - // Chance on hit: Stuns target for 3 sec. - // Equip: Chance on direct spell damage or melee attack to deal 325 to 500 Fire damage to your target. - // Deals extra damage to Silithid creatures in Silithus on almost every hit. - // (2.1s cooldown) - core.NewItemEffect(ObsidianDestroyer, func(agent core.Agent) { - ObsidianEdgedAura(ObsidianDestroyer, agent) - }) - - // https://www.wowhead.com/classic/item=234428/obsidian-heartseeker - // Equip: Chance on direct spell damage or melee attack to deal 325 to 500 Fire damage to your target. - // Deals extra damage to Silithid creatures in Silithus on almost every hit. - // (2.1s cooldown) - core.NewItemEffect(ObsidianHeartseeker, func(agent core.Agent) { - ObsidianEdgedAura(ObsidianHeartseeker, agent) - }) - - // https://www.wowhead.com/classic/item=233491/obsidian-reaver - // Equip: Chance on direct spell damage or melee attack to deal 325 to 500 Fire damage to your target. - // Deals extra damage to Silithid creatures in Silithus on almost every hit. - // (2.1s cooldown) - core.NewItemEffect(ObsidianReaver, func(agent core.Agent) { - ObsidianEdgedAura(ObsidianReaver, agent) - }) - - // https://www.wowhead.com/classic/item=233798/obsidian-sageblade - // Equip: Chance on direct spell damage or melee attack to deal 325 to 500 Fire damage to your target. - // Deals extra damage to Silithid creatures in Silithus on almost every hit. - // (2.1s cooldown) - core.NewItemEffect(ObsidianSageblade, func(agent core.Agent) { - ObsidianEdgedAura(ObsidianSageblade, agent) - }) - - // https://www.wowhead.com/classic/item=233797/obsidian-stormhammer - // Chance on hit: Blasts up to 3 targets for 105 to 145 Nature damage. - // Equip: Chance on direct spell damage or melee attack to deal 325 to 500 Fire damage to your target. - // Deals extra damage to Silithid creatures in Silithus on almost every hit. - // (2.1s cooldown) - core.NewItemEffect(ObsidianStormhammer, func(agent core.Agent) { - sod.StormhammerChainLightningProcAura(agent) - ObsidianEdgedAura(ObsidianStormhammer, agent) - }) - - /////////////////////////////////////////////////////////////////////////// - // Rings - /////////////////////////////////////////////////////////////////////////// - - // https://www.wowhead.com/classic/item=233507/ring-of-swarming-thought - // Your damaging non-periodic spells increase your spell damage by 15 for 15 sec. - // If the target is player controlled, gain 100 spell penetration for 15 sec instead. - // (15s cooldown) - core.NewItemEffect(RingOfSwarmingThought, func(agent core.Agent) { - character := agent.GetCharacter() - buffAura := character.RegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 474148}, - Label: "Swarming Thoughts", - Duration: time.Second * 15, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - character.AddStatDynamic(sim, stats.SpellDamage, 15) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - character.AddStatDynamic(sim, stats.SpellDamage, -15) - }, - }) - - core.MakeProcTriggerAura(&agent.GetCharacter().Unit, core.ProcTrigger{ - Name: "Swarming Thoughts Trigger", - Callback: core.CallbackOnSpellHitDealt, - Outcome: core.OutcomeLanded, - ProcMask: core.ProcMaskSpellDamage, - ProcChance: 1.00, - ICD: time.Second * 15, - Handler: func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - buffAura.Activate(sim) - }, - }) - }) - - // https://www.wowhead.com/classic/item=234198/signet-ring-of-the-bronze-dragonflight - /* core.NewItemEffect(SignetRingBronzeConquerorR5, TimeswornStrikeAura) - core.NewItemEffect(SignetRingBronzeConquerorR4, TimeswornStrikeAura) - core.NewItemEffect(SignetRingBronzeConquerorR3, TimeswornStrikeAura) - core.NewItemEffect(SignetRingBronzeConquerorR2, TimeswornStrikeAura) - core.NewItemEffect(SignetRingBronzeConquerorR1, TimeswornStrikeAura) - - // https://www.wowhead.com/classic/item=234034/signet-ring-of-the-bronze-dragonflight - core.NewItemEffect(SignetRingBronzeDominatorR5, TimeswornStrikeAura) - core.NewItemEffect(SignetRingBronzeDominatorR4, TimeswornStrikeAura) - core.NewItemEffect(SignetRingBronzeDominatorR3, TimeswornStrikeAura) - core.NewItemEffect(SignetRingBronzeDominatorR2, TimeswornStrikeAura) - core.NewItemEffect(SignetRingBronzeDominatorR1, TimeswornStrikeAura) - - // https://www.wowhead.com/classic/item=234964/signet-ring-of-the-bronze-dragonflight - core.NewItemEffect(SignetRingBronzeFlamekeeperR5, TimeswornPyromancyAura) - core.NewItemEffect(SignetRingBronzeFlamekeeperR4, TimeswornPyromancyAura) - core.NewItemEffect(SignetRingBronzeFlamekeeperR3, TimeswornPyromancyAura) - core.NewItemEffect(SignetRingBronzeFlamekeeperR2, TimeswornPyromancyAura) - core.NewItemEffect(SignetRingBronzeFlamekeeperR1, TimeswornPyromancyAura) - - // https://www.wowhead.com/classic/item=234032/signet-ring-of-the-bronze-dragonflight - core.NewItemEffect(SignetRingBronzeInvokerR5, TimeswornSpellAura) - core.NewItemEffect(SignetRingBronzeInvokerR4, TimeswornSpellAura) - core.NewItemEffect(SignetRingBronzeInvokerR3, TimeswornSpellAura) - core.NewItemEffect(SignetRingBronzeInvokerR2, TimeswornSpellAura) - core.NewItemEffect(SignetRingBronzeInvokerR1, TimeswornSpellAura) - - // https://www.wowhead.com/classic/item=234032/signet-ring-of-the-bronze-dragonflight - core.NewItemEffect(SignetRingBronzePreserverR5, TimewornHealing) - core.NewItemEffect(SignetRingBronzePreserverR4, TimewornHealing) - core.NewItemEffect(SignetRingBronzePreserverR3, TimewornHealing) - core.NewItemEffect(SignetRingBronzePreserverR2, TimewornHealing) - core.NewItemEffect(SignetRingBronzePreserverR1, TimewornHealing) - - // https://www.wowhead.com/classic/item=234035/signet-ring-of-the-bronze-dragonflight - core.NewItemEffect(SignetRingBronzeProtectorR5, TimeswornExpertiseAura) - core.NewItemEffect(SignetRingBronzeProtectorR4, TimeswornExpertiseAura) - core.NewItemEffect(SignetRingBronzeProtectorR3, TimeswornExpertiseAura) - core.NewItemEffect(SignetRingBronzeProtectorR2, TimeswornExpertiseAura) - core.NewItemEffect(SignetRingBronzeProtectorR1, TimeswornExpertiseAura) - - // https://www.wowhead.com/classic/item=234436/signet-ring-of-the-bronze-dragonflight - core.NewItemEffect(SignetRingBronzeSubjugatorR5, TimewornDecayAura) - core.NewItemEffect(SignetRingBronzeSubjugatorR4, TimewornDecayAura) - core.NewItemEffect(SignetRingBronzeSubjugatorR3, TimewornDecayAura) - core.NewItemEffect(SignetRingBronzeSubjugatorR2, TimewornDecayAura) - core.NewItemEffect(SignetRingBronzeSubjugatorR1, TimewornDecayAura) */ - - /////////////////////////////////////////////////////////////////////////// - // Other - /////////////////////////////////////////////////////////////////////////// - - // https://www.wowhead.com/classic/item=233505/leggings-of-immersion - // Your damaging non-periodic Nature spell critical strikes have a chance to grant you 40 increased spell damage for 10 sec. - // (Proc chance: 50%, 5s cooldown) - core.NewItemEffect(LeggingsOfImmersion, func(agent core.Agent) { - character := agent.GetCharacter() - buffAura := character.RegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 474126}, - Label: "Immersed", - Duration: time.Second * 10, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - character.AddStatDynamic(sim, stats.SpellDamage, 40) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - character.AddStatDynamic(sim, stats.SpellDamage, -40) - }, - }) - - icd := core.Cooldown{ - Timer: character.NewTimer(), - Duration: time.Second * 5, - } - - core.MakeProcTriggerAura(&agent.GetCharacter().Unit, core.ProcTrigger{ - Name: "Immersed Trigger", - Callback: core.CallbackOnSpellHitDealt, - ProcMask: core.ProcMaskSpellDamage, - Handler: func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if spell.SpellSchool.Matches(core.SpellSchoolNature) && result.DidCrit() && icd.IsReady(sim) && sim.Proc(0.50, "Immersed Proc") { - buffAura.Activate(sim) - icd.Use(sim) - } - }, - }) - }) - - // https://www.wowhead.com/classic/item=233575/robes-of-the-battleguard - // Your damaging non-periodic spells increase your spell damage by 20 for 15 sec. - // If the target is player controlled, gain 120 spell penetration for 15 sec instead. - // (15s cooldown) - core.NewItemEffect(RobesOfTheBattleguard, func(agent core.Agent) { - character := agent.GetCharacter() - buffAura := character.RegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 1213241}, - Label: "Resolve of the Battleguard", - Duration: time.Second * 15, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - character.AddStatDynamic(sim, stats.SpellDamage, 20) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - character.AddStatDynamic(sim, stats.SpellDamage, -20) - }, - }) - - core.MakeProcTriggerAura(&agent.GetCharacter().Unit, core.ProcTrigger{ - Name: "Resolve of the Battleguard Trigger", - Callback: core.CallbackOnSpellHitDealt, - Outcome: core.OutcomeLanded, - ProcMask: core.ProcMaskSpellDamage, - ProcChance: 1.00, - ICD: time.Second * 15, - Handler: func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - buffAura.Activate(sim) - }, - }) - }) - - core.AddEffectsToTest = true -} - -// https://www.wowhead.com/classic/spell=1214125/obsidian-edged -// Chance on direct spell damage or melee attack to deal 325 to 500 Fire damage to your target. -// Deals extra damage to Silithid creatures in Silithus on almost every hit. -// (2.1s cooldown) -func ObsidianEdgedAura(itemID int32, agent core.Agent) { - character := agent.GetCharacter() - - damageSpell := character.GetOrRegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 1213941}, - SpellSchool: core.SpellSchoolFire, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskSpellProc | core.ProcMaskSpellDamageProc, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagPassiveSpell, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - spell.CalcAndDealDamage(sim, target, sim.Roll(325, 500), spell.OutcomeMagicHitAndCrit) - }, - }) - - meleeProcMask := character.GetProcMaskForItem(itemID) - - core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - Name: "Obsidian Edged Proc Melee", - Callback: core.CallbackOnSpellHitDealt, - Outcome: core.OutcomeLanded, - ProcMask: meleeProcMask, - ProcChance: 0.05, - ICD: time.Millisecond * 2100, - Handler: func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - damageSpell.Cast(sim, result.Target) - }, - }) - - core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - Name: "Obsidian Edged Proc Spell", - Callback: core.CallbackOnSpellHitDealt, - Outcome: core.OutcomeLanded, - ProcMask: core.ProcMaskSpellDamage, - ProcChance: 0.05, - ICD: time.Millisecond * 2100, - Handler: func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - damageSpell.Cast(sim, result.Target) - }, - }) -} - -// https://www.wowhead.com/classic/spell=1214155/timeworn-decay -// Increases the damage dealt by all of your damage over time spells by 2% per piece of Timeworn armor equipped. -/* func TimewornDecayAura(agent core.Agent) { - character := agent.GetCharacter() - if character.PseudoStats.TimewornBonus == 0 { - return - } - - multiplier := 0.02 * float64(character.PseudoStats.TimewornBonus) - - character.OnSpellRegistered(func(spell *core.Spell) { - if spell.SpellCode != 0 && len(spell.Dots()) > 0 { - spell.PeriodicDamageMultiplierAdditive += multiplier - } - }) -} - -// https://www.wowhead.com/classic/spell=1213407/timeworn-expertise -// Reduces the chance for your attacks to be dodged or parried by 1% per piece of Timeworn armor equipped. -func TimeswornExpertiseAura(agent core.Agent) { - character := agent.GetCharacter() - if character.PseudoStats.TimewornBonus == 0 { - return - } - - stats := stats.Stats{stats.Expertise: float64(character.PseudoStats.TimewornBonus) * core.ExpertiseRatingPerExpertiseChance} - - core.MakePermanent(character.GetOrRegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 1214218}, - Label: "Timeworn Expertise Aura", - BuildPhase: core.CharacterBuildPhaseBuffs, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - if aura.Unit.Env.MeasuringStats && aura.Unit.Env.State != core.Finalized { - aura.Unit.AddStats(stats) - } else { - aura.Unit.AddStatsDynamic(sim, stats) - } - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - if aura.Unit.Env.MeasuringStats && aura.Unit.Env.State != core.Finalized { - aura.Unit.AddStats(stats.Multiply(-1)) - } else { - aura.Unit.AddStatsDynamic(sim, stats.Multiply(-1)) - } - }, - })) -} - -// https://www.wowhead.com/classic/spell=1213405/timeworn-healing -// Increases the effectiveness of your healing and shielding spells by 2% per piece of Timeworn armor equipped. -func TimewornHealing(agent core.Agent) { - character := agent.GetCharacter() - if character.PseudoStats.TimewornBonus == 0 { - return - } - - healShieldMultiplier := 1 + 0.02*float64(character.PseudoStats.TimewornBonus) - - core.MakePermanent(character.GetOrRegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 1213405}, - Label: "Timeworn Healing Aura", - OnGain: func(aura *core.Aura, sim *core.Simulation) { - character.PseudoStats.HealingDealtMultiplier *= healShieldMultiplier - character.PseudoStats.ShieldDealtMultiplier *= healShieldMultiplier - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - character.PseudoStats.HealingDealtMultiplier /= healShieldMultiplier - character.PseudoStats.ShieldDealtMultiplier /= healShieldMultiplier - }, - })) -} - -// https://www.wowhead.com/classic/spell=1215404/timeworn-pyromancy -// Increases the effectiveness of your Fire damage spells by 3% per piece of Timeworn armor equipped. -func TimeswornPyromancyAura(agent core.Agent) { - character := agent.GetCharacter() - if character.PseudoStats.TimewornBonus == 0 { - return - } - - fireMultiplier := 1 + 0.03*float64(character.PseudoStats.TimewornBonus) - - core.MakePermanent(character.GetOrRegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 1215404}, - Label: "Timeworn Pyromancy Aura", - OnGain: func(aura *core.Aura, sim *core.Simulation) { - character.PseudoStats.SchoolDamageDealtMultiplier[stats.SchoolIndexFire] *= fireMultiplier - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - character.PseudoStats.SchoolDamageDealtMultiplier[stats.SchoolIndexFire] /= fireMultiplier - }, - })) -} - -// https://www.wowhead.com/classic/spell=1213398/timeworn-spell -// Increases the casting speed of your spells by 2% per piece of Timeworn armor equipped. -func TimeswornSpellAura(agent core.Agent) { - character := agent.GetCharacter() - if character.PseudoStats.TimewornBonus == 0 { - return - } - - castSpeedMultiplier := 1 / (1 - 0.02*float64(character.PseudoStats.TimewornBonus)) - - core.MakePermanent(character.GetOrRegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 1213398}, - Label: "Timeworn Spell Aura", - OnGain: func(aura *core.Aura, sim *core.Simulation) { - character.MultiplyCastSpeed(castSpeedMultiplier) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - character.MultiplyCastSpeed(1 / castSpeedMultiplier) - }, - })) -} - -// https://www.wowhead.com/classic/spell=1213390/timeworn-strike -// Gives you 1% chance per piece of Timeworn armor equipped to get an extra attack on regular melee or ranged hit that deals 100% weapon damage. -// (100ms cooldown) -func TimeswornStrikeAura(agent core.Agent) { - character := agent.GetCharacter() - if character.PseudoStats.TimewornBonus == 0 { - return - } - - procChance := float64(character.PseudoStats.TimewornBonus) * 0.01 - - timeStrikeMelee := character.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 1213381}, - SpellSchool: core.SpellSchoolPhysical, - DefenseType: core.DefenseTypeMelee, - ProcMask: core.ProcMaskMeleeMHSpecial, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagPassiveSpell, - - BonusCoefficient: 1, - DamageMultiplier: 1, - ThreatMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - baseDamage := spell.Unit.MHNormalizedWeaponDamage(sim, spell.MeleeAttackPower()) - spell.CalcAndDealDamage(sim, target, baseDamage, spell.OutcomeMeleeSpecialHitAndCrit) - }, - }) - - timestrikeRanged := character.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 1213381}, - SpellSchool: core.SpellSchoolPhysical, - DefenseType: core.DefenseTypeMelee, - ProcMask: core.ProcMaskRangedSpecial, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagPassiveSpell, - // TODO: Copied from Chimera Shot - MissileSpeed: 24, - - BonusCoefficient: 1, - DamageMultiplier: 1, - ThreatMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - // TODO: Missing the hunter Ammo damage bonus. We need to be able to store it on the character instead of the hunter - baseDamage := character.AutoAttacks.Ranged().CalculateNormalizedWeaponDamage(sim, spell.RangedAttackPower(target, false)) - result := spell.CalcDamage(sim, target, baseDamage, spell.OutcomeRangedHitAndCrit) - - spell.WaitTravelTime(sim, func(s *core.Simulation) { - spell.DealDamage(sim, result) - }) - }, - }) - - core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - Name: "Timeworn Strike Aura Melee", - Callback: core.CallbackOnSpellHitDealt, - Outcome: core.OutcomeLanded, - ProcMask: core.ProcMaskMeleeWhiteHit, - ProcChance: procChance, - ICD: time.Millisecond * 100, - Handler: func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - timeStrikeMelee.Cast(sim, result.Target) - }, - }) - - core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - Name: "Timeworn Strike Aura Ranged", - Callback: core.CallbackOnSpellHitDealt, - Outcome: core.OutcomeLanded, - ProcMask: core.ProcMaskRangedAuto, - ProcChance: procChance, - ICD: time.Millisecond * 100, - Handler: func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - timestrikeRanged.Cast(sim, result.Target) - }, - }) -} -*/ diff --git a/sim/common/sod/items_sets/phase_1.go b/sim/common/sod/items_sets/phase_1.go deleted file mode 100644 index 62e8fd08b..000000000 --- a/sim/common/sod/items_sets/phase_1.go +++ /dev/null @@ -1,78 +0,0 @@ -package item_sets - -import ( - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/stats" -) - -/////////////////////////////////////////////////////////////////////////// -// Cloth -/////////////////////////////////////////////////////////////////////////// - -var ItemSetBlackfathomInvokerVestaments = core.NewItemSet(core.ItemSet{ - Name: "Twilight Invoker's Vestments", - Bonuses: map[int32]core.ApplyEffect{ - 2: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.SpellPower, 9) - }, - 3: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.MeleeHit, 1) - c.AddStat(stats.SpellHit, 1) - }, - }, -}) - -/////////////////////////////////////////////////////////////////////////// -// Leather -/////////////////////////////////////////////////////////////////////////// - -var ItemSetBlackfathomSlayerLeather = core.NewItemSet(core.ItemSet{ - Name: "Blackfathom Slayer's Leather", - Bonuses: map[int32]core.ApplyEffect{ - 2: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.AttackPower, 12) - }, - 3: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.MeleeHit, 1) - c.AddStat(stats.SpellHit, 1) - }, - }, -}) - -var ItemSetBlackfathomElementalistHide = core.NewItemSet(core.ItemSet{ - Name: "Blackfathom Elementalist's Hide", - Bonuses: map[int32]core.ApplyEffect{ - 2: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.SpellPower, 12) - }, - 3: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.MeleeHit, 1) - c.AddStat(stats.SpellHit, 1) - }, - }, -}) - -/////////////////////////////////////////////////////////////////////////// -// Mail -/////////////////////////////////////////////////////////////////////////// - -var ItemSetBlackfathomAvengerMail = core.NewItemSet(core.ItemSet{ - Name: "Blackfathom Avenger's Mail", - Bonuses: map[int32]core.ApplyEffect{ - 2: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.AttackPower, 12) - }, - 3: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.MeleeHit, 1) - c.AddStat(stats.SpellHit, 1) - }, - }, -}) diff --git a/sim/common/sod/items_sets/phase_2.go b/sim/common/sod/items_sets/phase_2.go deleted file mode 100644 index e388ea563..000000000 --- a/sim/common/sod/items_sets/phase_2.go +++ /dev/null @@ -1,187 +0,0 @@ -package item_sets - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/stats" -) - -/////////////////////////////////////////////////////////////////////////// -// Cloth -/////////////////////////////////////////////////////////////////////////// - -var ItemSetHyperconductiveMendersMeditation = core.NewItemSet(core.ItemSet{ - Name: "Hyperconductive Mender's Meditation", - Bonuses: map[int32]core.ApplyEffect{ - 2: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.Spirit, 14) - }, - 3: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.MP5, 7) - }, - }, -}) - -var ItemSetHyperconductiveWizardsAttire = core.NewItemSet(core.ItemSet{ - Name: "Hyperconductive Wizard's Attire", - Bonuses: map[int32]core.ApplyEffect{ - 2: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.MeleeHit, 1) - c.AddStat(stats.SpellHit, 1) - c.AddStat(stats.BonusArmor, 100) - }, - 3: func(agent core.Agent) { - character := agent.GetCharacter() - - procAura := character.NewTemporaryStatsAura("Energized Hyperconductor Proc", core.ActionID{SpellID: 435978}, stats.Stats{stats.SpellPower: 40}, time.Second*10) - - handler := func(sim *core.Simulation, _ *core.Spell, _ *core.SpellResult) { - procAura.Activate(sim) - } - - core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - ActionID: core.ActionID{ItemID: 435977}, - Name: "Energized Hyperconductor", - Callback: core.CallbackOnCastComplete, - ProcMask: core.ProcMaskSpellDamage, - ProcChance: 0.10, - Handler: handler, - }) - }, - }, -}) - -var ItemSetIrradiatedGarments = core.NewItemSet(core.ItemSet{ - Name: "Irradiated Garments", - Bonuses: map[int32]core.ApplyEffect{ - 2: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.MeleeCrit, 1) - c.AddStat(stats.SpellCrit, 1) - c.AddStat(stats.Stamina, -5) - }, - 3: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.SpellPower, 11) - }, - }, -}) - -/////////////////////////////////////////////////////////////////////////// -// Leather -/////////////////////////////////////////////////////////////////////////// - -var ItemSetInsulatedLeather = core.NewItemSet(core.ItemSet{ - Name: "Insulated Leathers", - Bonuses: map[int32]core.ApplyEffect{ - 2: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.MeleeCrit, 1) - c.AddStat(stats.SpellCrit, 1) - }, - 3: func(agent core.Agent) { - c := agent.GetCharacter() - c.PseudoStats.DaggersSkill += 3 - c.AddStat(stats.FeralAttackPower, 20) - }, - }, -}) - -var ItemSetInsulatedSorcerorLeather = core.NewItemSet(core.ItemSet{ - Name: "Insulated Sorceror's Leathers", - Bonuses: map[int32]core.ApplyEffect{ - 2: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.SpellPower, 16) - }, - 3: func(agent core.Agent) {}, - }, -}) - -/////////////////////////////////////////////////////////////////////////// -// Mail -/////////////////////////////////////////////////////////////////////////// - -var ItemSetElectromanticDevastator = core.NewItemSet(core.ItemSet{ - Name: "Electromantic Devastator's Mail", - Bonuses: map[int32]core.ApplyEffect{ - 2: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.AttackPower, 24) - c.AddStat(stats.RangedAttackPower, 24) - }, - 3: func(agent core.Agent) { - c := agent.GetCharacter() - if !c.HasManaBar() { - return - } - metrics := c.NewManaMetrics(core.ActionID{SpellID: 435982}) - proc := c.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 435981}, - SpellSchool: core.SpellSchoolHoly, - ApplyEffects: func(sim *core.Simulation, u *core.Unit, spell *core.Spell) { - c.AddMana(sim, 100, metrics) - }, - }) - procChance := 0.05 - c.RegisterAura(core.Aura{ - Label: "Electromantic Devastator's Mail 3pc", - ActionID: core.ActionID{SpellID: 435982}, - Duration: core.NeverExpires, - OnReset: func(aura *core.Aura, sim *core.Simulation) { - aura.Activate(sim) - }, - // Modeled after WotLK JoW https://github.com/wowsims/wotlk/blob/master/sim/core/debuffs.go#L202 - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - - if spell.ProcMask == core.ProcMaskEmpty { - return // Can't use Matches for ProcMaskEmpty - } - - if spell.ProcMask.Matches(core.ProcMaskProc|core.ProcMaskSpellDamageProc) && !spell.Flags.Matches(core.SpellFlagNotAProc) { - return // Phantom spells don't proc - } - - if spell.ProcMask.Matches(core.ProcMaskWhiteHit | core.ProcMaskRanged) { // Ranged/melee can proc on miss - if sim.RandomFloat("Electromantic Devastator's Mail 3pc") > procChance { - return - } - } else { // Spell Casting only procs on hits - if !result.Landed() { - return - } - if sim.RandomFloat("Electromantic Devastator's Mail 3pc") > procChance { - return - } - } - proc.Cast(sim, result.Target) - }, - }) - }, - }, -}) - -/////////////////////////////////////////////////////////////////////////// -// Plate -/////////////////////////////////////////////////////////////////////////// - -var ItemSetHazardSuit = core.NewItemSet(core.ItemSet{ - Name: "H.A.Z.A.R.D. Suit", - Bonuses: map[int32]core.ApplyEffect{ - 2: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.Defense, 7) - c.AddStat(stats.AttackPower, 16) - c.AddStat(stats.RangedAttackPower, 16) - }, - 3: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.MeleeHit, 1) - c.AddStat(stats.SpellHit, 1) - }, - }, -}) diff --git a/sim/common/sod/items_sets/phase_3.go b/sim/common/sod/items_sets/phase_3.go deleted file mode 100644 index ed27db5bb..000000000 --- a/sim/common/sod/items_sets/phase_3.go +++ /dev/null @@ -1,384 +0,0 @@ -package item_sets - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/stats" -) - -/////////////////////////////////////////////////////////////////////////// -// Cloth -/////////////////////////////////////////////////////////////////////////// - -var ItemSetMalevolentProphetsVestments = core.NewItemSet(core.ItemSet{ - Name: "Malevolent Prophet's Vestments", - Bonuses: map[int32]core.ApplyEffect{ - 2: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.MeleeCrit, 1) - c.AddStat(stats.SpellCrit, 1) - }, - 3: func(agent core.Agent) { - c := agent.GetCharacter() - - procAuras := c.NewEnemyAuraArray(func(target *core.Unit) *core.Aura { - return target.GetOrRegisterAura(core.Aura{ - Label: "Malelovance Proc", - ActionID: core.ActionID{SpellID: 449920}, - Duration: time.Second * 30, - MaxStacks: 1, - - OnGain: func(aura *core.Aura, sim *core.Simulation) { - aura.SetStacks(sim, aura.MaxStacks) - - for si := stats.SchoolIndexArcane; si < stats.SchoolLen; si++ { - aura.Unit.PseudoStats.SchoolBonusDamageTaken[si] += 50 - } - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - for si := stats.SchoolIndexArcane; si < stats.SchoolLen; si++ { - aura.Unit.PseudoStats.SchoolBonusDamageTaken[si] -= 50 - } - }, - OnSpellHitTaken: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - // OnCastComplete is called after OnSpellHitDealt / etc, so don't deactivate if it was just activated. - if aura.RemainingDuration(sim) == aura.Duration { - return - } - - if result.Landed() && spell.ProcMask.Matches(core.ProcMaskDirect) { - aura.RemoveStack(sim) - } - }, - }) - }) - - handler := func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - procAuras.Get(result.Target).Activate(sim) - } - - core.MakeProcTriggerAura(&c.Unit, core.ProcTrigger{ - ActionID: core.ActionID{SpellID: 449919}, - Name: "Malelovance", - Callback: core.CallbackOnSpellHitDealt, - Outcome: core.OutcomeLanded, - ProcMask: core.ProcMaskSpellDamage, - ProcChance: 0.2, - Handler: handler, - }) - }, - }, -}) - -var ItemSetKnightLieutenantsDreadweave = core.NewItemSet(core.ItemSet{ - Name: "Knight-Lieutenant's Dreadweave", - Bonuses: map[int32]core.ApplyEffect{ - 3: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.Stamina, 15) - }, - 6: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.SpellPower, 18) - }, - }, -}) - -var ItemSetBloodGuardsDreadweave = core.NewItemSet(core.ItemSet{ - Name: "Blood Guard's Dreadweave", - Bonuses: map[int32]core.ApplyEffect{ - 3: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.Stamina, 15) - }, - 6: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.SpellPower, 18) - }, - }, -}) - -var ItemSetKnightLieutenantsSatin = core.NewItemSet(core.ItemSet{ - Name: "Knight Lieutenant's Satin", - Bonuses: map[int32]core.ApplyEffect{ - 3: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.Stamina, 15) - }, - 6: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.HealingPower, 33) - }, - }, -}) - -var ItemSetBloodGuardsSatin = core.NewItemSet(core.ItemSet{ - Name: "Blood Guard's Satin", - Bonuses: map[int32]core.ApplyEffect{ - 3: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.Stamina, 15) - }, - 6: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.HealingPower, 33) - }, - }, -}) - -var ItemSetEmeraldEnchantedVestments = core.NewItemSet(core.ItemSet{ - Name: "Emerald Enchanted Vestments", - Bonuses: map[int32]core.ApplyEffect{ - 3: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.Stamina, 10) - }, - 6: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.SpellPower, 12) - }, - }, -}) - -var ItemSetEmeraldWovenGarb = core.NewItemSet(core.ItemSet{ - Name: "Emerald Woven Garb", - Bonuses: map[int32]core.ApplyEffect{ - 3: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.Stamina, 10) - }, - 6: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.HealingPower, 22) - }, - }, -}) - -/////////////////////////////////////////////////////////////////////////// -// Leather -/////////////////////////////////////////////////////////////////////////// - -var ItemSetKnightLieutenantsLeather = core.NewItemSet(core.ItemSet{ - Name: "Knight-Lieutenant's Leather", - Bonuses: map[int32]core.ApplyEffect{ - 3: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.Stamina, 15) - }, - 6: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.AttackPower, 30) - c.AddStat(stats.RangedAttackPower, 30) - }, - }, -}) - -var ItemSetBloodGuardsLeather = core.NewItemSet(core.ItemSet{ - Name: "Blood Guard's Leather", - Bonuses: map[int32]core.ApplyEffect{ - 3: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.Stamina, 15) - }, - 6: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.AttackPower, 30) - c.AddStat(stats.RangedAttackPower, 30) - }, - }, -}) - -var ItemSetEmeraldLeathers = core.NewItemSet(core.ItemSet{ - Name: "Emerald Leathers", - Bonuses: map[int32]core.ApplyEffect{ - 3: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.Stamina, 10) - }, - 6: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.AttackPower, 20) - c.AddStat(stats.RangedAttackPower, 20) - }, - }, -}) - -/////////////////////////////////////////////////////////////////////////// -// Mail -/////////////////////////////////////////////////////////////////////////// - -var ItemSetShunnedDevoteesChainmail = core.NewItemSet(core.ItemSet{ - Name: "Shunned Devotee's Chainmail", - Bonuses: map[int32]core.ApplyEffect{ - 2: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.MeleeCrit, 1) - c.AddStat(stats.SpellCrit, 1) - }, - 3: func(agent core.Agent) { - c := agent.GetCharacter() - - // Holy Spell Crit - c.OnSpellRegistered(func(spell *core.Spell) { - if spell.SpellSchool.Matches(core.SpellSchoolHoly) { - spell.BonusCritRating += 3 - } - }) - - // Nature Bonus Proc - procAura := c.NewTemporaryStatsAura("The Furious Storm Proc", core.ActionID{SpellID: 449934}, stats.Stats{stats.NaturePower: 60, stats.HealingPower: 60}, time.Second*10) - - handler := func(sim *core.Simulation, spell *core.Spell, _ *core.SpellResult) { - procAura.Activate(sim) - } - - core.MakeProcTriggerAura(&c.Unit, core.ProcTrigger{ - ActionID: core.ActionID{SpellID: 449935}, - Name: "The Furious Storm", - Callback: core.CallbackOnCastComplete, - ProcMask: core.ProcMaskSpellDamage | core.ProcMaskSpellHealing, - ProcChance: 0.10, - Handler: handler, - }) - }, - }, -}) - -/////////////////////////////////////////////////////////////////////////// -// Plate -/////////////////////////////////////////////////////////////////////////// - -var ItemSetWailingBerserkersPlateArmor = core.NewItemSet(core.ItemSet{ - Name: "Wailing Berserker's Plate Armor", - Bonuses: map[int32]core.ApplyEffect{ - 2: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.MeleeHit, 1) - c.AddStat(stats.SpellHit, 1) - }, - 3: func(agent core.Agent) { - c := agent.GetCharacter() - - handler := func(sim *core.Simulation, spell *core.Spell, _ *core.SpellResult) { - c.AutoAttacks.ExtraMHAttackProc(sim, 1, core.ActionID{SpellID: 449970}, spell) - } - - core.MakeProcTriggerAura(&c.Unit, core.ProcTrigger{ - ActionID: core.ActionID{SpellID: 449970}, - Name: "Extra Attack", - Callback: core.CallbackOnSpellHitDealt, - Outcome: core.OutcomeLanded, - ProcMask: core.ProcMaskMelee, - SpellFlagsExclude: core.SpellFlagSuppressEquipProcs, - ProcChance: 0.03, - ICD: 200 * time.Millisecond, - Handler: handler, - }) - }, - }, -}) - -var ItemSetBanishedMartyrsFullPlate = core.NewItemSet(core.ItemSet{ - Name: "Banished Martyr's Full Plate", - Bonuses: map[int32]core.ApplyEffect{ - 2: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.MeleeHit, 1) - c.AddStat(stats.SpellHit, 1) - }, - 3: func(agent core.Agent) { - c := agent.GetCharacter() - - procAura := c.NewTemporaryStatsAura("Stalwart Block Proc", core.ActionID{SpellID: 449975}, stats.Stats{stats.BlockValue: 50}, time.Second*6) - - handler := func(sim *core.Simulation, spell *core.Spell, _ *core.SpellResult) { - procAura.Activate(sim) - } - - core.MakeProcTriggerAura(&c.Unit, core.ProcTrigger{ - ActionID: core.ActionID{SpellID: 449974}, - Name: "Stalwart Block", - Callback: core.CallbackOnSpellHitTaken, - ProcMask: core.ProcMaskMelee, - Outcome: core.OutcomeBlock, - ProcChance: 1, - Handler: handler, - }) - }, - }, -}) - -var ItemSetKnightLieutenantsPlate = core.NewItemSet(core.ItemSet{ - Name: "Knight-Lieutenant's Plate", - Bonuses: map[int32]core.ApplyEffect{ - 3: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.Stamina, 15) - }, - 6: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.AttackPower, 30) - c.AddStat(stats.RangedAttackPower, 30) - }, - }, -}) - -var ItemSetBloodGuardsPlate = core.NewItemSet(core.ItemSet{ - Name: "Blood Guard's Plate", - Bonuses: map[int32]core.ApplyEffect{ - 3: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.Stamina, 15) - }, - 6: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.AttackPower, 30) - c.AddStat(stats.RangedAttackPower, 30) - }, - }, -}) - -var ItemSetEmeraldDreamPlate = core.NewItemSet(core.ItemSet{ - Name: "Emerald Dream Plate", - Bonuses: map[int32]core.ApplyEffect{ - 3: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.Stamina, 10) - }, - 6: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.AttackPower, 20) - c.AddStat(stats.RangedAttackPower, 20) - }, - }, -}) - -/////////////////////////////////////////////////////////////////////////// -// Other -/////////////////////////////////////////////////////////////////////////// - -var ItemSetSerpentsAscension = core.NewItemSet(core.ItemSet{ - Name: "Serpent's Ascension", - Bonuses: map[int32]core.ApplyEffect{ - 2: func(agent core.Agent) { - character := agent.GetCharacter() - procAura := character.NewTemporaryStatsAura("Serpent's Ascension Proc", core.ActionID{SpellID: 446231}, stats.Stats{stats.AttackPower: 150}, time.Second*12) - - handler := func(sim *core.Simulation, _ *core.Spell, _ *core.SpellResult) { - procAura.Activate(sim) - } - - core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - ActionID: core.ActionID{SpellID: 446233}, - Name: "Serpent's Ascension", - Callback: core.CallbackOnSpellHitDealt, - Outcome: core.OutcomeLanded, - ProcMask: core.ProcMaskMeleeOrRanged, - ProcChance: 0.03, - ICD: time.Second * 120, - Handler: handler, - }) - }, - }, -}) diff --git a/sim/common/sod/items_sets/phase_5.go b/sim/common/sod/items_sets/phase_5.go deleted file mode 100644 index 4ece24f85..000000000 --- a/sim/common/sod/items_sets/phase_5.go +++ /dev/null @@ -1,152 +0,0 @@ -package item_sets - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/stats" -) - -/////////////////////////////////////////////////////////////////////////// -// Cloth -/////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////// -// Leather -/////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////// -// Mail -/////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////// -// Plate -/////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////// -// Other -/////////////////////////////////////////////////////////////////////////// - -var ItemSetMajorMojoInfusion = core.NewItemSet(core.ItemSet{ - Name: "Major Mojo Infusion", - Bonuses: map[int32]core.ApplyEffect{ - // +30 Attack Power. - 2: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStats(stats.Stats{ - stats.AttackPower: 30, - stats.RangedAttackPower: 30, - }) - }, - }, -}) - -var ItemSetOverlordsResolution = core.NewItemSet(core.ItemSet{ - Name: "Overlord's Resolution", - Bonuses: map[int32]core.ApplyEffect{ - // Increased Defense +8. - 2: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.Defense, 8) - }, - }, -}) - -var ItemSetPrayerOfThePrimal = core.NewItemSet(core.ItemSet{ - Name: "Prayer of the Primal", - Bonuses: map[int32]core.ApplyEffect{ - // Increases healing done by up to 33 and damage done by up to 11 for all magical spells and effects. - 2: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStats(stats.Stats{ - stats.HealingPower: 33, - stats.SpellDamage: 11, - }) - }, - }, -}) - -var ItemSetPrimalBlessing = core.NewItemSet(core.ItemSet{ - Name: "Primal Blessing", - Bonuses: map[int32]core.ApplyEffect{ - // Grants a small chance when ranged or melee damage is dealt to infuse the wielder with a blessing from the Primal Gods. - // Ranged and melee attack power increased by 300 for 12 sec. - 2: func(agent core.Agent) { - character := agent.GetCharacter() - - aura := character.RegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 467742}, - Label: "Primal Blessing", - Duration: time.Second * 12, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - character.AddStatsDynamic(sim, stats.Stats{ - stats.AttackPower: 300, - stats.RangedAttackPower: 300, - }) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - character.AddStatsDynamic(sim, stats.Stats{ - stats.AttackPower: -300, - stats.RangedAttackPower: -300, - }) - }, - }) - - core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - Name: "Primal Blessing Trigger", - Callback: core.CallbackOnSpellHitDealt, - ProcMask: core.ProcMaskMeleeOrRanged, - Outcome: core.OutcomeLanded, - ProcChance: 0.05, - ICD: time.Second * 72, - Handler: func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - aura.Activate(sim) - }, - }) - }, - }, -}) - -var ItemSetTwinBladesofHakkari = core.NewItemSet(core.ItemSet{ - Name: "The Twin Blades of Hakkari", - Bonuses: map[int32]core.ApplyEffect{ - // Increases Swords +3 - // 2% chance on melee hit to gain 1 extra attack. (1%, 100ms cooldown) - 2: func(agent core.Agent) { - character := agent.GetCharacter() - character.PseudoStats.SwordsSkill += 3 - if !character.AutoAttacks.AutoSwingMelee { - return - } - - core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - Name: "Twin Blades of the Hakkari", - Callback: core.CallbackOnSpellHitDealt, - Outcome: core.OutcomeLanded, - ProcMask: core.ProcMaskMelee, - SpellFlagsExclude: core.SpellFlagSuppressEquipProcs, - ProcChance: 0.02, - ICD: time.Millisecond * 100, - Handler: func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - spell.Unit.AutoAttacks.ExtraMHAttackProc(sim, 1, core.ActionID{SpellID: 468255}, spell) - }, - }) - }, - }, -}) - -var ItemSetZanzilsConcentration = core.NewItemSet(core.ItemSet{ - Name: "Zanzil's Concentration", - Bonuses: map[int32]core.ApplyEffect{ - // Increases damage and healing done by magical spells and effects by up to 6. - // Improves your chance to hit with all spells and attacks by 1%. - 2: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStats(stats.Stats{ - stats.SpellPower: 6, - stats.SpellHit: 1 * core.SpellHitRatingPerHitChance, - stats.MeleeHit: 1 * core.MeleeHitRatingPerHitChance, - }) - }, - }, -}) diff --git a/sim/common/sod/items_sets/phase_4.go b/sim/common/vanilla/item_sets/item_sets_pve.go similarity index 53% rename from sim/common/sod/items_sets/phase_4.go rename to sim/common/vanilla/item_sets/item_sets_pve.go index b39e5bd79..092e46e25 100644 --- a/sim/common/sod/items_sets/phase_4.go +++ b/sim/common/vanilla/item_sets/item_sets_pve.go @@ -2,7 +2,6 @@ package item_sets import ( "time" - "github.com/wowsims/classic/sim/common/guardians" "github.com/wowsims/classic/sim/core" "github.com/wowsims/classic/sim/core/stats" @@ -12,39 +11,10 @@ import ( // Cloth /////////////////////////////////////////////////////////////////////////// -var ItemSetThePostmaster = core.NewItemSet(core.ItemSet{ - Name: "The Postmaster", - Bonuses: map[int32]core.ApplyEffect{ - // +50 Armor. - 2: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.Armor, 50) - }, - // +10 Fire Resistance. - // +10 Arcane Resistance. - 3: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.ArcaneResistance, 10) - character.AddStat(stats.FireResistance, 10) - }, - // Increases damage and healing done by magical spells and effects by up to 12. - 4: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.SpellPower, 12) - }, - // Increases run speed by 5%. - // +10 Intellect. - 5: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.Intellect, 10) - }, - }, -}) - var ItemSetNecropileRaiment = core.NewItemSet(core.ItemSet{ Name: "Necropile Raiment", Bonuses: map[int32]core.ApplyEffect{ - // +5 Stamina. + // +3 Defense. 2: func(agent core.Agent) { character := agent.GetCharacter() character.AddStat(stats.Stamina, 5) @@ -71,50 +41,42 @@ var ItemSetIronweaveBattlesuit = core.NewItemSet(core.ItemSet{ Name: "Ironweave Battlesuit", Bonuses: map[int32]core.ApplyEffect{ // Increases your chance to resist Silence and Interrupt effects by 10%. - 2: func(agent core.Agent) { + 4: func(agent core.Agent) { // Nothing to do }, // +200 Armor. - 4: func(agent core.Agent) { + 8: func(agent core.Agent) { character := agent.GetCharacter() character.AddStat(stats.Armor, 200) }, - // Increases damage and healing done by magical spells and effects by up to 23. - 6: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.SpellPower, 23) - }, }, }) -var ItemSetTheHighlandersIntent = core.NewItemSet(core.ItemSet{ - Name: "The Highlander's Intent", +var ItemSetThePostmaster = core.NewItemSet(core.ItemSet{ + Name: "The Postmaster", Bonuses: map[int32]core.ApplyEffect{ - // Increase Stamina +5 + // +50 Armor. 2: func(agent core.Agent) { character := agent.GetCharacter() - character.AddStat(stats.Stamina, 5) + character.AddStat(stats.Armor, 50) }, - // +1 Crit with Spells. + // +10 Fire Resistance. + // +10 Arcane Resistance. 3: func(agent core.Agent) { character := agent.GetCharacter() - character.AddStat(stats.SpellCrit, 1) + character.AddStat(stats.ArcaneResistance, 10) + character.AddStat(stats.FireResistance, 10) }, - }, -}) - -var ItemSetTheDefilersIntent = core.NewItemSet(core.ItemSet{ - Name: "The Defiler's Intent", - Bonuses: map[int32]core.ApplyEffect{ - // Increase Stamina +5 - 2: func(agent core.Agent) { + // Increases damage and healing done by magical spells and effects by up to 12. + 4: func(agent core.Agent) { character := agent.GetCharacter() - character.AddStat(stats.Stamina, 5) + character.AddStat(stats.SpellPower, 12) }, - // +1 Crit with Spells. - 3: func(agent core.Agent) { + // Increases run speed by 5%. + // +10 Intellect. + 5: func(agent core.Agent) { character := agent.GetCharacter() - character.AddStat(stats.SpellCrit, 1) + character.AddStat(stats.Intellect, 10) }, }, }) @@ -150,70 +112,6 @@ var ItemSetCadaverousGarb = core.NewItemSet(core.ItemSet{ }, }) -var ItemSetTheHighlandersWill = core.NewItemSet(core.ItemSet{ - Name: "The Highlander's Will", - Bonuses: map[int32]core.ApplyEffect{ - // Increase Stamina +5 - 2: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.Stamina, 5) - }, - // +1 Crit with Spells. - 3: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.SpellCrit, 1) - }, - }, -}) - -var ItemSetTheHighlandersPurpose = core.NewItemSet(core.ItemSet{ - Name: "The Highlander's Purpose", - Bonuses: map[int32]core.ApplyEffect{ - // Increase Stamina +5 - 2: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.Stamina, 5) - }, - // +1 Crit with Melee. - 3: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.MeleeCrit, 1) - }, - }, -}) - -var ItemSetTheDefilersPurpose = core.NewItemSet(core.ItemSet{ - Name: "The Defiler's Purpose", - Bonuses: map[int32]core.ApplyEffect{ - // Increase Stamina +5 - 2: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.Stamina, 5) - }, - // +1 Crit with Melee. - 3: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.MeleeCrit, 1) - }, - }, -}) - -var ItemSetTheDefilersWill = core.NewItemSet(core.ItemSet{ - Name: "The Defiler's Will", - Bonuses: map[int32]core.ApplyEffect{ - // Increase Stamina +5 - 2: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.Stamina, 5) - }, - // +1 Crit with Spells. - 3: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.SpellCrit, 1) - }, - }, -}) - /////////////////////////////////////////////////////////////////////////// // Mail /////////////////////////////////////////////////////////////////////////// @@ -245,70 +143,6 @@ var ItemSetBloodmailRegalia = core.NewItemSet(core.ItemSet{ }, }) -var ItemSetTheHighlandersFortitude = core.NewItemSet(core.ItemSet{ - Name: "The Highlander's Fortitude", - Bonuses: map[int32]core.ApplyEffect{ - // Increase Stamina +5 - 2: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.Stamina, 5) - }, - // +1 Crit with Spells. - 3: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.SpellCrit, 1) - }, - }, -}) - -var ItemSetTheHighlandersDetermination = core.NewItemSet(core.ItemSet{ - Name: "The Highlander's Determination", - Bonuses: map[int32]core.ApplyEffect{ - // Increase Stamina +5 - 2: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.Stamina, 5) - }, - // +1 Crit with Melee. - 3: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.MeleeCrit, 1) - }, - }, -}) - -var ItemSetTheDefilersDetermination = core.NewItemSet(core.ItemSet{ - Name: "The Defiler's Determination", - Bonuses: map[int32]core.ApplyEffect{ - // Increase Stamina +5 - 2: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.Stamina, 5) - }, - // +1 Crit with Melee. - 3: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.MeleeCrit, 1) - }, - }, -}) - -var ItemSetTheDefilersFortitude = core.NewItemSet(core.ItemSet{ - Name: "The Defiler's Fortitude", - Bonuses: map[int32]core.ApplyEffect{ - // Increase Stamina +5 - 2: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.Stamina, 5) - }, - // +1 Crit with Melee. - 3: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.MeleeCrit, 1) - }, - }, -}) - /////////////////////////////////////////////////////////////////////////// // Plate /////////////////////////////////////////////////////////////////////////// @@ -331,8 +165,7 @@ var ItemSetDeathboneGuardian = core.NewItemSet(core.ItemSet{ character := agent.GetCharacter() character.AddResistances(15) }, - // Increases run speed by 5%. - // +10 Intellect. + // Increases your chance to parry an attack by 1% 5: func(agent core.Agent) { character := agent.GetCharacter() character.AddStat(stats.Parry, 1) @@ -340,54 +173,6 @@ var ItemSetDeathboneGuardian = core.NewItemSet(core.ItemSet{ }, }) -var ItemSetTheHighlandersResolve = core.NewItemSet(core.ItemSet{ - Name: "The Highlander's Resolve", - Bonuses: map[int32]core.ApplyEffect{ - // Increase Stamina +5 - 2: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.Stamina, 5) - }, - // +1 Crit with Melee. - 3: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.MeleeCrit, 1) - }, - }, -}) - -var ItemSetTheHighlandersResolution = core.NewItemSet(core.ItemSet{ - Name: "The Highlander's Resolution", - Bonuses: map[int32]core.ApplyEffect{ - // Increase Stamina +5 - 2: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.Stamina, 5) - }, - // +1 Crit with Melee - 3: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.MeleeCrit, 1) - }, - }, -}) - -var ItemSetTheDefilersResolution = core.NewItemSet(core.ItemSet{ - Name: "The Defiler's Resolution", - Bonuses: map[int32]core.ApplyEffect{ - // Increase Stamina +5 - 2: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.Stamina, 5) - }, - // +1 Crit with Melee - 3: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.MeleeCrit, 1) - }, - }, -}) - /////////////////////////////////////////////////////////////////////////// // Other /////////////////////////////////////////////////////////////////////////// @@ -396,13 +181,13 @@ var ItemSetSpidersKiss = core.NewItemSet(core.ItemSet{ Name: "Spider's Kiss", Bonuses: map[int32]core.ApplyEffect{ // Chance on Hit: Immobilizes the target and lowers their armor by 100 for 10 sec. - // Increased Defense +7. + // Unsure about exlusive effects with this aura also looks like it might be lowering the characters armor instead of the enemy? 2: func(agent core.Agent) { character := agent.GetCharacter() procAura := character.NewTemporaryStatsAura("Spider's Kiss", core.ActionID{SpellID: 17333}, stats.Stats{stats.Armor: -100}, time.Second*10) core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - ActionID: core.ActionID{SpellID: 446570}, - Name: "Echoes of the Depraved", + ActionID: core.ActionID{SpellID: 17333}, + Name: "Spider's Kiss", Callback: core.CallbackOnSpellHitDealt, Outcome: core.OutcomeLanded, ProcMask: core.ProcMaskMelee, @@ -411,7 +196,6 @@ var ItemSetSpidersKiss = core.NewItemSet(core.ItemSet{ procAura.Activate(sim) }, }) - character.AddStat(stats.Defense, 7) }, }, }) @@ -431,14 +215,10 @@ var ItemSetDalRendsArms = core.NewItemSet(core.ItemSet{ var ItemSetShardOfTheGods = core.NewItemSet(core.ItemSet{ Name: "Shard of the Gods", Bonuses: map[int32]core.ApplyEffect{ - // Increases healing done by spells and effects by up to 55. - // Increases damage done by magical spells and effects by up to 29. - // Your spell casts have a chance to summon Servants of the Scale or Flame. + // +10 All Resistances. 2: func(agent core.Agent) { character := agent.GetCharacter() - character.AddStat(stats.HealingPower, 55) - character.AddStat(stats.SpellDamage, 29) - // TODO: pets [Your spell casts have a chance to summon Servants of the Scale or Flame.] + character.AddResistances(15) }, }, }) @@ -446,18 +226,6 @@ var ItemSetShardOfTheGods = core.NewItemSet(core.ItemSet{ var ItemSetSpiritOfEskhandar = core.NewItemSet(core.ItemSet{ Name: "Spirit of Eskhandar", Bonuses: map[int32]core.ApplyEffect{ - // Improves your chance to hit with all spells and attacks by 1%. - 2: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.MeleeHit, 1) - character.AddStat(stats.SpellHit, 1) - }, - // Improves your chance to get a critical strike with all spells and attacks by 1%. - 3: func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.MeleeCrit, 1*core.CritRatingPerCritChance) - character.AddStat(stats.SpellCrit, 1*core.SpellCritRatingPerCritChance) - }, // 1% chance on a melee hit to call forth the spirit of Eskhandar to protect you in battle for 2 min. 4: func(agent core.Agent) { character := agent.GetCharacter() @@ -481,54 +249,106 @@ var ItemSetSpiritOfEskhandar = core.NewItemSet(core.ItemSet{ }, }) -var ItemSetCoreHoundsCall = core.NewItemSet(core.ItemSet{ - Name: "Core Hound's Call", +var ItemSetMajorMojoInfusion = core.NewItemSet(core.ItemSet{ + Name: "Major Mojo Infusion", Bonuses: map[int32]core.ApplyEffect{ - // Small chance on melee hit to call forth a Core Hound for 1 min. + // +30 Attack Power. 2: func(agent core.Agent) { character := agent.GetCharacter() - core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - Name: "Core Hound's Call Trigger", - Callback: core.CallbackOnSpellHitDealt, - Outcome: core.OutcomeLanded, - ProcMask: core.ProcMaskMelee, - ProcChance: 1, - ICD: time.Minute * 1, - Handler: func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - for _, petAgent := range character.PetAgents { - if coreHound, ok := petAgent.(*guardians.CoreHound); ok { - coreHound.EnableWithTimeout(sim, coreHound, time.Minute*1) - break - } - } - }, + character.AddStats(stats.Stats{ + stats.AttackPower: 30, + stats.RangedAttackPower: 30, }) }, - // Small chance on melee hit to call forth the Spirit of Magmadar to assist you in battle. Increasing your attack speed by 10% for 20 sec. - 3: func(agent core.Agent) { + }, +}) + +var ItemSetOverlordsResolution = core.NewItemSet(core.ItemSet{ + Name: "Overlord's Resolution", + Bonuses: map[int32]core.ApplyEffect{ + // Increases our chance to dodge an attack by 1% + 2: func(agent core.Agent) { character := agent.GetCharacter() - procAura := character.RegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 461270}, - Label: "Magmadar's Return", - Duration: time.Second * 20, + character.AddStat(stats.Dodge, 1) + }, + }, +}) + +var ItemSetPrayerOfThePrimal = core.NewItemSet(core.ItemSet{ + Name: "Prayer of the Primal", + Bonuses: map[int32]core.ApplyEffect{ + // Increases healing done by up to 33 + 2: func(agent core.Agent) { + character := agent.GetCharacter() + character.AddStat(stats.HealingPower, 33) + }, + }, +}) + +var ItemSetPrimalBlessing = core.NewItemSet(core.ItemSet{ + Name: "Primal Blessing", + Bonuses: map[int32]core.ApplyEffect{ + // Grants a small chance when ranged or melee damage is dealt to infuse the wielder with a blessing from the Primal Gods. + // Ranged and melee attack power increased by 300 for 12 sec. + 2: func(agent core.Agent) { + character := agent.GetCharacter() + + aura := character.RegisterAura(core.Aura{ + ActionID: core.ActionID{SpellID: 467742}, + Label: "Primal Blessing", + Duration: time.Second * 12, OnGain: func(aura *core.Aura, sim *core.Simulation) { - character.MultiplyAttackSpeed(sim, 1.1) + character.AddStatsDynamic(sim, stats.Stats{ + stats.AttackPower: 300, + stats.RangedAttackPower: 300, + }) }, OnExpire: func(aura *core.Aura, sim *core.Simulation) { - character.MultiplyAttackSpeed(sim, 1/1.1) + character.AddStatsDynamic(sim, stats.Stats{ + stats.AttackPower: -300, + stats.RangedAttackPower: -300, + }) }, }) + core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - Name: "Magmadar's Return Trigger", + Name: "Primal Blessing Trigger", Callback: core.CallbackOnSpellHitDealt, + ProcMask: core.ProcMaskMeleeOrRanged, Outcome: core.OutcomeLanded, - ProcMask: core.ProcMaskMelee, - ProcChance: 1, - ICD: time.Minute * 1, + ProcChance: 0.05, + ICD: time.Second * 72, Handler: func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - procAura.Activate(sim) + aura.Activate(sim) }, }) }, }, }) + +var ItemSetTwinBladesofHakkari = core.NewItemSet(core.ItemSet{ + Name: "The Twin Blades of Hakkari", + Bonuses: map[int32]core.ApplyEffect{ + // Increases Swords +6 + 2: func(agent core.Agent) { + character := agent.GetCharacter() + character.PseudoStats.SwordsSkill += 6 + }, + }, +}) + +var ItemSetZanzilsConcentration = core.NewItemSet(core.ItemSet{ + Name: "Zanzil's Concentration", + Bonuses: map[int32]core.ApplyEffect{ + // Increases damage and healing done by magical spells and effects by up to 6. + // Improves your chance to hit with all spells and attacks by 1%. + 2: func(agent core.Agent) { + character := agent.GetCharacter() + character.AddStats(stats.Stats{ + stats.SpellPower: 6, + stats.SpellHit: 1 * core.SpellHitRatingPerHitChance, + stats.MeleeHit: 1 * core.MeleeHitRatingPerHitChance, + }) + }, + }, +}) \ No newline at end of file diff --git a/sim/common/vanilla/item_sets/item_sets_pvp.go b/sim/common/vanilla/item_sets/item_sets_pvp.go new file mode 100644 index 000000000..865021830 --- /dev/null +++ b/sim/common/vanilla/item_sets/item_sets_pvp.go @@ -0,0 +1,231 @@ +package item_sets + +import ( + "github.com/wowsims/classic/sim/core" + "github.com/wowsims/classic/sim/core/stats" +) + +/////////////////////////////////////////////////////////////////////////// +// Cloth +/////////////////////////////////////////////////////////////////////////// + +var ItemSetTheHighlandersIntent = core.NewItemSet(core.ItemSet{ + Name: "The Highlander's Intent", + Bonuses: map[int32]core.ApplyEffect{ + // Increase Stamina +5 + 2: func(agent core.Agent) { + character := agent.GetCharacter() + character.AddStat(stats.Stamina, 5) + }, + // +1 Crit with Spells. + 3: func(agent core.Agent) { + character := agent.GetCharacter() + character.AddStat(stats.SpellCrit, 1) + }, + }, +}) + +var ItemSetTheDefilersIntent = core.NewItemSet(core.ItemSet{ + Name: "The Defiler's Intent", + Bonuses: map[int32]core.ApplyEffect{ + // Increase Stamina +5 + 2: func(agent core.Agent) { + character := agent.GetCharacter() + character.AddStat(stats.Stamina, 5) + }, + // +1 Crit with Spells. + 3: func(agent core.Agent) { + character := agent.GetCharacter() + character.AddStat(stats.SpellCrit, 1) + }, + }, +}) + +/////////////////////////////////////////////////////////////////////////// +// Leather +/////////////////////////////////////////////////////////////////////////// + +var ItemSetTheHighlandersPurpose = core.NewItemSet(core.ItemSet{ + Name: "The Highlander's Purpose", + Bonuses: map[int32]core.ApplyEffect{ + // Increase Stamina +5 + 2: func(agent core.Agent) { + character := agent.GetCharacter() + character.AddStat(stats.Stamina, 5) + }, + // +1 Crit with Melee. + 3: func(agent core.Agent) { + character := agent.GetCharacter() + character.AddStat(stats.MeleeCrit, 1) + }, + }, +}) + +var ItemSetTheHighlandersWill = core.NewItemSet(core.ItemSet{ + Name: "The Highlander's Will", + Bonuses: map[int32]core.ApplyEffect{ + // Increase Stamina +5 + 2: func(agent core.Agent) { + character := agent.GetCharacter() + character.AddStat(stats.Stamina, 5) + }, + // +1 Crit with Spells. + 3: func(agent core.Agent) { + character := agent.GetCharacter() + character.AddStat(stats.SpellCrit, 1) + }, + }, +}) + +var ItemSetTheDefilersPurpose = core.NewItemSet(core.ItemSet{ + Name: "The Defiler's Purpose", + Bonuses: map[int32]core.ApplyEffect{ + // Increase Stamina +5 + 2: func(agent core.Agent) { + character := agent.GetCharacter() + character.AddStat(stats.Stamina, 5) + }, + // +1 Crit with Melee. + 3: func(agent core.Agent) { + character := agent.GetCharacter() + character.AddStat(stats.MeleeCrit, 1) + }, + }, +}) + +var ItemSetTheDefilersWill = core.NewItemSet(core.ItemSet{ + Name: "The Defiler's Will", + Bonuses: map[int32]core.ApplyEffect{ + // Increase Stamina +5 + 2: func(agent core.Agent) { + character := agent.GetCharacter() + character.AddStat(stats.Stamina, 5) + }, + // +1 Crit with Spells. + 3: func(agent core.Agent) { + character := agent.GetCharacter() + character.AddStat(stats.SpellCrit, 1) + }, + }, +}) + + +/////////////////////////////////////////////////////////////////////////// +// Mail +/////////////////////////////////////////////////////////////////////////// + +var ItemSetTheHighlandersFortitude = core.NewItemSet(core.ItemSet{ + Name: "The Highlander's Fortitude", + Bonuses: map[int32]core.ApplyEffect{ + // Increase Stamina +5 + 2: func(agent core.Agent) { + character := agent.GetCharacter() + character.AddStat(stats.Stamina, 5) + }, + // +1 Crit with Spells. + 3: func(agent core.Agent) { + character := agent.GetCharacter() + character.AddStat(stats.SpellCrit, 1) + }, + }, +}) + +var ItemSetTheHighlandersDetermination = core.NewItemSet(core.ItemSet{ + Name: "The Highlander's Determination", + Bonuses: map[int32]core.ApplyEffect{ + // Increase Stamina +5 + 2: func(agent core.Agent) { + character := agent.GetCharacter() + character.AddStat(stats.Stamina, 5) + }, + // +1 Crit with Melee. + 3: func(agent core.Agent) { + character := agent.GetCharacter() + character.AddStat(stats.MeleeCrit, 1) + }, + }, +}) + +var ItemSetTheDefilersFortitude = core.NewItemSet(core.ItemSet{ + Name: "The Defiler's Fortitude", + Bonuses: map[int32]core.ApplyEffect{ + // Increase Stamina +5 + 2: func(agent core.Agent) { + character := agent.GetCharacter() + character.AddStat(stats.Stamina, 5) + }, + // +1 Crit with Melee. + 3: func(agent core.Agent) { + character := agent.GetCharacter() + character.AddStat(stats.MeleeCrit, 1) + }, + }, +}) + +var ItemSetTheDefilersDetermination = core.NewItemSet(core.ItemSet{ + Name: "The Defiler's Determination", + Bonuses: map[int32]core.ApplyEffect{ + // Increase Stamina +5 + 2: func(agent core.Agent) { + character := agent.GetCharacter() + character.AddStat(stats.Stamina, 5) + }, + // +1 Crit with Melee. + 3: func(agent core.Agent) { + character := agent.GetCharacter() + character.AddStat(stats.MeleeCrit, 1) + }, + }, +}) + +/////////////////////////////////////////////////////////////////////////// +// Plate +/////////////////////////////////////////////////////////////////////////// + +var ItemSetTheHighlandersResolve = core.NewItemSet(core.ItemSet{ + Name: "The Highlander's Resolve", + Bonuses: map[int32]core.ApplyEffect{ + // Increase Stamina +5 + 2: func(agent core.Agent) { + character := agent.GetCharacter() + character.AddStat(stats.Stamina, 5) + }, + // +1 Crit with Melee. + 3: func(agent core.Agent) { + character := agent.GetCharacter() + character.AddStat(stats.MeleeCrit, 1) + }, + }, +}) + +var ItemSetTheHighlandersResolution = core.NewItemSet(core.ItemSet{ + Name: "The Highlander's Resolution", + Bonuses: map[int32]core.ApplyEffect{ + // Increase Stamina +5 + 2: func(agent core.Agent) { + character := agent.GetCharacter() + character.AddStat(stats.Stamina, 5) + }, + // +1 Crit with Melee + 3: func(agent core.Agent) { + character := agent.GetCharacter() + character.AddStat(stats.MeleeCrit, 1) + }, + }, +}) + +var ItemSetTheDefilersResolution = core.NewItemSet(core.ItemSet{ + Name: "The Defiler's Resolution", + Bonuses: map[int32]core.ApplyEffect{ + // Increase Stamina +5 + 2: func(agent core.Agent) { + character := agent.GetCharacter() + character.AddStat(stats.Stamina, 5) + }, + // +1 Crit with Melee + 3: func(agent core.Agent) { + character := agent.GetCharacter() + character.AddStat(stats.MeleeCrit, 1) + }, + }, +}) diff --git a/sim/mage/TestP1Mage.results b/sim/mage/TestP1Mage.results index bf6ec44af..84479bcaa 100644 --- a/sim/mage/TestP1Mage.results +++ b/sim/mage/TestP1Mage.results @@ -138,6 +138,13 @@ dps_results: { tps: 92.46523 } } +dps_results: { + key: "TestP1Mage-Phase1-AllItems-IronweaveBattlesuit" + value: { + dps: 65.51091 + tps: 72.7335 + } +} dps_results: { key: "TestP1Mage-Phase1-AllItems-LieutenantCommander'sRegalia" value: { @@ -148,8 +155,8 @@ dps_results: { dps_results: { key: "TestP1Mage-Phase1-AllItems-NetherwindRegalia" value: { - dps: 107.93251 - tps: 101.39714 + dps: 107.30217 + tps: 99.97337 } } dps_results: { diff --git a/sim/mage/ignite.go b/sim/mage/ignite.go index 2bde93841..01f3e528b 100644 --- a/sim/mage/ignite.go +++ b/sim/mage/ignite.go @@ -28,17 +28,29 @@ func (mage *Mage) applyIgnite() { } if spell.SpellSchool.Matches(core.SpellSchoolFire) && result.DidCrit() { newIgniteDamage = result.Damage * 0.08 * float64(mage.Talents.Ignite) - dot := mage.Ignite.Dot(result.Target) - dot.ApplyOrRefresh(sim) - if dot.GetStacks() < dot.MaxStacks{ - dot.AddStack(sim) - dot.TakeSnapshot(sim, true) - } + mage.Ignite.Cast(sim, result.Target) } }, }) mage.Ignite = mage.RegisterSpell(core.SpellConfig{ + ActionID: core.ActionID{SpellID: 12654}, + Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagPassiveSpell | SpellFlagMage, + + ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { +// result := spell.CalcAndDealOutcome(sim, target, spell.OutcomeMagicHit) + + dot := mage.igniteTick.Dot(target) + dot.ApplyOrRefresh(sim) + if dot.GetStacks() < dot.MaxStacks{ + dot.AddStack(sim) + dot.TakeSnapshot(sim, true) +} + + }, + }) + + mage.igniteTick = mage.RegisterSpell(core.SpellConfig{ SpellCode: SpellCode_MageIgnite, ActionID: core.ActionID{SpellID: 12654}, SpellSchool: core.SpellSchoolFire, diff --git a/sim/mage/item_sets_pve.go b/sim/mage/item_sets_pve.go index 86e180c61..8190c96d3 100644 --- a/sim/mage/item_sets_pve.go +++ b/sim/mage/item_sets_pve.go @@ -3,7 +3,7 @@ package mage import ( "slices" "time" - + "github.com/wowsims/classic/sim/core" "github.com/wowsims/classic/sim/core/stats" ) @@ -84,7 +84,7 @@ var ItemSetNetherwindRegalia = core.NewItemSet(core.ItemSet{ Duration: time.Second * 10, OnInit: func(aura *core.Aura, sim *core.Simulation) { for spellIdx := range mage.Spellbook { - if spell := mage.Spellbook[spellIdx]; spell.DefaultCast.CastTime > 0 && spell.DefaultCast.CastTime <= 10 { + if spell := mage.Spellbook[spellIdx]; (spell.DefaultCast.CastTime > 0 && spell.DefaultCast.CastTime <= 10*time.Second) { affectedSpells = append(affectedSpells, spell) } } @@ -103,6 +103,9 @@ var ItemSetNetherwindRegalia = core.NewItemSet(core.ItemSet{ if !slices.Contains(affectedSpells, spell) { return } + if (spell.CurCast.CastTime > 0) { //Returns if you are midcast when your aura procs from landing to prevent instant consumption + return + } aura.Deactivate(sim) }, }) @@ -115,7 +118,9 @@ var ItemSetNetherwindRegalia = core.NewItemSet(core.ItemSet{ }, OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { if (spell.SpellCode == SpellCode_MageArcaneMissiles || spell.SpellCode == SpellCode_MageFireball || spell.SpellCode == SpellCode_MageFrostbolt) { - netherwindFocusAura.Activate(sim) + if sim.Proc(0.10, "Netherwind Focus Proc") { + netherwindFocusAura.Activate(sim) + } } }, }) diff --git a/sim/mage/mage.go b/sim/mage/mage.go index b7db349b9..7e164f6ec 100644 --- a/sim/mage/mage.go +++ b/sim/mage/mage.go @@ -66,6 +66,7 @@ type Mage struct { Frostbolt []*core.Spell IceBarrier []*core.Spell Ignite *core.Spell + igniteTick *core.Spell ManaGem []*core.Spell PresenceOfMind *core.Spell Pyroblast []*core.Spell diff --git a/sim/priest/shadow/TestP1Shadow.results b/sim/priest/shadow/TestP1Shadow.results index 851627c54..2d6cd64c2 100644 --- a/sim/priest/shadow/TestP1Shadow.results +++ b/sim/priest/shadow/TestP1Shadow.results @@ -96,6 +96,13 @@ stat_weights_results: { weights: 0 } } +dps_results: { + key: "TestP1Shadow-Phase1-AllItems-IronweaveBattlesuit" + value: { + dps: 426.19902 + tps: 422.03243 + } +} dps_results: { key: "TestP1Shadow-Phase1-Average-Default" value: { diff --git a/sim/warlock/dps/TestWarlockDSRuin.results b/sim/warlock/dps/TestWarlockDSRuin.results index ea3a204c1..3fbf750de 100644 --- a/sim/warlock/dps/TestWarlockDSRuin.results +++ b/sim/warlock/dps/TestWarlockDSRuin.results @@ -138,6 +138,13 @@ dps_results: { tps: 913.455 } } +dps_results: { + key: "TestWarlockDSRuin-Phase1-AllItems-IronweaveBattlesuit" + value: { + dps: 688.5355 + tps: 742.04917 + } +} dps_results: { key: "TestWarlockDSRuin-Phase1-AllItems-LieutenantCommander'sDreadgear" value: { diff --git a/sim/warlock/dps/TestWarlockSMRuin.results b/sim/warlock/dps/TestWarlockSMRuin.results index bd91e54a1..cfb8a8da7 100644 --- a/sim/warlock/dps/TestWarlockSMRuin.results +++ b/sim/warlock/dps/TestWarlockSMRuin.results @@ -138,6 +138,13 @@ dps_results: { tps: 865.9166 } } +dps_results: { + key: "TestWarlockSMRuin-Phase1-AllItems-IronweaveBattlesuit" + value: { + dps: 869.24382 + tps: 706.68821 + } +} dps_results: { key: "TestWarlockSMRuin-Phase1-AllItems-LieutenantCommander'sDreadgear" value: {