From 4a51a54a2715d6fe9741fe245e5908596f5b4654 Mon Sep 17 00:00:00 2001 From: sanguinerarogue Date: Sat, 7 Dec 2024 23:10:20 -0700 Subject: [PATCH 1/3] First pass at mage set implementation --- assets/database/db.bin | Bin 5098725 -> 5098725 bytes assets/database/db.json | 6 +- assets/database/leftover_db.bin | Bin 849828 -> 849828 bytes assets/database/leftover_db.json | 4 +- sim/common/vanilla/item_sets/dungeon_set_1.go | 2 +- sim/mage/TestP1Mage.results | 70 +++ sim/mage/_item_sets_pve.go | 484 ------------------ sim/mage/counterspell.go | 2 +- sim/mage/evocation.go | 4 +- sim/mage/flamestrike.go | 1 + sim/mage/item_sets_pve.go | 441 ++++++++++++++++ .../{_item_sets_pvp.go => item_sets_pvp.go} | 0 sim/mage/items.go | 131 +---- sim/mage/mage.go | 3 + sim/warlock/dps/TestWarlockDSRuin.results | 8 +- sim/warlock/dps/TestWarlockSMRuin.results | 8 +- tools/database/gen_db/main.go | 4 +- ui/core/proto_utils/names.ts | 8 +- 18 files changed, 560 insertions(+), 616 deletions(-) delete mode 100644 sim/mage/_item_sets_pve.go create mode 100644 sim/mage/item_sets_pve.go rename sim/mage/{_item_sets_pvp.go => item_sets_pvp.go} (100%) diff --git a/assets/database/db.bin b/assets/database/db.bin index 314a49264d77e02c18e2ca7377f5ad4de64251cd..0f34528c8cc35639f1980a0f0c769a063c6e113a 100644 GIT binary patch delta 259 zcmWN=$u0w70KoBlH5f}RwJ*gCYN@ePduwKlt>Ri&2bUfjjZ@?BPv$@mgiIaWcmwi1 zfauX%^wu}fi0_yDDlalrQEw51s6(Tk1{%?6qL~(23DZV99dr_*i*9=8rH_6F7-WcH zqKq)g7zQTeOfX4|DW;iWmN;`*%(K8EODwa(Dr>BhV1rGz*k*@a_DGUq|HH1=XG?@HFaaH?fXR?E5crQ7s!SB_oFNxPOWzGzYX%M*s~en#?P yEs#j+-=1(ozgArS+!Ru#me60D!U(#JWIpDYm4bS#o~T9jR6SGArCGW7$ovE9K4#kh diff --git a/assets/database/db.json b/assets/database/db.json index 8ea77aa85..da8f841f7 100644 --- a/assets/database/db.json +++ b/assets/database/db.json @@ -8742,8 +8742,8 @@ {"effectId":63,"spellId":13538,"name":"Enchant Chest - Lesser Absorption","type":5,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":1}, {"effectId":66,"spellId":7457,"name":"Enchant Bracer - Minor Stamina","type":6,"stats":[0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":1}, {"effectId":66,"spellId":7863,"name":"Enchant Boots - Minor Stamina","type":10,"stats":[0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":1}, -{"effectId":241,"spellId":7745,"name":"Enchant 2H Weapon - Minor Impact","type":13,"enchantType":1,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":1}, {"effectId":241,"spellId":13503,"name":"Enchant Weapon - Lesser Striking","type":13,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":1}, +{"effectId":241,"spellId":7745,"name":"Enchant 2H Weapon - Minor Impact","type":13,"enchantType":1,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":1}, {"effectId":242,"spellId":7748,"name":"Enchant Chest - Lesser Health","type":5,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,0,0,0,0,0,0],"quality":1}, {"effectId":243,"spellId":7766,"name":"Enchant Bracer - Minor Spirit","type":6,"stats":[0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":2}, {"effectId":246,"spellId":7776,"name":"Enchant Chest - Lesser Mana","type":5,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":2}, @@ -10471,8 +10471,10 @@ {"id":11255,"name":"Improved Counterspell","icon":"spell_frost_iceshock","rank":1}, {"id":11269,"name":"Ambush","icon":"ability_rogue_ambush","rank":6}, {"id":11275,"name":"Rupture","icon":"ability_rogue_rupture","rank":6,"hasBuff":true}, +{"id":11281,"name":"Backstab","icon":"ability_backstab","rank":8}, {"id":11290,"name":"Garrote","icon":"ability_rogue_garrote","rank":6,"hasBuff":true}, {"id":11294,"name":"Sinister Strike","icon":"spell_shadow_ritualofsacrifice","rank":8}, +{"id":11300,"name":"Eviscerate","icon":"ability_rogue_eviscerate","rank":8}, {"id":11306,"name":"Fire Nova","icon":"spell_fire_sealoffire","rank":4}, {"id":11307,"name":"Fire Nova","icon":"spell_fire_sealoffire","rank":5}, {"id":11314,"name":"Fire Nova Totem","icon":"spell_fire_sealoffire","rank":4}, @@ -12700,7 +12702,6 @@ {"id":25297,"name":"Healing Touch","icon":"spell_nature_healingtouch","rank":11}, {"id":25298,"name":"Starfire","icon":"spell_arcane_starfire","rank":7}, {"id":25299,"name":"Rejuvenation","icon":"spell_nature_rejuvenation","rank":11,"hasBuff":true}, -{"id":25300,"name":"Backstab","icon":"ability_backstab","rank":9}, {"id":25304,"name":"Frostbolt","icon":"spell_frost_frostbolt02","rank":11,"hasBuff":true}, {"id":25306,"name":"Fireball","icon":"spell_fire_flamebolt","rank":12,"hasBuff":true}, {"id":25307,"name":"Shadow Bolt","icon":"spell_shadow_shadowbolt","rank":10}, @@ -12872,7 +12873,6 @@ {"id":30906,"name":"Deadliness","icon":"inv_weapon_crossbow_11","rank":5}, {"id":30919,"name":"Weapon Expertise","icon":"spell_holy_blessingofstrength","rank":1}, {"id":30920,"name":"Weapon Expertise","icon":"spell_holy_blessingofstrength","rank":2}, -{"id":31016,"name":"Eviscerate","icon":"ability_rogue_eviscerate"}, {"id":31018,"name":"Ferocious Bite","icon":"ability_druid_ferociousbite"}, {"id":400574,"name":"Arcane Blast","icon":"spell_arcane_blast"}, {"id":400610,"name":"Arcane Barrage","icon":"ability_mage_arcanebarrage"}, diff --git a/assets/database/leftover_db.bin b/assets/database/leftover_db.bin index b3740b07f13ddb82e56cf521e4177c35dfd54617..120938f01b3ea650e74652ae2e2c54c3a5daf51d 100644 GIT binary patch delta 87 zcmZ4T-gwD-F7M2#)7Pc1l7LFFq7OocVEj$Li+mG<^Ok&(_z{@j*aeJ5m qPg?PI_g0>%jNA7#^K>(AzthH(roR2cdXR|II-Wkp?Wr4i?A-uVXCIUR delta 87 zcmZ4T-gwD-F7M2#)7Pc1l7LFFq7OocVEj$Li+Yj;aOkvz^z{@jjB?A-uWcpswx diff --git a/assets/database/leftover_db.json b/assets/database/leftover_db.json index e6326a0b5..6b2f85cf2 100644 --- a/assets/database/leftover_db.json +++ b/assets/database/leftover_db.json @@ -1511,8 +1511,8 @@ {"effectId":929,"itemId":16217,"spellId":20069,"name":"Enchant Shield - Greater Stamina","type":13,"enchantType":2,"stats":[0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":1}, {"effectId":930,"spellId":13947,"name":"Enchant Gloves - Riding Skill","type":7,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":2}, {"effectId":931,"spellId":13948,"name":"Enchant Gloves - Minor Haste","type":7,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":1}, -{"effectId":943,"spellId":13529,"name":"Enchant 2H Weapon - Lesser Impact","type":13,"enchantType":1,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":1}, {"effectId":943,"spellId":13693,"name":"Enchant Weapon - Striking","type":13,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":1}, +{"effectId":943,"spellId":13529,"name":"Enchant 2H Weapon - Lesser Impact","type":13,"enchantType":1,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":1}, {"effectId":963,"spellId":13937,"name":"Enchant 2H Weapon - Greater Impact","type":13,"enchantType":1,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":1}, {"effectId":1483,"itemId":11622,"spellId":15340,"name":"Lesser Arcanum of Rumination","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,150,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":2}, {"effectId":1503,"itemId":11642,"spellId":15389,"name":"Lesser Arcanum of Constitution","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,100,0,0,0,0,0,0,0,0,0],"quality":2}, @@ -1538,8 +1538,8 @@ {"effectId":1893,"spellId":20028,"name":"Enchant Chest - Major Mana","type":5,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":2}, {"effectId":1894,"spellId":20029,"name":"Enchant Weapon - Icy Chill","type":13,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":2}, {"effectId":1896,"spellId":20030,"name":"Enchant 2H Weapon - Superior Impact","type":13,"enchantType":1,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":2}, -{"effectId":1897,"spellId":13695,"name":"Enchant 2H Weapon - Impact","type":13,"enchantType":1,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":1}, {"effectId":1897,"spellId":20031,"name":"Enchant Weapon - Superior Striking","type":13,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":2}, +{"effectId":1897,"spellId":13695,"name":"Enchant 2H Weapon - Impact","type":13,"enchantType":1,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":1}, {"effectId":1898,"spellId":20032,"name":"Enchant Weapon - Lifestealing","type":13,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":3}, {"effectId":1899,"spellId":20033,"name":"Enchant Weapon - Unholy Weapon","type":13,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":2}, {"effectId":1900,"spellId":20034,"name":"Enchant Weapon - Crusader","type":13,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":2}, diff --git a/sim/common/vanilla/item_sets/dungeon_set_1.go b/sim/common/vanilla/item_sets/dungeon_set_1.go index 66fd5a9e7..0e120ce93 100644 --- a/sim/common/vanilla/item_sets/dungeon_set_1.go +++ b/sim/common/vanilla/item_sets/dungeon_set_1.go @@ -121,7 +121,7 @@ var ItemSetMagistersRegalia = core.NewItemSet(core.ItemSet{ }, // When struck in combat has a chance of freezing the attacker in place for 3 sec. 6: func(agent core.Agent) { - //Not implemented due to raid boss immunity + // No implementation in sim }, // +8 All Resistances. 8: func(agent core.Agent) { diff --git a/sim/mage/TestP1Mage.results b/sim/mage/TestP1Mage.results index 3df624e50..bf6ec44af 100644 --- a/sim/mage/TestP1Mage.results +++ b/sim/mage/TestP1Mage.results @@ -96,6 +96,76 @@ stat_weights_results: { weights: 0 } } +dps_results: { + key: "TestP1Mage-Phase1-AllItems-ArcanistRegalia" + value: { + dps: 97.10096 + tps: 90.36367 + } +} +dps_results: { + key: "TestP1Mage-Phase1-AllItems-Champion'sRegalia" + value: { + dps: 84.10533 + tps: 91.33828 + } +} +dps_results: { + key: "TestP1Mage-Phase1-AllItems-EnigmaVestments" + value: { + dps: 107.96625 + tps: 114.91555 + } +} +dps_results: { + key: "TestP1Mage-Phase1-AllItems-FieldMarshal'sRegalia" + value: { + dps: 106.14672 + tps: 113.43537 + } +} +dps_results: { + key: "TestP1Mage-Phase1-AllItems-FrostfireRegalia" + value: { + dps: 146.34232 + tps: 134.14575 + } +} +dps_results: { + key: "TestP1Mage-Phase1-AllItems-Illusionist'sAttire" + value: { + dps: 85.18755 + tps: 92.46523 + } +} +dps_results: { + key: "TestP1Mage-Phase1-AllItems-LieutenantCommander'sRegalia" + value: { + dps: 84.10533 + tps: 91.33828 + } +} +dps_results: { + key: "TestP1Mage-Phase1-AllItems-NetherwindRegalia" + value: { + dps: 107.93251 + tps: 101.39714 + } +} +dps_results: { + key: "TestP1Mage-Phase1-AllItems-Sorcerer'sRegalia" + value: { + dps: 92.73649 + tps: 100.01821 + } +} +dps_results: { + key: "TestP1Mage-Phase1-AllItems-Warlord'sRegalia" + value: { + dps: 106.14672 + tps: 113.43537 + } +} dps_results: { key: "TestP1Mage-Phase1-Average-Default" value: { diff --git a/sim/mage/_item_sets_pve.go b/sim/mage/_item_sets_pve.go deleted file mode 100644 index 5930dacde..000000000 --- a/sim/mage/_item_sets_pve.go +++ /dev/null @@ -1,484 +0,0 @@ -package mage - -import ( - "math" - "slices" - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" - "github.com/wowsims/classic/sim/core/stats" -) - -/////////////////////////////////////////////////////////////////////////// -// SoD Phase 4 Item Sets -/////////////////////////////////////////////////////////////////////////// - -var ItemSetSorcerersRegalia = core.NewItemSet(core.ItemSet{ - Name: "Sorcerer's Regalia", - Bonuses: map[int32]core.ApplyEffect{ - // Increases damage and healing done by magical spells and effects by up to 23. - 2: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.SpellPower, 23) - }, - // Your spellcasts have a 6% chance to energize you for 300 mana. - 4: func(agent core.Agent) { - c := agent.GetCharacter() - actionID := core.ActionID{SpellID: 450527} - manaMetrics := c.NewManaMetrics(actionID) - - core.MakeProcTriggerAura(&c.Unit, core.ProcTrigger{ - Name: "S03 - Mana Proc on Cast - Magister's Regalia", - Callback: core.CallbackOnSpellHitDealt, - Outcome: core.OutcomeLanded, - ProcMask: core.ProcMaskSpellDamage | core.ProcMaskSpellHealing, - ProcChance: 0.06, - Handler: func(sim *core.Simulation, spell *core.Spell, _ *core.SpellResult) { - if c.HasManaBar() { - c.AddMana(sim, 300, manaMetrics) - } - }, - }) - }, - // +8 All Resistances. - 6: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddResistances(8) - }, - // +200 Armor. - 8: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.Armor, 200) - }, - }, -}) - -var ItemSetArcanistMoment = core.NewItemSet(core.ItemSet{ - Name: "Arcanist Moment", - Bonuses: map[int32]core.ApplyEffect{ - // Your Temporal Beacons last 20% longer. - 2: func(agent core.Agent) { - // Nothing to do - }, - // Increases all chronomantic healing you deal by 10%. - 4: func(agent core.Agent) { - // Nothing to do - }, - // Each time you heal a target with Regeneration, the remaining cooldown on Rewind Time is reduced by 1 sec. - 6: func(agent core.Agent) { - // Nothing to do - }, - }, -}) - -var ItemSetArcanistInsight = core.NewItemSet(core.ItemSet{ - Name: "Arcanist Insight", - Bonuses: map[int32]core.ApplyEffect{ - // You are immune to all damage while channeling Evocation. - 2: func(agent core.Agent) { - // May important later but for now nothing to do - }, - // You gain 1% increased damage for 15 sec each time you cast a spell from a different school of magic. - 4: func(agent core.Agent) { - // TODO: This is all a bit of an assumption about how this may work without having more information. - // We may need to rework it as we get more information - mage := agent.(MageAgent).GetMage() - - damageMultiplierPerSchool := 1.01 - auraDuration := time.Second * 15 - - arcaneAura := mage.RegisterAura(core.Aura{ - Label: "S03 - Item - T1 - Mage - Damage 4P Bonus (Arcane)", - ActionID: core.ActionID{SpellID: 456398}.WithTag(int32(stats.SchoolIndexArcane)), - Duration: auraDuration, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - mage.PseudoStats.DamageDealtMultiplier *= damageMultiplierPerSchool - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - mage.PseudoStats.DamageDealtMultiplier /= damageMultiplierPerSchool - }, - }) - - fireAura := mage.RegisterAura(core.Aura{ - Label: "S03 - Item - T1 - Mage - Damage 4P Bonus (Fire)", - ActionID: core.ActionID{SpellID: 456398}.WithTag(int32(stats.SchoolIndexFire)), - Duration: auraDuration, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - mage.PseudoStats.DamageDealtMultiplier *= damageMultiplierPerSchool - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - mage.PseudoStats.DamageDealtMultiplier /= damageMultiplierPerSchool - }, - }) - - frostAura := mage.RegisterAura(core.Aura{ - Label: "S03 - Item - T1 - Mage - Damage 4P Bonus (Frost)", - ActionID: core.ActionID{SpellID: 456398}.WithTag(int32(stats.SchoolIndexFrost)), - Duration: auraDuration, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - mage.PseudoStats.DamageDealtMultiplier *= damageMultiplierPerSchool - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - mage.PseudoStats.DamageDealtMultiplier /= damageMultiplierPerSchool - }, - }) - - core.MakePermanent(mage.RegisterAura(core.Aura{ - Label: "S03 - Item - T1 - Mage - Damage 4P Bonus", - OnCastComplete: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell) { - if spell.SpellSchool.Matches(core.SpellSchoolPhysical) { - return - } - if spell.SpellSchool.Matches(core.SpellSchoolArcane) { - arcaneAura.Activate(sim) - } - if spell.SpellSchool.Matches(core.SpellSchoolFire) { - fireAura.Activate(sim) - } - if spell.SpellSchool.Matches(core.SpellSchoolFrost) { - frostAura.Activate(sim) - } - }, - })) - }, - // Mage Armor increases your mana regeneration while casting by an additional 15%. Molten Armor increases your spell damage and healing by 18. Ice Armor grants 20% increased chance to trigger Fingers of Frost. - 6: func(agent core.Agent) { - mage := agent.(MageAgent).GetMage() - - bonusFoFProcChance := .20 - bonusSpiritRegenRateCasting := .15 - bonusSpellPower := 18.0 - - core.MakePermanent(mage.RegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 456402}, - Label: "S03 - Item - T1 - Mage - Damage 6P Bonus", - BuildPhase: core.CharacterBuildPhaseBuffs, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - switch mage.Options.Armor { - case proto.Mage_Options_IceArmor: - mage.FingersOfFrostProcChance += bonusFoFProcChance - case proto.Mage_Options_MageArmor: - mage.PseudoStats.SpiritRegenRateCasting += bonusSpiritRegenRateCasting - case proto.Mage_Options_MoltenArmor: - if aura.Unit.Env.MeasuringStats && aura.Unit.Env.State != core.Finalized { - mage.AddStat(stats.SpellPower, bonusSpellPower) - } else { - mage.AddStatDynamic(sim, stats.SpellPower, bonusSpellPower) - } - } - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - switch mage.Options.Armor { - case proto.Mage_Options_IceArmor: - mage.FingersOfFrostProcChance -= bonusFoFProcChance - case proto.Mage_Options_MageArmor: - mage.PseudoStats.SpiritRegenRateCasting -= bonusSpiritRegenRateCasting - case proto.Mage_Options_MoltenArmor: - if mage.Options.Armor == proto.Mage_Options_MoltenArmor && aura.Unit.Env.MeasuringStats && aura.Unit.Env.State != core.Finalized { - mage.AddStat(stats.SpellPower, -bonusSpellPower) - } else { - mage.AddStatDynamic(sim, stats.SpellPower, -bonusSpellPower) - } - } - }, - })) - }, - }, -}) - -/////////////////////////////////////////////////////////////////////////// -// SoD Phase 5 Item Sets -/////////////////////////////////////////////////////////////////////////// - -var ItemSetNetherwindInsight = core.NewItemSet(core.ItemSet{ - Name: "Netherwind Insight", - Bonuses: map[int32]core.ApplyEffect{ - // Decreases the threat generated by your Fire spells by 20%. - 2: func(agent core.Agent) { - mage := agent.(MageAgent).GetMage() - mage.RegisterAura(core.Aura{ - Label: "S03 - Item - T2 - Mage - Damage 2P Bonus", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - for _, spell := range mage.Spellbook { - if spell.SpellSchool == core.SpellSchoolFire && spell.Flags.Matches(SpellFlagMage) { - spell.ThreatMultiplier *= .80 - } - } - }, - }) - }, - // Your Pyroblast deals 20% increased damage to targets afflicted with your Fireball's periodic effect. - 4: func(agent core.Agent) { - mage := agent.(MageAgent).GetMage() - mage.RegisterAura(core.Aura{ - Label: "S03 - Item - T2 - Mage - Damage 4P Bonus", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - fireballSpells := core.FilterSlice(mage.Fireball, func(spell *core.Spell) bool { return spell != nil }) - - for _, spell := range mage.Pyroblast { - if spell == nil { - continue - } - - oldApplyEffects := spell.ApplyEffects - spell.ApplyEffects = func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - multiplier := 1.0 - - for _, spell := range fireballSpells { - if spell.Dot(target).IsActive() { - multiplier *= 1.20 - break - } - } - - spell.DamageMultiplier *= multiplier - oldApplyEffects(sim, target, spell) - spell.DamageMultiplier /= multiplier - } - } - }, - }) - }, - // Your Fireball's periodic effect gains increased damage over its duration equal to 20% of its impact damage. - 6: func(agent core.Agent) { - mage := agent.(MageAgent).GetMage() - mage.MaintainFireballDoT = true - core.MakePermanent(mage.RegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 467399}, - Label: "S03 - Item - T2 - Mage - Damage 6P Bonus", - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if spell.SpellCode == SpellCode_MageFireball && result.Landed() { - mage.BonusFireballDoTAmount += result.Damage * 1.00 / float64(spell.Dot(result.Target).NumberOfTicks) - } - }, - })) - }, - }, -}) - -var ItemSetNetherwindMoment = core.NewItemSet(core.ItemSet{ - Name: "Netherwind Moment", - Bonuses: map[int32]core.ApplyEffect{ - // Your Arcane Missiles refunds 10% of its base mana cost each time it deals damage. - 2: func(agent core.Agent) { - mage := agent.(MageAgent).GetMage() - actionID := core.ActionID{SpellID: 467401} - manaMetrics := mage.NewManaMetrics(actionID) - core.MakePermanent(mage.RegisterAura(core.Aura{ - Label: "S03 - Item - T2 - Mage - Healer 2P Bonus", - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if spell.SpellCode == SpellCode_MageArcaneMissilesTick && result.Landed() { - mage.AddMana(sim, mage.ArcaneMissiles[spell.Rank].Cost.BaseCost*0.1, manaMetrics) - } - }, - })) - }, - // Arcane Blast gains a 10% additional change to trigger Missile Barrage, and Missile Barrage now affects Regeneration the same way it affects Arcane Missiles. - 4: func(agent core.Agent) { - mage := agent.(MageAgent).GetMage() - mage.RegisterAura(core.Aura{ - Label: "S03 - Item - T2 - Mage - Healer 4P Bonus", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - mage.ArcaneBlastMissileBarrageChance += .10 - }, - }) - }, - // Your Temporal Beacons caused by Mass Regeneration now last 30 sec. - 6: func(agent core.Agent) { - }, - }, -}) - -var ItemSetIllusionistsAttire = core.NewItemSet(core.ItemSet{ - Name: "Illusionist's Attire", - Bonuses: map[int32]core.ApplyEffect{ - // Increases damage done by Frost spells and effects by up to 14. - 2: func(agent core.Agent) { - mage := agent.(MageAgent).GetMage() - mage.AddStat(stats.FrostPower, 14) - }, - // Increases the chance to trigger your Fingers of Frost rune by an additional 15%. - 3: func(agent core.Agent) { - mage := agent.(MageAgent).GetMage() - mage.RegisterAura(core.Aura{ - Label: "S03 - Item - ZG - Mage - Frost 3P Bonus", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - mage.FingersOfFrostProcChance += .15 - }, - }) - }, - // Increases damage done by your Frostbolt spell by 65%. - 5: func(agent core.Agent) { - mage := agent.(MageAgent).GetMage() - mage.RegisterAura(core.Aura{ - Label: "S03 - Item - ZG - Mage - Frost 5P Bonus", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - for _, spell := range mage.Frostbolt { - if spell != nil { - spell.DamageMultiplier *= 1.65 - } - } - - if mage.SpellfrostBolt != nil { - mage.SpellfrostBolt.DamageMultiplier *= 1.65 - } - }, - }) - }, - }, -}) - -/////////////////////////////////////////////////////////////////////////// -// SoD Phase 6 Item Sets -/////////////////////////////////////////////////////////////////////////// - -var ItemSetEnigmaInsight = core.NewItemSet(core.ItemSet{ - Name: "Enigma Insight", - Bonuses: map[int32]core.ApplyEffect{ - // Your Fire Blast now also causes your next Fire spell to gain 50% increased critical strike chance for 10 sec. - 2: func(agent core.Agent) { - mage := agent.(MageAgent).GetMage() - - var affectedSpells []*core.Spell - - buffAura := mage.RegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 1213317}, - Label: "Fire Blast", - Duration: time.Second * 10, - OnInit: func(aura *core.Aura, sim *core.Simulation) { - affectedSpells = core.FilterSlice(mage.Spellbook, func(spell *core.Spell) bool { - return spell.Flags.Matches(SpellFlagMage) && spell.SpellSchool.Matches(core.SpellSchoolFire) && !spell.Flags.Matches(core.SpellFlagPassiveSpell) - }) - }, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - for _, spell := range affectedSpells { - spell.BonusCritRating += 50 * core.SpellCritRatingPerCritChance - } - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - for _, spell := range affectedSpells { - spell.BonusCritRating -= 50 * core.SpellCritRatingPerCritChance - } - }, - OnCastComplete: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell) { - // OnCastComplete is called after OnSpellHitDealt / etc, so don't deactivate if it was just activated. - if aura.RemainingDuration(sim) == aura.Duration { - return - } - - if !slices.Contains(affectedSpells, spell) { - return - } - - core.StartDelayedAction(sim, core.DelayedActionOptions{ - DoAt: sim.CurrentTime + core.SpellBatchWindow, - OnAction: func(sim *core.Simulation) { - if aura.IsActive() { - aura.Deactivate(sim) - } - }, - }) - }, - }) - - core.MakePermanent(mage.RegisterAura(core.Aura{ - Label: "S03 - Item - TAQ - Mage - Fire 2P Bonus", - OnCastComplete: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell) { - if spell.SpellCode == SpellCode_MageFireBlast { - buffAura.Activate(sim) - } - }, - })) - }, - // Increases the damage done by your Ignite talent by 20%. - 4: func(agent core.Agent) { - mage := agent.(MageAgent).GetMage() - if mage.Talents.Ignite == 0 { - return - } - - mage.RegisterAura(core.Aura{ - Label: "S03 - Item - TAQ - Mage - Fire 4P Bonus", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - mage.Ignite.DamageMultiplier *= 1.20 - }, - }) - }, - }, -}) - -var ItemSetEnigmaMoment = core.NewItemSet(core.ItemSet{ - Name: "Enigma Moment", - Bonuses: map[int32]core.ApplyEffect{ - // Your Arcane Blast increases damage and healing done by an additional 10% per stack. - 2: func(agent core.Agent) { - mage := agent.(MageAgent).GetMage() - mage.RegisterAura(core.Aura{ - Label: "S03 - Item - TAQ - Mage - Arcane 2P Bonus", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - mage.ArcaneBlastDamageMultiplier += 0.10 - }, - }) - }, - // Your Mana Shield, Fire Ward, and Frost Ward absorb 50% more damage and also place a Temporal Beacon on the target for 30 sec. - 4: func(agent core.Agent) { - // Nothing to do - }, - }, -}) - -var ItemSetTrappingsOfVaultedSecrets = core.NewItemSet(core.ItemSet{ - Name: "Trappings of Vaulted Secrets", - Bonuses: map[int32]core.ApplyEffect{ - // Your Fireball, Frostfire Bolt, and Balefire Bolt spells gain 5% increased damage for each of your Fire effects on your target, up to a maximum increased of 20%. - 3: func(agent core.Agent) { - mage := agent.(MageAgent).GetMage() - - hasImprovedScorch := mage.Talents.ImprovedScorch > 0 - - mage.RegisterAura(core.Aura{ - Label: "S03 - Item - RAQ - Mage - Fire 3P Bonus", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - dotSpells := core.FilterSlice(mage.Spellbook, func(spell *core.Spell) bool { - return spell.Flags.Matches(SpellFlagMage) && spell.SpellSchool.Matches(core.SpellSchoolFire) && len(spell.Dots()) > 0 - }) - - affectedSpells := core.FilterSlice( - core.Flatten( - [][]*core.Spell{ - mage.Fireball, - {mage.FrostfireBolt}, - {mage.BalefireBolt}, - }, - ), func(spell *core.Spell) bool { return spell != nil }, - ) - - for _, spell := range affectedSpells { - oldApplyEffects := spell.ApplyEffects - spell.ApplyEffects = func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - multiplier := 1.0 - - for _, spell := range dotSpells { - if spell.Dot(target).IsActive() { - multiplier += 0.05 - } - } - - if hasImprovedScorch && mage.ImprovedScorchAuras.Get(target).IsActive() { - multiplier += 0.05 - } - - multiplier = math.Max(1.20, multiplier) - - // TODO: Additive or Multiplicative? - spell.DamageMultiplier *= multiplier - oldApplyEffects(sim, target, spell) - spell.DamageMultiplier /= multiplier - } - } - }, - }) - }, - }, -}) diff --git a/sim/mage/counterspell.go b/sim/mage/counterspell.go index 1d1ec34b1..d6e97ced4 100644 --- a/sim/mage/counterspell.go +++ b/sim/mage/counterspell.go @@ -9,7 +9,7 @@ import ( // This exists purely so that it can be used to extend the arcane buff from the mage T1 4pc // Not relevant in classic currently but will keep func (mage *Mage) registerCounterspellSpell() { - mage.RegisterSpell(core.SpellConfig{ + mage.Counterspell = mage.RegisterSpell(core.SpellConfig{ ActionID: core.ActionID{SpellID: 2139}, SpellSchool: core.SpellSchoolArcane, ProcMask: core.ProcMaskSpellDamage, diff --git a/sim/mage/evocation.go b/sim/mage/evocation.go index 2666ea7c8..b9e20c906 100644 --- a/sim/mage/evocation.go +++ b/sim/mage/evocation.go @@ -30,7 +30,7 @@ func (mage *Mage) registerEvocationCD() { }, }) - evocation := mage.GetOrRegisterSpell(core.SpellConfig{ + mage.Evocation = mage.GetOrRegisterSpell(core.SpellConfig{ ActionID: actionID, Flags: core.SpellFlagHelpful | core.SpellFlagChanneled | core.SpellFlagAPL, @@ -72,7 +72,7 @@ func (mage *Mage) registerEvocationCD() { }) mage.AddMajorCooldown(core.MajorCooldown{ - Spell: evocation, + Spell: mage.Evocation, Type: core.CooldownTypeMana, ShouldActivate: func(sim *core.Simulation, character *core.Character) bool { if character.HasActiveAuraWithTag(core.InnervateAuraTag) || character.HasActiveAuraWithTag(core.ManaTideTotemAuraTag) { diff --git a/sim/mage/flamestrike.go b/sim/mage/flamestrike.go index faded12b9..c047d1307 100644 --- a/sim/mage/flamestrike.go +++ b/sim/mage/flamestrike.go @@ -50,6 +50,7 @@ func (mage *Mage) newFlamestrikeSpellConfig(rank int) core.SpellConfig { DefenseType: core.DefenseTypeMagic, ProcMask: core.ProcMaskSpellDamage, Flags: SpellFlagMage | core.SpellFlagAPL, + SpellCode: SpellCode_MageFlamestrike, RequiredLevel: level, Rank: rank, diff --git a/sim/mage/item_sets_pve.go b/sim/mage/item_sets_pve.go new file mode 100644 index 000000000..86e180c61 --- /dev/null +++ b/sim/mage/item_sets_pve.go @@ -0,0 +1,441 @@ +package mage + +import ( + "slices" + "time" + + "github.com/wowsims/classic/sim/core" + "github.com/wowsims/classic/sim/core/stats" +) + +/////////////////////////////////////////////////////////////////////////// +// Classic Phase 1 - Molten Core +/////////////////////////////////////////////////////////////////////////// + +var ItemSetArcanistRegalia = core.NewItemSet(core.ItemSet{ + Name: "Arcanist Regalia", + Bonuses: map[int32]core.ApplyEffect{ + // Increases damage and healing done by magical spells and effects by up to 18. + 3: func(agent core.Agent) { + c := agent.GetCharacter() + c.AddStat(stats.SpellPower, 18) + }, + // Decreases the magical resistances of your spell targets by 10. + 5: func(agent core.Agent) { + c := agent.GetCharacter() + c.AddStat(stats.SpellPenetration, 10) + }, + // Decreases the threat generated by your spells by 15%. + 8: func(agent core.Agent) { + mage := agent.(MageAgent).GetMage() + mage.RegisterAura(core.Aura{ + Label: "Subtlety", + ActionID: core.ActionID{SpellID: 23545}, + Duration: core.NeverExpires, + OnReset: func(aura *core.Aura, sim *core.Simulation){ + mage.PseudoStats.ThreatMultiplier /= 1.15 + }, + }) + }, + }, +}) + +/////////////////////////////////////////////////////////////////////////// +// Phase 2 Item Sets - Dire Maul +/////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////// +// Phase 3 Item Sets - BWL +/////////////////////////////////////////////////////////////////////////// + +var ItemSetNetherwindRegalia = core.NewItemSet(core.ItemSet{ + Name: "Netherwind Regalia", + Bonuses: map[int32]core.ApplyEffect{ + // Reduces the threat generated by your Scorch, Arcane Missiles, Fireball, and Frostbolt spells. + 3: func(agent core.Agent) { + mage := agent.(MageAgent).GetMage() + mage.RegisterAura(core.Aura{ + Label: "Friendly Nukes", + OnInit: func(aura *core.Aura, sim *core.Simulation) { + for _, spell := range mage.Spellbook { + if spell.SpellCode == SpellCode_MageFireball || spell.SpellCode == SpellCode_MageArcaneMissilesTick { + spell.FlatThreatBonus -= 20 + } + if spell.SpellCode == SpellCode_MageScorch || spell.SpellCode == SpellCode_MageFrostbolt { + spell.FlatThreatBonus -= 100 + } + } + }, + }) + }, + // Increases the radius of Arcane Explosion, Flamestrike, and Blizzard by 25%. + 5: func(agent core.Agent) { + // No implementation in sim + }, + // 10% chance after casting Arcane Missiles, Fireball, or Frostbolt that your next spell with a casting time under 10 seconds cast instantly. + 8: func(agent core.Agent) { + mage := agent.(MageAgent).GetMage() + actionID := core.ActionID{SpellID: 22008} + + affectedSpells := []*core.Spell{} + netherwindFocusAura := mage.RegisterAura(core.Aura{ + Label: "Netherwind Focus", + ActionID: actionID, + 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 { + affectedSpells = append(affectedSpells, spell) + } + } + }, + OnGain: func(aura *core.Aura, sim *core.Simulation) { + core.Each(affectedSpells, func(spell *core.Spell) { + spell.CastTimeMultiplier -= 1 + }) + }, + OnExpire: func(aura *core.Aura, sim *core.Simulation) { + core.Each(affectedSpells, func(spell *core.Spell) { + spell.CastTimeMultiplier += 1 + }) + }, + OnCastComplete: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell) { + if !slices.Contains(affectedSpells, spell) { + return + } + aura.Deactivate(sim) + }, + }) + + mage.RegisterAura(core.Aura{ + Label: "Netherwind Focus - Proc Aura", + 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 (spell.SpellCode == SpellCode_MageArcaneMissiles || spell.SpellCode == SpellCode_MageFireball || spell.SpellCode == SpellCode_MageFrostbolt) { + netherwindFocusAura.Activate(sim) + } + }, + }) + }, + }, +}) +/////////////////////////////////////////////////////////////////////////// +// Phase 4 Item Sets - ZG and AB +/////////////////////////////////////////////////////////////////////////// + +var ItemSetIllusionistsAttire = core.NewItemSet(core.ItemSet{ + Name: "Illusionist's Attire", + Bonuses: map[int32]core.ApplyEffect{ + // Increases damage and healing done by magical spells and effects by up to 12. + 2: func(agent core.Agent) { + c := agent.GetCharacter() + c.AddStat(stats.SpellPower, 12) + }, + // Decreases the mana cost of Arcane Intellect and Arcane Brilliance by 5%. + 3: func(agent core.Agent) { + // No implementation in sim + }, + // Reduces the casting time of your Flamestrike spell by 0.5 sec. + 5: func(agent core.Agent) { + mage := agent.(MageAgent).GetMage() + mage.RegisterAura(core.Aura{ + Label: "Improved Flamestrike", + ActionID: core.ActionID{SpellID: 24491}, + Duration: core.NeverExpires, + OnInit: func(aura *core.Aura, sim *core.Simulation) { + for _, spell := range mage.Spellbook { + if spell.SpellCode == SpellCode_MageFlamestrike { + spell.DefaultCast.CastTime -= time.Millisecond * 500 + spell.DefaultCast.GCD -= time.Millisecond * 500 + } + } + }, + }) + }, + }, +}) + +/////////////////////////////////////////////////////////////////////////// +// Phase 5 Item Sets - AQ +/////////////////////////////////////////////////////////////////////////// + + +var ItemSetSorcerersRegalia = core.NewItemSet(core.ItemSet{ + Name: "Sorcerer's Regalia", + Bonuses: map[int32]core.ApplyEffect{ + // +8 All Resistances. + 2: func(agent core.Agent) { + c := agent.GetCharacter() + c.AddResistances(8) + }, + // Your spellcasts have a 6% chance to energize you for 300 mana. + 4: func(agent core.Agent) { + // No implementation in sim + }, + // Increases damage and healing done by magical spells and effects by up to 23. + 6: func(agent core.Agent) { + c := agent.GetCharacter() + c.AddStat(stats.SpellPower, 23) + }, + // +200 Armor. + 8: func(agent core.Agent) { + c := agent.GetCharacter() + c.AddStat(stats.Armor, 200) + }, + }, +}) + +var ItemSetEnigmaVestments = core.NewItemSet(core.ItemSet{ + Name: "Enigma Vestments", + Bonuses: map[int32]core.ApplyEffect{ + // Your Blizzard spell has a 30% chance to be uninterruptible. + 3: func(agent core.Agent) { + // No implementation in sim + }, + // Grants +5% increased spell hit chance for 20 sec when one of your spells is resisted. + 5: func(agent core.Agent) { + mage := agent.(MageAgent).GetMage() + actionID := core.ActionID{SpellID: 26129} + + enigmasAnswerAura := mage.RegisterAura(core.Aura{ + Label: "Enigma's Answer", + ActionID: actionID, + Duration: time.Second * 20, + MaxStacks: 4, + OnStacksChange: func(aura *core.Aura, sim *core.Simulation, oldStacks, newStacks int32) { + mage.AddStatDynamic(sim, stats.SpellHit, float64(-5 * oldStacks)) + mage.AddStatDynamic(sim, stats.SpellHit, float64(5 * newStacks)) + }, + }) + + // Wowhead suggests this does not work on all spell (imp scorch and arcane missiles). Would need testing to confirm. + mage.RegisterAura(core.Aura{ + Label: "Enigma Resist Bonus", + 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.Outcome.Matches(core.OutcomeMiss) && spell.ProcMask.Matches(core.ProcMaskDirect) { + enigmasAnswerAura.Activate(sim) + enigmasAnswerAura.AddStack(sim) + } + }, + }) + }, + }, +}) + +/////////////////////////////////////////////////////////////////////////// +// Phase 6 Item Sets - Naxx +/////////////////////////////////////////////////////////////////////////// + +var ItemSetFrostfireRegalia = core.NewItemSet(core.ItemSet{ + Name: "Frostfire Regalia", + Bonuses: map[int32]core.ApplyEffect{ + // Reduces cooldown on your Evocation by 1 minute. + 2: func(agent core.Agent) { + mage := agent.(MageAgent).GetMage() + mage.RegisterAura(core.Aura{ + Label: "Evocation", + OnInit: func(aura *core.Aura, sim *core.Simulation) { + if mage.Evocation != nil { + mage.Evocation.CD.Duration -= time.Second * 60 + } + }, + }) + }, + // Gives your Mage Armor a chance when struck by a harmful spell to increase resistance against that school of magic by 35 for 30 sec. (Proc chance: 20%) + // Fire - https://www.wowhead.com/classic/spell=28765/fire-resistance + // Frost - https://www.wowhead.com/classic/spell=28766/frost-resistance + // Nature - https://www.wowhead.com/classic/spell=28768/nature-resistance + // Shadow - https://www.wowhead.com/classic/spell=28769/shadow-resistance + // Arcane - https://www.wowhead.com/classic/spell=28770/arcane-resistance + + 4: func(agent core.Agent) { + mage := agent.(MageAgent).GetMage() + + fireWardingAura := mage.RegisterAura(core.Aura{ + Label: "Fire Resistance", + ActionID: core.ActionID{SpellID: 28765}, + Duration: time.Second * 30, + OnGain: func(aura *core.Aura, sim *core.Simulation) { + mage.AddStatDynamic(sim, stats.FireResistance, 35) + }, + OnExpire: func(aura *core.Aura, sim *core.Simulation) { + mage.AddStatDynamic(sim, stats.FireResistance, -35) + }, + }) + + frostWardingAura := mage.RegisterAura(core.Aura{ + Label: "Frost Resistance", + ActionID: core.ActionID{SpellID: 28766}, + Duration: time.Second * 30, + OnGain: func(aura *core.Aura, sim *core.Simulation) { + mage.AddStatDynamic(sim, stats.FrostResistance, 35) + }, + OnExpire: func(aura *core.Aura, sim *core.Simulation) { + mage.AddStatDynamic(sim, stats.FrostResistance, -35) + }, + }) + + natureWardingAura := mage.RegisterAura(core.Aura{ + Label: "Nature Resistance", + ActionID: core.ActionID{SpellID: 28768}, + Duration: time.Second * 30, + OnGain: func(aura *core.Aura, sim *core.Simulation) { + mage.AddStatDynamic(sim, stats.NatureResistance, 35) + }, + OnExpire: func(aura *core.Aura, sim *core.Simulation) { + mage.AddStatDynamic(sim, stats.NatureResistance, -35) + }, + }) + + shadowWardingAura := mage.RegisterAura(core.Aura{ + Label: "Shadow Resistance", + ActionID: core.ActionID{SpellID: 28769}, + Duration: time.Second * 30, + OnGain: func(aura *core.Aura, sim *core.Simulation) { + mage.AddStatDynamic(sim, stats.ShadowResistance, 35) + }, + OnExpire: func(aura *core.Aura, sim *core.Simulation) { + mage.AddStatDynamic(sim, stats.ShadowResistance, -35) + }, + }) + + arcaneWardingAura := mage.RegisterAura(core.Aura{ + Label: "Arcane Resistance", + ActionID: core.ActionID{SpellID: 28770}, + Duration: time.Second * 30, + OnGain: func(aura *core.Aura, sim *core.Simulation) { + mage.AddStatDynamic(sim, stats.ArcaneResistance, 35) + }, + OnExpire: func(aura *core.Aura, sim *core.Simulation) { + mage.AddStatDynamic(sim, stats.ArcaneResistance, -35) + }, + }) + + // Wowhead suggests this does not work on all spell (imp scorch and arcane missiles). Would need testing to confirm. + mage.RegisterAura(core.Aura{ + Label: "Adaptive Warding", + Duration: core.NeverExpires, + OnReset: func(aura *core.Aura, sim *core.Simulation) { + aura.Activate(sim) + }, + OnSpellHitTaken: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { + if sim.Proc(0.20, "Adaptive Warding") { + if spell.SpellSchool.Matches(core.SpellSchoolFire) { + fireWardingAura.Activate(sim) + return + } + if spell.SpellSchool.Matches(core.SpellSchoolFrost) { + frostWardingAura.Activate(sim) + return + } + if spell.SpellSchool.Matches(core.SpellSchoolNature) { + natureWardingAura.Activate(sim) + return + } + if spell.SpellSchool.Matches(core.SpellSchoolShadow) { + shadowWardingAura.Activate(sim) + return + } + if spell.SpellSchool.Matches(core.SpellSchoolArcane) { + arcaneWardingAura.Activate(sim) + return + } + } + }, + }) + }, + // Your damage spells have a chance to cause your target to take up to 200 increased damage from subsequent spells. (Proc chance: 20%) + 6: func(agent core.Agent) { + mage := agent.(MageAgent).GetMage() + + procAuras := mage.NewEnemyAuraArray(func(target *core.Unit) *core.Aura { + return target.GetOrRegisterAura(core.Aura{ + Label: "Elemental Vulnerability", + ActionID: core.ActionID{SpellID: 28772}, + 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] += 200 + } + }, + OnExpire: func(aura *core.Aura, sim *core.Simulation) { + for si := stats.SchoolIndexArcane; si < stats.SchoolLen; si++ { + aura.Unit.PseudoStats.SchoolBonusDamageTaken[si] -= 200 + } + }, + 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(&mage.Unit, core.ProcTrigger{ + ActionID: core.ActionID{SpellID: 28771}, + Name: "Elemental Vulnerability", + Callback: core.CallbackOnSpellHitDealt, + Outcome: core.OutcomeLanded, + ProcMask: core.ProcMaskSpellDamage, + ProcChance: 0.2, + Handler: handler, + }) + }, + // Your damage spells have a chance to displace you, causing the next spell cast to generate no threat. (Proc chance: 15%) + 8: func(agent core.Agent) { + mage := agent.(MageAgent).GetMage() + + notThereAura := mage.RegisterAura(core.Aura{ + Label: "Not There", + ActionID: core.ActionID{SpellID: 28762}, + Duration: time.Second * 8, + OnGain: func(aura *core.Aura, sim *core.Simulation) { + mage.PseudoStats.ThreatMultiplier -= 1 + }, + OnExpire: func(aura *core.Aura, sim *core.Simulation) { + mage.PseudoStats.ThreatMultiplier += 1 + }, + OnCastComplete: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell) { + // OnCastComplete is called after OnSpellHitDealt / etc, so don't deactivate if it was just activated. + if aura.RemainingDuration(sim) == aura.Duration { + return + } + aura.Deactivate(sim) + }, + }) + + mage.RegisterAura(core.Aura{ + Label: "NotThere", + 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 sim.Proc(0.15, "Not There") && result.Landed() && spell.ProcMask.Matches(core.ProcMaskDirect) { + notThereAura.Activate(sim) + } + }, + }) + }, + }, +}) \ No newline at end of file diff --git a/sim/mage/_item_sets_pvp.go b/sim/mage/item_sets_pvp.go similarity index 100% rename from sim/mage/_item_sets_pvp.go rename to sim/mage/item_sets_pvp.go diff --git a/sim/mage/items.go b/sim/mage/items.go index fd9d40c87..79a42955c 100644 --- a/sim/mage/items.go +++ b/sim/mage/items.go @@ -9,12 +9,9 @@ import ( const ( FireRuby = 20036 - // StaffOfOrder = 229909 - // StaffOfInferno = 229971 - // StaffOfRime = 229972 - // MindQuickeningGem = 230243 - // HazzarahsCharmOfChilledMagic = 231282 - // JewelOfKajaro = 231324 + MindQuickeningGem = 19339 + HazzarahsCharmOfMagic = 19959 + JewelOfKajaro = 19601 ) func init() { @@ -67,26 +64,24 @@ func init() { }) }) - // https://www.wowhead.com/classic/item=231282/hazzarahs-charm-of-chilled-magic - // Use: Increases the critical hit chance of your Frostbolt and Frozen Orb spells by 5%, and increases the critical hit damage of your Frostbolt and Frozen Orb spells by 50% for 20 sec. - // (2 Min Cooldown) - /* core.NewItemEffect(HazzarahsCharmOfChilledMagic, func(agent core.Agent) { + // https://www.wowhead.com/classic/item=19959/hazzarahs-charm-of-magic + // Increases the critical hit chance of your Arcane spells by 5%, and increases the critical hit damage of your Arcane spells by 50% for 20 sec. + // (3 Min Cooldown) + core.NewItemEffect(HazzarahsCharmOfMagic, func(agent core.Agent) { mage := agent.(MageAgent).GetMage() duration := time.Second * 20 affectedSpells := []*core.Spell{} aura := mage.RegisterAura(core.Aura{ - ActionID: core.ActionID{ItemID: HazzarahsCharmOfChilledMagic}, - Label: "Frost Potency", + ActionID: core.ActionID{SpellID: 24544}, + Label: "Arcane Potency", Duration: duration, OnInit: func(aura *core.Aura, sim *core.Simulation) { - affectedSpells = core.FilterSlice( - core.Flatten([][]*core.Spell{mage.Frostbolt, {mage.SpellfrostBolt}}), func(spell *core.Spell) bool { return spell != nil }, - ) - - if mage.HasRune(proto.MageRune_RuneCloakFrozenOrb) { - affectedSpells = append(affectedSpells, core.MapSlice(mage.frozenOrbPets, func(orb *FrozenOrb) *core.Spell { return orb.FrozenOrbTick })...) + for spellIdx := range mage.Spellbook { + if spell := mage.Spellbook[spellIdx]; spell.SpellSchool == core.SpellSchoolArcane { + affectedSpells = append(affectedSpells, spell) + } } }, OnGain: func(aura *core.Aura, sim *core.Simulation) { @@ -104,13 +99,13 @@ func init() { }) spell := mage.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{ItemID: HazzarahsCharmOfChilledMagic}, + ActionID: core.ActionID{ItemID: HazzarahsCharmOfMagic}, SpellSchool: core.SpellSchoolArcane, Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagOffensiveEquipment, Cast: core.CastConfig{ CD: core.Cooldown{ Timer: mage.NewTimer(), - Duration: time.Minute * 2, + Duration: time.Minute * 3, }, SharedCD: core.Cooldown{ Timer: mage.GetOffensiveTrinketCD(), @@ -129,23 +124,20 @@ func init() { }) }) - // https://www.wowhead.com/classic/item=231324/jewel-of-kajaro - // Equip: Reduces the cooldown on your Frozen Orb spell by 10 sec. + // https://www.wowhead.com/classic/item=19601/jewel-of-kajaro + // Equip: Reduces the cooldown of Counterspell by 2 sec. core.NewItemEffect(JewelOfKajaro, func(agent core.Agent) { mage := agent.(MageAgent).GetMage() - if !mage.HasRune(proto.MageRune_RuneCloakFrozenOrb) { - return - } mage.RegisterAura(core.Aura{ - Label: "Decreased Frozen Orb Cooldown", + Label: "Improved Counterspell", OnInit: func(aura *core.Aura, sim *core.Simulation) { - mage.FrozenOrb.CD.Duration -= time.Second * 10 + mage.Counterspell.CD.Duration -= time.Second * 2 }, }) }) - // https://www.wowhead.com/classic/item=230243/mind-quickening-gem + // https://www.wowhead.com/classic/item=19339/mind-quickening-gem // Use: Quickens the mind, increasing the Mage's casting speed of non-channeled spells by 33% for 20 sec. (2 Min Cooldown) core.NewItemEffect(MindQuickeningGem, func(agent core.Agent) { mage := agent.(MageAgent).GetMage() @@ -154,7 +146,7 @@ func init() { duration := time.Second * 20 buffAura := mage.RegisterAura(core.Aura{ - ActionID: actionID, + ActionID: core.ActionID{SpellID: 23723}, Label: "Mind Quickening", Duration: duration, OnGain: func(aura *core.Aura, sim *core.Simulation) { @@ -171,7 +163,7 @@ func init() { Cast: core.CastConfig{ CD: core.Cooldown{ Timer: mage.NewTimer(), - Duration: time.Minute * 2, + Duration: time.Minute * 5, }, SharedCD: core.Cooldown{ Timer: mage.GetOffensiveTrinketCD(), @@ -190,84 +182,5 @@ func init() { }) }) - // https://www.wowhead.com/classic/item=229971/staff-of-inferno - // Equip: When Improved Scorch is talented, targets hit by your Blast Wave will also have 5 stacks of Fire Vulnerability applied to them. - core.NewItemEffect(StaffOfInferno, func(agent core.Agent) { - mage := agent.(MageAgent).GetMage() - if mage.Talents.ImprovedScorch == 0 { - return - } - - core.MakePermanent(mage.RegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 469237}, - Label: "Staff of Inferno", - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if spell.SpellCode == SpellCode_MageBlastWave && result.Landed() { - aura := mage.ImprovedScorchAuras.Get(result.Target) - aura.Activate(sim) - aura.SetStacks(sim, 5) - } - }, - })) - }) - - core.NewItemEffect(StaffOfOrder, func(agent core.Agent) { - mage := agent.(MageAgent).GetMage() - if !mage.Talents.PresenceOfMind { - return - } - - core.MakePermanent(mage.RegisterAura(core.Aura{ - Label: "Staff of Order", - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if spell.SpellSchool == core.SpellSchoolArcane && spell.ProcMask.Matches(core.ProcMaskSpellDamage) && result.Landed() { - mage.PresenceOfMind.CD.Set(mage.PresenceOfMind.CD.ReadyAt() - time.Second) - } - }, - })) - }) - - core.NewItemEffect(StaffOfRime, func(agent core.Agent) { - mage := agent.(MageAgent).GetMage() - if !mage.Talents.IceBarrier { - return - } - - statsAura := mage.RegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 469238}, - Label: "Staff of Rime", - Duration: time.Minute, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - mage.AddStatDynamic(sim, stats.FrostPower, 100) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - mage.AddStatDynamic(sim, stats.FrostPower, -100) - }, - }) - - mage.RegisterAura(core.Aura{ - Label: "Staff of Rime Dummy", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - for _, aura := range mage.IceBarrierAuras { - if aura == nil { - continue - } - - oldOnGain := aura.OnGain - aura.OnGain = func(aura *core.Aura, sim *core.Simulation) { - oldOnGain(aura, sim) - statsAura.Activate(sim) - } - - oldOnExpire := aura.OnExpire - aura.OnExpire = func(aura *core.Aura, sim *core.Simulation) { - oldOnExpire(aura, sim) - statsAura.Deactivate(sim) - } - } - }, - }) - }) */ - core.AddEffectsToTest = true } diff --git a/sim/mage/mage.go b/sim/mage/mage.go index 8944e68aa..b7db349b9 100644 --- a/sim/mage/mage.go +++ b/sim/mage/mage.go @@ -20,6 +20,7 @@ const ( SpellCode_MageBlastWave SpellCode_MageFireball SpellCode_MageFireBlast + SpellCode_MageFlamestrike SpellCode_MageFrostbolt SpellCode_MageIgnite SpellCode_MageScorch @@ -57,6 +58,8 @@ type Mage struct { ArcaneMissilesTickSpell []*core.Spell BlastWave []*core.Spell Blizzard []*core.Spell + Counterspell *core.Spell + Evocation *core.Spell Fireball []*core.Spell FireBlast []*core.Spell Flamestrike []*core.Spell diff --git a/sim/warlock/dps/TestWarlockDSRuin.results b/sim/warlock/dps/TestWarlockDSRuin.results index 695113d49..ea3a204c1 100644 --- a/sim/warlock/dps/TestWarlockDSRuin.results +++ b/sim/warlock/dps/TestWarlockDSRuin.results @@ -106,8 +106,8 @@ dps_results: { dps_results: { key: "TestWarlockDSRuin-Phase1-AllItems-DeathmistRaiment" value: { - dps: 861.87319 - tps: 922.49357 + dps: 793.71062 + tps: 846.83968 } } dps_results: { @@ -155,8 +155,8 @@ dps_results: { dps_results: { key: "TestWarlockDSRuin-Phase1-AllItems-PlagueheartRaiment" value: { - dps: 1007.47674 - tps: 1069.18079 + dps: 941.36791 + tps: 996.27398 } } dps_results: { diff --git a/sim/warlock/dps/TestWarlockSMRuin.results b/sim/warlock/dps/TestWarlockSMRuin.results index 0fe707b71..bd91e54a1 100644 --- a/sim/warlock/dps/TestWarlockSMRuin.results +++ b/sim/warlock/dps/TestWarlockSMRuin.results @@ -106,8 +106,8 @@ dps_results: { dps_results: { key: "TestWarlockSMRuin-Phase1-AllItems-DeathmistRaiment" value: { - dps: 1080.97179 - tps: 903.66134 + dps: 993.7709 + tps: 821.18879 } } dps_results: { @@ -155,8 +155,8 @@ dps_results: { dps_results: { key: "TestWarlockSMRuin-Phase1-AllItems-PlagueheartRaiment" value: { - dps: 1235.01715 - tps: 1049.06851 + dps: 1138.48078 + tps: 955.41236 } } dps_results: { diff --git a/tools/database/gen_db/main.go b/tools/database/gen_db/main.go index 9583aab2e..d1a11f2d4 100644 --- a/tools/database/gen_db/main.go +++ b/tools/database/gen_db/main.go @@ -529,10 +529,10 @@ func GetPhaseData(item *proto.UIItem) int32 { if dropSource != nil { // Zone IDs as defined by WoWHead - does NOT match the in-game Zone ID! // P1 - Molten Core, Ony - if slices.Contains([]int32{2717, 2159}, dropSource.ZoneId) { + if slices.Contains([]int32{2717, 2159}, dropSource.ZoneId) || dropSource.NpcId == 10184 { return 1 } - + // P2 - Dire Maul if dropSource.ZoneId == 2557 { return 2 diff --git a/ui/core/proto_utils/names.ts b/ui/core/proto_utils/names.ts index 8312ff539..9d023e002 100644 --- a/ui/core/proto_utils/names.ts +++ b/ui/core/proto_utils/names.ts @@ -324,12 +324,12 @@ export const sourceNames: Map = new Map([ export const raidNames: Map = new Map([ [RaidFilterOption.RaidUnknown, 'Unknown'], - [RaidFilterOption.RaidMoltenCore, "Molten Core"], + [RaidFilterOption.RaidMoltenCore, 'Molten Core'], [RaidFilterOption.RaidOnyxiasLair, "Onyxia's Lair"], - [RaidFilterOption.RaidBlackwingLair, "Blackwing Lair"], + [RaidFilterOption.RaidBlackwingLair, 'Blackwing Lair'], [RaidFilterOption.RaidZulGurub, "Zul'Gurub"], - [RaidFilterOption.RaidRuinsOfAQ, "AQ 20"], - [RaidFilterOption.RaidTempleOfAQ, "AQ 40"], + [RaidFilterOption.RaidRuinsOfAQ, 'AQ 20'], + [RaidFilterOption.RaidTempleOfAQ, 'AQ 40'], [RaidFilterOption.RaidNaxxramas, 'Naxxramas'], ]); From f2e078b47a347ef22423992c1c6aa78ed3d26e48 Mon Sep 17 00:00:00 2001 From: sanguinerarogue Date: Wed, 18 Dec 2024 22:13:12 -0700 Subject: [PATCH 2/3] 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: { From b78971edec85bbe78ca0311041a5e1cb3ba42bd7 Mon Sep 17 00:00:00 2001 From: sanguinerarogue Date: Wed, 18 Dec 2024 22:19:45 -0700 Subject: [PATCH 3/3] conflict fix --- tools/database/gen_db/main.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tools/database/gen_db/main.go b/tools/database/gen_db/main.go index b29e66fa8..ca6418f60 100644 --- a/tools/database/gen_db/main.go +++ b/tools/database/gen_db/main.go @@ -528,10 +528,6 @@ func GetPhaseData(item *proto.UIItem) int32 { dropSource := itemSource.GetDrop() if dropSource != nil { // Zone IDs as defined by WoWHead - does NOT match the in-game Zone ID! -<<<<<<< HEAD - // P1 - Molten Core, Ony - if slices.Contains([]int32{2717, 2159}, dropSource.ZoneId) || dropSource.NpcId == 10184 { -======= // P1 - Molten Core, Ony (Go down one check) if dropSource.ZoneId == 2717 { return 1 @@ -540,7 +536,6 @@ func GetPhaseData(item *proto.UIItem) int32 { // Ony items don't have a ZoneID. Let's add it for UI filtering, then return phase 1 if dropSource.NpcId == 10184 { dropSource.ZoneId = 2159 ->>>>>>> master return 1 }