diff --git a/assets/database/db.bin b/assets/database/db.bin index 3675cf002e..f5bd5b46f9 100644 Binary files a/assets/database/db.bin and b/assets/database/db.bin differ diff --git a/assets/database/db.json b/assets/database/db.json index c7f09a7ffa..af2dc26036 100644 --- a/assets/database/db.json +++ b/assets/database/db.json @@ -8802,7 +8802,7 @@ {"effectId":907,"spellId":13846,"name":"Enchant Bracer - Greater Spirit","type":6,"stats":[0,0,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],"quality":1}, {"effectId":908,"spellId":13858,"name":"Enchant Chest - Superior 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,50,0,0,0,0,0,0,0,0,0],"quality":1}, {"effectId":909,"spellId":13868,"name":"Enchant Gloves - Advanced Herbalism","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":910,"spellId":25083,"name":"Enchant Cloak - Stealth","type":4,"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":910,"spellId":25083,"name":"Enchant Cloak - Stealth","type":4,"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,"phase":4}, {"effectId":911,"spellId":13890,"name":"Enchant Boots - Minor Speed","type":10,"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":912,"spellId":13915,"name":"Enchant Weapon - Demonslaying","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":913,"spellId":13917,"name":"Enchant Chest - Superior 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,65,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":2}, @@ -8845,8 +8845,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":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":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":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}, @@ -8858,43 +8858,43 @@ {"effectId":2504,"spellId":22749,"name":"Enchant Weapon - Spell Power","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,30,0],"quality":3}, {"effectId":2505,"spellId":22750,"name":"Enchant Weapon - Healing Power","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,55,0,0],"quality":3}, {"effectId":2523,"itemId":18283,"spellId":22779,"name":"Biznicks 247x128 Accurascope","type":14,"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":2543,"itemId":18329,"spellId":22840,"name":"Arcanum of Rapidity","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,0,0,0,0,0,0,0,0,0,0],"quality":2}, -{"effectId":2544,"itemId":18330,"spellId":22844,"name":"Arcanum of Focus","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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":2545,"itemId":18331,"spellId":22846,"name":"Arcanum of Protection","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,1,0,0,0,0,0,0,0,0,0,0,0,0],"quality":2}, +{"effectId":2543,"itemId":18329,"spellId":22840,"name":"Arcanum of Rapidity","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,0,0,0,0,0,0,0,0,0,0],"quality":2,"phase":2}, +{"effectId":2544,"itemId":18330,"spellId":22844,"name":"Arcanum of Focus","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,"phase":2}, +{"effectId":2545,"itemId":18331,"spellId":22846,"name":"Arcanum of Protection","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,1,0,0,0,0,0,0,0,0,0,0,0,0],"quality":2,"phase":2}, {"effectId":2563,"spellId":23799,"name":"Enchant Weapon - Strength","type":13,"stats":[15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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":2564,"spellId":25080,"name":"Enchant Gloves - Superior Agility","type":7,"stats":[0,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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":2564,"spellId":25080,"name":"Enchant Gloves - Superior Agility","type":7,"stats":[0,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,"phase":4}, {"effectId":2564,"spellId":23800,"name":"Enchant Weapon - Agility","type":13,"stats":[0,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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":2565,"spellId":23801,"name":"Enchant Bracer - Mana Regeneration","type":6,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,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":2566,"spellId":23802,"name":"Enchant Bracer - Healing Power","type":6,"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,24,0,0],"quality":1}, {"effectId":2567,"spellId":23803,"name":"Enchant Weapon - Mighty Spirit","type":13,"stats":[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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":1}, {"effectId":2568,"spellId":23804,"name":"Enchant Weapon - Mighty Intellect","type":13,"stats":[0,0,0,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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":2583,"itemId":19782,"spellId":24149,"name":"Presence of Might","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,15,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":3,"classAllowlist":[9]}, -{"effectId":2584,"itemId":19783,"spellId":24160,"name":"Syncretist's Sigil","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,24,0,0],"quality":3,"classAllowlist":[4]}, -{"effectId":2585,"itemId":19784,"spellId":24161,"name":"Death's Embrace","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,28,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0],"quality":3,"classAllowlist":[6]}, -{"effectId":2586,"itemId":19785,"spellId":24162,"name":"Falcon's Call","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,10,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":3,"classAllowlist":[2]}, -{"effectId":2587,"itemId":19786,"spellId":24163,"name":"Vodouisant's Vigilant Embrace","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,0,15,0,13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,"classAllowlist":[7]}, -{"effectId":2588,"itemId":19787,"spellId":24164,"name":"Presence of Sight","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,0,0,0,18,0,0,0,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],"quality":3,"classAllowlist":[3]}, -{"effectId":2589,"itemId":19788,"spellId":24165,"name":"Hoodoo Hex","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,10,0,0,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,"classAllowlist":[8]}, -{"effectId":2590,"itemId":19789,"spellId":24167,"name":"Prophetic Aura","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,10,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,0,0],"quality":3,"classAllowlist":[5]}, -{"effectId":2591,"itemId":19790,"spellId":24168,"name":"Animist's Caress","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,10,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,0,0],"quality":3,"classAllowlist":[1]}, -{"effectId":2604,"itemId":20078,"spellId":24420,"name":"Zandalar Signet of Serenity","type":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,0,0,0,0,0,0,0,33,0,0],"quality":3}, -{"effectId":2605,"itemId":20076,"spellId":24421,"name":"Zandalar Signet of Mojo","type":3,"stats":[0,0,0,0,0,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,0,0],"quality":3}, -{"effectId":2606,"itemId":20077,"spellId":24422,"name":"Zandalar Signet of Might","type":3,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,30,0,0,0,0,0,0,0,0,0,30,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":3}, -{"effectId":2613,"spellId":25072,"name":"Enchant Gloves - Threat","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":3}, -{"effectId":2614,"spellId":25073,"name":"Enchant Gloves - Shadow Power","type":7,"stats":[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,0,0,0,0,0,0,0,0,0,0,0,0],"quality":3}, -{"effectId":2615,"spellId":25074,"name":"Enchant Gloves - Frost Power","type":7,"stats":[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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":3}, -{"effectId":2616,"spellId":25078,"name":"Enchant Gloves - Fire Power","type":7,"stats":[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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":3}, -{"effectId":2617,"spellId":25079,"name":"Enchant Gloves - Healing Power","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,30,0,0],"quality":3}, -{"effectId":2619,"spellId":25081,"name":"Enchant Cloak - Greater Fire Resistance","type":4,"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,15,0,0,0,0,0,0,0],"quality":1}, -{"effectId":2620,"spellId":25082,"name":"Enchant Cloak - Greater Nature Resistance","type":4,"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,15,0,0,0,0,0],"quality":1}, -{"effectId":2621,"spellId":25084,"name":"Enchant Cloak - Subtlety","type":4,"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":2622,"spellId":25086,"name":"Enchant Cloak - Dodge","type":4,"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,1,0,0,0,0,0,0,0,0,0,0,0,0],"quality":3}, +{"effectId":2583,"itemId":19782,"spellId":24149,"name":"Presence of Might","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,15,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":3,"phase":4,"classAllowlist":[9]}, +{"effectId":2584,"itemId":19783,"spellId":24160,"name":"Syncretist's Sigil","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,24,0,0],"quality":3,"phase":4,"classAllowlist":[4]}, +{"effectId":2585,"itemId":19784,"spellId":24161,"name":"Death's Embrace","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,28,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0],"quality":3,"phase":4,"classAllowlist":[6]}, +{"effectId":2586,"itemId":19785,"spellId":24162,"name":"Falcon's Call","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,10,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":3,"phase":4,"classAllowlist":[2]}, +{"effectId":2587,"itemId":19786,"spellId":24163,"name":"Vodouisant's Vigilant Embrace","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,0,15,0,13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,"phase":4,"classAllowlist":[7]}, +{"effectId":2588,"itemId":19787,"spellId":24164,"name":"Presence of Sight","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,0,0,0,18,0,0,0,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],"quality":3,"phase":4,"classAllowlist":[3]}, +{"effectId":2589,"itemId":19788,"spellId":24165,"name":"Hoodoo Hex","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,10,0,0,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,"phase":4,"classAllowlist":[8]}, +{"effectId":2590,"itemId":19789,"spellId":24167,"name":"Prophetic Aura","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,10,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,0,0],"quality":3,"phase":4,"classAllowlist":[5]}, +{"effectId":2591,"itemId":19790,"spellId":24168,"name":"Animist's Caress","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,10,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,0,0],"quality":3,"phase":4,"classAllowlist":[1]}, +{"effectId":2604,"itemId":20078,"spellId":24420,"name":"Zandalar Signet of Serenity","type":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,0,0,0,0,0,0,0,33,0,0],"quality":3,"phase":4}, +{"effectId":2605,"itemId":20076,"spellId":24421,"name":"Zandalar Signet of Mojo","type":3,"stats":[0,0,0,0,0,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,0,0],"quality":3,"phase":4}, +{"effectId":2606,"itemId":20077,"spellId":24422,"name":"Zandalar Signet of Might","type":3,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,30,0,0,0,0,0,0,0,0,0,30,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":3,"phase":4}, +{"effectId":2613,"spellId":25072,"name":"Enchant Gloves - Threat","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":3,"phase":4}, +{"effectId":2614,"spellId":25073,"name":"Enchant Gloves - Shadow Power","type":7,"stats":[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,0,0,0,0,0,0,0,0,0,0,0,0],"quality":3,"phase":4}, +{"effectId":2615,"spellId":25074,"name":"Enchant Gloves - Frost Power","type":7,"stats":[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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":3,"phase":4}, +{"effectId":2616,"spellId":25078,"name":"Enchant Gloves - Fire Power","type":7,"stats":[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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":3,"phase":4}, +{"effectId":2617,"spellId":25079,"name":"Enchant Gloves - Healing Power","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,30,0,0],"quality":3,"phase":4}, +{"effectId":2619,"spellId":25081,"name":"Enchant Cloak - Greater Fire Resistance","type":4,"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,15,0,0,0,0,0,0,0],"quality":1,"phase":4}, +{"effectId":2620,"spellId":25082,"name":"Enchant Cloak - Greater Nature Resistance","type":4,"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,15,0,0,0,0,0],"quality":1,"phase":4}, +{"effectId":2621,"spellId":25084,"name":"Enchant Cloak - Subtlety","type":4,"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,"phase":4}, +{"effectId":2622,"spellId":25086,"name":"Enchant Cloak - Dodge","type":4,"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,1,0,0,0,0,0,0,0,0,0,0,0,0],"quality":3,"phase":4}, {"effectId":2646,"spellId":27837,"name":"Enchant 2H Weapon - Agility","type":13,"enchantType":1,"stats":[0,25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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":2681,"itemId":22635,"spellId":28161,"name":"Savage Guard","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,0,0,0,0,10,0,0,0,0,0],"quality":3}, -{"effectId":2715,"itemId":23547,"spellId":29475,"name":"Resilience of the Scourge","type":3,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31,0,0],"quality":4}, -{"effectId":2716,"itemId":23549,"spellId":29480,"name":"Fortitude of the Scourge","type":3,"stats":[0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,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],"quality":4}, -{"effectId":2717,"itemId":23548,"spellId":29483,"name":"Might of the Scourge","type":3,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,26,0,0.01,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":4}, -{"effectId":2721,"itemId":23545,"spellId":29467,"name":"Power of the Scourge","type":3,"stats":[0,0,0,0,0,15,0,0,0,0,0,0,0,0,0.01,0,0,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],"quality":4}, +{"effectId":2681,"itemId":22635,"spellId":28161,"name":"Savage Guard","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,0,0,0,0,10,0,0,0,0,0],"quality":3,"phase":4}, +{"effectId":2715,"itemId":23547,"spellId":29475,"name":"Resilience of the Scourge","type":3,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31,0,0],"quality":4,"phase":6}, +{"effectId":2716,"itemId":23549,"spellId":29480,"name":"Fortitude of the Scourge","type":3,"stats":[0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,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],"quality":4,"phase":6}, +{"effectId":2717,"itemId":23548,"spellId":29483,"name":"Might of the Scourge","type":3,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,26,0,0.01,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":4,"phase":6}, +{"effectId":2721,"itemId":23545,"spellId":29467,"name":"Power of the Scourge","type":3,"stats":[0,0,0,0,0,15,0,0,0,0,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],"quality":4,"phase":6}, {"effectId":7210,"spellId":435481,"name":"Enchant Weapon - Dismantle","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":4}, {"effectId":7223,"spellId":435903,"name":"Enchant Chest - Retricutioner","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":4}, {"effectId":7603,"itemId":228982,"spellId":463871,"name":"Enchant Shield - Law of Nature","type":13,"enchantType":2,"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,55,30,0],"quality":2} diff --git a/assets/database/leftover_db.bin b/assets/database/leftover_db.bin index 00fd1d3309..fa55ec23db 100644 Binary files a/assets/database/leftover_db.bin and b/assets/database/leftover_db.bin differ diff --git a/assets/database/leftover_db.json b/assets/database/leftover_db.json index 7bcfae8f74..11f373d860 100644 --- a/assets/database/leftover_db.json +++ b/assets/database/leftover_db.json @@ -1435,8 +1435,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":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":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":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}, @@ -1495,7 +1495,7 @@ {"effectId":907,"spellId":13846,"name":"Enchant Bracer - Greater Spirit","type":6,"stats":[0,0,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],"quality":1}, {"effectId":908,"spellId":13858,"name":"Enchant Chest - Superior 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,50,0,0,0,0,0,0,0,0,0],"quality":1}, {"effectId":909,"spellId":13868,"name":"Enchant Gloves - Advanced Herbalism","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":910,"spellId":25083,"name":"Enchant Cloak - Stealth","type":4,"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":910,"spellId":25083,"name":"Enchant Cloak - Stealth","type":4,"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,"phase":4}, {"effectId":911,"spellId":13890,"name":"Enchant Boots - Minor Speed","type":10,"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":912,"spellId":13915,"name":"Enchant Weapon - Demonslaying","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":913,"spellId":13917,"name":"Enchant Chest - Superior 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,65,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":2}, @@ -1511,8 +1511,8 @@ {"effectId":929,"itemId":16217,"spellId":20017,"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":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":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":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}, @@ -1551,43 +1551,43 @@ {"effectId":2504,"spellId":22749,"name":"Enchant Weapon - Spell Power","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,30,0],"quality":3}, {"effectId":2505,"spellId":22750,"name":"Enchant Weapon - Healing Power","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,55,0,0],"quality":3}, {"effectId":2523,"itemId":18283,"spellId":22779,"name":"Biznicks 247x128 Accurascope","type":14,"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":2543,"itemId":18329,"spellId":22840,"name":"Arcanum of Rapidity","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,0,0,0,0,0,0,0,0,0,0],"quality":2}, -{"effectId":2544,"itemId":18330,"spellId":22844,"name":"Arcanum of Focus","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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":2545,"itemId":18331,"spellId":22846,"name":"Arcanum of Protection","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,1,0,0,0,0,0,0,0,0,0,0,0,0],"quality":2}, +{"effectId":2543,"itemId":18329,"spellId":22840,"name":"Arcanum of Rapidity","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,0,0,0,0,0,0,0,0,0,0],"quality":2,"phase":2}, +{"effectId":2544,"itemId":18330,"spellId":22844,"name":"Arcanum of Focus","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,"phase":2}, +{"effectId":2545,"itemId":18331,"spellId":22846,"name":"Arcanum of Protection","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,1,0,0,0,0,0,0,0,0,0,0,0,0],"quality":2,"phase":2}, {"effectId":2563,"spellId":23799,"name":"Enchant Weapon - Strength","type":13,"stats":[15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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":2564,"spellId":25080,"name":"Enchant Gloves - Superior Agility","type":7,"stats":[0,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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":2564,"spellId":25080,"name":"Enchant Gloves - Superior Agility","type":7,"stats":[0,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,"phase":4}, {"effectId":2564,"spellId":23800,"name":"Enchant Weapon - Agility","type":13,"stats":[0,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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":2565,"spellId":23801,"name":"Enchant Bracer - Mana Regeneration","type":6,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,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":2566,"spellId":23802,"name":"Enchant Bracer - Healing Power","type":6,"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,24,0,0],"quality":1}, {"effectId":2567,"spellId":23803,"name":"Enchant Weapon - Mighty Spirit","type":13,"stats":[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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":1}, {"effectId":2568,"spellId":23804,"name":"Enchant Weapon - Mighty Intellect","type":13,"stats":[0,0,0,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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":2583,"itemId":19782,"spellId":24149,"name":"Presence of Might","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,15,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":3,"classAllowlist":[9]}, -{"effectId":2584,"itemId":19783,"spellId":24160,"name":"Syncretist's Sigil","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,24,0,0],"quality":3,"classAllowlist":[4]}, -{"effectId":2585,"itemId":19784,"spellId":24161,"name":"Death's Embrace","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,28,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0],"quality":3,"classAllowlist":[6]}, -{"effectId":2586,"itemId":19785,"spellId":24162,"name":"Falcon's Call","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,10,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":3,"classAllowlist":[2]}, -{"effectId":2587,"itemId":19786,"spellId":24163,"name":"Vodouisant's Vigilant Embrace","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,0,15,0,13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,"classAllowlist":[7]}, -{"effectId":2588,"itemId":19787,"spellId":24164,"name":"Presence of Sight","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,0,0,0,18,0,0,0,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],"quality":3,"classAllowlist":[3]}, -{"effectId":2589,"itemId":19788,"spellId":24165,"name":"Hoodoo Hex","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,10,0,0,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,"classAllowlist":[8]}, -{"effectId":2590,"itemId":19789,"spellId":24167,"name":"Prophetic Aura","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,10,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,0,0],"quality":3,"classAllowlist":[5]}, -{"effectId":2591,"itemId":19790,"spellId":24168,"name":"Animist's Caress","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,10,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,0,0],"quality":3,"classAllowlist":[1]}, -{"effectId":2604,"itemId":20078,"spellId":24420,"name":"Zandalar Signet of Serenity","type":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,0,0,0,0,0,0,0,33,0,0],"quality":3}, -{"effectId":2605,"itemId":20076,"spellId":24421,"name":"Zandalar Signet of Mojo","type":3,"stats":[0,0,0,0,0,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,0,0],"quality":3}, -{"effectId":2606,"itemId":20077,"spellId":24422,"name":"Zandalar Signet of Might","type":3,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,30,0,0,0,0,0,0,0,0,0,30,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":3}, -{"effectId":2613,"spellId":25072,"name":"Enchant Gloves - Threat","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":3}, -{"effectId":2614,"spellId":25073,"name":"Enchant Gloves - Shadow Power","type":7,"stats":[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,0,0,0,0,0,0,0,0,0,0,0,0],"quality":3}, -{"effectId":2615,"spellId":25074,"name":"Enchant Gloves - Frost Power","type":7,"stats":[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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":3}, -{"effectId":2616,"spellId":25078,"name":"Enchant Gloves - Fire Power","type":7,"stats":[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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":3}, -{"effectId":2617,"spellId":25079,"name":"Enchant Gloves - Healing Power","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,30,0,0],"quality":3}, -{"effectId":2619,"spellId":25081,"name":"Enchant Cloak - Greater Fire Resistance","type":4,"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,15,0,0,0,0,0,0,0],"quality":1}, -{"effectId":2620,"spellId":25082,"name":"Enchant Cloak - Greater Nature Resistance","type":4,"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,15,0,0,0,0,0],"quality":1}, -{"effectId":2621,"spellId":25084,"name":"Enchant Cloak - Subtlety","type":4,"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":2622,"spellId":25086,"name":"Enchant Cloak - Dodge","type":4,"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,1,0,0,0,0,0,0,0,0,0,0,0,0],"quality":3}, +{"effectId":2583,"itemId":19782,"spellId":24149,"name":"Presence of Might","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,15,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":3,"phase":4,"classAllowlist":[9]}, +{"effectId":2584,"itemId":19783,"spellId":24160,"name":"Syncretist's Sigil","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,24,0,0],"quality":3,"phase":4,"classAllowlist":[4]}, +{"effectId":2585,"itemId":19784,"spellId":24161,"name":"Death's Embrace","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,28,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0],"quality":3,"phase":4,"classAllowlist":[6]}, +{"effectId":2586,"itemId":19785,"spellId":24162,"name":"Falcon's Call","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,10,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":3,"phase":4,"classAllowlist":[2]}, +{"effectId":2587,"itemId":19786,"spellId":24163,"name":"Vodouisant's Vigilant Embrace","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,0,15,0,13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,"phase":4,"classAllowlist":[7]}, +{"effectId":2588,"itemId":19787,"spellId":24164,"name":"Presence of Sight","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,0,0,0,18,0,0,0,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],"quality":3,"phase":4,"classAllowlist":[3]}, +{"effectId":2589,"itemId":19788,"spellId":24165,"name":"Hoodoo Hex","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,10,0,0,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,"phase":4,"classAllowlist":[8]}, +{"effectId":2590,"itemId":19789,"spellId":24167,"name":"Prophetic Aura","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,10,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,0,0],"quality":3,"phase":4,"classAllowlist":[5]}, +{"effectId":2591,"itemId":19790,"spellId":24168,"name":"Animist's Caress","type":1,"extraTypes":[9],"enchantType":3,"stats":[0,0,10,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,0,0],"quality":3,"phase":4,"classAllowlist":[1]}, +{"effectId":2604,"itemId":20078,"spellId":24420,"name":"Zandalar Signet of Serenity","type":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,0,0,0,0,0,0,0,33,0,0],"quality":3,"phase":4}, +{"effectId":2605,"itemId":20076,"spellId":24421,"name":"Zandalar Signet of Mojo","type":3,"stats":[0,0,0,0,0,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,0,0],"quality":3,"phase":4}, +{"effectId":2606,"itemId":20077,"spellId":24422,"name":"Zandalar Signet of Might","type":3,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,30,0,0,0,0,0,0,0,0,0,30,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":3,"phase":4}, +{"effectId":2613,"spellId":25072,"name":"Enchant Gloves - Threat","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":3,"phase":4}, +{"effectId":2614,"spellId":25073,"name":"Enchant Gloves - Shadow Power","type":7,"stats":[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,0,0,0,0,0,0,0,0,0,0,0,0],"quality":3,"phase":4}, +{"effectId":2615,"spellId":25074,"name":"Enchant Gloves - Frost Power","type":7,"stats":[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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":3,"phase":4}, +{"effectId":2616,"spellId":25078,"name":"Enchant Gloves - Fire Power","type":7,"stats":[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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":3,"phase":4}, +{"effectId":2617,"spellId":25079,"name":"Enchant Gloves - Healing Power","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,30,0,0],"quality":3,"phase":4}, +{"effectId":2619,"spellId":25081,"name":"Enchant Cloak - Greater Fire Resistance","type":4,"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,15,0,0,0,0,0,0,0],"quality":1,"phase":4}, +{"effectId":2620,"spellId":25082,"name":"Enchant Cloak - Greater Nature Resistance","type":4,"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,15,0,0,0,0,0],"quality":1,"phase":4}, +{"effectId":2621,"spellId":25084,"name":"Enchant Cloak - Subtlety","type":4,"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,"phase":4}, +{"effectId":2622,"spellId":25086,"name":"Enchant Cloak - Dodge","type":4,"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,1,0,0,0,0,0,0,0,0,0,0,0,0],"quality":3,"phase":4}, {"effectId":2646,"spellId":27837,"name":"Enchant 2H Weapon - Agility","type":13,"enchantType":1,"stats":[0,25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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":2681,"itemId":22635,"spellId":28161,"name":"Savage Guard","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,0,0,0,0,10,0,0,0,0,0],"quality":3}, -{"effectId":2715,"itemId":23547,"spellId":29475,"name":"Resilience of the Scourge","type":3,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31,0,0],"quality":4}, -{"effectId":2716,"itemId":23549,"spellId":29480,"name":"Fortitude of the Scourge","type":3,"stats":[0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,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],"quality":4}, -{"effectId":2717,"itemId":23548,"spellId":29483,"name":"Might of the Scourge","type":3,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,26,0,0.01,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":4}, -{"effectId":2721,"itemId":23545,"spellId":29467,"name":"Power of the Scourge","type":3,"stats":[0,0,0,0,0,15,0,0,0,0,0,0,0,0,0.01,0,0,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],"quality":4}, +{"effectId":2681,"itemId":22635,"spellId":28161,"name":"Savage Guard","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,0,0,0,0,10,0,0,0,0,0],"quality":3,"phase":4}, +{"effectId":2715,"itemId":23547,"spellId":29475,"name":"Resilience of the Scourge","type":3,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31,0,0],"quality":4,"phase":6}, +{"effectId":2716,"itemId":23549,"spellId":29480,"name":"Fortitude of the Scourge","type":3,"stats":[0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,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],"quality":4,"phase":6}, +{"effectId":2717,"itemId":23548,"spellId":29483,"name":"Might of the Scourge","type":3,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,26,0,0.01,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":4,"phase":6}, +{"effectId":2721,"itemId":23545,"spellId":29467,"name":"Power of the Scourge","type":3,"stats":[0,0,0,0,0,15,0,0,0,0,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],"quality":4,"phase":6}, {"effectId":7210,"spellId":435481,"name":"Enchant Weapon - Dismantle","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":4}, {"effectId":7223,"spellId":435903,"name":"Enchant Chest - Retricutioner","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":4}, {"effectId":7603,"itemId":228982,"spellId":463871,"name":"Enchant Shield - Law of Nature","type":13,"enchantType":2,"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,55,30,0],"quality":2} diff --git a/proto/api.proto b/proto/api.proto index c77049cef8..0fca23db26 100644 --- a/proto/api.proto +++ b/proto/api.proto @@ -15,7 +15,7 @@ import "shaman.proto"; import "warlock.proto"; import "warrior.proto"; -// NextIndex: 47 +// NextIndex: 49 message Player { // Label used for logging. string name = 1; @@ -54,6 +54,10 @@ message Player { int32 isb_warlocks = 43; int32 isb_spriests = 44; + // Stormstrike Info + double stormstrike_frequency = 47; + double stormstrike_nature_attacker_frequency = 48; + // Items/enchants/etc to include in the database. SimDatabase database = 18; HealingModel healing_model = 19; diff --git a/sim/common/includes.go b/sim/common/includes.go index 9269b246fc..3f3005907f 100644 --- a/sim/common/includes.go +++ b/sim/common/includes.go @@ -2,5 +2,6 @@ package common // Just import other directories, so importing common from elsewhere is enough. import ( + _ "github.com/wowsims/classic/sim/common/item_effects" _ "github.com/wowsims/classic/sim/common/item_sets" ) diff --git a/sim/common/item_effects.go b/sim/common/item_effects.go index d9591603c4..e2e8351e36 100644 --- a/sim/common/item_effects.go +++ b/sim/common/item_effects.go @@ -60,8 +60,6 @@ const ( ZandalariHeroBadge = 19948 ZandalariHeroMedallion = 19949 ZandalariHeroCharm = 19950 - MarkOfTheChampionPhys = 23206 - MarkOfTheChampionSpell = 23207 Ragehammer = 10626 SulfurasHandOfRagnaros = 17182 SulfuronHammer = 17193 @@ -2349,21 +2347,6 @@ func init() { }) }) - /* core.NewItemEffect(MarkOfTheChampionPhys, func(agent core.Agent) { - character := agent.GetCharacter() - if character.CurrentTarget.MobType == proto.MobType_MobTypeUndead || character.CurrentTarget.MobType == proto.MobType_MobTypeDemon { - character.PseudoStats.MobTypeAttackPower += 150 - } - }) - - core.NewItemEffect(MarkOfTheChampionSpell, func(agent core.Agent) { - character := agent.GetCharacter() - - if character.CurrentTarget.MobType == proto.MobType_MobTypeUndead || character.CurrentTarget.MobType == proto.MobType_MobTypeDemon { - character.PseudoStats.MobTypeSpellPower += 85 - } - }) */ - // https://www.wowhead.com/classic/item=17774/mark-of-the-chosen core.NewItemEffect(MarkOfTheChosen, func(agent core.Agent) { character := agent.GetCharacter() diff --git a/sim/common/item_effects/phase_6.go b/sim/common/item_effects/phase_6.go new file mode 100644 index 0000000000..8f57c7e5e0 --- /dev/null +++ b/sim/common/item_effects/phase_6.go @@ -0,0 +1,44 @@ +package item_effects + +import ( + "time" + + "github.com/wowsims/classic/sim/core" + "github.com/wowsims/classic/sim/core/proto" + "github.com/wowsims/classic/sim/core/stats" +) + +const ( + TheRestrainedEssenceOfSapphiron = 23046 + MarkOfTheChampionPhys = 23206 + MarkOfTheChampionSpell = 23207 +) + +func init() { + core.AddEffectsToTest = false + + // https://wowhead.com/classic/item=23206?level=60&rand=0 + // Equip: +150 Attack Power when fighting Undead and Demons. + core.NewItemEffect(MarkOfTheChampionPhys, func(agent core.Agent) { + character := agent.GetCharacter() + if character.CurrentTarget.MobType == proto.MobType_MobTypeUndead || character.CurrentTarget.MobType == proto.MobType_MobTypeDemon { + character.PseudoStats.MobTypeAttackPower += 150 + } + }) + + // https://www.wowhead.com/classic/item=23207/mark-of-the-champion + // Equip: Increases damage done to Undead and Demons by magical spells and effects by up to 85. + core.NewItemEffect(MarkOfTheChampionSpell, func(agent core.Agent) { + character := agent.GetCharacter() + + if character.CurrentTarget.MobType == proto.MobType_MobTypeUndead || character.CurrentTarget.MobType == proto.MobType_MobTypeDemon { + character.PseudoStats.MobTypeSpellPower += 85 + } + }) + + // https://www.wowhead.com/classic/item=23046/the-restrained-essence-of-sapphiron + // Use: Increases damage and healing done by magical spells and effects by up to 130 for 20 sec. (2 Min Cooldown) + core.NewSimpleStatOffensiveTrinketEffect(TheRestrainedEssenceOfSapphiron, stats.Stats{stats.SpellPower: 130}, time.Second*20, time.Minute*2) + + core.AddEffectsToTest = true +} diff --git a/sim/core/character.go b/sim/core/character.go index 7186ec3e44..edba658d99 100644 --- a/sim/core/character.go +++ b/sim/core/character.go @@ -51,6 +51,8 @@ type Character struct { // ISB External configuration IsbConfig IsbConfig + // Stormstrike External Configuration + StormstrikeConfig StormstrikeConfig // Base stats for this Character. baseStats stats.Stats @@ -146,6 +148,7 @@ func NewCharacter(party *Party, partyIndex int, player *proto.Player) Character } character.createIsbConfig(player) + character.createStormstrikeConfig(player) character.baseStats = getBaseStatsCombo(character.Race, character.Class) diff --git a/sim/core/debuffs.go b/sim/core/debuffs.go index 851b5f53f8..b9d444f5c4 100644 --- a/sim/core/debuffs.go +++ b/sim/core/debuffs.go @@ -92,8 +92,8 @@ func applyDebuffEffects(target *Unit, targetIdx int, debuffs *proto.Debuffs, rai }, raid) } - if debuffs.Stormstrike { - MakePermanent(StormstrikeAura(target)) + if debuffs.Stormstrike && targetIdx == 0 { + ExternalStormstrikeCaster(debuffs, target) } if debuffs.GiftOfArthas { @@ -179,21 +179,92 @@ func applyDebuffEffects(target *Unit, targetIdx int, debuffs *proto.Debuffs, rai } } +type StormstrikeConfig struct { + stormstrikeFrequency float64 + natureAttackersFrequency float64 +} + +func (character *Character) createStormstrikeConfig(player *proto.Player) { + character.StormstrikeConfig = StormstrikeConfig{ + stormstrikeFrequency: player.StormstrikeFrequency, + natureAttackersFrequency: player.StormstrikeNatureAttackerFrequency, + } + // Defaults if not configured + if character.StormstrikeConfig.stormstrikeFrequency == 0.0 { + character.StormstrikeConfig.stormstrikeFrequency = 20.0 + } +} + +const ( + StormstrikeCooldown = time.Second * 20 +) + +func ExternalStormstrikeCaster(_ *proto.Debuffs, target *Unit) { + stormstrikeConfig := target.Env.Raid.Parties[0].Players[0].GetCharacter().StormstrikeConfig + stormstrikeAura := StormstrikeAura(target) + var pa *PendingAction + MakePermanent(target.GetOrRegisterAura(Aura{ + Label: "Stormstrike External Proc Aura", + OnGain: func(aura *Aura, sim *Simulation) { + pa = NewPeriodicAction(sim, PeriodicActionOptions{ + Period: DurationFromSeconds(stormstrikeConfig.stormstrikeFrequency), + TickImmediately: true, + OnAction: func(s *Simulation) { + stormstrikeAura.Activate(sim) + stormstrikeAura.SetStacks(sim, stormstrikeAura.MaxStacks) + }, + }) + sim.AddPendingAction(pa) + }, + OnExpire: func(aura *Aura, sim *Simulation) { + pa.Cancel(sim) + }, + })) +} + func StormstrikeAura(unit *Unit) *Aura { + stormstrikeConfig := unit.Env.Raid.Parties[0].Players[0].GetCharacter().StormstrikeConfig + aura := unit.GetOrRegisterAura(Aura{ - Label: "Stormstrike", - ActionID: ActionID{SpellID: 17364}, - Duration: time.Second * 12, + Label: "Stormstrike", + ActionID: ActionID{SpellID: 17364}, + Duration: time.Second * 12, + MaxStacks: 2, + OnGain: func(aura *Aura, sim *Simulation) { + aura.Unit.PseudoStats.SchoolDamageTakenMultiplier[stats.SchoolIndexNature] *= 1.20 + }, + OnExpire: func(aura *Aura, sim *Simulation) { + aura.Unit.PseudoStats.SchoolDamageTakenMultiplier[stats.SchoolIndexNature] /= 1.20 + }, + OnSpellHitTaken: func(aura *Aura, sim *Simulation, spell *Spell, result *SpellResult) { + if aura.IsActive() && spell.SpellSchool.Matches(SpellSchoolNature) && result.Landed() && result.Damage > 0 { + aura.RemoveStack(sim) + } + }, }) - //Needs updating to classic version + // External attacks using nature strike + if stormstrikeConfig.natureAttackersFrequency > 0 { + aura.OnReset = func(aura *Aura, sim *Simulation) { + sim.AddPendingAction( + NewPeriodicAction(sim, PeriodicActionOptions{ + Period: DurationFromSeconds(stormstrikeConfig.natureAttackersFrequency), + OnAction: func(s *Simulation) { + if aura.IsActive() { + aura.RemoveStack(sim) + } + }, + }), + ) + } + } + return aura } func ExternalIsbCaster(_ *proto.Debuffs, target *Unit) { isbConfig := target.Env.Raid.Parties[0].Players[0].GetCharacter().IsbConfig - baseStacks := int32(ISBNumStacksBase) - isbAura := ImprovedShadowBoltAura(target, 5, baseStacks) + isbAura := ImprovedShadowBoltAura(target, 5) isbCrit := isbConfig.casterCrit / 100.0 var pa *PendingAction MakePermanent(target.GetOrRegisterAura(Aura{ @@ -205,7 +276,7 @@ func ExternalIsbCaster(_ *proto.Debuffs, target *Unit) { for i := 0; i < int(isbConfig.isbWarlocks); i++ { if sim.Proc(isbCrit, "External Isb Crit") { isbAura.Activate(sim) - isbAura.SetStacks(sim, baseStacks) + isbAura.SetStacks(sim, isbAura.MaxStacks) } else if isbAura.IsActive() { isbAura.RemoveStack(sim) } @@ -250,7 +321,7 @@ const ( ISBNumStacksBase = 4 ) -func ImprovedShadowBoltAura(unit *Unit, rank int32, stackCount int32) *Aura { +func ImprovedShadowBoltAura(unit *Unit, rank int32) *Aura { isbLabel := "Improved Shadow Bolt" if unit.GetAura(isbLabel) != nil { return unit.GetAura(isbLabel) @@ -268,7 +339,7 @@ func ImprovedShadowBoltAura(unit *Unit, rank int32, stackCount int32) *Aura { Label: isbLabel, ActionID: ActionID{SpellID: 17800}, Duration: 12 * time.Second, - MaxStacks: stackCount, + MaxStacks: ISBNumStacksBase, OnReset: func(aura *Aura, sim *Simulation) { // External shadow priests simulation if externalShadowPriests > 0 { @@ -751,10 +822,10 @@ func ExposeWeaknessAura(target *Unit) *Aura { ActionID: ActionID{SpellID: 23577}, Label: "Expose Weakness", Duration: time.Second * 7, - OnGain: func(aura *Aura, sim *Simulation) { + OnGain: func(aura *Aura, sim *Simulation) { target.PseudoStats.BonusRangedAttackPowerTaken += bonus }, - OnExpire: func(aura *Aura, sim *Simulation) { + OnExpire: func(aura *Aura, sim *Simulation) { target.PseudoStats.BonusRangedAttackPowerTaken -= bonus }, }) diff --git a/sim/druid/balance/TestP1Balance.results b/sim/druid/balance/TestP1Balance.results index 79b5706545..65e33ed1b7 100644 --- a/sim/druid/balance/TestP1Balance.results +++ b/sim/druid/balance/TestP1Balance.results @@ -53,9 +53,9 @@ stat_weights_results: { weights: 0 weights: 0 weights: 0 - weights: 0.02507 + weights: 0.02529 weights: 0 - weights: 0.44857 + weights: 0.46351 weights: 0 weights: 0 weights: 0 @@ -63,8 +63,8 @@ stat_weights_results: { weights: 0 weights: 0 weights: 0 - weights: 2.16443 - weights: 1.70064 + weights: 2.16569 + weights: 1.7517 weights: 0 weights: 0 weights: 0 @@ -99,29 +99,29 @@ stat_weights_results: { dps_results: { key: "TestP1Balance-Phase1-Average-Default" value: { - dps: 155.39007 - tps: 168.86746 + dps: 160.65508 + tps: 174.13247 } } dps_results: { key: "TestP1Balance-Phase1-Settings-NightElf-p0.bis-Default-p1-FullBuffs-P1-Consumes-LongMultiTarget" value: { - dps: 154.27378 - tps: 402.57966 + dps: 157.76801 + tps: 406.0739 } } dps_results: { key: "TestP1Balance-Phase1-Settings-NightElf-p0.bis-Default-p1-FullBuffs-P1-Consumes-LongSingleTarget" value: { - dps: 154.27378 - tps: 166.68907 + dps: 157.76801 + tps: 170.1833 } } dps_results: { key: "TestP1Balance-Phase1-Settings-NightElf-p0.bis-Default-p1-FullBuffs-P1-Consumes-ShortSingleTarget" value: { - dps: 148.49645 - tps: 157.09674 + dps: 152.61124 + tps: 161.21153 } } dps_results: { @@ -148,22 +148,22 @@ dps_results: { dps_results: { key: "TestP1Balance-Phase1-Settings-Tauren-p0.bis-Default-p1-FullBuffs-P1-Consumes-LongMultiTarget" value: { - dps: 153.21715 - tps: 420.2473 + dps: 156.60707 + tps: 423.63721 } } dps_results: { key: "TestP1Balance-Phase1-Settings-Tauren-p0.bis-Default-p1-FullBuffs-P1-Consumes-LongSingleTarget" value: { - dps: 153.21715 - tps: 166.56866 + dps: 156.60707 + tps: 169.95858 } } dps_results: { key: "TestP1Balance-Phase1-Settings-Tauren-p0.bis-Default-p1-FullBuffs-P1-Consumes-ShortSingleTarget" value: { - dps: 147.42161 - tps: 156.0408 + dps: 151.53758 + tps: 160.15677 } } dps_results: { @@ -190,7 +190,7 @@ dps_results: { dps_results: { key: "TestP1Balance-Phase1-SwitchInFrontOfTarget-Default" value: { - dps: 153.88456 - tps: 167.30175 + dps: 158.97674 + tps: 172.39393 } } diff --git a/sim/hunter/TestP1Hunter.results b/sim/hunter/TestP1Hunter.results index e9a608d5b6..29a6cbaf8a 100644 --- a/sim/hunter/TestP1Hunter.results +++ b/sim/hunter/TestP1Hunter.results @@ -239,22 +239,22 @@ dps_results: { dps_results: { key: "TestP1Hunter-Phase1-Settings-Dwarf-p0.bis-Hunter-p1-FullBuffs-P1-Consumes-LongMultiTarget" value: { - dps: 863.52491 - tps: 924.48318 + dps: 867.06674 + tps: 928.02501 } } dps_results: { key: "TestP1Hunter-Phase1-Settings-Dwarf-p0.bis-Hunter-p1-FullBuffs-P1-Consumes-LongSingleTarget" value: { - dps: 664.65503 - tps: 534.16299 + dps: 668.19685 + tps: 537.70481 } } dps_results: { key: "TestP1Hunter-Phase1-Settings-Dwarf-p0.bis-Hunter-p1-FullBuffs-P1-Consumes-ShortSingleTarget" value: { - dps: 718.64976 - tps: 586.55548 + dps: 723.032 + tps: 590.93771 } } dps_results: { @@ -281,22 +281,22 @@ dps_results: { dps_results: { key: "TestP1Hunter-Phase1-Settings-Orc-p0.bis-Hunter-p1-FullBuffs-P1-Consumes-LongMultiTarget" value: { - dps: 872.95199 - tps: 923.14089 + dps: 875.92883 + tps: 926.11773 } } dps_results: { key: "TestP1Hunter-Phase1-Settings-Orc-p0.bis-Hunter-p1-FullBuffs-P1-Consumes-LongSingleTarget" value: { - dps: 682.52182 - tps: 546.92277 + dps: 685.49865 + tps: 549.8996 } } dps_results: { key: "TestP1Hunter-Phase1-Settings-Orc-p0.bis-Hunter-p1-FullBuffs-P1-Consumes-ShortSingleTarget" value: { - dps: 750.61136 - tps: 610.848 + dps: 754.51741 + tps: 614.75404 } } dps_results: { diff --git a/sim/priest/shadow/TestP1Shadow.results b/sim/priest/shadow/TestP1Shadow.results index 2d6cd64c2a..af714cfc3a 100644 --- a/sim/priest/shadow/TestP1Shadow.results +++ b/sim/priest/shadow/TestP1Shadow.results @@ -53,17 +53,17 @@ stat_weights_results: { weights: 0 weights: 0 weights: 0 - weights: 0.35086 + weights: 0.34801 weights: 0 - weights: 0.29454 + weights: 0.29455 weights: 0 weights: 0 weights: 0 weights: 0 weights: 0 - weights: 0.29454 + weights: 0.29455 weights: 0 - weights: 5.04465 + weights: 5.04844 weights: 0.47054 weights: 0 weights: 0 @@ -99,29 +99,29 @@ stat_weights_results: { dps_results: { key: "TestP1Shadow-Phase1-AllItems-IronweaveBattlesuit" value: { - dps: 426.19902 - tps: 422.03243 + dps: 426.23566 + tps: 422.0676 } } dps_results: { key: "TestP1Shadow-Phase1-Average-Default" value: { - dps: 492.24694 - tps: 485.41017 + dps: 492.25971 + tps: 485.42242 } } dps_results: { key: "TestP1Shadow-Phase1-Settings-Dwarf-p0.bis-Basic-p1-FullBuffs-P1-Consumes-LongMultiTarget" value: { - dps: 517.34195 - tps: 757.48523 + dps: 517.35618 + tps: 757.49889 } } dps_results: { key: "TestP1Shadow-Phase1-Settings-Dwarf-p0.bis-Basic-p1-FullBuffs-P1-Consumes-LongSingleTarget" value: { - dps: 517.34195 - tps: 509.69012 + dps: 517.35618 + tps: 509.70378 } } dps_results: { @@ -155,15 +155,15 @@ dps_results: { dps_results: { key: "TestP1Shadow-Phase1-Settings-Undead-p0.bis-Basic-p1-FullBuffs-P1-Consumes-LongMultiTarget" value: { - dps: 494.22915 - tps: 732.37054 + dps: 494.24338 + tps: 732.3842 } } dps_results: { key: "TestP1Shadow-Phase1-Settings-Undead-p0.bis-Basic-p1-FullBuffs-P1-Consumes-LongSingleTarget" value: { - dps: 494.22915 - tps: 487.35551 + dps: 494.24338 + tps: 487.36917 } } dps_results: { @@ -197,7 +197,7 @@ dps_results: { dps_results: { key: "TestP1Shadow-Phase1-SwitchInFrontOfTarget-Default" value: { - dps: 494.22915 - tps: 487.35551 + dps: 494.24338 + tps: 487.36917 } } diff --git a/sim/rogue/dps_rogue/TestCombatDaggers.results b/sim/rogue/dps_rogue/TestCombatDaggers.results index a28e1c817c..c32719076e 100644 --- a/sim/rogue/dps_rogue/TestCombatDaggers.results +++ b/sim/rogue/dps_rogue/TestCombatDaggers.results @@ -68,7 +68,7 @@ stat_weights_results: { weights: 0 weights: 0 weights: 0.34851 - weights: 12.13747 + weights: 12.14813 weights: 2.03849 weights: 0 weights: 0 @@ -99,78 +99,78 @@ stat_weights_results: { dps_results: { key: "TestCombatDaggers-Phase5-AllItems-BloodfangArmor" value: { - dps: 1053.94136 - tps: 748.29836 + dps: 1056.39762 + tps: 750.04231 } } dps_results: { key: "TestCombatDaggers-Phase5-AllItems-BonescytheArmor" value: { - dps: 1165.086 - tps: 809.17588 + dps: 1167.23639 + tps: 810.70266 } } dps_results: { key: "TestCombatDaggers-Phase5-AllItems-Champion'sGuard" value: { - dps: 982.91434 - tps: 697.86918 + dps: 985.04018 + tps: 699.37853 } } dps_results: { key: "TestCombatDaggers-Phase5-AllItems-DarkmantleArmor" value: { - dps: 1056.19891 - tps: 749.90123 + dps: 1058.25366 + tps: 751.3601 } } dps_results: { key: "TestCombatDaggers-Phase5-AllItems-Deathdealer'sEmbrace" value: { - dps: 1056.85034 - tps: 750.36374 + dps: 1058.97619 + tps: 751.87309 } } dps_results: { key: "TestCombatDaggers-Phase5-AllItems-FieldMarshal'sVestments" value: { - dps: 1021.28147 - tps: 725.10984 + dps: 1023.43175 + tps: 726.63655 } } dps_results: { key: "TestCombatDaggers-Phase5-AllItems-LieutenantCommander'sGuard" value: { - dps: 982.91434 - tps: 697.86918 + dps: 985.04018 + tps: 699.37853 } } dps_results: { key: "TestCombatDaggers-Phase5-AllItems-Madcap'sOutfit" value: { - dps: 994.1002 - tps: 705.81114 + dps: 996.17261 + tps: 707.28255 } } dps_results: { key: "TestCombatDaggers-Phase5-AllItems-NightslayerArmor" value: { - dps: 1001.27286 - tps: 710.90373 + dps: 1003.40413 + tps: 712.41693 } } dps_results: { key: "TestCombatDaggers-Phase5-AllItems-Warlord'sVestments" value: { - dps: 1021.28147 - tps: 725.10984 + dps: 1023.43175 + tps: 726.63655 } } dps_results: { key: "TestCombatDaggers-Phase5-Average-Default" value: { - dps: 997.39618 - tps: 708.15129 + dps: 999.55768 + tps: 709.68595 } } dps_results: { @@ -260,7 +260,7 @@ dps_results: { dps_results: { key: "TestCombatDaggers-Phase5-SwitchInFrontOfTarget-Default" value: { - dps: 380.90013 - tps: 270.4391 + dps: 382.43536 + tps: 271.52911 } } diff --git a/sim/rogue/dps_rogue/TestCombatSinisterStrike.results b/sim/rogue/dps_rogue/TestCombatSinisterStrike.results index 1a389efcc8..43ed98ff3c 100644 --- a/sim/rogue/dps_rogue/TestCombatSinisterStrike.results +++ b/sim/rogue/dps_rogue/TestCombatSinisterStrike.results @@ -50,8 +50,8 @@ character_stats_results: { stat_weights_results: { key: "TestCombatSinisterStrike-Phase5-StatWeights-Default" value: { - weights: 0.45983 - weights: 0.81833 + weights: 0.45984 + weights: 0.82151 weights: 0 weights: 0 weights: 0 @@ -68,8 +68,8 @@ stat_weights_results: { weights: 0 weights: 0 weights: 0.36351 - weights: 10.34575 - weights: 6.42015 + weights: 10.31614 + weights: 6.42228 weights: 0 weights: 0 weights: 0 @@ -99,78 +99,78 @@ stat_weights_results: { dps_results: { key: "TestCombatSinisterStrike-Phase5-AllItems-BloodfangArmor" value: { - dps: 1066.94208 - tps: 757.52888 + dps: 1068.92675 + tps: 758.93799 } } dps_results: { key: "TestCombatSinisterStrike-Phase5-AllItems-BonescytheArmor" value: { - dps: 1179.86194 - tps: 820.6033 + dps: 1181.54653 + tps: 821.79936 } } dps_results: { key: "TestCombatSinisterStrike-Phase5-AllItems-Champion'sGuard" value: { - dps: 981.45571 - tps: 696.83355 + dps: 983.02112 + tps: 697.94499 } } dps_results: { key: "TestCombatSinisterStrike-Phase5-AllItems-DarkmantleArmor" value: { - dps: 1070.58658 - tps: 760.11647 + dps: 1072.24977 + tps: 761.29734 } } dps_results: { key: "TestCombatSinisterStrike-Phase5-AllItems-Deathdealer'sEmbrace" value: { - dps: 1078.95523 - tps: 766.05822 + dps: 1080.51564 + tps: 767.1661 } } dps_results: { key: "TestCombatSinisterStrike-Phase5-AllItems-FieldMarshal'sVestments" value: { - dps: 1033.16916 - tps: 733.5501 + dps: 1034.82461 + tps: 734.72547 } } dps_results: { key: "TestCombatSinisterStrike-Phase5-AllItems-LieutenantCommander'sGuard" value: { - dps: 981.45571 - tps: 696.83355 + dps: 983.02112 + tps: 697.94499 } } dps_results: { key: "TestCombatSinisterStrike-Phase5-AllItems-Madcap'sOutfit" value: { - dps: 1011.59214 - tps: 718.23042 + dps: 1013.18847 + tps: 719.36382 } } dps_results: { key: "TestCombatSinisterStrike-Phase5-AllItems-NightslayerArmor" value: { - dps: 1009.29883 - tps: 716.60217 + dps: 1010.95691 + tps: 717.77941 } } dps_results: { key: "TestCombatSinisterStrike-Phase5-AllItems-Warlord'sVestments" value: { - dps: 1033.16916 - tps: 733.5501 + dps: 1034.82461 + tps: 734.72547 } } dps_results: { key: "TestCombatSinisterStrike-Phase5-Average-Default" value: { - dps: 1006.04864 - tps: 714.29453 + dps: 1007.77748 + tps: 715.52201 } } dps_results: { @@ -260,7 +260,7 @@ dps_results: { dps_results: { key: "TestCombatSinisterStrike-Phase5-SwitchInFrontOfTarget-Default" value: { - dps: 766.70501 - tps: 544.36056 + dps: 768.17302 + tps: 545.40284 } } diff --git a/sim/shaman/_item_sets_pve.go b/sim/shaman/_item_sets_pve.go deleted file mode 100644 index 9e13af11e3..0000000000 --- a/sim/shaman/_item_sets_pve.go +++ /dev/null @@ -1,800 +0,0 @@ -package shaman - -import ( - "slices" - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" - "github.com/wowsims/classic/sim/core/stats" -) - -/////////////////////////////////////////////////////////////////////////// -// SoD Phase 2 Item Sets -/////////////////////////////////////////////////////////////////////////// - -var ItemSetElectromanticStormbringer = core.NewItemSet(core.ItemSet{ - Name: "Electromantic Stormbringer's Chain", - Bonuses: map[int32]core.ApplyEffect{ - 2: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.SpellPower, 12) - }, - 3: func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - shaman.OnSpellRegistered(func(spell *core.Spell) { - if spell.SpellCode == SpellCode_ShamanLightningBolt { - spell.DefaultCast.CastTime -= time.Millisecond * 100 - } - }) - }, - }, -}) - -/////////////////////////////////////////////////////////////////////////// -// SoD Phase 3 Item Sets -/////////////////////////////////////////////////////////////////////////// - -var OstracizedBerserksBattlemail = core.NewItemSet(core.ItemSet{ - Name: "Ostracized Berserker's Battlemail", - Bonuses: map[int32]core.ApplyEffect{ - 2: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.AttackPower, 20) - }, - 3: func(agent core.Agent) { - c := agent.GetCharacter() - - procAura := c.GetOrRegisterAura(core.Aura{ - Label: "Fiery Strength Proc", - ActionID: core.ActionID{SpellID: 449932}, - Duration: time.Second * 12, - MaxStacks: 10, - OnStacksChange: func(aura *core.Aura, sim *core.Simulation, oldStacks, newStacks int32) { - statsDelta := float64(newStacks-oldStacks) * 5.0 - aura.Unit.AddStatDynamic(sim, stats.AttackPower, statsDelta) - }, - }) - - core.MakeProcTriggerAura(&c.Unit, core.ProcTrigger{ - Name: "Fiery Strength", - Callback: core.CallbackOnSpellHitDealt | core.CallbackOnPeriodicDamageDealt, - Outcome: core.OutcomeLanded, - ProcMask: core.ProcMaskDirect, - Handler: func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if spell.SpellSchool.Matches(core.SpellSchoolFire) { - procAura.Activate(sim) - procAura.AddStack(sim) - } - }, - }) - }, - }, -}) - -var ItemSetEmeraldChainmail = core.NewItemSet(core.ItemSet{ - Name: "Emerald Chainmail", - 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 ItemSetEmeraldScalemail = core.NewItemSet(core.ItemSet{ - Name: "Emerald Scalemail", - 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) - }, - }, -}) - -var ItemSetEmeraldLadenChain = core.NewItemSet(core.ItemSet{ - Name: "Emerald Laden Chain", - 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) - }, - }, -}) - -/////////////////////////////////////////////////////////////////////////// -// SoD Phase 4 Item Sets -/////////////////////////////////////////////////////////////////////////// - -var ItemSetTheFiveThunders = core.NewItemSet(core.ItemSet{ - Name: "The Five Thunders", - Bonuses: map[int32]core.ApplyEffect{ - // +40 Attack Power, up to 23 increased damage from spells, and up to 44 increased healing from spells. - 2: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStats(stats.Stats{ - stats.AttackPower: 40, - stats.RangedAttackPower: 40, - stats.SpellDamage: 23, - stats.HealingPower: 44, - }) - }, - // 6% chance on mainhand autoattack and 4% chance on spellcast to increase your damage and healing done by magical spells and effects by up to 95 for 10 sec. - 4: func(agent core.Agent) { - c := agent.GetCharacter() - - procAura := c.NewTemporaryStatsAura("The Furious Storm", core.ActionID{SpellID: 27775}, stats.Stats{stats.SpellPower: 95}, time.Second*10) - handler := func(sim *core.Simulation, spell *core.Spell, _ *core.SpellResult) { - procAura.Activate(sim) - } - - core.MakeProcTriggerAura(&c.Unit, core.ProcTrigger{ - Name: "Item - The Furious Storm Proc (MH Auto)", - Callback: core.CallbackOnSpellHitDealt, - Outcome: core.OutcomeLanded, - ProcMask: core.ProcMaskMeleeMHAuto, - ProcChance: 0.06, - Handler: handler, - }) - core.MakeProcTriggerAura(&c.Unit, core.ProcTrigger{ - Name: "Item - The Furious Storm Proc (Spell Cast)", - Callback: core.CallbackOnCastComplete, - ProcMask: core.ProcMaskSpellDamage | core.ProcMaskSpellHealing, - ProcChance: 0.04, - Handler: handler, - }) - }, - // +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 ItemSetEarthfuryEruption = core.NewItemSet(core.ItemSet{ - Name: "Earthfury Eruption", - Bonuses: map[int32]core.ApplyEffect{ - // The radius of your totems that affect friendly targets is increased to 40 yd. - 2: func(agent core.Agent) { - // Nothing to do - }, - // Your Lightning Bolt critical strikes have a 35% chance to reset the cooldown on Lava Burst and Chain Lightning and make the next Lava Burst, Chain Heal, or Chain Lightning within 10 sec instant. - 4: func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - shaman.GetOrRegisterAura(core.Aura{ - Label: "S03 - Item - T1 - Shaman - Elemental 4P 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 spell.SpellCode == SpellCode_ShamanLightningBolt && spell.ProcMask.Matches(core.ProcMaskSpellDamage) && result.DidCrit() && sim.Proc(.35, "Power Surge") { - shaman.PowerSurgeDamageAura.Activate(sim) - } - }, - }) - }, - // Lava Burst now also refreshes the duration of Flame Shock on your target back to 12 sec. - 6: func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - core.MakePermanent(shaman.GetOrRegisterAura(core.Aura{ - Label: "S03 - Item - T1 - Shaman - Elemental 6P Bonus", - OnCastComplete: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell) { - if spell.SpellCode == SpellCode_ShamanLavaBurst { - for _, spell := range shaman.FlameShock { - if spell == nil { - continue - } - - if dot := spell.Dot(shaman.CurrentTarget); dot.IsActive() { - dot.NumberOfTicks = dot.OriginalNumberOfTicks - dot.Rollover(sim) - } - } - } - }, - })) - }, - }, -}) - -var ItemSetEarthfuryRelief = core.NewItemSet(core.ItemSet{ - Name: "Earthfury Relief", - Bonuses: map[int32]core.ApplyEffect{ - // The radius of your totems that affect friendly targets is increased to 40 yd. - 2: func(agent core.Agent) { - // Nothing to do - }, - // After casting your Healing Wave, Lesser Healing Wave, or Riptide spell, gives you a 25% chance to gain Mana equal to 35% of the base cost of the spell. - 4: func(agent core.Agent) { - // Not implementing for now - }, - // Your Healing Wave will now jump to additional nearby targets. Each jump reduces the effectiveness of the heal by 80%, and the spell will jump to up to 2 additional targets. - 6: func(agent core.Agent) { - // Not implementing for now - }, - }, -}) - -var ItemSetEarthfuryImpact = core.NewItemSet(core.ItemSet{ - Name: "Earthfury Impact", - Bonuses: map[int32]core.ApplyEffect{ - // The radius of your totems that affect friendly targets is increased to 40 yd. - 2: func(agent core.Agent) { - // Nothing to do - }, - // Increases your critical strike chance with spells and attacks by 2%. - 4: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStats(stats.Stats{ - stats.MeleeCrit: 2 * core.CritRatingPerCritChance, - stats.SpellCrit: 2 * core.CritRatingPerCritChance, - }) - }, - // Your Flurry talent grants an additional 10% increase to your attack speed. - 6: func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - shaman.RegisterAura(core.Aura{ - Label: "S03 - Item - T1 - Shaman - Enhancement 6P Bonus", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - shaman.bonusFlurrySpeed += .10 - }, - }) - }, - }, -}) - -var ItemSetEarthfuryResolve = core.NewItemSet(core.ItemSet{ - Name: "Earthfury Resolve", - Bonuses: map[int32]core.ApplyEffect{ - // Increases your attack speed by 30% for your next 3 swings after you parry, dodge, or block. - 2: func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - - flurryAura := shaman.makeFlurryAura(5) - // The consumption trigger may not exist if the Shaman doesn't talent into Flurry - shaman.makeFlurryConsumptionTrigger(flurryAura) - - core.MakePermanent(shaman.GetOrRegisterAura(core.Aura{ - Label: "S03 - Item - T1 - Shaman - Tank 2P Bonus", - OnSpellHitTaken: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if result.DidParry() || result.DidDodge() || result.DidBlock() { - flurryAura.Activate(sim) - flurryAura.SetStacks(sim, 3) - } - }, - })) - }, - // Your parries and dodges also activate your Shield Mastery rune ability. - 4: func(agent core.Agent) { - // Implemented in runes.go - }, - // Your Stoneskin Totem also reduces Physical damage taken by 5% and your Windwall Totem also reduces Magical damage taken by 5%. - 6: func(agent core.Agent) { - // Debuffs implemented in core/buffs.go, activated with a raid buff setting or in earth_totems.go and air_totems.go - }, - }, -}) - -/////////////////////////////////////////////////////////////////////////// -// SoD Phase 5 Item Sets -/////////////////////////////////////////////////////////////////////////// - -var ItemSetEruptionOfTheTenStorms = core.NewItemSet(core.ItemSet{ - Name: "Eruption of the Ten Storms", - Bonuses: map[int32]core.ApplyEffect{ - // Your spell critical strikes now have a 100% chance trigger your Elemental Focus talent. - 2: func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - if !shaman.Talents.ElementalFocus { - return - } - - core.MakePermanent(shaman.RegisterAura(core.Aura{ - Label: "S03 - Item - T2 - Shaman - Elemental 2P Bonus", - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if shaman.isShamanDamagingSpell(spell) && result.DidCrit() { - shaman.ClearcastingAura.Activate(sim) - shaman.ClearcastingAura.SetStacks(sim, shaman.ClearcastingAura.MaxStacks) - } - }, - })) - }, - // Loyal Beta from your Spirit of the Alpha ability now also increases Fire, Frost, and Nature damage by 5%. - 4: func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - if !shaman.HasRune(proto.ShamanRune_RuneFeetSpiritOfTheAlpha) { - return - } - - core.MakePermanent(shaman.RegisterAura(core.Aura{ - Label: "S03 - Item - T2 - Shaman - Elemental 4P Bonus", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - oldOnGain := shaman.LoyalBetaAura.OnGain - shaman.LoyalBetaAura.OnGain = func(aura *core.Aura, sim *core.Simulation) { - oldOnGain(aura, sim) - shaman.PseudoStats.SchoolDamageDealtMultiplier[stats.SchoolIndexFrost] *= 1.05 - shaman.PseudoStats.SchoolDamageDealtMultiplier[stats.SchoolIndexFire] *= 1.05 - shaman.PseudoStats.SchoolDamageDealtMultiplier[stats.SchoolIndexNature] *= 1.05 - } - }, - })) - }, - // While Clearcasting is active, you deal 15% more non-Physical damage. - 6: func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - if !shaman.Talents.ElementalFocus { - return - } - - core.MakePermanent(shaman.RegisterAura(core.Aura{ - Label: "S03 - Item - T2 - Shaman - Elemental 6P Bonus", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - oldOnGain := shaman.ClearcastingAura.OnGain - shaman.ClearcastingAura.OnGain = func(aura *core.Aura, sim *core.Simulation) { - oldOnGain(aura, sim) - shaman.PseudoStats.SchoolDamageDealtMultiplier.MultiplyMagicSchools(1.15) - } - - oldOnExpire := shaman.ClearcastingAura.OnExpire - shaman.ClearcastingAura.OnExpire = func(aura *core.Aura, sim *core.Simulation) { - oldOnExpire(aura, sim) - shaman.PseudoStats.SchoolDamageDealtMultiplier.MultiplyMagicSchools(1 / 1.15) - } - }, - })) - }, - }, -}) - -var ItemSetResolveOfTheTenStorms = core.NewItemSet(core.ItemSet{ - Name: "Resolve of the Ten Storms", - Bonuses: map[int32]core.ApplyEffect{ - // Your Flame Shock also grants 30% increased chance to Block for 5 sec or until you Block an attack. - 2: func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - - shieldBlockAura := shaman.RegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 467891}, - Label: "Shield Block", - Duration: time.Second * 5, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - shaman.AddStatDynamic(sim, stats.Block, 30*core.BlockRatingPerBlockChance) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - shaman.AddStatDynamic(sim, stats.Block, -30*core.BlockRatingPerBlockChance) - }, - OnSpellHitTaken: func(aura *core.Aura, sim *core.Simulation, _ *core.Spell, result *core.SpellResult) { - if result.DidBlock() { - aura.Deactivate(sim) - } - }, - }) - - core.MakePermanent(shaman.RegisterAura(core.Aura{ - Label: "S03 - Item - T2 - Shaman - Tank 2P Bonus", - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if spell.SpellCode == SpellCode_ShamanFlameShock { - shieldBlockAura.Activate(sim) - } - }, - })) - }, - // Each time you Block, your Block amount is increased by 10% of your Spell Damage for 6 sec, stacking up to 3 times. - 4: func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - - statDeps := []*stats.StatDependency{ - nil, - shaman.NewDynamicMultiplyStat(stats.BlockValue, 1.10), - shaman.NewDynamicMultiplyStat(stats.BlockValue, 1.20), - shaman.NewDynamicMultiplyStat(stats.BlockValue, 1.30), - } - - // Couldn't find a separate spell for this - blockAura := shaman.RegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 467909}, - Label: "S03 - Item - T2 - Shaman - Tank 4P Bonus", - Duration: time.Second * 6, - MaxStacks: 3, - OnStacksChange: func(aura *core.Aura, sim *core.Simulation, oldStacks, newStacks int32) { - if oldStacks != 0 { - shaman.DisableDynamicStatDep(sim, statDeps[oldStacks]) - } - if newStacks != 0 { - shaman.EnableDynamicStatDep(sim, statDeps[newStacks]) - } - }, - }) - - core.MakePermanent(shaman.RegisterAura(core.Aura{ - Label: "S03 - Item - T2 - Shaman - Tank 4P Bonus Trigger", - OnSpellHitTaken: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if result.DidBlock() { - blockAura.Activate(sim) - blockAura.AddStack(sim) - } - }, - })) - }, - // Each time you Block an attack, you have a 50% chance to trigger your Maelstrom Weapon rune. - 6: func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - if !shaman.HasRune(proto.ShamanRune_RuneWaistMaelstromWeapon) { - return - } - - core.MakePermanent(shaman.RegisterAura(core.Aura{ - Label: "S03 - Item - T2 - Shaman - Tank 6P Bonus", - OnSpellHitTaken: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if result.DidBlock() && sim.Proc(0.50, "T2 6P Proc Maelstrom Weapon") { - shaman.MaelstromWeaponAura.Activate(sim) - shaman.MaelstromWeaponAura.AddStack(sim) - } - }, - })) - }, - }, -}) - -var ItemSetImpactOfTheTenStorms = core.NewItemSet(core.ItemSet{ - Name: "Impact of the Ten Storms", - Bonuses: map[int32]core.ApplyEffect{ - // Your chance to trigger Static Shock is increased by 12% (6% while dual-wielding) - 2: func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - if !shaman.HasRune(proto.ShamanRune_RuneBracersStaticShock) { - return - } - - core.MakePermanent(shaman.RegisterAura(core.Aura{ - Label: "S03 - Item - T2 - Shaman - Enhancement 2P Bonus", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - shaman.staticSHocksProcChance += 0.06 - }, - })) - }, - // Main-hand Stormstrike now deals 50% more damage. - 4: func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - if !shaman.Talents.Stormstrike { - return - } - - shaman.RegisterAura(core.Aura{ - Label: "S03 - Item - T2 - Shaman - Enhancement 4P Bonus", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - shaman.StormstrikeMH.DamageMultiplier *= 1.50 - }, - }) - }, - // Your Lightning Shield now gains a charge each time you hit a target with Lightning Bolt or Chain Lightning, up to a maximum of 9 charges. - // In addition, your Lightning Shield can now deal critical damage. - // Note: Only works with Static Shock - 6: func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - if !shaman.HasRune(proto.ShamanRune_RuneBracersStaticShock) { - return - } - - affectedSpellCodes := []int32{SpellCode_ShamanLightningBolt, SpellCode_ShamanChainLightning} - core.MakePermanent(shaman.RegisterAura(core.Aura{ - Label: "S03 - Item - T2 - Shaman - Enhancement 6P Bonus", - OnInit: func(t26pAura *core.Aura, sim *core.Simulation) { - for _, aura := range shaman.LightningShieldAuras { - if aura == nil { - continue - } - - oldOnGain := aura.OnGain - aura.OnGain = func(aura *core.Aura, sim *core.Simulation) { - oldOnGain(aura, sim) - t26pAura.Activate(sim) - } - - oldOnExpire := aura.OnExpire - aura.OnExpire = func(aura *core.Aura, sim *core.Simulation) { - oldOnExpire(aura, sim) - t26pAura.Deactivate(sim) - } - } - - shaman.lightningShieldCanCrit = true - }, - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - // Tested and it doesn't proc from overloads - if slices.Contains(affectedSpellCodes, spell.SpellCode) && spell.ActionID.Tag != CastTagOverload && result.Landed() { - shaman.ActiveShieldAura.AddStack(sim) - } - }, - })) - }, - }, -}) - -var ItemSetReliefOfTheTenStorms = core.NewItemSet(core.ItemSet{ - Name: "Relief of the Ten Storms", - Bonuses: map[int32]core.ApplyEffect{ - // Your damaging and healing critical strikes now have a 100% chance to trigger your Water Shield, but do not consume a charge or trigger its cooldown. - 2: func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - - core.MakePermanent(shaman.RegisterAura(core.Aura{ - Label: "S03 - Item - T2 - Shaman - Restoration 2P Bonus", - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if spell.ProcMask.Matches(core.ProcMaskSpellDamage) && result.DidCrit() { - shaman.WaterShieldRestore.Cast(sim, aura.Unit) - } - }, - })) - }, - // Your Chain Lightning now also heals the target of your Earth Shield for 100% of the damage done. - 4: func(agent core.Agent) { - // TODO: Implement Earth Shield - // shaman := agent.(ShamanAgent).GetShaman() - - // core.MakePermanent(shaman.RegisterAura()) - }, - // Increases the healing of Chain Heal and the damage of Chain Lightning by 20%. - 6: func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - - shaman.RegisterAura(core.Aura{ - Label: "S03 - Item - T2 - Shaman - Restoration 6P Bonus", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - spells := core.Flatten([][]*core.Spell{ - shaman.ChainHeal, - shaman.ChainHealOverload, - shaman.ChainLightning, - shaman.ChainLightningOverload, - }) - - for _, spell := range spells { - if spell != nil { - spell.DamageMultiplier *= 1.20 - } - } - }, - }) - }, - }, -}) - -var ItemSetAugursRegalia = core.NewItemSet(core.ItemSet{ - Name: "Augur's Regalia", - Bonuses: map[int32]core.ApplyEffect{ - // Increased Defense +7. - 2: func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - shaman.AddStat(stats.Defense, 7) - }, - // Increases your chance to block attacks with a shield by 10%. - 3: func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - shaman.AddStat(stats.Block, 10*core.BlockRatingPerBlockChance) - }, - // Increases the chance to trigger your Power Surge rune by an additional 5%. - 5: func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - if !shaman.HasRune(proto.ShamanRune_RuneWaistPowerSurge) { - return - } - - shaman.RegisterAura(core.Aura{ - Label: "S03 - Item - ZG - Shaman - Tank 5P Bonus", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - shaman.powerSurgeProcChance += .05 - }, - }) - }, - }, -}) - -/////////////////////////////////////////////////////////////////////////// -// SoD Phase 6 Item Sets -/////////////////////////////////////////////////////////////////////////// - -var ItemSetStormcallersEruption = core.NewItemSet(core.ItemSet{ - Name: "Stormcaller's Eruption", - Bonuses: map[int32]core.ApplyEffect{ - // You have a 70% chance to avoid interruption caused by damage while casting Lightning Bolt, Chain Lightning, or Lava Burst, and a 10% increased chance to trigger your Elemental Focus talent. - 2: func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - - shaman.RegisterAura(core.Aura{ - Label: "S03 - Item - TAQ - Shaman - Elemental 2P Bonus", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - affectedPushbackSpells := core.FilterSlice( - core.Flatten( - [][]*core.Spell{ - shaman.LightningBolt, - shaman.ChainLightning, - {shaman.LavaBurst}, - }, - ), - func(spell *core.Spell) bool { return spell != nil }, - ) - - for _, spell := range affectedPushbackSpells { - spell.PushbackReduction += .70 - } - - shaman.elementalFocusProcChance += .10 - }, - }) - }, - // Increases the critical strike damage bonus of your Fire, Frost, and Nature spells by 60%. - 4: func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - shaman.OnSpellRegistered(func(spell *core.Spell) { - if (spell.Flags.Matches(SpellFlagShaman) || spell.Flags.Matches(SpellFlagTotem)) && spell.DefenseType == core.DefenseTypeMagic { - spell.CritDamageBonus += 0.60 - } - }) - }, - }, -}) - -var ItemSetStormcallersResolve = core.NewItemSet(core.ItemSet{ - Name: "Stormcaller's Resolve", - Bonuses: map[int32]core.ApplyEffect{ - // Damaging a target with Stormstrike also reduces all damage you take by 10% for 10 sec. - 2: func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - - buffAura := shaman.RegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 1213934}, - Label: "Stormbraced", - Duration: time.Second * 10, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - aura.Unit.PseudoStats.DamageTakenMultiplier *= 0.90 - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - aura.Unit.PseudoStats.DamageTakenMultiplier /= 0.90 - }, - }) - - core.MakePermanent(shaman.RegisterAura(core.Aura{ - Label: "S03 - Item - TAQ - Shaman - Elemental 2P Bonus", - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if spell.SpellCode == SpellCode_ShamanStormstrike && result.Landed() { - buffAura.Activate(sim) - } - }, - })) - }, - // Your Spirit of the Alpha also increases your health by 10% when cast on self. - 4: func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - // Do a simple multiply stat because we assume that a tank shaman is using Alpha on theirself - if shaman.HasRune(proto.ShamanRune_RuneFeetSpiritOfTheAlpha) && shaman.IsTanking() { - shaman.MultiplyStat(stats.Health, 1.10) - } - }, - }, -}) - -var ItemSetStormcallersRelief = core.NewItemSet(core.ItemSet{ - Name: "Stormcaller's Relief", - Bonuses: map[int32]core.ApplyEffect{ - // Your Riptide increases the amount healed by Chain Heal by an additional 25%. - 2: func(agent core.Agent) { - }, - // Reduces the cast time of Chain Heal by 0.5 sec. - 4: func(agent core.Agent) { - }, - }, -}) - -var ItemSetStormcallersImpact = core.NewItemSet(core.ItemSet{ - Name: "Stormcaller's Impact", - Bonuses: map[int32]core.ApplyEffect{ - // Increases Stormstrike and Lava Lash damage by 50%. - 2: func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - shaman.RegisterAura(core.Aura{ - Label: "S03 - Item - TAQ - Shaman - Enhancement 2P Bonus", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - if shaman.StormstrikeMH != nil { - shaman.StormstrikeMH.DamageMultiplier *= 1.50 - } - - if shaman.StormstrikeOH != nil { - shaman.StormstrikeOH.DamageMultiplier *= 1.50 - } - - if shaman.LavaLash != nil { - shaman.LavaLash.DamageMultiplier *= 1.50 - } - }, - }) - }, - // Your Stormstrike and Lava Lash critical strikes cause your target to burn for 30% of the damage done over 4 sec. - 4: func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - - // This is the spell used for the burn proc. - // https://www.wowhead.com/classic/spell=1213915/burning - burnSpell := shaman.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 1213915}, - SpellSchool: core.SpellSchoolFire, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskEmpty, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagPassiveSpell, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - BonusCoefficient: 1, - - Dot: core.DotConfig{ - Aura: core.Aura{ - Label: "Burning", - }, - NumberOfTicks: 2, - TickLength: time.Second * 2, - 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) { - spell.Dot(target).ApplyOrRefresh(sim) - spell.CalcAndDealOutcome(sim, target, spell.OutcomeAlwaysHitNoHitCounter) - }, - }) - - core.MakePermanent(shaman.RegisterAura(core.Aura{ - Label: "S03 - Item - TAQ - Shaman - Enhancement 4P Bonus", - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if !result.Outcome.Matches(core.OutcomeCrit) || !(spell == shaman.StormstrikeMH || spell == shaman.LavaLash) { - return - } - - dot := burnSpell.Dot(result.Target) - dotDamage := result.Damage * 0.3 - if dot.IsActive() { - dotDamage += dot.SnapshotBaseDamage * float64(dot.MaxTicksRemaining()) - } - dot.SnapshotBaseDamage = dotDamage / float64(dot.NumberOfTicks) - dot.SnapshotAttackerMultiplier = 1 - - burnSpell.Cast(sim, result.Target) - }, - })) - }, - }, -}) - -var ItemSetGiftOfTheGatheringStorm = core.NewItemSet(core.ItemSet{ - Name: "Gift of the Gathering Storm", - Bonuses: map[int32]core.ApplyEffect{ - // Your Lava Burst deals increased damage equal to its critical strike chance. - 3: func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - shaman.RegisterAura(core.Aura{ - Label: "S03 - Item - RAQ - Shaman - Elemental 3P Bonus", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - shaman.useLavaBurstCritScaling = true - }, - }) - }, - }, -}) diff --git a/sim/shaman/_item_sets_pvp.go b/sim/shaman/_item_sets_pvp.go deleted file mode 100644 index 01b78f6ee6..0000000000 --- a/sim/shaman/_item_sets_pvp.go +++ /dev/null @@ -1,256 +0,0 @@ -package shaman - -import ( - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/stats" -) - -/////////////////////////////////////////////////////////////////////////// -// SoD Phase 3 Item Sets -/////////////////////////////////////////////////////////////////////////// - -var ItemSetBloodGuardsMail = core.NewItemSet(core.ItemSet{ - Name: "Blood Guard's Mail", - 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) - }, - }, -}) - -var ItemSetBloodGuardsInscribedMail = core.NewItemSet(core.ItemSet{ - Name: "Blood Guard's Inscribed Mail", - 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 ItemSetBloodGuardsPulsingMail = core.NewItemSet(core.ItemSet{ - Name: "Blood Guard's Pulsing Mail", - 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) - }, - }, -}) - -/////////////////////////////////////////////////////////////////////////// -// SoD Phase 4 Item Sets -/////////////////////////////////////////////////////////////////////////// - -var ItemSetChampionsWartide = core.NewItemSet(core.ItemSet{ - Name: "Champion's Wartide", - Bonuses: map[int32]core.ApplyEffect{ - // Increases healing done by spells and effects by up to 44. - 2: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.HealingPower, 44) - }, - // Improves your chance to get a critical strike with all Shock spells by 2%. - 4: func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - shaman.GetOrRegisterAura(core.Aura{ - Label: "Shaman Shock Crit Bonus", - ActionID: core.ActionID{SpellID: 22804}, - OnInit: func(aura *core.Aura, sim *core.Simulation) { - for _, spell := range core.Flatten([][]*core.Spell{shaman.EarthShock, shaman.FlameShock, shaman.FrostShock}) { - if spell != nil { - spell.BonusCritRating += 2 * core.CritRatingPerCritChance - } - } - }, - }) - }, - // +20 Stamina. - 6: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.Stamina, 20) - }, - }, -}) - -var ItemSetChampionsThunderfist = core.NewItemSet(core.ItemSet{ - Name: "Champion's Thunderfist", - 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) - }, - // Improves your chance to get a critical strike with all Shock spells by 2%. - 4: func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - shaman.GetOrRegisterAura(core.Aura{ - Label: "Shaman Shock Crit Bonus", - ActionID: core.ActionID{SpellID: 22804}, - OnInit: func(aura *core.Aura, sim *core.Simulation) { - for _, spell := range core.Flatten([][]*core.Spell{shaman.EarthShock, shaman.FlameShock, shaman.FrostShock}) { - if spell != nil { - spell.BonusCritRating += 2 * core.CritRatingPerCritChance - } - } - }, - }) - }, - // +20 Stamina. - 6: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.Stamina, 20) - }, - }, -}) - -var ItemSetChampionsEarthshaker = core.NewItemSet(core.ItemSet{ - Name: "Champion's Earthshaker", - Bonuses: map[int32]core.ApplyEffect{ - // +40 Attack Power. - 2: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStats(stats.Stats{ - stats.AttackPower: 40, - stats.RangedAttackPower: 40, - }) - }, - // Improves your chance to get a critical strike with all Shock spells by 2%. - 4: func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - shaman.GetOrRegisterAura(core.Aura{ - Label: "Shaman Shock Crit Bonus", - ActionID: core.ActionID{SpellID: 22804}, - OnInit: func(aura *core.Aura, sim *core.Simulation) { - for _, spell := range core.Flatten([][]*core.Spell{shaman.EarthShock, shaman.FlameShock, shaman.FrostShock}) { - if spell != nil { - spell.BonusCritRating += 2 * core.CritRatingPerCritChance - } - } - }, - }) - }, - // +20 Stamina. - 6: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.Stamina, 20) - }, - }, -}) - -/////////////////////////////////////////////////////////////////////////// -// SoD Phase 3 Item Sets -/////////////////////////////////////////////////////////////////////////// - -var ItemSetWarlordsWartide = core.NewItemSet(core.ItemSet{ - Name: "Warlord's Wartide", - Bonuses: map[int32]core.ApplyEffect{ - // +20 Stamina. - 2: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.Stamina, 20) - }, - // Improves your chance to get a critical strike with all Shock spells by 2%. - 4: func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - shaman.GetOrRegisterAura(core.Aura{ - Label: "Shaman Shock Crit Bonus", - ActionID: core.ActionID{SpellID: 22804}, - OnInit: func(aura *core.Aura, sim *core.Simulation) { - for _, spell := range core.Flatten([][]*core.Spell{shaman.EarthShock, shaman.FlameShock, shaman.FrostShock}) { - if spell != nil { - spell.BonusCritRating += 2 * core.CritRatingPerCritChance - } - } - }, - }) - }, - // Increases healing done by spells and effects by up to 44. - // Increases healing done by up to 44 and damage done by up to 15 for all magical spells and effects. - 6: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStats(stats.Stats{ - stats.HealingPower: 88, - stats.SpellDamage: 15, - }) - }, - }, -}) - -var ItemSetWarlordsThunderfist = core.NewItemSet(core.ItemSet{ - Name: "Warlord's Thunderfist", - Bonuses: map[int32]core.ApplyEffect{ - // +20 Stamina. - 2: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.Stamina, 20) - }, - // Improves your chance to get a critical strike with all Shock spells by 2%. - 4: func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - shaman.GetOrRegisterAura(core.Aura{ - Label: "Shaman Shock Crit Bonus", - ActionID: core.ActionID{SpellID: 22804}, - OnInit: func(aura *core.Aura, sim *core.Simulation) { - for _, spell := range core.Flatten([][]*core.Spell{shaman.EarthShock, shaman.FlameShock, shaman.FrostShock}) { - if spell != nil { - spell.BonusCritRating += 2 * core.CritRatingPerCritChance - } - } - }, - }) - }, - // 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) - }, - }, -}) - -var ItemSetWarlordsEarthshaker = core.NewItemSet(core.ItemSet{ - Name: "Warlord's Earthshaker", - Bonuses: map[int32]core.ApplyEffect{ - // +20 Stamina. - 2: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.Stamina, 20) - }, - // Improves your chance to get a critical strike with all Shock spells by 2%. - 4: func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - shaman.GetOrRegisterAura(core.Aura{ - Label: "Shaman Shock Crit Bonus", - ActionID: core.ActionID{SpellID: 22804}, - OnInit: func(aura *core.Aura, sim *core.Simulation) { - for _, spell := range core.Flatten([][]*core.Spell{shaman.EarthShock, shaman.FlameShock, shaman.FrostShock}) { - if spell != nil { - spell.BonusCritRating += 2 * core.CritRatingPerCritChance - } - } - }, - }) - }, - // +40 Attack Power. - 6: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStats(stats.Stats{ - stats.AttackPower: 40, - stats.RangedAttackPower: 40, - }) - }, - }, -}) diff --git a/sim/shaman/chain_heal.go b/sim/shaman/chain_heal.go deleted file mode 100644 index 394235fbc0..0000000000 --- a/sim/shaman/chain_heal.go +++ /dev/null @@ -1,86 +0,0 @@ -package shaman - -import ( - "time" - - "github.com/wowsims/classic/sim/core" -) - -const ChainHealRanks = 3 -const ChainHealTargetCount = int32(3) - -var ChainHealSpellId = [ChainHealRanks + 1]int32{0, 1064, 10622, 10623} -var ChainHealBaseHealing = [ChainHealRanks + 1][]float64{{0}, {332, 381}, {416, 477}, {567, 646}} -var ChainHealSpellCoef = [ChainHealRanks + 1]float64{0, .714, .714, .714} -var ChainHealCastTime = [ChainHealRanks + 1]int32{0, 2500, 2500, 2500} -var ChainHealManaCost = [ChainHealRanks + 1]float64{0, 260, 315, 405} -var ChainHealLevel = [ChainHealRanks + 1]int{0, 40, 46, 54} - -func (shaman *Shaman) registerChainHealSpell() { - shaman.ChainHeal = make([]*core.Spell, ChainHealRanks+1) - - for rank := 1; rank <= ChainHealRanks; rank++ { - config := shaman.newChainHealSpellConfig(rank) - - if config.RequiredLevel <= int(shaman.Level) { - shaman.ChainHeal[rank] = shaman.RegisterSpell(config) - } - } -} - -func (shaman *Shaman) newChainHealSpellConfig(rank int) core.SpellConfig { - spellId := ChainHealSpellId[rank] - baseHealingMultiplier := 1 + shaman.purificationHealingModifier() - baseHealingLow := ChainHealBaseHealing[rank][0] * baseHealingMultiplier - baseHealingHigh := ChainHealBaseHealing[rank][1] * baseHealingMultiplier - spellCoeff := ChainHealSpellCoef[rank] - castTime := ChainHealCastTime[rank] - manaCost := ChainHealManaCost[rank] - level := ChainHealLevel[rank] - - bounceCoef := 0.50 // 50% reduction per bounce - targetCount := ChainHealTargetCount - - return core.SpellConfig{ - ActionID: core.ActionID{SpellID: spellId}, - SpellCode: SpellCode_ShamanChainHeal, - DefenseType: core.DefenseTypeMagic, - SpellSchool: core.SpellSchoolNature, - ProcMask: core.ProcMaskSpellHealing, - Flags: core.SpellFlagHelpful | core.SpellFlagAPL | SpellFlagShaman, - - RequiredLevel: level, - Rank: rank, - - ManaCost: core.ManaCostOptions{ - FlatCost: manaCost, - }, - - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - CastTime: time.Millisecond * time.Duration(castTime), - }, - }, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - BonusCoefficient: spellCoeff, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - targets := sim.Environment.Raid.GetFirstNPlayersOrPets(targetCount) - curTarget := targets[0] - origMult := spell.DamageMultiplier - // TODO: This bounces to most hurt friendly... - for hitIndex := 0; hitIndex < len(targets); hitIndex++ { - originalDamageMultiplier := spell.DamageMultiplier - spell.CalcAndDealHealing(sim, curTarget, sim.Roll(baseHealingLow, baseHealingHigh), spell.OutcomeHealingCrit) - spell.DamageMultiplier = originalDamageMultiplier - spell.DamageMultiplier *= bounceCoef - - curTarget = targets[hitIndex] - } - spell.DamageMultiplier = origMult - }, - } -} diff --git a/sim/shaman/chain_lightning.go b/sim/shaman/chain_lightning.go index 4b6e4ae81f..fe721d361b 100644 --- a/sim/shaman/chain_lightning.go +++ b/sim/shaman/chain_lightning.go @@ -40,7 +40,7 @@ func (shaman *Shaman) newChainLightningSpellConfig(rank int, cdTimer *core.Timer cooldown := time.Second * 6 castTime := time.Millisecond * 2500 - bounceCoef := .7 // 30% reduction per bounce + shaman.ChainLightningBounceCoefficient = .70 // 30% reduction per bounce targetCount := ChainLightningTargetCount spell := shaman.newElectricSpellConfig( @@ -66,7 +66,7 @@ func (shaman *Shaman) newChainLightningSpellConfig(rank int, cdTimer *core.Timer baseDamage := sim.Roll(baseDamageLow, baseDamageHigh) results[hitIndex] = spell.CalcDamage(sim, target, baseDamage, spell.OutcomeMagicHitAndCrit) target = sim.Environment.NextTargetUnit(target) - spell.DamageMultiplier *= bounceCoef + spell.DamageMultiplier *= shaman.ChainLightningBounceCoefficient } for _, result := range results { diff --git a/sim/shaman/elemental/TestElemental.results b/sim/shaman/elemental/TestElemental.results index a788f08895..e666ea6ddc 100644 --- a/sim/shaman/elemental/TestElemental.results +++ b/sim/shaman/elemental/TestElemental.results @@ -1,70 +1,315 @@ character_stats_results: { - key: "TestElemental-Phase5-CharacterStats-Default" + key: "TestElemental-Phase1-CharacterStats-Default" value: { - final_stats: 215.05 - final_stats: 189.75 - final_stats: 331.9475 - final_stats: 181.7 - final_stats: 197.8 - final_stats: 150 + final_stats: 219.65 + final_stats: 194.35 + final_stats: 452.295 + final_stats: 317.4 + final_stats: 228.85 + final_stats: 518 final_stats: 0 final_stats: 40 final_stats: 0 final_stats: 0 + final_stats: 61 + final_stats: 0 + final_stats: 54.25 + final_stats: 5 + final_stats: 32.66406 final_stats: 0 final_stats: 0 - final_stats: 41.25 + final_stats: 1220.3 + final_stats: 3 + final_stats: 24.57298 + final_stats: 0 + final_stats: 0 + final_stats: 0 + final_stats: 6001 + final_stats: 0 + final_stats: 0 + final_stats: 1815.7 + final_stats: 440 + final_stats: 0 + final_stats: 5 + final_stats: 0 + final_stats: 11.57298 + final_stats: 5 + final_stats: 0 + final_stats: 6065.95 + final_stats: 33 + final_stats: 91 + final_stats: 66 + final_stats: 60 + final_stats: 60 + final_stats: 384 + final_stats: 0 + final_stats: 65 + final_stats: 0 + } +} +character_stats_results: { + key: "TestElemental-Phase2-CharacterStats-Default" + value: { + final_stats: 219.65 + final_stats: 194.35 + final_stats: 448.3275 + final_stats: 305.9 + final_stats: 236.9 + final_stats: 587 + final_stats: 0 + final_stats: 40 + final_stats: 0 + final_stats: 0 + final_stats: 40 + final_stats: 0 + final_stats: 50.25 + final_stats: 5 + final_stats: 33.46971 + final_stats: 0 + final_stats: 0 + final_stats: 1220.3 + final_stats: 3 + final_stats: 24.57298 + final_stats: 0 + final_stats: 0 + final_stats: 0 + final_stats: 5828.5 + final_stats: 0 + final_stats: 0 + final_stats: 1716.7 + final_stats: 440 + final_stats: 0 + final_stats: 5 + final_stats: 0 + final_stats: 11.57298 + final_stats: 5 + final_stats: 0 + final_stats: 6026.275 + final_stats: 27 + final_stats: 81 + final_stats: 60 + final_stats: 60 + final_stats: 60 + final_stats: 384 + final_stats: 0 + final_stats: 65 + final_stats: 0 + } +} +character_stats_results: { + key: "TestElemental-Phase3-CharacterStats-Default" + value: { + final_stats: 219.65 + final_stats: 194.35 + final_stats: 494.615 + final_stats: 378.35 + final_stats: 271.4 + final_stats: 636 + final_stats: 0 + final_stats: 40 + final_stats: 0 + final_stats: 0 + final_stats: 40 + final_stats: 0 + final_stats: 51.25 + final_stats: 8 + final_stats: 35.69411 + final_stats: 0 + final_stats: 0 + final_stats: 1220.3 final_stats: 3 - final_stats: 26.37073 + final_stats: 24.57298 + final_stats: 0 + final_stats: 0 + final_stats: 0 + final_stats: 6915.25 + final_stats: 0 + final_stats: 0 + final_stats: 2100.7 + final_stats: 440 + final_stats: 0 + final_stats: 5 + final_stats: 0 + final_stats: 11.57298 + final_stats: 5 + final_stats: 0 + final_stats: 6489.15 + final_stats: 37 + final_stats: 75 + final_stats: 60 + final_stats: 60 + final_stats: 60 + final_stats: 384 final_stats: 0 + final_stats: 65 final_stats: 0 - final_stats: 1211.1 + } +} +character_stats_results: { + key: "TestElemental-Phase4-CharacterStats-Default" + value: { + final_stats: 219.65 + final_stats: 194.35 + final_stats: 457.585 + final_stats: 416.3 + final_stats: 241.5 + final_stats: 660 + final_stats: 0 + final_stats: 40 + final_stats: 0 + final_stats: 0 + final_stats: 40 + final_stats: 0 + final_stats: 46.25 + final_stats: 14 + final_stats: 32.33547 + final_stats: 0 + final_stats: 0 + final_stats: 1220.3 final_stats: 3 - final_stats: 24.3393 + final_stats: 24.57298 final_stats: 0 final_stats: 0 final_stats: 0 - final_stats: 3965.5 + final_stats: 7484.5 final_stats: 0 final_stats: 0 - final_stats: 763.5 + final_stats: 1736.7 final_stats: 440 final_stats: 0 final_stats: 5 final_stats: 0 - final_stats: 11.3393 + final_stats: 11.57298 final_stats: 5 final_stats: 0 - final_stats: 4862.475 + final_stats: 6118.85 final_stats: 27 + final_stats: 65 final_stats: 60 final_stats: 60 final_stats: 60 + final_stats: 384 + final_stats: 18 + final_stats: 65 + final_stats: 0 + } +} +character_stats_results: { + key: "TestElemental-Phase5-CharacterStats-Default" + value: { + final_stats: 219.65 + final_stats: 194.35 + final_stats: 560.74 + final_stats: 407.1 + final_stats: 239.2 + final_stats: 738 + final_stats: 0 + final_stats: 40 + final_stats: 0 + final_stats: 0 + final_stats: 40 + final_stats: 0 + final_stats: 41.25 + final_stats: 13 + final_stats: 37.17999 + final_stats: 0 + final_stats: 0 + final_stats: 1220.3 + final_stats: 3 + final_stats: 24.57298 + final_stats: 0 + final_stats: 0 + final_stats: 0 + final_stats: 7346.5 + final_stats: 0 + final_stats: 0 + final_stats: 1829.7 + final_stats: 440 + final_stats: 0 + final_stats: 5 + final_stats: 0 + final_stats: 11.57298 + final_stats: 5 + final_stats: 0 + final_stats: 7150.4 + final_stats: 27 + final_stats: 65 + final_stats: 60 final_stats: 60 + final_stats: 85 final_stats: 384 + final_stats: 18 + final_stats: 65 + final_stats: 0 + } +} +character_stats_results: { + key: "TestElemental-Phase6-CharacterStats-Default" + value: { + final_stats: 219.65 + final_stats: 194.35 + final_stats: 575.2875 + final_stats: 395.6 + final_stats: 212.75 + final_stats: 748 + final_stats: 0 + final_stats: 40 + final_stats: 0 + final_stats: 0 + final_stats: 0 + final_stats: 0 + final_stats: 46.25 + final_stats: 12 + final_stats: 40.98564 + final_stats: 0 + final_stats: 0 + final_stats: 1220.3 + final_stats: 3 + final_stats: 24.57298 + final_stats: 0 + final_stats: 0 + final_stats: 0 + final_stats: 7174 + final_stats: 0 + final_stats: 0 + final_stats: 1848.7 + final_stats: 440 + final_stats: 0 + final_stats: 5 final_stats: 0 - final_stats: 35 + final_stats: 11.57298 + final_stats: 5 + final_stats: 0 + final_stats: 7295.875 + final_stats: 27 + final_stats: 65 + final_stats: 60 + final_stats: 60 + final_stats: 85 + final_stats: 384 final_stats: 0 + final_stats: 65 + final_stats: 305 } } stat_weights_results: { - key: "TestElemental-Phase5-StatWeights-Default" + key: "TestElemental-Phase1-StatWeights-Default" value: { weights: 0 weights: 0 weights: 0 - weights: 0.28545 + weights: 0.3783 weights: 0 - weights: 0.34779 + weights: 0.61768 weights: 0 - weights: 0.06737 weights: 0 weights: 0 - weights: 0.28041 weights: 0 + weights: 0.61768 weights: 0 - weights: 3.68699 - weights: 1.69771 + weights: 0 + weights: 7.79114 + weights: 4.12646 weights: 0 weights: 0 weights: 0 @@ -96,101 +341,1214 @@ stat_weights_results: { weights: 0 } } -dps_results: { - key: "TestElemental-Phase5-Average-Default" - value: { - dps: 315.07058 - tps: 305.15394 - } -} -dps_results: { - key: "TestElemental-Phase5-Settings-Orc-blank-Adaptive-phase_5-FullBuffs-P5-Consumes-LongMultiTarget" - value: { - dps: 438.54113 - tps: 423.67921 - } -} -dps_results: { - key: "TestElemental-Phase5-Settings-Orc-blank-Adaptive-phase_5-FullBuffs-P5-Consumes-LongSingleTarget" - value: { - dps: 231.03268 - tps: 213.0393 - } -} -dps_results: { - key: "TestElemental-Phase5-Settings-Orc-blank-Adaptive-phase_5-FullBuffs-P5-Consumes-ShortSingleTarget" - value: { - dps: 411.24888 - tps: 403.27209 - } -} -dps_results: { - key: "TestElemental-Phase5-Settings-Orc-blank-Adaptive-phase_5-NoBuffs-P5-Consumes-LongMultiTarget" +stat_weights_results: { + key: "TestElemental-Phase2-StatWeights-Default" value: { - dps: 251.27196 - tps: 266.58356 + weights: 0 + weights: 0 + weights: 0 + weights: 0.25437 + weights: 0 + weights: 0.6207 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0.6207 + weights: 0 + weights: 0 + weights: 8.21241 + weights: 4.22423 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 } } -dps_results: { - key: "TestElemental-Phase5-Settings-Orc-blank-Adaptive-phase_5-NoBuffs-P5-Consumes-LongSingleTarget" +stat_weights_results: { + key: "TestElemental-Phase3-StatWeights-Default" value: { - dps: 117.28075 - tps: 106.78686 + weights: 0 + weights: 0 + weights: 0 + weights: 0.29286 + weights: 0 + weights: 0.66009 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0.66009 + weights: 0 + weights: 0 + weights: 7.95565 + weights: 4.7165 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 } } -dps_results: { - key: "TestElemental-Phase5-Settings-Orc-blank-Adaptive-phase_5-NoBuffs-P5-Consumes-ShortSingleTarget" +stat_weights_results: { + key: "TestElemental-Phase4-StatWeights-Default" value: { - dps: 211.38078 - tps: 207.61972 - } -} -dps_results: { - key: "TestElemental-Phase5-Settings-Troll-blank-Adaptive-phase_5-FullBuffs-P5-Consumes-LongMultiTarget" + weights: 0 + weights: 0 + weights: 0 + weights: 0.17493 + weights: 0 + weights: 0.68942 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0.68942 + weights: 0 + weights: 0 + weights: 8.38606 + weights: 5.16538 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + } +} +stat_weights_results: { + key: "TestElemental-Phase5-StatWeights-Default" + value: { + weights: 0 + weights: 0 + weights: 0 + weights: 0.18623 + weights: 0 + weights: 0.70254 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0.70254 + weights: 0 + weights: 0 + weights: 9.86423 + weights: 5.58504 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + } +} +stat_weights_results: { + key: "TestElemental-Phase6-StatWeights-Default" + value: { + weights: 0 + weights: 0 + weights: 0 + weights: 0.28177 + weights: 0 + weights: 0.71336 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0.71336 + weights: 0 + weights: 0 + weights: 9.55979 + weights: 6.2511 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + weights: 0 + } +} +dps_results: { + key: "TestElemental-Phase1-AllItems-Champion'sEarthshaker" + value: { + dps: 545.71933 + tps: 567.03928 + } +} +dps_results: { + key: "TestElemental-Phase1-AllItems-Champion'sStormcaller" + value: { + dps: 552.48697 + tps: 573.80692 + } +} +dps_results: { + key: "TestElemental-Phase1-AllItems-GiftoftheGatheringStorm" + value: { + dps: 618.63401 + tps: 640.02394 + } +} +dps_results: { + key: "TestElemental-Phase1-AllItems-Stormcaller'sGarb" + value: { + dps: 647.10915 + tps: 668.42727 + } +} +dps_results: { + key: "TestElemental-Phase1-AllItems-TheEarthfury" + value: { + dps: 518.75319 + tps: 540.06826 + } +} +dps_results: { + key: "TestElemental-Phase1-AllItems-TheEarthshatterer" + value: { + dps: 509.6622 + tps: 530.83488 + } +} +dps_results: { + key: "TestElemental-Phase1-AllItems-TheFiveThunders" + value: { + dps: 556.81608 + tps: 578.13302 + } +} +dps_results: { + key: "TestElemental-Phase1-AllItems-TheTenStorms" + value: { + dps: 569.53537 + tps: 590.8517 + } +} +dps_results: { + key: "TestElemental-Phase1-AllItems-Warlord'sEarthshaker" + value: { + dps: 577.22226 + tps: 598.54171 + } +} +dps_results: { + key: "TestElemental-Phase1-Average-Default" + value: { + dps: 636.79753 + tps: 658.34661 + } +} +dps_results: { + key: "TestElemental-Phase1-Settings-Orc-phase_1-Adaptive-default-FullBuffs-P1-Consumes-LongMultiTarget" + value: { + dps: 720.55777 + tps: 1138.66668 + } +} +dps_results: { + key: "TestElemental-Phase1-Settings-Orc-phase_1-Adaptive-default-FullBuffs-P1-Consumes-LongSingleTarget" + value: { + dps: 607.82469 + tps: 628.8105 + } +} +dps_results: { + key: "TestElemental-Phase1-Settings-Orc-phase_1-Adaptive-default-FullBuffs-P1-Consumes-ShortSingleTarget" + value: { + dps: 702.99968 + tps: 734.24858 + } +} +dps_results: { + key: "TestElemental-Phase1-Settings-Orc-phase_1-Adaptive-default-NoBuffs-P1-Consumes-LongMultiTarget" + value: { + dps: 399.0541 + tps: 694.93469 + } +} +dps_results: { + key: "TestElemental-Phase1-Settings-Orc-phase_1-Adaptive-default-NoBuffs-P1-Consumes-LongSingleTarget" + value: { + dps: 358.93761 + tps: 373.73164 + } +} +dps_results: { + key: "TestElemental-Phase1-Settings-Orc-phase_1-Adaptive-default-NoBuffs-P1-Consumes-ShortSingleTarget" + value: { + dps: 536.71355 + tps: 561.86579 + } +} +dps_results: { + key: "TestElemental-Phase1-Settings-Troll-phase_1-Adaptive-default-FullBuffs-P1-Consumes-LongMultiTarget" + value: { + dps: 722.08902 + tps: 1141.0896 + } +} +dps_results: { + key: "TestElemental-Phase1-Settings-Troll-phase_1-Adaptive-default-FullBuffs-P1-Consumes-LongSingleTarget" + value: { + dps: 617.66009 + tps: 638.95921 + } +} +dps_results: { + key: "TestElemental-Phase1-Settings-Troll-phase_1-Adaptive-default-FullBuffs-P1-Consumes-ShortSingleTarget" + value: { + dps: 734.23666 + tps: 765.78224 + } +} +dps_results: { + key: "TestElemental-Phase1-Settings-Troll-phase_1-Adaptive-default-NoBuffs-P1-Consumes-LongMultiTarget" + value: { + dps: 393.14296 + tps: 689.02354 + } +} +dps_results: { + key: "TestElemental-Phase1-Settings-Troll-phase_1-Adaptive-default-NoBuffs-P1-Consumes-LongSingleTarget" + value: { + dps: 360.84458 + tps: 375.63861 + } +} +dps_results: { + key: "TestElemental-Phase1-Settings-Troll-phase_1-Adaptive-default-NoBuffs-P1-Consumes-ShortSingleTarget" + value: { + dps: 559.89369 + tps: 585.04594 + } +} +dps_results: { + key: "TestElemental-Phase1-SwitchInFrontOfTarget-Default" + value: { + dps: 633.22455 + tps: 654.61825 + } +} +dps_results: { + key: "TestElemental-Phase2-AllItems-Champion'sEarthshaker" + value: { + dps: 558.79695 + tps: 580.11458 + } +} +dps_results: { + key: "TestElemental-Phase2-AllItems-Champion'sStormcaller" + value: { + dps: 565.66136 + tps: 586.979 + } +} +dps_results: { + key: "TestElemental-Phase2-AllItems-GiftoftheGatheringStorm" + value: { + dps: 635.25513 + tps: 656.64615 + } +} +dps_results: { + key: "TestElemental-Phase2-AllItems-Stormcaller'sGarb" + value: { + dps: 660.6588 + tps: 681.97856 + } +} +dps_results: { + key: "TestElemental-Phase2-AllItems-TheEarthfury" + value: { + dps: 528.4875 + tps: 549.8045 + } +} +dps_results: { + key: "TestElemental-Phase2-AllItems-TheEarthshatterer" + value: { + dps: 522.28475 + tps: 543.45341 + } +} +dps_results: { + key: "TestElemental-Phase2-AllItems-TheFiveThunders" + value: { + dps: 568.97759 + tps: 590.29725 + } +} +dps_results: { + key: "TestElemental-Phase2-AllItems-TheTenStorms" + value: { + dps: 581.89073 + tps: 603.21039 + } +} +dps_results: { + key: "TestElemental-Phase2-AllItems-Warlord'sEarthshaker" + value: { + dps: 590.11107 + tps: 611.43142 + } +} +dps_results: { + key: "TestElemental-Phase2-Average-Default" + value: { + dps: 666.2129 + tps: 687.76255 + } +} +dps_results: { + key: "TestElemental-Phase2-Settings-Orc-phase_2-Adaptive-default-FullBuffs-P2-Consumes-LongMultiTarget" + value: { + dps: 751.21114 + tps: 1169.71339 + } +} +dps_results: { + key: "TestElemental-Phase2-Settings-Orc-phase_2-Adaptive-default-FullBuffs-P2-Consumes-LongSingleTarget" + value: { + dps: 636.92388 + tps: 657.9097 + } +} +dps_results: { + key: "TestElemental-Phase2-Settings-Orc-phase_2-Adaptive-default-FullBuffs-P2-Consumes-ShortSingleTarget" + value: { + dps: 734.92604 + tps: 766.17495 + } +} +dps_results: { + key: "TestElemental-Phase2-Settings-Orc-phase_2-Adaptive-default-NoBuffs-P2-Consumes-LongMultiTarget" + value: { + dps: 418.22805 + tps: 714.10863 + } +} +dps_results: { + key: "TestElemental-Phase2-Settings-Orc-phase_2-Adaptive-default-NoBuffs-P2-Consumes-LongSingleTarget" + value: { + dps: 373.73606 + tps: 388.53009 + } +} +dps_results: { + key: "TestElemental-Phase2-Settings-Orc-phase_2-Adaptive-default-NoBuffs-P2-Consumes-ShortSingleTarget" + value: { + dps: 559.55413 + tps: 584.70637 + } +} +dps_results: { + key: "TestElemental-Phase2-Settings-Troll-phase_2-Adaptive-default-FullBuffs-P2-Consumes-LongMultiTarget" + value: { + dps: 752.41739 + tps: 1171.35443 + } +} +dps_results: { + key: "TestElemental-Phase2-Settings-Troll-phase_2-Adaptive-default-FullBuffs-P2-Consumes-LongSingleTarget" + value: { + dps: 647.76852 + tps: 669.06789 + } +} +dps_results: { + key: "TestElemental-Phase2-Settings-Troll-phase_2-Adaptive-default-FullBuffs-P2-Consumes-ShortSingleTarget" + value: { + dps: 767.43304 + tps: 798.97995 + } +} +dps_results: { + key: "TestElemental-Phase2-Settings-Troll-phase_2-Adaptive-default-NoBuffs-P2-Consumes-LongMultiTarget" + value: { + dps: 408.4279 + tps: 704.30849 + } +} +dps_results: { + key: "TestElemental-Phase2-Settings-Troll-phase_2-Adaptive-default-NoBuffs-P2-Consumes-LongSingleTarget" + value: { + dps: 376.24244 + tps: 391.03647 + } +} +dps_results: { + key: "TestElemental-Phase2-Settings-Troll-phase_2-Adaptive-default-NoBuffs-P2-Consumes-ShortSingleTarget" + value: { + dps: 582.71817 + tps: 607.87041 + } +} +dps_results: { + key: "TestElemental-Phase2-SwitchInFrontOfTarget-Default" + value: { + dps: 663.36368 + tps: 684.75778 + } +} +dps_results: { + key: "TestElemental-Phase3-AllItems-Champion'sEarthshaker" + value: { + dps: 608.59939 + tps: 630.27906 + } +} +dps_results: { + key: "TestElemental-Phase3-AllItems-Champion'sStormcaller" + value: { + dps: 615.13038 + tps: 636.81005 + } +} +dps_results: { + key: "TestElemental-Phase3-AllItems-GiftoftheGatheringStorm" + value: { + dps: 660.2386 + tps: 681.91777 + } +} +dps_results: { + key: "TestElemental-Phase3-AllItems-Stormcaller'sGarb" + value: { + dps: 717.52069 + tps: 739.19872 + } +} +dps_results: { + key: "TestElemental-Phase3-AllItems-TheEarthfury" + value: { + dps: 564.58686 + tps: 586.14212 + } +} +dps_results: { + key: "TestElemental-Phase3-AllItems-TheEarthshatterer" + value: { + dps: 559.45309 + tps: 580.86307 + } +} +dps_results: { + key: "TestElemental-Phase3-AllItems-TheFiveThunders" + value: { + dps: 605.03167 + tps: 626.58773 + } +} +dps_results: { + key: "TestElemental-Phase3-AllItems-TheTenStorms" + value: { + dps: 619.94229 + tps: 641.49834 + } +} +dps_results: { + key: "TestElemental-Phase3-AllItems-Warlord'sEarthshaker" + value: { + dps: 642.66328 + tps: 664.34245 + } +} +dps_results: { + key: "TestElemental-Phase3-Average-Default" + value: { + dps: 727.67718 + tps: 749.46031 + } +} +dps_results: { + key: "TestElemental-Phase3-Settings-Orc-phase_3-Adaptive-default-FullBuffs-P2-Consumes-LongMultiTarget" + value: { + dps: 832.06097 + tps: 1257.34822 + } +} +dps_results: { + key: "TestElemental-Phase3-Settings-Orc-phase_3-Adaptive-default-FullBuffs-P2-Consumes-LongSingleTarget" + value: { + dps: 693.51119 + tps: 714.89847 + } +} +dps_results: { + key: "TestElemental-Phase3-Settings-Orc-phase_3-Adaptive-default-FullBuffs-P2-Consumes-ShortSingleTarget" + value: { + dps: 832.74241 + tps: 864.21257 + } +} +dps_results: { + key: "TestElemental-Phase3-Settings-Orc-phase_3-Adaptive-default-NoBuffs-P2-Consumes-LongMultiTarget" + value: { + dps: 466.63544 + tps: 762.51602 + } +} +dps_results: { + key: "TestElemental-Phase3-Settings-Orc-phase_3-Adaptive-default-NoBuffs-P2-Consumes-LongSingleTarget" + value: { + dps: 426.08484 + tps: 440.87887 + } +} +dps_results: { + key: "TestElemental-Phase3-Settings-Orc-phase_3-Adaptive-default-NoBuffs-P2-Consumes-ShortSingleTarget" + value: { + dps: 633.30525 + tps: 658.45749 + } +} +dps_results: { + key: "TestElemental-Phase3-Settings-Troll-phase_3-Adaptive-default-FullBuffs-P2-Consumes-LongMultiTarget" + value: { + dps: 829.58351 + tps: 1255.86476 + } +} +dps_results: { + key: "TestElemental-Phase3-Settings-Troll-phase_3-Adaptive-default-FullBuffs-P2-Consumes-LongSingleTarget" + value: { + dps: 705.86168 + tps: 727.42559 + } +} +dps_results: { + key: "TestElemental-Phase3-Settings-Troll-phase_3-Adaptive-default-FullBuffs-P2-Consumes-ShortSingleTarget" + value: { + dps: 866.93868 + tps: 898.77575 + } +} +dps_results: { + key: "TestElemental-Phase3-Settings-Troll-phase_3-Adaptive-default-NoBuffs-P2-Consumes-LongMultiTarget" + value: { + dps: 455.03168 + tps: 750.91226 + } +} +dps_results: { + key: "TestElemental-Phase3-Settings-Troll-phase_3-Adaptive-default-NoBuffs-P2-Consumes-LongSingleTarget" + value: { + dps: 429.94482 + tps: 444.73885 + } +} +dps_results: { + key: "TestElemental-Phase3-Settings-Troll-phase_3-Adaptive-default-NoBuffs-P2-Consumes-ShortSingleTarget" + value: { + dps: 659.82435 + tps: 684.97659 + } +} +dps_results: { + key: "TestElemental-Phase3-SwitchInFrontOfTarget-Default" + value: { + dps: 722.65774 + tps: 744.33692 + } +} +dps_results: { + key: "TestElemental-Phase4-AllItems-Champion'sEarthshaker" + value: { + dps: 615.4778 + tps: 637.23122 + } +} +dps_results: { + key: "TestElemental-Phase4-AllItems-Champion'sStormcaller" + value: { + dps: 621.46598 + tps: 643.2194 + } +} +dps_results: { + key: "TestElemental-Phase4-AllItems-GiftoftheGatheringStorm" + value: { + dps: 702.40562 + tps: 724.45896 + } +} +dps_results: { + key: "TestElemental-Phase4-AllItems-Stormcaller'sGarb" + value: { + dps: 725.49397 + tps: 747.29546 + } +} +dps_results: { + key: "TestElemental-Phase4-AllItems-TheEarthfury" + value: { + dps: 574.18908 + tps: 595.86725 + } +} +dps_results: { + key: "TestElemental-Phase4-AllItems-TheEarthshatterer" + value: { + dps: 567.30375 + tps: 588.83664 + } +} +dps_results: { + key: "TestElemental-Phase4-AllItems-TheFiveThunders" + value: { + dps: 615.26846 + tps: 636.94743 + } +} +dps_results: { + key: "TestElemental-Phase4-AllItems-TheTenStorms" + value: { + dps: 629.83497 + tps: 651.51394 + } +} +dps_results: { + key: "TestElemental-Phase4-AllItems-Warlord'sEarthshaker" + value: { + dps: 648.10727 + tps: 669.86019 + } +} +dps_results: { + key: "TestElemental-Phase4-Average-Default" + value: { + dps: 776.72722 + tps: 798.95101 + } +} +dps_results: { + key: "TestElemental-Phase4-Settings-Orc-phase_4-Adaptive-default-FullBuffs-P2-Consumes-LongMultiTarget" + value: { + dps: 895.04459 + tps: 1330.65683 + } +} +dps_results: { + key: "TestElemental-Phase4-Settings-Orc-phase_4-Adaptive-default-FullBuffs-P2-Consumes-LongSingleTarget" + value: { + dps: 740.1213 + tps: 761.97075 + } +} +dps_results: { + key: "TestElemental-Phase4-Settings-Orc-phase_4-Adaptive-default-FullBuffs-P2-Consumes-ShortSingleTarget" + value: { + dps: 882.82585 + tps: 914.64018 + } +} +dps_results: { + key: "TestElemental-Phase4-Settings-Orc-phase_4-Adaptive-default-NoBuffs-P2-Consumes-LongMultiTarget" + value: { + dps: 491.13505 + tps: 787.01563 + } +} +dps_results: { + key: "TestElemental-Phase4-Settings-Orc-phase_4-Adaptive-default-NoBuffs-P2-Consumes-LongSingleTarget" + value: { + dps: 457.06676 + tps: 471.86079 + } +} +dps_results: { + key: "TestElemental-Phase4-Settings-Orc-phase_4-Adaptive-default-NoBuffs-P2-Consumes-ShortSingleTarget" + value: { + dps: 670.5592 + tps: 695.71144 + } +} +dps_results: { + key: "TestElemental-Phase4-Settings-Troll-phase_4-Adaptive-default-FullBuffs-P2-Consumes-LongMultiTarget" + value: { + dps: 888.83634 + tps: 1323.67926 + } +} +dps_results: { + key: "TestElemental-Phase4-Settings-Troll-phase_4-Adaptive-default-FullBuffs-P2-Consumes-LongSingleTarget" + value: { + dps: 753.62589 + tps: 775.66304 + } +} +dps_results: { + key: "TestElemental-Phase4-Settings-Troll-phase_4-Adaptive-default-FullBuffs-P2-Consumes-ShortSingleTarget" + value: { + dps: 918.94991 + tps: 951.21107 + } +} +dps_results: { + key: "TestElemental-Phase4-Settings-Troll-phase_4-Adaptive-default-NoBuffs-P2-Consumes-LongMultiTarget" + value: { + dps: 486.53498 + tps: 782.41556 + } +} +dps_results: { + key: "TestElemental-Phase4-Settings-Troll-phase_4-Adaptive-default-NoBuffs-P2-Consumes-LongSingleTarget" + value: { + dps: 461.39287 + tps: 476.1869 + } +} +dps_results: { + key: "TestElemental-Phase4-Settings-Troll-phase_4-Adaptive-default-NoBuffs-P2-Consumes-ShortSingleTarget" + value: { + dps: 700.63784 + tps: 725.79008 + } +} +dps_results: { + key: "TestElemental-Phase4-SwitchInFrontOfTarget-Default" + value: { + dps: 771.60037 + tps: 793.72746 + } +} +dps_results: { + key: "TestElemental-Phase5-AllItems-Champion'sEarthshaker" + value: { + dps: 653.95126 + tps: 675.75435 + } +} +dps_results: { + key: "TestElemental-Phase5-AllItems-Champion'sStormcaller" + value: { + dps: 662.51987 + tps: 684.32296 + } +} +dps_results: { + key: "TestElemental-Phase5-AllItems-GiftoftheGatheringStorm" + value: { + dps: 760.70322 + tps: 782.5948 + } +} +dps_results: { + key: "TestElemental-Phase5-AllItems-Stormcaller'sGarb" + value: { + dps: 787.18253 + tps: 809.07302 + } +} +dps_results: { + key: "TestElemental-Phase5-AllItems-TheEarthfury" + value: { + dps: 608.34709 + tps: 630.09901 + } +} +dps_results: { + key: "TestElemental-Phase5-AllItems-TheEarthshatterer" + value: { + dps: 602.43088 + tps: 623.96377 + } +} +dps_results: { + key: "TestElemental-Phase5-AllItems-TheFiveThunders" + value: { + dps: 650.05036 + tps: 671.80308 + } +} +dps_results: { + key: "TestElemental-Phase5-AllItems-TheTenStorms" + value: { + dps: 666.30778 + tps: 688.0605 + } +} +dps_results: { + key: "TestElemental-Phase5-AllItems-Warlord'sEarthshaker" + value: { + dps: 690.00182 + tps: 711.80441 + } +} +dps_results: { + key: "TestElemental-Phase5-Average-Default" + value: { + dps: 844.28557 + tps: 866.44078 + } +} +dps_results: { + key: "TestElemental-Phase5-Settings-Orc-phase_5-Adaptive-default-FullBuffs-P5-Consumes-LongMultiTarget" + value: { + dps: 950.35715 + tps: 1380.9544 + } +} +dps_results: { + key: "TestElemental-Phase5-Settings-Orc-phase_5-Adaptive-default-FullBuffs-P5-Consumes-LongSingleTarget" + value: { + dps: 803.10503 + tps: 824.88565 + } +} +dps_results: { + key: "TestElemental-Phase5-Settings-Orc-phase_5-Adaptive-default-FullBuffs-P5-Consumes-ShortSingleTarget" + value: { + dps: 949.0364 + tps: 980.77698 + } +} +dps_results: { + key: "TestElemental-Phase5-Settings-Orc-phase_5-Adaptive-default-NoBuffs-P5-Consumes-LongMultiTarget" + value: { + dps: 524.04464 + tps: 819.92523 + } +} +dps_results: { + key: "TestElemental-Phase5-Settings-Orc-phase_5-Adaptive-default-NoBuffs-P5-Consumes-LongSingleTarget" + value: { + dps: 493.29059 + tps: 508.08462 + } +} +dps_results: { + key: "TestElemental-Phase5-Settings-Orc-phase_5-Adaptive-default-NoBuffs-P5-Consumes-ShortSingleTarget" value: { - dps: 427.65433 - tps: 413.58194 + dps: 727.57401 + tps: 752.72625 } } dps_results: { - key: "TestElemental-Phase5-Settings-Troll-blank-Adaptive-phase_5-FullBuffs-P5-Consumes-LongSingleTarget" + key: "TestElemental-Phase5-Settings-Troll-phase_5-Adaptive-default-FullBuffs-P5-Consumes-LongMultiTarget" value: { - dps: 226.47569 - tps: 208.42126 + dps: 957.61323 + tps: 1389.61114 } } dps_results: { - key: "TestElemental-Phase5-Settings-Troll-blank-Adaptive-phase_5-FullBuffs-P5-Consumes-ShortSingleTarget" + key: "TestElemental-Phase5-Settings-Troll-phase_5-Adaptive-default-FullBuffs-P5-Consumes-LongSingleTarget" value: { - dps: 412.45881 - tps: 405.1777 + dps: 816.49066 + tps: 838.44947 } } dps_results: { - key: "TestElemental-Phase5-Settings-Troll-blank-Adaptive-phase_5-NoBuffs-P5-Consumes-LongMultiTarget" + key: "TestElemental-Phase5-Settings-Troll-phase_5-Adaptive-default-FullBuffs-P5-Consumes-ShortSingleTarget" value: { - dps: 242.22557 - tps: 264.41278 + dps: 988.32085 + tps: 1020.46076 } } dps_results: { - key: "TestElemental-Phase5-Settings-Troll-blank-Adaptive-phase_5-NoBuffs-P5-Consumes-LongSingleTarget" + key: "TestElemental-Phase5-Settings-Troll-phase_5-Adaptive-default-NoBuffs-P5-Consumes-LongMultiTarget" value: { - dps: 109.08185 - tps: 98.65562 + dps: 516.20786 + tps: 812.08844 } } dps_results: { - key: "TestElemental-Phase5-Settings-Troll-blank-Adaptive-phase_5-NoBuffs-P5-Consumes-ShortSingleTarget" + key: "TestElemental-Phase5-Settings-Troll-phase_5-Adaptive-default-NoBuffs-P5-Consumes-LongSingleTarget" value: { - dps: 204.43526 - tps: 201.00836 + dps: 496.28083 + tps: 511.07486 + } +} +dps_results: { + key: "TestElemental-Phase5-Settings-Troll-phase_5-Adaptive-default-NoBuffs-P5-Consumes-ShortSingleTarget" + value: { + dps: 759.47415 + tps: 784.62639 } } dps_results: { key: "TestElemental-Phase5-SwitchInFrontOfTarget-Default" value: { - dps: 312.30983 - tps: 302.89056 + dps: 836.14346 + tps: 858.19729 + } +} +dps_results: { + key: "TestElemental-Phase6-AllItems-Champion'sEarthshaker" + value: { + dps: 691.47254 + tps: 713.15221 + } +} +dps_results: { + key: "TestElemental-Phase6-AllItems-Champion'sStormcaller" + value: { + dps: 699.31045 + tps: 720.99012 + } +} +dps_results: { + key: "TestElemental-Phase6-AllItems-GiftoftheGatheringStorm" + value: { + dps: 789.40722 + tps: 811.21031 + } +} +dps_results: { + key: "TestElemental-Phase6-AllItems-Stormcaller'sGarb" + value: { + dps: 819.33223 + tps: 841.08456 + } +} +dps_results: { + key: "TestElemental-Phase6-AllItems-TheEarthfury" + value: { + dps: 640.85749 + tps: 662.41224 + } +} +dps_results: { + key: "TestElemental-Phase6-AllItems-TheEarthshatterer" + value: { + dps: 624.23721 + tps: 645.55818 + } +} +dps_results: { + key: "TestElemental-Phase6-AllItems-TheFiveThunders" + value: { + dps: 683.21006 + tps: 704.76561 + } +} +dps_results: { + key: "TestElemental-Phase6-AllItems-TheTenStorms" + value: { + dps: 701.07545 + tps: 722.631 + } +} +dps_results: { + key: "TestElemental-Phase6-AllItems-Warlord'sEarthshaker" + value: { + dps: 725.21926 + tps: 746.89843 + } +} +dps_results: { + key: "TestElemental-Phase6-Average-Default" + value: { + dps: 897.88204 + tps: 919.9585 + } +} +dps_results: { + key: "TestElemental-Phase6-Settings-Orc-phase_6-Adaptive-default-FullBuffs-P5-Consumes-LongMultiTarget" + value: { + dps: 1011.35064 + tps: 1441.84955 + } +} +dps_results: { + key: "TestElemental-Phase6-Settings-Orc-phase_6-Adaptive-default-FullBuffs-P5-Consumes-LongSingleTarget" + value: { + dps: 852.10026 + tps: 873.8022 + } +} +dps_results: { + key: "TestElemental-Phase6-Settings-Orc-phase_6-Adaptive-default-FullBuffs-P5-Consumes-ShortSingleTarget" + value: { + dps: 996.77493 + tps: 1028.44176 + } +} +dps_results: { + key: "TestElemental-Phase6-Settings-Orc-phase_6-Adaptive-default-NoBuffs-P5-Consumes-LongMultiTarget" + value: { + dps: 554.15321 + tps: 850.03379 + } +} +dps_results: { + key: "TestElemental-Phase6-Settings-Orc-phase_6-Adaptive-default-NoBuffs-P5-Consumes-LongSingleTarget" + value: { + dps: 527.00917 + tps: 541.8032 + } +} +dps_results: { + key: "TestElemental-Phase6-Settings-Orc-phase_6-Adaptive-default-NoBuffs-P5-Consumes-ShortSingleTarget" + value: { + dps: 765.75437 + tps: 790.90661 + } +} +dps_results: { + key: "TestElemental-Phase6-Settings-Troll-phase_6-Adaptive-default-FullBuffs-P5-Consumes-LongMultiTarget" + value: { + dps: 1013.23816 + tps: 1444.54108 + } +} +dps_results: { + key: "TestElemental-Phase6-Settings-Troll-phase_6-Adaptive-default-FullBuffs-P5-Consumes-LongSingleTarget" + value: { + dps: 869.03756 + tps: 890.90753 + } +} +dps_results: { + key: "TestElemental-Phase6-Settings-Troll-phase_6-Adaptive-default-FullBuffs-P5-Consumes-ShortSingleTarget" + value: { + dps: 1040.6457 + tps: 1072.71019 + } +} +dps_results: { + key: "TestElemental-Phase6-Settings-Troll-phase_6-Adaptive-default-NoBuffs-P5-Consumes-LongMultiTarget" + value: { + dps: 551.97699 + tps: 847.85757 + } +} +dps_results: { + key: "TestElemental-Phase6-Settings-Troll-phase_6-Adaptive-default-NoBuffs-P5-Consumes-LongSingleTarget" + value: { + dps: 527.6199 + tps: 542.41393 + } +} +dps_results: { + key: "TestElemental-Phase6-Settings-Troll-phase_6-Adaptive-default-NoBuffs-P5-Consumes-ShortSingleTarget" + value: { + dps: 799.98562 + tps: 825.13786 + } +} +dps_results: { + key: "TestElemental-Phase6-SwitchInFrontOfTarget-Default" + value: { + dps: 890.3558 + tps: 912.32556 } } diff --git a/sim/shaman/elemental/elemental_test.go b/sim/shaman/elemental/elemental_test.go index 9020efb424..65a07ad070 100644 --- a/sim/shaman/elemental/elemental_test.go +++ b/sim/shaman/elemental/elemental_test.go @@ -14,15 +14,100 @@ func init() { func TestElemental(t *testing.T) { core.RunTestSuite(t, t.Name(), core.FullCharacterTestSuiteGenerator([]core.CharacterSuiteConfig{ + { + Class: proto.Class_ClassShaman, + Phase: 1, + Race: proto.Race_RaceTroll, + OtherRaces: []proto.Race{proto.Race_RaceOrc}, + + Talents: DefaultTalents, + GearSet: core.GetGearSet("../../../ui/elemental_shaman/gear_sets", "phase_1"), + Rotation: core.GetAplRotation("../../../ui/elemental_shaman/apls", "default"), + Buffs: core.FullBuffs, + Consumes: Phase1Consumes, + SpecOptions: core.SpecOptionsCombo{Label: "Adaptive", SpecOptions: PlayerOptionsAdaptive}, + + ItemFilter: ItemFilters, + EPReferenceStat: proto.Stat_StatSpellPower, + StatsToWeigh: Stats, + }, + { + Class: proto.Class_ClassShaman, + Phase: 2, + Race: proto.Race_RaceTroll, + OtherRaces: []proto.Race{proto.Race_RaceOrc}, + + Talents: DefaultTalents, + GearSet: core.GetGearSet("../../../ui/elemental_shaman/gear_sets", "phase_2"), + Rotation: core.GetAplRotation("../../../ui/elemental_shaman/apls", "default"), + Buffs: core.FullBuffs, + Consumes: Phase2Consumes, + SpecOptions: core.SpecOptionsCombo{Label: "Adaptive", SpecOptions: PlayerOptionsAdaptive}, + + ItemFilter: ItemFilters, + EPReferenceStat: proto.Stat_StatSpellPower, + StatsToWeigh: Stats, + }, + { + Class: proto.Class_ClassShaman, + Phase: 3, + Race: proto.Race_RaceTroll, + OtherRaces: []proto.Race{proto.Race_RaceOrc}, + + Talents: DefaultTalents, + GearSet: core.GetGearSet("../../../ui/elemental_shaman/gear_sets", "phase_3"), + Rotation: core.GetAplRotation("../../../ui/elemental_shaman/apls", "default"), + Buffs: core.FullBuffs, + Consumes: Phase2Consumes, + SpecOptions: core.SpecOptionsCombo{Label: "Adaptive", SpecOptions: PlayerOptionsAdaptive}, + + ItemFilter: ItemFilters, + EPReferenceStat: proto.Stat_StatSpellPower, + StatsToWeigh: Stats, + }, + { + Class: proto.Class_ClassShaman, + Phase: 4, + Race: proto.Race_RaceTroll, + OtherRaces: []proto.Race{proto.Race_RaceOrc}, + + Talents: DefaultTalents, + GearSet: core.GetGearSet("../../../ui/elemental_shaman/gear_sets", "phase_4"), + Rotation: core.GetAplRotation("../../../ui/elemental_shaman/apls", "default"), + Buffs: core.FullBuffs, + Consumes: Phase2Consumes, + SpecOptions: core.SpecOptionsCombo{Label: "Adaptive", SpecOptions: PlayerOptionsAdaptive}, + + ItemFilter: ItemFilters, + EPReferenceStat: proto.Stat_StatSpellPower, + StatsToWeigh: Stats, + }, { Class: proto.Class_ClassShaman, Phase: 5, Race: proto.Race_RaceTroll, OtherRaces: []proto.Race{proto.Race_RaceOrc}, - Talents: Phase4Talents, - GearSet: core.GetGearSet("../../../ui/elemental_shaman/gear_sets", "blank"), - Rotation: core.GetAplRotation("../../../ui/elemental_shaman/apls", "phase_5"), + Talents: DefaultTalents, + GearSet: core.GetGearSet("../../../ui/elemental_shaman/gear_sets", "phase_5"), + Rotation: core.GetAplRotation("../../../ui/elemental_shaman/apls", "default"), + Buffs: core.FullBuffs, + Consumes: Phase5Consumes, + SpecOptions: core.SpecOptionsCombo{Label: "Adaptive", SpecOptions: PlayerOptionsAdaptive}, + + ItemFilter: ItemFilters, + EPReferenceStat: proto.Stat_StatSpellPower, + StatsToWeigh: Stats, + }, + { + Class: proto.Class_ClassShaman, + Phase: 6, + Race: proto.Race_RaceTroll, + OtherRaces: []proto.Race{proto.Race_RaceOrc}, + + Talents: DefaultTalents, + GearSet: core.GetGearSet("../../../ui/elemental_shaman/gear_sets", "phase_6"), + Rotation: core.GetAplRotation("../../../ui/elemental_shaman/apls", "default"), Buffs: core.FullBuffs, Consumes: Phase5Consumes, SpecOptions: core.SpecOptionsCombo{Label: "Adaptive", SpecOptions: PlayerOptionsAdaptive}, @@ -34,10 +119,7 @@ func TestElemental(t *testing.T) { })) } -var Phase1Talents = "25003105" -var Phase2Talents = "550031550000151" -var Phase3Talents = "550031550000151-500203" -var Phase4Talents = "550301550000151--50205300005" +var DefaultTalents = "550331050002151--50105301005" var PlayerOptionsAdaptive = &proto.Player_ElementalShaman{ ElementalShaman: &proto.ElementalShaman{ @@ -45,16 +127,42 @@ var PlayerOptionsAdaptive = &proto.Player_ElementalShaman{ }, } +var Phase1Consumes = core.ConsumesCombo{ + Label: "P1-Consumes", + Consumes: &proto.Consumes{ + DefaultConjured: proto.Conjured_ConjuredDemonicRune, + DefaultPotion: proto.Potions_MajorManaPotion, + Flask: proto.Flask_FlaskOfSupremePower, + FirePowerBuff: proto.FirePowerBuff_ElixirOfGreaterFirepower, + Food: proto.Food_FoodNightfinSoup, + MainHandImbue: proto.WeaponImbue_LesserWizardOil, + SpellPowerBuff: proto.SpellPowerBuff_GreaterArcaneElixir, + }, +} + +var Phase2Consumes = core.ConsumesCombo{ + Label: "P2-Consumes", + Consumes: &proto.Consumes{ + DefaultConjured: proto.Conjured_ConjuredDemonicRune, + DefaultPotion: proto.Potions_MajorManaPotion, + Flask: proto.Flask_FlaskOfSupremePower, + FirePowerBuff: proto.FirePowerBuff_ElixirOfGreaterFirepower, + Food: proto.Food_FoodRunnTumTuberSurprise, + MainHandImbue: proto.WeaponImbue_LesserWizardOil, + SpellPowerBuff: proto.SpellPowerBuff_GreaterArcaneElixir, + }, +} + var Phase5Consumes = core.ConsumesCombo{ Label: "P5-Consumes", Consumes: &proto.Consumes{ - DefaultPotion: proto.Potions_MajorManaPotion, - Flask: proto.Flask_FlaskOfSupremePower, - FirePowerBuff: proto.FirePowerBuff_ElixirOfGreaterFirepower, - Food: proto.Food_FoodRunnTumTuberSurprise, - MainHandImbue: proto.WeaponImbue_FlametongueWeapon, - //OffHandImbue: proto.WeaponImbue_MagnificentTrollshine, - SpellPowerBuff: proto.SpellPowerBuff_GreaterArcaneElixir, + DefaultConjured: proto.Conjured_ConjuredDemonicRune, + DefaultPotion: proto.Potions_MajorManaPotion, + Flask: proto.Flask_FlaskOfSupremePower, + FirePowerBuff: proto.FirePowerBuff_ElixirOfGreaterFirepower, + Food: proto.Food_FoodRunnTumTuberSurprise, + MainHandImbue: proto.WeaponImbue_BrilliantWizardOil, + SpellPowerBuff: proto.SpellPowerBuff_GreaterArcaneElixir, }, } diff --git a/sim/shaman/enhancement/enhancement_test.go b/sim/shaman/enhancement/enhancement_test.go index f2831bfa9b..b16b171c5f 100644 --- a/sim/shaman/enhancement/enhancement_test.go +++ b/sim/shaman/enhancement/enhancement_test.go @@ -1,8 +1,6 @@ package enhancement import ( - "testing" - _ "github.com/wowsims/classic/sim/common" // imported to get item effects included. "github.com/wowsims/classic/sim/core" "github.com/wowsims/classic/sim/core/proto" @@ -12,33 +10,33 @@ func init() { RegisterEnhancementShaman() } -func TestEnhancement(t *testing.T) { - core.RunTestSuite(t, t.Name(), core.FullCharacterTestSuiteGenerator([]core.CharacterSuiteConfig{ - { - Class: proto.Class_ClassShaman, - Phase: 5, - Race: proto.Race_RaceTroll, - OtherRaces: []proto.Race{proto.Race_RaceOrc}, +// func TestEnhancement(t *testing.T) { +// core.RunTestSuite(t, t.Name(), core.FullCharacterTestSuiteGenerator([]core.CharacterSuiteConfig{ +// { +// Class: proto.Class_ClassShaman, +// Phase: 5, +// Race: proto.Race_RaceTroll, +// OtherRaces: []proto.Race{proto.Race_RaceOrc}, - Talents: Phase4Talents, - GearSet: core.GetGearSet("../../../ui/enhancement_shaman/gear_sets", "blank"), - // OtherGearSets: []core.GearSetCombo{ - // core.GetGearSet("../../../ui/enhancement_shaman/gear_sets", "phase_5_2h"), - // }, - Rotation: core.GetAplRotation("../../../ui/enhancement_shaman/apls", "phase_5"), - Buffs: core.FullBuffs, - Consumes: Phase4ConsumesWFWF, - SpecOptions: core.SpecOptionsCombo{Label: "Sync Auto", SpecOptions: PlayerOptionsSyncAuto}, - OtherSpecOptions: []core.SpecOptionsCombo{ - {Label: "Sync Delay OH", SpecOptions: PlayerOptionsSyncDelayOH}, - }, +// Talents: Phase4Talents, +// GearSet: core.GetGearSet("../../../ui/enhancement_shaman/gear_sets", "blank"), +// // OtherGearSets: []core.GearSetCombo{ +// // core.GetGearSet("../../../ui/enhancement_shaman/gear_sets", "phase_5_2h"), +// // }, +// Rotation: core.GetAplRotation("../../../ui/enhancement_shaman/apls", "phase_5"), +// Buffs: core.FullBuffs, +// Consumes: Phase4ConsumesWFWF, +// SpecOptions: core.SpecOptionsCombo{Label: "Sync Auto", SpecOptions: PlayerOptionsSyncAuto}, +// OtherSpecOptions: []core.SpecOptionsCombo{ +// {Label: "Sync Delay OH", SpecOptions: PlayerOptionsSyncDelayOH}, +// }, - ItemFilter: ItemFilters, - EPReferenceStat: proto.Stat_StatAttackPower, - StatsToWeigh: Stats, - }, - })) -} +// ItemFilter: ItemFilters, +// EPReferenceStat: proto.Stat_StatAttackPower, +// StatsToWeigh: Stats, +// }, +// })) +// } var Phase1Talents = "-5005202101" var Phase2Talents = "-5005202105023051" diff --git a/sim/shaman/healing_wave.go b/sim/shaman/healing_wave.go deleted file mode 100644 index 2a633bbb6e..0000000000 --- a/sim/shaman/healing_wave.go +++ /dev/null @@ -1,73 +0,0 @@ -package shaman - -import ( - "time" - - "github.com/wowsims/classic/sim/core" -) - -const HealingWaveRanks = 10 - -var HealingWaveSpellId = [HealingWaveRanks + 1]int32{0, 331, 332, 547, 913, 939, 959, 8005, 10395, 10396, 25357} -var HealingWaveBaseHealing = [HealingWaveRanks + 1][]float64{{0}, {36, 47}, {69, 83}, {136, 163}, {279, 328}, {378, 443}, {552, 639}, {759, 874}, {1026, 1177}, {1389, 1583}, {1620, 1850}} -var HealingWaveSpellCoef = [HealingWaveRanks + 1]float64{0, .123, .271, .5, .793, .857, .857, .857, .857, .857, .857} -var HealingWaveCastTime = [HealingWaveRanks + 1]int32{0, 1500, 2000, 2500, 3000, 3000, 3000, 3000, 3000, 3000, 3000} -var HealingWaveManaCost = [HealingWaveRanks + 1]float64{0, 25, 45, 80, 155, 200, 265, 340, 440, 560, 620} -var HealingWaveLevel = [HealingWaveRanks + 1]int{0, 1, 6, 12, 18, 24, 32, 40, 48, 56, 60} - -func (shaman *Shaman) registerHealingWaveSpell() { - shaman.HealingWave = make([]*core.Spell, HealingWaveRanks+1) - - for rank := 1; rank <= HealingWaveRanks; rank++ { - config := shaman.newHealingWaveSpellConfig(rank) - - if config.RequiredLevel <= int(shaman.Level) { - shaman.HealingWave[rank] = shaman.RegisterSpell(config) - } - } -} - -func (shaman *Shaman) newHealingWaveSpellConfig(rank int) core.SpellConfig { - spellId := HealingWaveSpellId[rank] - baseHealingMultiplier := 1 + shaman.purificationHealingModifier() - baseHealingLow := HealingWaveBaseHealing[rank][0] * baseHealingMultiplier - baseHealingHigh := HealingWaveBaseHealing[rank][1] * baseHealingMultiplier - spellCoeff := HealingWaveSpellCoef[rank] - castTime := HealingWaveCastTime[rank] - manaCost := HealingWaveManaCost[rank] - level := HealingWaveLevel[rank] - - return core.SpellConfig{ - ActionID: core.ActionID{SpellID: spellId}, - SpellCode: SpellCode_ShamanHealingWave, - SpellSchool: core.SpellSchoolNature, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskSpellHealing, - Flags: core.SpellFlagHelpful | core.SpellFlagAPL | SpellFlagShaman, - - RequiredLevel: level, - Rank: rank, - - ManaCost: core.ManaCostOptions{ - FlatCost: manaCost, - }, - - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - CastTime: time.Millisecond * time.Duration( - castTime-(100*shaman.Talents.ImprovedHealingWave), - ), - }, - }, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - BonusCoefficient: spellCoeff, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - // TODO: Take Healing Way into account 6% stacking up to 3x - spell.CalcAndDealHealing(sim, spell.Unit, sim.Roll(baseHealingLow, baseHealingHigh), spell.OutcomeHealingCrit) - }, - } -} diff --git a/sim/shaman/item_sets_pve.go b/sim/shaman/item_sets_pve.go new file mode 100644 index 0000000000..ec80036739 --- /dev/null +++ b/sim/shaman/item_sets_pve.go @@ -0,0 +1,185 @@ +package shaman + +import ( + "slices" + "time" + + "github.com/wowsims/classic/sim/core" + "github.com/wowsims/classic/sim/core/stats" +) + +var ItemSetTheFiveThunders = core.NewItemSet(core.ItemSet{ + Name: "The Five Thunders", + Bonuses: map[int32]core.ApplyEffect{ + // +8 All Resistances. + 2: func(agent core.Agent) { + c := agent.GetCharacter() + c.AddResistances(8) + }, + // Chance on spell cast to increase your damage and healing by up to 95 for 10 sec. + // (Proc chance: 4%) + 4: func(agent core.Agent) { + c := agent.GetCharacter() + + procAura := c.NewTemporaryStatsAura("The Furious Storm", core.ActionID{SpellID: 27775}, stats.Stats{stats.SpellPower: 95}, time.Second*10) + handler := func(sim *core.Simulation, spell *core.Spell, _ *core.SpellResult) { + procAura.Activate(sim) + } + + core.MakeProcTriggerAura(&c.Unit, core.ProcTrigger{ + Name: "Item - The Furious Storm Proc (Spell Cast)", + Callback: core.CallbackOnCastComplete, + ProcMask: core.ProcMaskSpellDamage | core.ProcMaskSpellHealing, + ProcChance: 0.04, + Handler: handler, + }) + }, + // Increases damage and healing done by magical spells and effects by up to 23. + 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 ItemSetTheEarthfury = core.NewItemSet(core.ItemSet{ + Name: "The Earthfury", + Bonuses: map[int32]core.ApplyEffect{ + // The radius of your totems that affect friendly targets is increased to 30 yd. + 3: func(agent core.Agent) { + // Nothing to do + }, + // After casting your Healing Wave or Lesser Healing Wave spell, gives you a 25% chance to gain Mana equal to 35% of the base cost of the spell. + 5: func(agent core.Agent) { + // Nothing to do + }, + // Your Healing Wave will now jump to additional nearby targets. Each jump reduces the effectiveness of the heal by 80%, and the spell will jump to up to two additional targets. + 8: func(agent core.Agent) { + // Nothing to do + }, + }, +}) + +var ItemSetTheTenStorms = core.NewItemSet(core.ItemSet{ + Name: "The Ten Storms", + Bonuses: map[int32]core.ApplyEffect{ + // Increases the amount healed by Chain Heal to targets beyond the first by 30%. + 3: func(agent core.Agent) { + // Nothing to do + }, + // Improves your chance to get a critical strike with Nature spells by 3%. + 5: func(agent core.Agent) { + shaman := agent.(ShamanAgent).GetShaman() + shaman.PseudoStats.SchoolBonusCritChance[stats.SchoolIndexNature] += 3 * core.SpellCritRatingPerCritChance + }, + // When you cast a Healing Wave or Lesser Healing Wave, there is a 25% chance the target also receives a free Lightning Shield that causes 50 Nature damage to attacker on hit. + 8: func(agent core.Agent) { + // Nothing to do + }, + }, +}) + +var ItemSetStormcallersGarb = core.NewItemSet(core.ItemSet{ + Name: "Stormcaller's Garb", + Bonuses: map[int32]core.ApplyEffect{ + // Your Lightning Bolt, Chain Lightning, and Shock spells have a 20% chance to grant up to 50 Nature damage to spells for 8 sec. (Proc chance: 20%) + 3: func(agent core.Agent) { + shaman := agent.(ShamanAgent).GetShaman() + + buffAura := shaman.RegisterAura(core.Aura{ + ActionID: core.ActionID{SpellID: 26121}, + Label: "Stormcaller's Wrath", + Duration: time.Second * 8, + OnGain: func(aura *core.Aura, sim *core.Simulation) { + shaman.AddStatDynamic(sim, stats.NaturePower, 50) + }, + OnExpire: func(aura *core.Aura, sim *core.Simulation) { + shaman.AddStatDynamic(sim, stats.NaturePower, -50) + }, + }) + + affectedSpellCodes := []int32{SpellCode_ShamanLightningBolt, SpellCode_ShamanChainLightning, SpellCode_ShamanEarthShock, SpellCode_ShamanFlameShock, SpellCode_ShamanFrostShock} + + core.MakeProcTriggerAura(&shaman.Unit, core.ProcTrigger{ + Name: "Stormcaller Spelldamage Bonus", + Callback: core.CallbackOnCastComplete, + Handler: func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { + if slices.Contains(affectedSpellCodes, spell.SpellCode) && sim.Proc(0.20, "Stormcaller's Wrath") { + buffAura.Activate(sim) + } + }, + }) + }, + // -0.4 seconds on the casting time of your Chain Heal spell. + 5: func(agent core.Agent) { + }, + }, +}) + +var ItemSetGiftOfTheGatheringStorm = core.NewItemSet(core.ItemSet{ + Name: "Gift of the Gathering Storm", + Bonuses: map[int32]core.ApplyEffect{ + // Increases the chain target damage multiplier of your Chain Lightning spell by 5%. + 3: func(agent core.Agent) { + shaman := agent.(ShamanAgent).GetShaman() + shaman.RegisterAura(core.Aura{ + Label: "Gift of the Gathering Storm Chain Lightning Bonus", + OnInit: func(aura *core.Aura, sim *core.Simulation) { + shaman.ChainLightningBounceCoefficient += 0.05 + }, + }) + }, + }, +}) + +var ItemSetTheEarthshatterer = core.NewItemSet(core.ItemSet{ + Name: "The Earthshatterer", + Bonuses: map[int32]core.ApplyEffect{ + // Reduces the mana cost of your totem spells by 12%. + 2: func(agent core.Agent) { + shaman := agent.(ShamanAgent).GetShaman() + shaman.OnSpellRegistered(func(spell *core.Spell) { + if spell.Flags.Matches(SpellFlagTotem) { + spell.Cost.Multiplier -= 12 + } + }) + }, + // Increases the mana gained from your Mana Spring totems by 25%. + 4: func(agent core.Agent) { + }, + // Your Healing Wave and Lesser Healing Wave spells have a chance to imbue your target with Totemic Power. + 6: func(agent core.Agent) { + }, + // Your Lightning Shield spell also grants you 15 mana per 5 sec. while active. + 8: func(agent core.Agent) { + shaman := agent.(ShamanAgent).GetShaman() + shaman.RegisterAura(core.Aura{ + Label: "Lightning Shield", + OnInit: func(_ *core.Aura, _ *core.Simulation) { + for _, lsAura := range shaman.LightningShieldAuras { + if lsAura == nil { + return + } + + oldOnGain := lsAura.OnGain + lsAura.OnGain = func(aura *core.Aura, sim *core.Simulation) { + oldOnGain(aura, sim) + shaman.AddStatDynamic(sim, stats.MP5, 15) + } + + oldOnExpire := lsAura.OnExpire + lsAura.OnExpire = func(aura *core.Aura, sim *core.Simulation) { + oldOnExpire(aura, sim) + shaman.AddStatDynamic(sim, stats.MP5, -15) + } + } + }, + }) + }, + }, +}) diff --git a/sim/shaman/item_sets_pvp.go b/sim/shaman/item_sets_pvp.go new file mode 100644 index 0000000000..4890d2ea17 --- /dev/null +++ b/sim/shaman/item_sets_pvp.go @@ -0,0 +1,108 @@ +package shaman + +import ( + "github.com/wowsims/classic/sim/core" + "github.com/wowsims/classic/sim/core/stats" +) + +var ItemSetChampionsEarthshaker = core.NewItemSet(core.ItemSet{ + Name: "Champion's Earthshaker", + Bonuses: map[int32]core.ApplyEffect{ + // +40 Attack Power. + 2: func(agent core.Agent) { + c := agent.GetCharacter() + c.AddStats(stats.Stats{ + stats.AttackPower: 40, + stats.RangedAttackPower: 40, + }) + }, + // Improves your chance to get a critical strike with all Shock spells by 2%. + 4: func(agent core.Agent) { + shaman := agent.(ShamanAgent).GetShaman() + shaman.GetOrRegisterAura(core.Aura{ + Label: "Shaman Shock Crit Bonus", + ActionID: core.ActionID{SpellID: 22804}, + OnInit: func(aura *core.Aura, sim *core.Simulation) { + for _, spell := range core.Flatten([][]*core.Spell{shaman.EarthShock, shaman.FlameShock, shaman.FrostShock}) { + if spell != nil { + spell.BonusCritRating += 2 * core.CritRatingPerCritChance + } + } + }, + }) + }, + // +15 Stamina. + 6: func(agent core.Agent) { + c := agent.GetCharacter() + c.AddStat(stats.Stamina, 15) + }, + }, +}) + +var ItemSetChampionsStormcaller = core.NewItemSet(core.ItemSet{ + Name: "Champion's Stormcaller", + Bonuses: map[int32]core.ApplyEffect{ + // +40 Attack Power. + 2: func(agent core.Agent) { + c := agent.GetCharacter() + c.AddStats(stats.Stats{ + stats.AttackPower: 40, + stats.RangedAttackPower: 40, + }) + }, + // Improves your chance to get a critical strike with all Shock spells by 2%. + 4: func(agent core.Agent) { + shaman := agent.(ShamanAgent).GetShaman() + shaman.GetOrRegisterAura(core.Aura{ + Label: "Shaman Shock Crit Bonus", + ActionID: core.ActionID{SpellID: 22804}, + OnInit: func(aura *core.Aura, sim *core.Simulation) { + for _, spell := range core.Flatten([][]*core.Spell{shaman.EarthShock, shaman.FlameShock, shaman.FrostShock}) { + if spell != nil { + spell.BonusCritRating += 2 * core.CritRatingPerCritChance + } + } + }, + }) + }, + // +20 Stamina. + 6: func(agent core.Agent) { + c := agent.GetCharacter() + c.AddStat(stats.Stamina, 20) + }, + }, +}) + +var ItemSetWarlordsEarthshaker = core.NewItemSet(core.ItemSet{ + Name: "Warlord's Earthshaker", + Bonuses: map[int32]core.ApplyEffect{ + // +20 Stamina. + 2: func(agent core.Agent) { + c := agent.GetCharacter() + c.AddStat(stats.Stamina, 20) + }, + // Improves your chance to get a critical strike with all Shock spells by 2%. + 4: func(agent core.Agent) { + shaman := agent.(ShamanAgent).GetShaman() + shaman.GetOrRegisterAura(core.Aura{ + Label: "Shaman Shock Crit Bonus", + ActionID: core.ActionID{SpellID: 22804}, + OnInit: func(aura *core.Aura, sim *core.Simulation) { + for _, spell := range core.Flatten([][]*core.Spell{shaman.EarthShock, shaman.FlameShock, shaman.FrostShock}) { + if spell != nil { + spell.BonusCritRating += 2 * core.CritRatingPerCritChance + } + } + }, + }) + }, + // +40 Attack Power. + 6: func(agent core.Agent) { + c := agent.GetCharacter() + c.AddStats(stats.Stats{ + stats.AttackPower: 40, + stats.RangedAttackPower: 40, + }) + }, + }, +}) diff --git a/sim/shaman/items.go b/sim/shaman/items.go index edcc15b1b3..1dcbdec432 100644 --- a/sim/shaman/items.go +++ b/sim/shaman/items.go @@ -2,32 +2,17 @@ package shaman import ( "slices" + "time" "github.com/wowsims/classic/sim/core" ) const ( // Keep these ordered by ID - TotemOfRage = 22395 - TotemOfTheStorm = 23199 - TotemOfSustaining = 23200 - // CarvedDriftwoodIcon = 209575 - // TotemOfInvigoratingFlame = 215436 - // TotemOfTormentedAncestry = 220607 - // TerrestrisTank = 224279 - // TotemOfThunder = 228176 - // TotemOfRagingFire = 228177 - // TotemOfEarthenVitality = 228178 - // NaturalAlignmentCrystal = 230273 - // WushoolaysCharmOfSpirits = 231281 - // TerrestrisEle = 231890 - // TotemOfRelentlessThunder = 232392 - // TotemOfTheElements = 232409 - // TotemOfAstralFlow = 232416 - // TotemOfConductiveCurrents = 232419 - // TotemOfThunderousStrikes = 234478 - // TotemOfFlowingMagma = 234479 - // TotemOfPyroclasticThunder = 234480 + NaturalAlignmentCrystal = 19344 + WushoolaysCharmOfSpirits = 19956 + TotemOfRage = 22395 + TotemOfTheStorm = 23199 ) func init() { @@ -35,14 +20,9 @@ func init() { // Keep these ordered by name - /* core.NewItemEffect(CarvedDriftwoodIcon, func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.MP5, 2) - }) - - // https://www.wowhead.com/classic/item=230273/natural-alignment-crystal + // https://www.wowhead.com/classic/item=19344/natural-alignment-crystal // Use: Aligns the Shaman with nature, increasing the damage done by spells by 20%, improving heal effects by 20%, and increasing mana cost of spells by 20% for 20 sec. - // (2 Min Cooldown) + // (5 Min Cooldown) core.NewItemEffect(NaturalAlignmentCrystal, func(agent core.Agent) { shaman := agent.(ShamanAgent).GetShaman() @@ -71,7 +51,7 @@ func init() { Cast: core.CastConfig{ CD: core.Cooldown{ Timer: shaman.NewTimer(), - Duration: time.Minute * 2, + Duration: time.Minute * 5, }, SharedCD: core.Cooldown{ Timer: shaman.GetOffensiveTrinketCD(), @@ -90,365 +70,6 @@ func init() { }) }) - // https://www.wowhead.com/classic/item=231890/terrestris - core.NewItemEffect(TerrestrisEle, func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - - boonOfEarth := shaman.RegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 469208}, - Label: "Boon of Earth", - Duration: time.Minute * 2, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - shaman.AddStatDynamic(sim, stats.MeleeCrit, 1*core.CritRatingPerCritChance) - shaman.AddStatDynamic(sim, stats.SpellCrit, 1*core.SpellCritRatingPerCritChance) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - shaman.AddStatDynamic(sim, stats.MeleeCrit, -1*core.CritRatingPerCritChance) - shaman.AddStatDynamic(sim, stats.SpellCrit, -1*core.SpellCritRatingPerCritChance) - }, - }) - - boonOfFire := shaman.RegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 469209}, - Label: "Boon of Fire", - Duration: time.Minute * 2, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - shaman.AddStatDynamic(sim, stats.SpellDamage, 16) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - shaman.AddStatDynamic(sim, stats.SpellDamage, -16) - }, - }) - - boonOfWater := shaman.RegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 469210}, - Label: "Boon of Water", - Duration: time.Minute * 2, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - shaman.AddStatDynamic(sim, stats.HealingPower, 31) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - shaman.AddStatDynamic(sim, stats.HealingPower, 31) - }, - }) - - boonOfAir := shaman.RegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 452456}, - Label: "Boon of Air", - Duration: time.Minute * 2, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - shaman.Unit.AddMoveSpeedModifier(&aura.ActionID, 1.15) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - shaman.Unit.RemoveMoveSpeedModifier(&aura.ActionID) - }, - }) - - core.MakePermanent(shaman.RegisterAura(core.Aura{ - Label: "Terrestris Boon Trigger", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - core.Each(shaman.EarthTotems, func(spell *core.Spell) { - oldApplyEffects := spell.ApplyEffects - spell.ApplyEffects = func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - oldApplyEffects(sim, target, spell) - boonOfEarth.Activate(sim) - } - }) - core.Each(shaman.FireTotems, func(spell *core.Spell) { - oldApplyEffects := spell.ApplyEffects - spell.ApplyEffects = func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - oldApplyEffects(sim, target, spell) - boonOfFire.Activate(sim) - } - }) - core.Each(shaman.WaterTotems, func(spell *core.Spell) { - oldApplyEffects := spell.ApplyEffects - spell.ApplyEffects = func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - oldApplyEffects(sim, target, spell) - boonOfWater.Activate(sim) - } - }) - core.Each(shaman.AirTotems, func(spell *core.Spell) { - oldApplyEffects := spell.ApplyEffects - spell.ApplyEffects = func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - oldApplyEffects(sim, target, spell) - boonOfAir.Activate(sim) - } - }) - }, - })) - }) - - // https://www.wowhead.com/classic/item=224279/terrestris - core.NewItemEffect(TerrestrisTank, func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - - boonOfEarth := shaman.RegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 452464}, - Label: "Boon of Earth", - Duration: time.Minute * 2, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - shaman.AddStatDynamic(sim, stats.Block, 3*core.BlockRatingPerBlockChance) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - shaman.AddStatDynamic(sim, stats.Block, 31*core.BlockRatingPerBlockChance) - }, - }) - - fireExplosion := shaman.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 453085}, - SpellSchool: core.SpellSchoolFire, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskEmpty, - Flags: core.SpellFlagNoOnCastComplete, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - for _, aoeTarget := range sim.Encounter.TargetUnits { - spell.CalcAndDealDamage(sim, aoeTarget, 8, spell.OutcomeMagicHitAndCrit) - } - }, - }) - - boonOfFire := shaman.RegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 452460}, - Label: "Boon of Fire", - Duration: time.Minute * 2, - OnSpellHitTaken: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if result.DidBlock() { - fireExplosion.Cast(sim, result.Target) - } - }, - }) - - waterHealActionID := core.ActionID{SpellID: 453081} - waterHealthMetrics := shaman.NewHealthMetrics(waterHealActionID) - waterHeal := shaman.RegisterSpell(core.SpellConfig{ - ActionID: waterHealActionID, - SpellSchool: core.SpellSchoolPhysical, - ProcMask: core.ProcMaskEmpty, - Flags: core.SpellFlagHelpful | core.SpellFlagNoOnCastComplete, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - shaman.GainHealth(sim, 20, waterHealthMetrics) - }, - }) - - boonOfWater := shaman.RegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 452454}, - Label: "Boon of Water", - Duration: time.Minute * 2, - OnSpellHitTaken: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if result.DidBlock() { - waterHeal.Cast(sim, aura.Unit) - } - }, - }) - - boonOfAir := shaman.RegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 452456}, - Label: "Boon of Air", - Duration: time.Minute * 2, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - shaman.Unit.AddMoveSpeedModifier(&aura.ActionID, 1.15) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - shaman.Unit.RemoveMoveSpeedModifier(&aura.ActionID) - }, - }) - - core.MakePermanent(shaman.RegisterAura(core.Aura{ - Label: "Terrestris Boon Trigger", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - core.Each(shaman.EarthTotems, func(spell *core.Spell) { - oldApplyEffects := spell.ApplyEffects - spell.ApplyEffects = func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - oldApplyEffects(sim, target, spell) - boonOfEarth.Activate(sim) - } - }) - core.Each(shaman.FireTotems, func(spell *core.Spell) { - oldApplyEffects := spell.ApplyEffects - spell.ApplyEffects = func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - oldApplyEffects(sim, target, spell) - boonOfFire.Activate(sim) - } - }) - core.Each(shaman.WaterTotems, func(spell *core.Spell) { - oldApplyEffects := spell.ApplyEffects - spell.ApplyEffects = func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - oldApplyEffects(sim, target, spell) - boonOfWater.Activate(sim) - } - }) - core.Each(shaman.AirTotems, func(spell *core.Spell) { - oldApplyEffects := spell.ApplyEffects - spell.ApplyEffects = func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - oldApplyEffects(sim, target, spell) - boonOfAir.Activate(sim) - } - }) - }, - })) - }) - - // https://www.wowhead.com/classic/item=232416/totem-of-astral-flow - // Increases the attack power bonus on Windfury Weapon attacks by 68. - core.NewItemEffect(TotemOfAstralFlow, func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - shaman.bonusWindfuryWeaponAP += 68 - }) - - // https://www.wowhead.com/classic/item=232419/totem-of-conductive-currents - // While Frostbrand Weapon is active, your Water Shield triggers reduce the cast time of your next Chain Lightning spell within 15 sec by 20%, and increases its damage by 20%. - // Stacking up to 5 times. - core.NewItemEffect(TotemOfConductiveCurrents, func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - if shaman.Consumes.MainHandImbue != proto.WeaponImbue_FrostbrandWeapon || !shaman.HasRune(proto.ShamanRune_RuneHandsWaterShield) { - return - } - - affectedSpells := []*core.Spell{} - - buffAura := shaman.RegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 470272}, - Label: "Totem of Conductive Currents", - Duration: time.Second * 15, - MaxStacks: 5, - OnInit: func(aura *core.Aura, sim *core.Simulation) { - affectedSpells = core.FilterSlice(shaman.ChainLightning, func(spell *core.Spell) bool { return spell != nil }) - affectedSpells = core.FilterSlice(shaman.ChainLightningOverload, func(spell *core.Spell) bool { return spell != nil }) - }, - OnStacksChange: func(aura *core.Aura, sim *core.Simulation, oldStacks, newStacks int32) { - oldStackValue := .20 * float64(oldStacks) - newStackValue := .20 * float64(newStacks) - - for _, spell := range affectedSpells { - spell.DamageMultiplier /= 1 + oldStackValue - spell.DamageMultiplier *= 1 + newStackValue - - spell.CastTimeMultiplier += oldStackValue - spell.CastTimeMultiplier -= newStackValue - } - }, - OnCastComplete: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell) { - if spell.SpellCode == SpellCode_ShamanChainLightning { - aura.Deactivate(sim) - } - }, - }) - - core.MakePermanent(shaman.RegisterAura(core.Aura{ - Label: "Totem of Conductive Currents Trigger", - OnSpellHitTaken: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if spell == shaman.WaterShieldRestore { - buffAura.Activate(sim) - buffAura.AddStack(sim) - } - }, - })) - }) - - // https://www.wowhead.com/classic/item=234479/totem-of-flowing-magma - // Increases the damage of Flame Shock and Molten Blast by 3%. - core.NewItemEffect(TotemOfFlowingMagma, func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - shaman.RegisterAura(core.Aura{ - Label: "Improved Flame Shock/Molten Blast", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - affectedSpells := core.FilterSlice( - core.Flatten( - [][]*core.Spell{ - shaman.FlameShock, - {shaman.MoltenBlast}, - }, - ), - func(spell *core.Spell) bool { return spell != nil }, - ) - - for _, spell := range affectedSpells { - spell.DamageMultiplierAdditive += 0.03 - } - }, - }) - }) - - // https://www.wowhead.com/classic/item=234480/totem-of-pyroclastic-thunder - // Increases the damage of Lightning Bolt, Chain Lightning, and Lava Burst by 3%. - core.NewItemEffect(TotemOfPyroclasticThunder, func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - shaman.RegisterAura(core.Aura{ - Label: "Improved Lightning Bolt/Lava Burst", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - affectedSpells := core.FilterSlice( - core.Flatten( - [][]*core.Spell{ - shaman.LightningBolt, - shaman.ChainLightning, - {shaman.LavaBurst}, - }, - ), - func(spell *core.Spell) bool { return spell != nil }, - ) - - for _, spell := range affectedSpells { - spell.DamageMultiplierAdditive += 0.03 - } - }, - }) - }) - - // https://www.wowhead.com/classic/item=232392/totem-of-relentless-thunder - // While a Shield is equipped, your melee attacks with Rockbiter Weapon trigger your Maelstrom Weapon rune 100% more often. - core.NewItemEffect(TotemOfRelentlessThunder, func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - if !shaman.HasRune(proto.ShamanRune_RuneWaistMaelstromWeapon) { - return - } - - core.MakePermanent(shaman.RegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 470081}, - Label: "Totem of Raging Storms", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - oldPPMM := shaman.maelstromWeaponPPMM - newPPMM := shaman.AutoAttacks.NewPPMManager(oldPPMM.GetPPM()*2, core.ProcMaskMelee) - shaman.maelstromWeaponPPMM = &newPPMM - - core.StartPeriodicAction(sim, core.PeriodicActionOptions{ - Period: time.Second * 2, - TickImmediately: true, - OnAction: func(sim *core.Simulation) { - if shaman.OffHand().WeaponType != proto.WeaponType_WeaponTypeShield { - shaman.maelstromWeaponPPMM = oldPPMM - aura.Deactivate(sim) - return - } - - if !aura.IsActive() { - shaman.maelstromWeaponPPMM = &newPPMM - aura.Activate(sim) - } - }, - }) - }, - })) - }) - - core.NewItemEffect(TotemOfTheElements, func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - shaman.RegisterAura(core.Aura{ - Label: "Totem of the Elements", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - shaman.ClearcastingAura.MaxStacks += 1 - }, - }) - }) */ - // https://www.wowhead.com/classic/item=23199/totem-of-the-storm // Equip: Increases damage done by Chain Lightning and Lightning Bolt by up to 33. core.NewItemEffect(TotemOfTheStorm, func(agent core.Agent) { @@ -460,85 +81,6 @@ func init() { }) }) - // https://www.wowhead.com/classic/item=23200/totem-of-sustaining - // Equip: Increases healing done by Lesser Healing Wave by up to 53. - core.NewItemEffect(TotemOfSustaining, func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - shaman.OnSpellRegistered(func(spell *core.Spell) { - if spell.SpellCode == SpellCode_ShamanLesserHealingWave { - spell.BonusDamage += 53 - } - }) - }) - - /* core.NewItemEffect(TotemOfInvigoratingFlame, func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - - shaman.OnSpellRegistered(func(spell *core.Spell) { - if spell.SpellCode == SpellCode_ShamanFlameShock { - spell.Cost.FlatModifier -= 10 - } - }) - }) - - // Ancestral Bloodstorm Beacon - core.NewItemEffect(216615, func(agent core.Agent) { - character := agent.GetCharacter() - - spell := character.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 436413}, - SpellSchool: core.SpellSchoolNature | core.SpellSchoolShadow, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskSpellDamage, - Flags: core.SpellFlagAPL | core.SpellFlagOffensiveEquipment, - - Cast: core.CastConfig{ - CD: core.Cooldown{ - Timer: character.NewTimer(), - Duration: time.Minute * 5, - }, - }, - - DamageMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - for _, aoeTarget := range sim.Encounter.TargetUnits { - spell.CalcAndDealDamage(sim, aoeTarget, 150, spell.OutcomeMagicHitAndCrit) - } - }, - }) - - character.AddMajorCooldown(core.MajorCooldown{ - Spell: spell, - Priority: core.CooldownPriorityLow, - Type: core.CooldownTypeDPS, - }) - }) - - // Totem of Tormented Ancestry - core.NewItemEffect(TotemOfTormentedAncestry, func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - procAura := shaman.NewTemporaryStatsAura( - "Totem of Tormented Ancestry Proc", - core.ActionID{SpellID: 446219}, - stats.Stats{stats.AttackPower: 10, stats.SpellDamage: 10, stats.HealingPower: 10}, - 12*time.Second, - ) - - shaman.RegisterAura(core.Aura{ - Label: "Totem of Tormented Ancestry", - Duration: core.NeverExpires, - OnReset: func(aura *core.Aura, sim *core.Simulation) { - aura.Activate(sim) - }, - OnCastComplete: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell) { - if spell.SpellCode == SpellCode_ShamanFlameShock { - procAura.Activate(sim) - } - }, - }) - }) */ - // Totem of Rage // Equip: Increases damage done by Earth Shock, Flame Shock, and Frost Shock by up to 30. // Acts as extra 30 spellpower for shocks. @@ -552,113 +94,8 @@ func init() { }) }) - // https://www.wowhead.com/classic/item=228176/totem-of-thunder - // Equip: The cast time of your Lightning Bolt spell is reduced by -0.1 sec. - /* core.NewItemEffect(TotemOfThunder, func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - shaman.OnSpellRegistered(func(spell *core.Spell) { - if spell.SpellCode == SpellCode_ShamanLightningBolt { - spell.DefaultCast.CastTime -= time.Millisecond * 100 - } - }) - }) - - // https://www.wowhead.com/classic/item=234478/totem-of-thunderous-strikes - // Increases the damage of Stormstrike and Windfury Weapon by 3%. - core.NewItemEffect(TotemOfThunderousStrikes, func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - shaman.RegisterAura(core.Aura{ - Label: "Improved Stormstrike/Windfury Weapon", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - affectedSpells := core.FilterSlice( - core.Flatten( - [][]*core.Spell{ - {shaman.StormstrikeMH}, - {shaman.StormstrikeOH}, - {shaman.WindfuryWeaponMH}, - {shaman.WindfuryWeaponOH}, - }, - ), - func(spell *core.Spell) bool { return spell != nil }, - ) - - for _, spell := range affectedSpells { - spell.DamageMultiplierAdditive += 0.03 - } - }, - }) - }) - - // https://www.wowhead.com/classic/item=228177/totem-of-raging-fire - // Equip: Your Stormstrike spell causes you to gain 24 attack power for 12 sec. (More effective with a two - handed weapon). - core.NewItemEffect(TotemOfRagingFire, func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - procAura1H := shaman.RegisterAura(core.Aura{ - ActionID: core.ActionID{ItemID: TotemOfRagingFire}.WithTag(1), - Label: "Totem of Raging Fire (1H)", - Duration: time.Second * 12, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - shaman.AddStatDynamic(sim, stats.AttackPower, 24) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - shaman.AddStatDynamic(sim, stats.AttackPower, -24) - }, - }) - // TODO: Verify 2H value - procAura2H := shaman.RegisterAura(core.Aura{ - ActionID: core.ActionID{ItemID: TotemOfRagingFire}.WithTag(2), - Label: "Totem of Raging Fire (2H)", - Duration: time.Second * 12, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - shaman.AddStatDynamic(sim, stats.AttackPower, 48) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - shaman.AddStatDynamic(sim, stats.AttackPower, -48) - }, - }) - - shaman.RegisterAura(core.Aura{ - Label: "Totem of Raging Fire Trigger", - Duration: core.NeverExpires, - OnReset: func(aura *core.Aura, sim *core.Simulation) { - aura.Activate(sim) - }, - OnCastComplete: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell) { - if spell.SpellCode != SpellCode_ShamanStormstrike { - return - } - - if shaman.MainHand().HandType == proto.HandType_HandTypeOneHand { - procAura2H.Deactivate(sim) - procAura1H.Activate(sim) - } else if shaman.MainHand().HandType == proto.HandType_HandTypeTwoHand { - procAura1H.Deactivate(sim) - procAura2H.Activate(sim) - } - }, - }) - }) - - // https://www.wowhead.com/classic/item=228178/totem-of-earthen-vitality - // Equip: While a Shield is equipped, your melee attacks with Rockbiter Weapon restore 2% of your total mana. - core.NewItemEffect(TotemOfEarthenVitality, func(agent core.Agent) { - shaman := agent.(ShamanAgent).GetShaman() - - manaMetrics := shaman.NewManaMetrics(core.ActionID{SpellID: 461299}) - core.MakePermanent(shaman.RegisterAura(core.Aura{ - Label: "Totem of Earthen Vitality Trigger", - Duration: core.NeverExpires, - OnSpellHitDealt: func(_ *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if !spell.ProcMask.Matches(core.ProcMaskMeleeMHAuto) || !result.Landed() || shaman.OffHand().WeaponType != proto.WeaponType_WeaponTypeShield { - return - } - shaman.AddMana(sim, shaman.MaxMana()*.02, manaMetrics) - }, - })) - }) - - // https://www.wowhead.com/classic/item=231281/wushoolays-charm-of-spirits - // Use: Increases the damage dealt by your Lightning Shield spell by 100% for 20 sec. (2 Min Cooldown) + // https://www.wowhead.com/classic/item=19956/wushoolays-charm-of-spirits + // Use: Increases the damage dealt by your Lightning Shield spell by 100% for 20 sec. (3 Min Cooldown) core.NewItemEffect(WushoolaysCharmOfSpirits, func(agent core.Agent) { shaman := agent.(ShamanAgent).GetShaman() @@ -673,10 +110,7 @@ func init() { Duration: time.Second * 20, OnInit: func(aura *core.Aura, sim *core.Simulation) { affectedSpells = core.FilterSlice( - core.Flatten([][]*core.Spell{ - shaman.LightningShieldProcs, - {shaman.RollingThunder}, - }), + shaman.LightningShieldProcs, func(spell *core.Spell) bool { return spell != nil }, ) }, @@ -700,7 +134,7 @@ func init() { Cast: core.CastConfig{ CD: core.Cooldown{ Timer: shaman.NewTimer(), - Duration: time.Minute * 2, + Duration: time.Minute * 3, }, SharedCD: core.Cooldown{ Timer: shaman.GetOffensiveTrinketCD(), @@ -717,7 +151,7 @@ func init() { Priority: core.CooldownPriorityDefault, Type: core.CooldownTypeDPS, }) - }) */ + }) core.AddEffectsToTest = true } diff --git a/sim/shaman/lesser_healing_wave.go b/sim/shaman/lesser_healing_wave.go deleted file mode 100644 index 4158d5df7d..0000000000 --- a/sim/shaman/lesser_healing_wave.go +++ /dev/null @@ -1,81 +0,0 @@ -package shaman - -import ( - "time" - - "github.com/wowsims/classic/sim/core" -) - -const LesserHealingWaveRanks = 6 - -var LesserHealingWaveSpellId = [LesserHealingWaveRanks + 1]int32{0, 8004, 8008, 8010, 10466, 10467, 10468} -var LesserHealingWaveBaseHealing = [LesserHealingWaveRanks + 1][]float64{{0}, {170, 195}, {257, 292}, {347, 391}, {473, 529}, {649, 723}, {832, 928}} -var LesserHealingWaveSpellCoef = [LesserHealingWaveRanks + 1]float64{0, .429, .429, .429, .429, .429, .429} -var LesserHealingWaveCastTime = [LesserHealingWaveRanks + 1]int32{0, 1500, 1500, 1500, 1500, 1500, 1500} -var LesserHealingWaveManaCost = [LesserHealingWaveRanks + 1]float64{0, 105, 145, 185, 235, 305, 380} -var LesserHealingWaveLevel = [LesserHealingWaveRanks + 1]int{0, 20, 28, 36, 44, 52, 60} - -func (shaman *Shaman) registerLesserHealingWaveSpell() { - shaman.LesserHealingWave = make([]*core.Spell, LesserHealingWaveRanks+1) - - for rank := 1; rank <= LesserHealingWaveRanks; rank++ { - config := shaman.newLesserHealingWaveSpellConfig(rank) - - if config.RequiredLevel <= int(shaman.Level) { - shaman.LesserHealingWave[rank] = shaman.RegisterSpell(config) - } - } -} - -func (shaman *Shaman) newLesserHealingWaveSpellConfig(rank int) core.SpellConfig { - spellId := LesserHealingWaveSpellId[rank] - baseHealingMultiplier := 1 + shaman.purificationHealingModifier() - baseHealingLow := LesserHealingWaveBaseHealing[rank][0] * baseHealingMultiplier - baseHealingHigh := LesserHealingWaveBaseHealing[rank][1] * baseHealingMultiplier - spellCoeff := LesserHealingWaveSpellCoef[rank] - castTime := LesserHealingWaveCastTime[rank] - manaCost := LesserHealingWaveManaCost[rank] - level := LesserHealingWaveLevel[rank] - - switch shaman.Ranged().ID { - case TotemOfTheStorm: - baseHealingLow += 53 - baseHealingHigh += 53 - } - - return core.SpellConfig{ - ActionID: core.ActionID{SpellID: spellId}, - SpellCode: SpellCode_ShamanLesserHealingWave, - SpellSchool: core.SpellSchoolNature, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskSpellHealing, - Flags: core.SpellFlagHelpful | core.SpellFlagAPL | SpellFlagShaman, - MetricSplits: 6, - - RequiredLevel: level, - Rank: rank, - - ManaCost: core.ManaCostOptions{ - FlatCost: manaCost, - }, - - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - CastTime: time.Millisecond * time.Duration(castTime), - }, - ModifyCast: func(sim *core.Simulation, spell *core.Spell, cast *core.Cast) { - castTime := shaman.ApplyCastSpeedForSpell(cast.CastTime, spell) - shaman.AutoAttacks.StopMeleeUntil(sim, sim.CurrentTime+castTime, false) - }, - }, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - BonusCoefficient: spellCoeff, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - spell.CalcAndDealHealing(sim, spell.Unit, sim.Roll(baseHealingLow, baseHealingHigh), spell.OutcomeHealingCrit) - }, - } -} diff --git a/sim/shaman/rockbiter_weapon.go b/sim/shaman/rockbiter_weapon.go index 3735bf2967..27396b45e6 100644 --- a/sim/shaman/rockbiter_weapon.go +++ b/sim/shaman/rockbiter_weapon.go @@ -65,8 +65,7 @@ func (shaman *Shaman) ApplyRockbiterImbueToItem(item *core.Item) { rank := RockbiterWeaponRankByLevel[shaman.Level] enchantId := RockbiterWeaponEnchantId[rank] - // Nerfed by 90% going into SoD Phase 3, in a... weird way ;) - bonusAP := RockbiterWeaponBonusAP[rank] * ([]float64{1, 1.07, 1.14, 1.2}[shaman.Talents.ElementalWeapons] - 0.9) + bonusAP := RockbiterWeaponBonusAP[rank] * []float64{1, 1.07, 1.14, 1.2}[shaman.Talents.ElementalWeapons] newStats := stats.Stats{stats.AttackPower: bonusAP} diff --git a/sim/shaman/shaman.go b/sim/shaman/shaman.go index 0b9a1ddeab..e37a9ba94e 100644 --- a/sim/shaman/shaman.go +++ b/sim/shaman/shaman.go @@ -104,7 +104,7 @@ type Shaman struct { ManaSpringTotem []*core.Spell SearingTotem []*core.Spell StoneskinTotem []*core.Spell - StormstrikeMH *core.Spell + Stormstrike *core.Spell StrengthOfEarthTotem []*core.Spell TremorTotem *core.Spell WindfuryTotem []*core.Spell @@ -128,6 +128,8 @@ type Shaman struct { // Shield ActiveShield *core.Spell // Tracks the Shaman's active shield spell ActiveShieldAura *core.Aura + + ChainLightningBounceCoefficient float64 } // Implemented by each Shaman spec. @@ -173,17 +175,6 @@ func (shaman *Shaman) Initialize() { shaman.registerWindfuryTotemSpell() shaman.registerGraceOfAirTotemSpell() shaman.registerWindwallTotemSpell() - - // // This registration must come after all the totems are registered - // shaman.registerCallOfTheElements() - - shaman.RegisterHealingSpells() -} - -func (shaman *Shaman) RegisterHealingSpells() { - shaman.registerLesserHealingWaveSpell() - shaman.registerHealingWaveSpell() - shaman.registerChainHealSpell() } func (shaman *Shaman) Reset(_ *core.Simulation) { diff --git a/sim/shaman/stormstrike.go b/sim/shaman/stormstrike.go index 636a154966..0f69351bd9 100644 --- a/sim/shaman/stormstrike.go +++ b/sim/shaman/stormstrike.go @@ -6,22 +6,22 @@ import ( "github.com/wowsims/classic/sim/core" ) -// TODO: All of this needs to be refactored for how it works in Vanilla vs SoD. -// Gives an extra attack instead of a true yellow hit func (shaman *Shaman) registerStormstrikeSpell() { if !shaman.Talents.Stormstrike { return } - shaman.StormstrikeMH = shaman.newStormstrikeHitSpell() - shaman.StormstrikeMH.SpellCode = SpellCode_ShamanStormstrike + stormStrikeAuras := shaman.NewEnemyAuraArray(func(target *core.Unit) *core.Aura { + return core.StormstrikeAura(target) + }) shaman.RegisterSpell(core.SpellConfig{ + SpellCode: SpellCode_ShamanStormstrike, ActionID: core.ActionID{SpellID: 17364}, SpellSchool: core.SpellSchoolPhysical, DefenseType: core.DefenseTypeMelee, ProcMask: core.ProcMaskMeleeMHSpecial, - Flags: SpellFlagShaman | core.SpellFlagAPL | core.SpellFlagNoOnCastComplete, + Flags: SpellFlagShaman | core.SpellFlagAPL | core.SpellFlagMeleeMetrics, ManaCost: core.ManaCostOptions{ BaseCost: .21, @@ -36,25 +36,6 @@ func (shaman *Shaman) registerStormstrikeSpell() { }, }, - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - shaman.StormstrikeMH.Cast(sim, target) - }, - }) -} - -// Only the main-hand hit triggers procs / the debuff -func (shaman *Shaman) newStormstrikeHitSpell() *core.Spell { - stormStrikeAuras := shaman.NewEnemyAuraArray(func(target *core.Unit) *core.Aura { - return core.StormstrikeAura(target) - }) - - return shaman.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 17364}.WithTag(1), - SpellSchool: core.SpellSchoolPhysical, - DefenseType: core.DefenseTypeMelee, - ProcMask: core.ProcMaskMeleeMHSpecial, - Flags: core.SpellFlagMeleeMetrics, - DamageMultiplier: 1, ThreatMultiplier: 1, @@ -63,7 +44,6 @@ func (shaman *Shaman) newStormstrikeHitSpell() *core.Spell { result := spell.CalcAndDealDamage(sim, target, baseDamage, spell.OutcomeMeleeWeaponSpecialHitAndCrit) if result.Landed() { - // TODO: Stormstrike with 2 stacks instead of unlimited stormStrikeAuras.Get(target).Activate(sim) } }, diff --git a/sim/shaman/warden/warden_test.go b/sim/shaman/warden/warden_test.go index c6aae70148..0cd5dd0bc1 100644 --- a/sim/shaman/warden/warden_test.go +++ b/sim/shaman/warden/warden_test.go @@ -1,8 +1,6 @@ package warden import ( - "testing" - "github.com/wowsims/classic/sim/core" "github.com/wowsims/classic/sim/core/proto" ) @@ -11,27 +9,27 @@ func init() { RegisterWardenShaman() } -func TestWardenShaman(t *testing.T) { - core.RunTestSuite(t, t.Name(), core.FullCharacterTestSuiteGenerator([]core.CharacterSuiteConfig{ - { - Class: proto.Class_ClassShaman, - Phase: 4, - Race: proto.Race_RaceTroll, - OtherRaces: []proto.Race{proto.Race_RaceOrc}, +// func TestWardenShaman(t *testing.T) { +// core.RunTestSuite(t, t.Name(), core.FullCharacterTestSuiteGenerator([]core.CharacterSuiteConfig{ +// { +// Class: proto.Class_ClassShaman, +// Phase: 4, +// Race: proto.Race_RaceTroll, +// OtherRaces: []proto.Race{proto.Race_RaceOrc}, - Talents: Phase4Talents, - GearSet: core.GetGearSet("../../../ui/warden_shaman/gear_sets", "blank"), - Rotation: core.GetAplRotation("../../../ui/warden_shaman/apls", "phase_4_enh_tank"), - Buffs: core.FullBuffs, - Consumes: Phase4Consumes, - SpecOptions: core.SpecOptionsCombo{Label: "Default", SpecOptions: PlayerOptionsBasic}, +// Talents: Phase4Talents, +// GearSet: core.GetGearSet("../../../ui/warden_shaman/gear_sets", "blank"), +// Rotation: core.GetAplRotation("../../../ui/warden_shaman/apls", "phase_4_enh_tank"), +// Buffs: core.FullBuffs, +// Consumes: Phase4Consumes, +// SpecOptions: core.SpecOptionsCombo{Label: "Default", SpecOptions: PlayerOptionsBasic}, - ItemFilter: ItemFilters, - EPReferenceStat: proto.Stat_StatAttackPower, - StatsToWeigh: Stats, - }, - })) -} +// ItemFilter: ItemFilters, +// EPReferenceStat: proto.Stat_StatAttackPower, +// StatsToWeigh: Stats, +// }, +// })) +// } var PlayerOptionsBasic = &proto.Player_WardenShaman{ WardenShaman: &proto.WardenShaman{ diff --git a/sim/warlock/dps/TestWarlockSMRuin.results b/sim/warlock/dps/TestWarlockSMRuin.results index cfb8a8da79..2a65537a27 100644 --- a/sim/warlock/dps/TestWarlockSMRuin.results +++ b/sim/warlock/dps/TestWarlockSMRuin.results @@ -176,8 +176,8 @@ dps_results: { dps_results: { key: "TestWarlockSMRuin-Phase1-Average-Default" value: { - dps: 1044.59721 - tps: 869.64229 + dps: 1044.59711 + tps: 869.64219 } } dps_results: { diff --git a/sim/warlock/talents.go b/sim/warlock/talents.go index a010f581e9..f7888ad930 100644 --- a/sim/warlock/talents.go +++ b/sim/warlock/talents.go @@ -519,9 +519,8 @@ func (warlock *Warlock) applyImprovedShadowBolt() { return } - stackCount := int32(core.ISBNumStacksBase) warlock.ImprovedShadowBoltAuras = warlock.NewEnemyAuraArray(func(unit *core.Unit) *core.Aura { - return core.ImprovedShadowBoltAura(unit, warlock.Talents.ImprovedShadowBolt, stackCount) + return core.ImprovedShadowBoltAura(unit, warlock.Talents.ImprovedShadowBolt) }) affectedSpellCodes := []int32{SpellCode_WarlockShadowBolt} @@ -535,9 +534,9 @@ func (warlock *Warlock) applyImprovedShadowBolt() { }, OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { if result.Landed() && result.DidCrit() && slices.Contains(affectedSpellCodes, spell.SpellCode) { - impShadowBoltAura := warlock.ImprovedShadowBoltAuras.Get(result.Target) - impShadowBoltAura.Activate(sim) - impShadowBoltAura.SetStacks(sim, stackCount) + isbAura := warlock.ImprovedShadowBoltAuras.Get(result.Target) + isbAura.Activate(sim) + isbAura.SetStacks(sim, isbAura.MaxStacks) } }, })) diff --git a/tools/database/enchant_overrides.go b/tools/database/enchant_overrides.go index 3f72cd465e..5c57416879 100644 --- a/tools/database/enchant_overrides.go +++ b/tools/database/enchant_overrides.go @@ -33,44 +33,44 @@ var EnchantOverrides = []*proto.UIEnchant{ {EffectId: 1510, ItemId: 11649, SpellId: 15406, Name: "Lesser Arcanum of Voracity", Quality: proto.ItemQuality_ItemQualityUncommon, Stats: stats.Stats{stats.Spirit: 8}.ToFloatArray(), Type: proto.ItemType_ItemTypeHead, ExtraTypes: []proto.ItemType{proto.ItemType_ItemTypeLegs}, EnchantType: proto.EnchantType_EnchantTypeKit}, // Drop in Dire Maul - {EffectId: 2544, ItemId: 18330, SpellId: 22844, Name: "Arcanum of Focus", Quality: proto.ItemQuality_ItemQualityUncommon, Stats: stats.Stats{stats.SpellPower: 8}.ToFloatArray(), Type: proto.ItemType_ItemTypeHead, ExtraTypes: []proto.ItemType{proto.ItemType_ItemTypeLegs}, EnchantType: proto.EnchantType_EnchantTypeKit}, - {EffectId: 2545, ItemId: 18331, SpellId: 22846, Name: "Arcanum of Protection", Quality: proto.ItemQuality_ItemQualityUncommon, Stats: stats.Stats{stats.Dodge: 1}.ToFloatArray(), Type: proto.ItemType_ItemTypeHead, ExtraTypes: []proto.ItemType{proto.ItemType_ItemTypeLegs}, EnchantType: proto.EnchantType_EnchantTypeKit}, + {EffectId: 2544, ItemId: 18330, SpellId: 22844, Name: "Arcanum of Focus", Quality: proto.ItemQuality_ItemQualityUncommon, Stats: stats.Stats{stats.SpellPower: 8}.ToFloatArray(), Type: proto.ItemType_ItemTypeHead, ExtraTypes: []proto.ItemType{proto.ItemType_ItemTypeLegs}, EnchantType: proto.EnchantType_EnchantTypeKit, Phase: 2}, + {EffectId: 2545, ItemId: 18331, SpellId: 22846, Name: "Arcanum of Protection", Quality: proto.ItemQuality_ItemQualityUncommon, Stats: stats.Stats{stats.Dodge: 1}.ToFloatArray(), Type: proto.ItemType_ItemTypeHead, ExtraTypes: []proto.ItemType{proto.ItemType_ItemTypeLegs}, EnchantType: proto.EnchantType_EnchantTypeKit, Phase: 2}, // Melee Haste isn't actually a stat, so use Pseudostats.MeleeSpeedMultiplier - {EffectId: 2543, ItemId: 18329, SpellId: 22840, Name: "Arcanum of Rapidity", Quality: proto.ItemQuality_ItemQualityUncommon, Stats: stats.Stats{}.ToFloatArray(), Type: proto.ItemType_ItemTypeHead, ExtraTypes: []proto.ItemType{proto.ItemType_ItemTypeLegs}, EnchantType: proto.EnchantType_EnchantTypeKit}, + {EffectId: 2543, ItemId: 18329, SpellId: 22840, Name: "Arcanum of Rapidity", Quality: proto.ItemQuality_ItemQualityUncommon, Stats: stats.Stats{}.ToFloatArray(), Type: proto.ItemType_ItemTypeHead, ExtraTypes: []proto.ItemType{proto.ItemType_ItemTypeLegs}, EnchantType: proto.EnchantType_EnchantTypeKit, Phase: 2}, // ZG Enchants - {EffectId: 2681, ItemId: 22635, SpellId: 28161, Name: "Savage Guard", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.NatureResistance: 10}.ToFloatArray(), Type: proto.ItemType_ItemTypeHead, ExtraTypes: []proto.ItemType{proto.ItemType_ItemTypeLegs}, EnchantType: proto.EnchantType_EnchantTypeKit}, + {EffectId: 2681, ItemId: 22635, SpellId: 28161, Name: "Savage Guard", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.NatureResistance: 10}.ToFloatArray(), Type: proto.ItemType_ItemTypeHead, ExtraTypes: []proto.ItemType{proto.ItemType_ItemTypeLegs}, EnchantType: proto.EnchantType_EnchantTypeKit, Phase: 4}, // Druid - {EffectId: 2591, ItemId: 19790, SpellId: 24168, Name: "Animist's Caress", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.Stamina: 10, stats.Intellect: 10, stats.HealingPower: 24}.ToFloatArray(), Type: proto.ItemType_ItemTypeHead, ExtraTypes: []proto.ItemType{proto.ItemType_ItemTypeLegs}, EnchantType: proto.EnchantType_EnchantTypeKit, ClassAllowlist: []proto.Class{proto.Class_ClassDruid}}, + {EffectId: 2591, ItemId: 19790, SpellId: 24168, Name: "Animist's Caress", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.Stamina: 10, stats.Intellect: 10, stats.HealingPower: 24}.ToFloatArray(), Type: proto.ItemType_ItemTypeHead, ExtraTypes: []proto.ItemType{proto.ItemType_ItemTypeLegs}, EnchantType: proto.EnchantType_EnchantTypeKit, Phase: 4, ClassAllowlist: []proto.Class{proto.Class_ClassDruid}}, // Hunter - {EffectId: 2586, ItemId: 19785, SpellId: 24162, Name: "Falcon's Call", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.Stamina: 10, stats.RangedAttackPower: 24, stats.MeleeHit: 1 * core.MeleeHitRatingPerHitChance, stats.SpellHit: 1 * core.SpellHitRatingPerHitChance}.ToFloatArray(), Type: proto.ItemType_ItemTypeHead, ExtraTypes: []proto.ItemType{proto.ItemType_ItemTypeLegs}, EnchantType: proto.EnchantType_EnchantTypeKit, ClassAllowlist: []proto.Class{proto.Class_ClassHunter}}, + {EffectId: 2586, ItemId: 19785, SpellId: 24162, Name: "Falcon's Call", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.Stamina: 10, stats.RangedAttackPower: 24, stats.MeleeHit: 1 * core.MeleeHitRatingPerHitChance, stats.SpellHit: 1 * core.SpellHitRatingPerHitChance}.ToFloatArray(), Type: proto.ItemType_ItemTypeHead, ExtraTypes: []proto.ItemType{proto.ItemType_ItemTypeLegs}, EnchantType: proto.EnchantType_EnchantTypeKit, Phase: 4, ClassAllowlist: []proto.Class{proto.Class_ClassHunter}}, // Mage - {EffectId: 2588, ItemId: 19787, SpellId: 24164, Name: "Presence of Sight", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.SpellPower: 18, stats.SpellHit: 1 * core.SpellHitRatingPerHitChance}.ToFloatArray(), Type: proto.ItemType_ItemTypeHead, ExtraTypes: []proto.ItemType{proto.ItemType_ItemTypeLegs}, EnchantType: proto.EnchantType_EnchantTypeKit, ClassAllowlist: []proto.Class{proto.Class_ClassMage}}, + {EffectId: 2588, ItemId: 19787, SpellId: 24164, Name: "Presence of Sight", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.SpellPower: 18, stats.SpellHit: 1 * core.SpellHitRatingPerHitChance}.ToFloatArray(), Type: proto.ItemType_ItemTypeHead, ExtraTypes: []proto.ItemType{proto.ItemType_ItemTypeLegs}, EnchantType: proto.EnchantType_EnchantTypeKit, Phase: 4, ClassAllowlist: []proto.Class{proto.Class_ClassMage}}, // Paladin - {EffectId: 2584, ItemId: 19783, SpellId: 24160, Name: "Syncretist's Sigil", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.Stamina: 10, stats.Defense: 7, stats.HealingPower: 24}.ToFloatArray(), Type: proto.ItemType_ItemTypeHead, ExtraTypes: []proto.ItemType{proto.ItemType_ItemTypeLegs}, EnchantType: proto.EnchantType_EnchantTypeKit, ClassAllowlist: []proto.Class{proto.Class_ClassPaladin}}, + {EffectId: 2584, ItemId: 19783, SpellId: 24160, Name: "Syncretist's Sigil", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.Stamina: 10, stats.Defense: 7, stats.HealingPower: 24}.ToFloatArray(), Type: proto.ItemType_ItemTypeHead, ExtraTypes: []proto.ItemType{proto.ItemType_ItemTypeLegs}, EnchantType: proto.EnchantType_EnchantTypeKit, Phase: 4, ClassAllowlist: []proto.Class{proto.Class_ClassPaladin}}, // Priest - {EffectId: 2590, ItemId: 19789, SpellId: 24167, Name: "Prophetic Aura", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.Stamina: 10, stats.MP5: 4, stats.HealingPower: 24}.ToFloatArray(), Type: proto.ItemType_ItemTypeHead, ExtraTypes: []proto.ItemType{proto.ItemType_ItemTypeLegs}, EnchantType: proto.EnchantType_EnchantTypeKit, ClassAllowlist: []proto.Class{proto.Class_ClassPriest}}, + {EffectId: 2590, ItemId: 19789, SpellId: 24167, Name: "Prophetic Aura", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.Stamina: 10, stats.MP5: 4, stats.HealingPower: 24}.ToFloatArray(), Type: proto.ItemType_ItemTypeHead, ExtraTypes: []proto.ItemType{proto.ItemType_ItemTypeLegs}, EnchantType: proto.EnchantType_EnchantTypeKit, Phase: 4, ClassAllowlist: []proto.Class{proto.Class_ClassPriest}}, // Rogue - {EffectId: 2585, ItemId: 19784, SpellId: 24161, Name: "Death's Embrace", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.AttackPower: 28, stats.Dodge: 1 * core.DodgeRatingPerDodgeChance}.ToFloatArray(), Type: proto.ItemType_ItemTypeHead, ExtraTypes: []proto.ItemType{proto.ItemType_ItemTypeLegs}, EnchantType: proto.EnchantType_EnchantTypeKit, ClassAllowlist: []proto.Class{proto.Class_ClassRogue}}, + {EffectId: 2585, ItemId: 19784, SpellId: 24161, Name: "Death's Embrace", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.AttackPower: 28, stats.Dodge: 1 * core.DodgeRatingPerDodgeChance}.ToFloatArray(), Type: proto.ItemType_ItemTypeHead, ExtraTypes: []proto.ItemType{proto.ItemType_ItemTypeLegs}, EnchantType: proto.EnchantType_EnchantTypeKit, Phase: 4, ClassAllowlist: []proto.Class{proto.Class_ClassRogue}}, // Shaman - {EffectId: 2587, ItemId: 19786, SpellId: 24163, Name: "Vodouisant's Vigilant Embrace", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.Intellect: 15, stats.SpellPower: 13}.ToFloatArray(), Type: proto.ItemType_ItemTypeHead, ExtraTypes: []proto.ItemType{proto.ItemType_ItemTypeLegs}, EnchantType: proto.EnchantType_EnchantTypeKit, ClassAllowlist: []proto.Class{proto.Class_ClassShaman}}, + {EffectId: 2587, ItemId: 19786, SpellId: 24163, Name: "Vodouisant's Vigilant Embrace", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.Intellect: 15, stats.SpellPower: 13}.ToFloatArray(), Type: proto.ItemType_ItemTypeHead, ExtraTypes: []proto.ItemType{proto.ItemType_ItemTypeLegs}, EnchantType: proto.EnchantType_EnchantTypeKit, Phase: 4, ClassAllowlist: []proto.Class{proto.Class_ClassShaman}}, // Warlock - {EffectId: 2589, ItemId: 19788, SpellId: 24165, Name: "Hoodoo Hex", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.Stamina: 10, stats.SpellPower: 18}.ToFloatArray(), Type: proto.ItemType_ItemTypeHead, ExtraTypes: []proto.ItemType{proto.ItemType_ItemTypeLegs}, EnchantType: proto.EnchantType_EnchantTypeKit, ClassAllowlist: []proto.Class{proto.Class_ClassWarlock}}, + {EffectId: 2589, ItemId: 19788, SpellId: 24165, Name: "Hoodoo Hex", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.Stamina: 10, stats.SpellPower: 18}.ToFloatArray(), Type: proto.ItemType_ItemTypeHead, ExtraTypes: []proto.ItemType{proto.ItemType_ItemTypeLegs}, EnchantType: proto.EnchantType_EnchantTypeKit, Phase: 4, ClassAllowlist: []proto.Class{proto.Class_ClassWarlock}}, // Warrior - {EffectId: 2583, ItemId: 19782, SpellId: 24149, Name: "Presence of Might", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.Stamina: 20, stats.Defense: 7, stats.BlockValue: 15}.ToFloatArray(), Type: proto.ItemType_ItemTypeHead, ExtraTypes: []proto.ItemType{proto.ItemType_ItemTypeLegs}, EnchantType: proto.EnchantType_EnchantTypeKit, ClassAllowlist: []proto.Class{proto.Class_ClassWarrior}}, + {EffectId: 2583, ItemId: 19782, SpellId: 24149, Name: "Presence of Might", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.Stamina: 20, stats.Defense: 7, stats.BlockValue: 15}.ToFloatArray(), Type: proto.ItemType_ItemTypeHead, ExtraTypes: []proto.ItemType{proto.ItemType_ItemTypeLegs}, EnchantType: proto.EnchantType_EnchantTypeKit, Phase: 4, ClassAllowlist: []proto.Class{proto.Class_ClassWarrior}}, // Head // Shoulder // Drop in ZG - {EffectId: 2604, ItemId: 20078, SpellId: 24420, Name: "Zandalar Signet of Serenity", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.HealingPower: 33}.ToFloatArray(), Type: proto.ItemType_ItemTypeShoulder}, - {EffectId: 2605, ItemId: 20076, SpellId: 24421, Name: "Zandalar Signet of Mojo", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.SpellPower: 18, stats.HealingPower: 18}.ToFloatArray(), Type: proto.ItemType_ItemTypeShoulder}, - {EffectId: 2606, ItemId: 20077, SpellId: 24422, Name: "Zandalar Signet of Might", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.AttackPower: 30, stats.RangedAttackPower: 30}.ToFloatArray(), Type: proto.ItemType_ItemTypeShoulder}, + {EffectId: 2604, ItemId: 20078, SpellId: 24420, Name: "Zandalar Signet of Serenity", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.HealingPower: 33}.ToFloatArray(), Type: proto.ItemType_ItemTypeShoulder, Phase: 4}, + {EffectId: 2605, ItemId: 20076, SpellId: 24421, Name: "Zandalar Signet of Mojo", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.SpellPower: 18, stats.HealingPower: 18}.ToFloatArray(), Type: proto.ItemType_ItemTypeShoulder, Phase: 4}, + {EffectId: 2606, ItemId: 20077, SpellId: 24422, Name: "Zandalar Signet of Might", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.AttackPower: 30, stats.RangedAttackPower: 30}.ToFloatArray(), Type: proto.ItemType_ItemTypeShoulder, Phase: 4}, // Drop in naxxramas - {EffectId: 2715, ItemId: 23547, SpellId: 29475, Name: "Resilience of the Scourge", Quality: proto.ItemQuality_ItemQualityEpic, Stats: stats.Stats{stats.HealingPower: 31, stats.MP5: 5}.ToFloatArray(), Type: proto.ItemType_ItemTypeShoulder}, - {EffectId: 2717, ItemId: 23548, SpellId: 29483, Name: "Might of the Scourge", Quality: proto.ItemQuality_ItemQualityEpic, Stats: stats.Stats{stats.AttackPower: 26, stats.MeleeCrit: 0.01}.ToFloatArray(), Type: proto.ItemType_ItemTypeShoulder}, - {EffectId: 2716, ItemId: 23549, SpellId: 29480, Name: "Fortitude of the Scourge", Quality: proto.ItemQuality_ItemQualityEpic, Stats: stats.Stats{stats.Stamina: 16, stats.BonusArmor: 100}.ToFloatArray(), Type: proto.ItemType_ItemTypeShoulder}, - {EffectId: 2721, ItemId: 23545, SpellId: 29467, Name: "Power of the Scourge", Quality: proto.ItemQuality_ItemQualityEpic, Stats: stats.Stats{stats.SpellPower: 15, stats.HealingPower: 15, stats.SpellCrit: 0.01}.ToFloatArray(), Type: proto.ItemType_ItemTypeShoulder}, + {EffectId: 2715, ItemId: 23547, SpellId: 29475, Name: "Resilience of the Scourge", Quality: proto.ItemQuality_ItemQualityEpic, Stats: stats.Stats{stats.HealingPower: 31, stats.MP5: 5}.ToFloatArray(), Type: proto.ItemType_ItemTypeShoulder, Phase: 6}, + {EffectId: 2717, ItemId: 23548, SpellId: 29483, Name: "Might of the Scourge", Quality: proto.ItemQuality_ItemQualityEpic, Stats: stats.Stats{stats.AttackPower: 26, stats.MeleeCrit: 0.01}.ToFloatArray(), Type: proto.ItemType_ItemTypeShoulder, Phase: 6}, + {EffectId: 2716, ItemId: 23549, SpellId: 29480, Name: "Fortitude of the Scourge", Quality: proto.ItemQuality_ItemQualityEpic, Stats: stats.Stats{stats.Stamina: 16, stats.BonusArmor: 100}.ToFloatArray(), Type: proto.ItemType_ItemTypeShoulder, Phase: 6}, + {EffectId: 2721, ItemId: 23545, SpellId: 29467, Name: "Power of the Scourge", Quality: proto.ItemQuality_ItemQualityEpic, Stats: stats.Stats{stats.SpellPower: 15, stats.SpellCrit: 1 * core.SpellCritRatingPerCritChance}.ToFloatArray(), Type: proto.ItemType_ItemTypeShoulder, Phase: 6}, // Back {EffectId: 2, SpellId: 7454, Name: "Enchant Cloak - Minor Resistance", Quality: proto.ItemQuality_ItemQualityCommon, Stats: stats.Stats{stats.ArcaneResistance: 1, stats.FrostResistance: 1, stats.FireResistance: 1, stats.NatureResistance: 1, stats.ShadowResistance: 1}.ToFloatArray(), Type: proto.ItemType_ItemTypeBack}, @@ -87,12 +87,12 @@ var EnchantOverrides = []*proto.UIEnchant{ {EffectId: 1888, SpellId: 20014, Name: "Enchant Cloak - Greater Resistance", Quality: proto.ItemQuality_ItemQualityCommon, Stats: stats.Stats{stats.ArcaneResistance: 5, stats.FireResistance: 5, stats.FrostResistance: 5, stats.NatureResistance: 5, stats.ShadowResistance: 5}.ToFloatArray(), Type: proto.ItemType_ItemTypeBack}, {EffectId: 1889, SpellId: 20015, Name: "Enchant Cloak - Superior Defense", Quality: proto.ItemQuality_ItemQualityCommon, Stats: stats.Stats{stats.BonusArmor: 70}.ToFloatArray(), Type: proto.ItemType_ItemTypeBack}, // Requires Cenarion Circle - Friendly - {EffectId: 2619, SpellId: 25081, Name: "Enchant Cloak - Greater Fire Resistance", Quality: proto.ItemQuality_ItemQualityCommon, Stats: stats.Stats{stats.FireResistance: 15}.ToFloatArray(), Type: proto.ItemType_ItemTypeBack}, - {EffectId: 2620, SpellId: 25082, Name: "Enchant Cloak - Greater Nature Resistance", Quality: proto.ItemQuality_ItemQualityCommon, Stats: stats.Stats{stats.NatureResistance: 15}.ToFloatArray(), Type: proto.ItemType_ItemTypeBack}, + {EffectId: 2619, SpellId: 25081, Name: "Enchant Cloak - Greater Fire Resistance", Quality: proto.ItemQuality_ItemQualityCommon, Stats: stats.Stats{stats.FireResistance: 15}.ToFloatArray(), Type: proto.ItemType_ItemTypeBack, Phase: 4}, + {EffectId: 2620, SpellId: 25082, Name: "Enchant Cloak - Greater Nature Resistance", Quality: proto.ItemQuality_ItemQualityCommon, Stats: stats.Stats{stats.NatureResistance: 15}.ToFloatArray(), Type: proto.ItemType_ItemTypeBack, Phase: 4}, // Drop in AQ - {EffectId: 910, SpellId: 25083, Name: "Enchant Cloak - Stealth", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{}.ToFloatArray(), Type: proto.ItemType_ItemTypeBack}, - {EffectId: 2621, SpellId: 25084, Name: "Enchant Cloak - Subtlety", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{}.ToFloatArray(), Type: proto.ItemType_ItemTypeBack}, - {EffectId: 2622, SpellId: 25086, Name: "Enchant Cloak - Dodge", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.Dodge: 1 * core.DodgeRatingPerDodgeChance}.ToFloatArray(), Type: proto.ItemType_ItemTypeBack}, + {EffectId: 910, SpellId: 25083, Name: "Enchant Cloak - Stealth", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{}.ToFloatArray(), Type: proto.ItemType_ItemTypeBack, Phase: 4}, + {EffectId: 2621, SpellId: 25084, Name: "Enchant Cloak - Subtlety", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{}.ToFloatArray(), Type: proto.ItemType_ItemTypeBack, Phase: 4}, + {EffectId: 2622, SpellId: 25086, Name: "Enchant Cloak - Dodge", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.Dodge: 1 * core.DodgeRatingPerDodgeChance}.ToFloatArray(), Type: proto.ItemType_ItemTypeBack, Phase: 4}, // Chest {EffectId: 41, SpellId: 7420, Name: "Enchant Chest - Minor Health", Quality: proto.ItemQuality_ItemQualityCommon, Stats: stats.Stats{stats.Health: 5}.ToFloatArray(), Type: proto.ItemType_ItemTypeChest}, @@ -157,12 +157,12 @@ var EnchantOverrides = []*proto.UIEnchant{ {EffectId: 1887, SpellId: 20012, Name: "Enchant Gloves - Greater Agility", Quality: proto.ItemQuality_ItemQualityUncommon, Stats: stats.Stats{stats.Agility: 7}.ToFloatArray(), Type: proto.ItemType_ItemTypeHands}, {EffectId: 927, SpellId: 20013, Name: "Enchant Gloves - Greater Strength", Quality: proto.ItemQuality_ItemQualityCommon, Stats: stats.Stats{stats.Strength: 7}.ToFloatArray(), Type: proto.ItemType_ItemTypeHands}, // All drops in AQ - {EffectId: 2616, SpellId: 25078, Name: "Enchant Gloves - Fire Power", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.FirePower: 20}.ToFloatArray(), Type: proto.ItemType_ItemTypeHands}, - {EffectId: 2615, SpellId: 25074, Name: "Enchant Gloves - Frost Power", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.FrostPower: 20}.ToFloatArray(), Type: proto.ItemType_ItemTypeHands}, - {EffectId: 2617, SpellId: 25079, Name: "Enchant Gloves - Healing Power", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.HealingPower: 30}.ToFloatArray(), Type: proto.ItemType_ItemTypeHands}, - {EffectId: 2614, SpellId: 25073, Name: "Enchant Gloves - Shadow Power", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.ShadowPower: 20}.ToFloatArray(), Type: proto.ItemType_ItemTypeHands}, - {EffectId: 2564, SpellId: 25080, Name: "Enchant Gloves - Superior Agility", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.Agility: 15}.ToFloatArray(), Type: proto.ItemType_ItemTypeHands}, - {EffectId: 2613, SpellId: 25072, Name: "Enchant Gloves - Threat", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{}.ToFloatArray(), Type: proto.ItemType_ItemTypeHands}, + {EffectId: 2616, SpellId: 25078, Name: "Enchant Gloves - Fire Power", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.FirePower: 20}.ToFloatArray(), Type: proto.ItemType_ItemTypeHands, Phase: 4}, + {EffectId: 2615, SpellId: 25074, Name: "Enchant Gloves - Frost Power", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.FrostPower: 20}.ToFloatArray(), Type: proto.ItemType_ItemTypeHands, Phase: 4}, + {EffectId: 2617, SpellId: 25079, Name: "Enchant Gloves - Healing Power", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.HealingPower: 30}.ToFloatArray(), Type: proto.ItemType_ItemTypeHands, Phase: 4}, + {EffectId: 2614, SpellId: 25073, Name: "Enchant Gloves - Shadow Power", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.ShadowPower: 20}.ToFloatArray(), Type: proto.ItemType_ItemTypeHands, Phase: 4}, + {EffectId: 2564, SpellId: 25080, Name: "Enchant Gloves - Superior Agility", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{stats.Agility: 15}.ToFloatArray(), Type: proto.ItemType_ItemTypeHands, Phase: 4}, + {EffectId: 2613, SpellId: 25072, Name: "Enchant Gloves - Threat", Quality: proto.ItemQuality_ItemQualityRare, Stats: stats.Stats{}.ToFloatArray(), Type: proto.ItemType_ItemTypeHands, Phase: 4}, // Feet {EffectId: 247, SpellId: 7867, Name: "Enchant Boots - Minor Agility", Quality: proto.ItemQuality_ItemQualityUncommon, Stats: stats.Stats{stats.Agility: 1}.ToFloatArray(), Type: proto.ItemType_ItemTypeFeet}, diff --git a/ui/core/components/individual_sim_ui/item_swap_picker.tsx b/ui/core/components/individual_sim_ui/item_swap_picker.tsx index 18ce8c59b9..38917ea325 100644 --- a/ui/core/components/individual_sim_ui/item_swap_picker.tsx +++ b/ui/core/components/individual_sim_ui/item_swap_picker.tsx @@ -90,8 +90,8 @@ export class ItemSwapPicker extends Component { const gearItem = player.getGear().getEquippedItem(slot); const swapItem = player.getItemSwapGear().getEquippedItem(slot); - newGear = newGear.withEquippedItem(slot, swapItem, player.canDualWield2H()); - newIsg = newIsg.withEquippedItem(slot, gearItem, player.canDualWield2H()); + newGear = newGear.withEquippedItem(slot, swapItem); + newIsg = newIsg.withEquippedItem(slot, gearItem); }); TypedEvent.freezeAllAndDo(() => { diff --git a/ui/core/components/individual_sim_ui/settings_tab.ts b/ui/core/components/individual_sim_ui/settings_tab.ts index 55bf6d8bbd..909f2cca99 100644 --- a/ui/core/components/individual_sim_ui/settings_tab.ts +++ b/ui/core/components/individual_sim_ui/settings_tab.ts @@ -21,7 +21,7 @@ import { MultiIconPicker, MultiIconPickerItemConfig } from '../multi_icon_picker import { NumberPicker } from '../number_picker'; import { SavedDataManager } from '../saved_data_manager'; import { SimTab } from '../sim_tab'; -import { IsbConfig } from './../other_inputs'; +import { IsbConfig, StormstrikeConfig } from './../other_inputs'; import { ConsumesPicker } from './consumes_picker'; import { ItemSwapPicker } from './item_swap_picker'; import { PresetConfigurationPicker } from './preset_configuration_picker'; @@ -74,6 +74,7 @@ export class SettingsTab extends SimTab { this.buildConsumesSection(); this.buildOtherSettings(); this.buildIsbSettings(); + this.buildStormstrikeSettings(); if (!this.simUI.isWithinRaidSim) { this.buildBuffsSettings(); @@ -222,6 +223,24 @@ export class SettingsTab extends SimTab { } } + private buildStormstrikeSettings() { + if (!this.simUI.isWithinRaidSim) { + const contentBlock = new ContentBlock(this.column1, 'other-settings', { + header: { title: 'Stormstrike' }, + }); + + this.configureInputSection(contentBlock.bodyElement, StormstrikeConfig); + + this.simUI.player.getRaid()!.debuffsChangeEmitter.on(() => { + if (this.simUI.player.getRaid()?.getDebuffs()?.stormstrike) { + contentBlock.rootElem.classList.remove('hide'); + } else { + contentBlock.rootElem.classList.add('hide'); + } + }); + } + } + private buildBuffsSettings() { const buffOptions = relevantStatOptions(BuffDebuffInputs.RAID_BUFFS_CONFIG, this.simUI); const miscBuffOptions = relevantStatOptions(BuffDebuffInputs.MISC_BUFFS_CONFIG, this.simUI); diff --git a/ui/core/components/inputs/buffs_debuffs.ts b/ui/core/components/inputs/buffs_debuffs.ts index 7ab90abc41..6f9343adfa 100644 --- a/ui/core/components/inputs/buffs_debuffs.ts +++ b/ui/core/components/inputs/buffs_debuffs.ts @@ -474,6 +474,14 @@ export const SpellWintersChillDebuff = withLabel( 'Frost Damage', ); +export const SpellStormstrikeDebuff = withLabel( + makeBooleanDebuffInput({ + actionId: () => ActionId.fromSpellId(17364), + fieldName: 'stormstrike', + }), + 'Stormstrike', +) + export const SpellShadowWeavingDebuff = withLabel( makeBooleanDebuffInput({ actionId: () => ActionId.fromSpellId(15334), @@ -783,6 +791,11 @@ export const DEBUFFS_CONFIG = [ picker: IconPicker, stats: [Stat.StatFrostPower], }, + { + config: SpellStormstrikeDebuff, + picker: IconPicker, + stats: [Stat.StatNaturePower], + }, { config: SpellShadowWeavingDebuff, picker: IconPicker, diff --git a/ui/core/components/inputs/consumables.ts b/ui/core/components/inputs/consumables.ts index 254730ac9f..e4fa3be9bb 100644 --- a/ui/core/components/inputs/consumables.ts +++ b/ui/core/components/inputs/consumables.ts @@ -26,7 +26,6 @@ import { Stat, StrengthBuff, WeaponImbue, - WeaponType, ZanzaBuff, } from '../../proto/common'; import { ActionId } from '../../proto_utils/action_id'; @@ -969,9 +968,6 @@ const ROGUE_IMBUES: ConsumableStatOption[] = [ { config: InstantPoisonWeaponImbue, stats: [] }, { config: DeadlyPoisonWeaponImbue, stats: [] }, { config: WoundPoisonWeaponImbue, stats: [] }, - // These are not yet implemented for rogues - // { config: OccultPoisonWeaponImbue, stats: [] }, - // { config: SebaciousPoisonWeaponImbue, stats: [] }, ]; const CONSUMABLES_IMBUES = (slot: ItemSlot): ConsumableStatOption[] => [ diff --git a/ui/core/components/other_inputs.ts b/ui/core/components/other_inputs.ts index cf4f65b2b7..fb9e3b13c4 100644 --- a/ui/core/components/other_inputs.ts +++ b/ui/core/components/other_inputs.ts @@ -1,6 +1,4 @@ import { BooleanPicker } from '../components/boolean_picker.js'; -import { CURRENT_LEVEL_CAP } from '../constants/mechanics.js'; -import { CURRENT_PHASE } from '../constants/other.js'; import { Player } from '../player.js'; import { Spec, UnitReference } from '../proto/common.js'; import { emptyUnitReference } from '../proto_utils/utils.js'; @@ -125,22 +123,6 @@ export const DistanceFromTarget = { }, }; -export const IsbUsingShadowflame = { - id: 'isb-using-shadowflame', - type: 'boolean' as const, - label: 'Has Shadowflame Rune', - labelTooltip: 'Whether or not the Warlock is using the Shadowflame rune (4 stacks of ISB vs. 10)', - float: true, - defaultValue: true, - inline: true, - changedEvent: (player: Player) => TypedEvent.onAny([player.changeEmitter, player.getRaid()!.debuffsChangeEmitter]), - getValue: (player: Player) => player.getIsbUsingShadowflame(), - setValue: (eventID: EventID, player: Player, newValue: boolean) => { - player.setIsbUsingShadowflame(eventID, newValue); - }, - showWhen: (player: Player) => player.getRaid()?.getDebuffs().improvedShadowBolt == true, -}; - export const IsbSbFrequencey = { id: 'isb-sb-frequency', type: 'number' as const, @@ -154,7 +136,7 @@ export const IsbSbFrequencey = { setValue: (eventID: EventID, player: Player, newValue: number) => { player.setIsbSbFrequency(eventID, newValue); }, - showWhen: (player: Player) => player.getRaid()?.getDebuffs().improvedShadowBolt == true, + showWhen: (player: Player) => player.getRaid()?.getDebuffs().improvedShadowBolt === true, }; export const IsbCrit = { @@ -170,7 +152,7 @@ export const IsbCrit = { setValue: (eventID: EventID, player: Player, newValue: number) => { player.setIsbCrit(eventID, newValue); }, - showWhen: (player: Player) => player.getRaid()?.getDebuffs().improvedShadowBolt == true, + showWhen: (player: Player) => player.getRaid()?.getDebuffs().improvedShadowBolt === true, }; export const IsbWarlocks = { @@ -185,7 +167,7 @@ export const IsbWarlocks = { setValue: (eventID: EventID, player: Player, newValue: number) => { player.setIsbWarlocks(eventID, newValue); }, - showWhen: (player: Player) => player.getRaid()?.getDebuffs().improvedShadowBolt == true, + showWhen: (player: Player) => player.getRaid()?.getDebuffs().improvedShadowBolt === true, }; export const IsbSpriests = { @@ -200,12 +182,49 @@ export const IsbSpriests = { player.setIsbSpriests(eventID, newValue); }, showWhen: (player: Player) => - player.getRaid()?.getDebuffs().improvedShadowBolt == true || (player as Player)?.getTalents().improvedShadowBolt > 0, + player.getRaid()?.getDebuffs().improvedShadowBolt === true || (player as Player)?.getTalents().improvedShadowBolt > 0, }; export const IsbConfig = { tooltip: 'Improved Shadow Bolt debuff configuration', - inputs: [IsbUsingShadowflame, IsbSbFrequencey, IsbCrit, IsbWarlocks, IsbSpriests], + inputs: [IsbSbFrequencey, IsbCrit, IsbWarlocks, IsbSpriests], +}; + +export const StormstrikeFrequency = { + id: 'stormstrike-frequency', + type: 'number' as const, + label: 'Stormstrike Cast Frequency', + labelTooltip: 'How often (in Seconds) that Stormstrike is cast by an external Enhancement Shaman.', + float: true, + defaultValue: 20.0, + inline: true, + changedEvent: (player: Player) => TypedEvent.onAny([player.changeEmitter, player.getRaid()!.debuffsChangeEmitter]), + getValue: (player: Player) => player.getStormstrikeFrequency(), + setValue: (eventID: EventID, player: Player, newValue: number) => { + player.setStormstrikeFrequency(eventID, newValue); + }, + showWhen: (player: Player) => player.getRaid()?.getDebuffs().stormstrike === true, +}; + +export const StormstrikeNatureAttackersFrequencey = { + id: 'stormstrike-attackers-frequency', + type: 'number' as const, + label: 'Other Nature Attacks Frequency', + labelTooltip: 'How often (in Seconds) that external attackers deal Nature damage to the target.', + float: true, + defaultValue: 4.0, + inline: true, + changedEvent: (player: Player) => TypedEvent.onAny([player.changeEmitter, player.getRaid()!.debuffsChangeEmitter]), + getValue: (player: Player) => player.getStormstrikeNatureAttackerFrequency(), + setValue: (eventID: EventID, player: Player, newValue: number) => { + player.setStormstrikeNatureAttackerFrequency(eventID, newValue); + }, + showWhen: (player: Player) => player.getRaid()?.getDebuffs().stormstrike === true, +}; + +export const StormstrikeConfig = { + tooltip: 'Stormstrike debuff configuration', + inputs: [StormstrikeFrequency, StormstrikeNatureAttackersFrequencey], }; export const TankAssignment = { diff --git a/ui/core/constants/tooltips.ts b/ui/core/constants/tooltips.ts index ea9a76a749..9dca0bbc21 100644 --- a/ui/core/constants/tooltips.ts +++ b/ui/core/constants/tooltips.ts @@ -19,8 +19,6 @@ export const EP_TOOLTIP = ` export const UNSPECT_TALENT_POINTS_WARNING = 'Unspent talent points.'; export const TOO_MANY_TALENT_POINTS_WARNING = 'More talent points spent than current level selected.'; -export const TITANS_GRIP_WARNING = "Dual wielding two-handed weapon(s) without Titan's Grip spec."; - export const GEAR_MIN_LEVEL_WARNING = (playerLevel: number) => `Wearing gear with a minumum level requirement above level ${playerLevel}.`; export const TOOLTIP_METRIC_LABELS = { diff --git a/ui/core/individual_sim_ui.ts b/ui/core/individual_sim_ui.ts index 7cae0ab571..0f58b6abb4 100644 --- a/ui/core/individual_sim_ui.ts +++ b/ui/core/individual_sim_ui.ts @@ -29,9 +29,7 @@ import { Encounter as EncounterProto, EquipmentSpec, Faction, - HandType, IndividualBuffs, - ItemSlot, PartyBuffs, Profession, PseudoStat, @@ -229,21 +227,6 @@ export abstract class IndividualSimUI extends SimUI { } }, }); - this.addWarning({ - updateOn: TypedEvent.onAny([this.player.gearChangeEmitter, this.player.talentsChangeEmitter]), - getContent: () => { - if ( - !this.player.canDualWield2H() && - ((this.player.getEquippedItem(ItemSlot.ItemSlotMainHand)?.item.handType == HandType.HandTypeTwoHand && - this.player.getEquippedItem(ItemSlot.ItemSlotOffHand) != null) || - this.player.getEquippedItem(ItemSlot.ItemSlotOffHand)?.item.handType == HandType.HandTypeTwoHand) - ) { - return Tooltips.TITANS_GRIP_WARNING; - } else { - return ''; - } - }, - }); // TODO: This is showing the warning even when no items above player level are equipped // this.addWarning({ // updateOn: TypedEvent.onAny([this.player.gearChangeEmitter]), diff --git a/ui/core/launched_sims.ts b/ui/core/launched_sims.ts index 142820e46e..2387a754a5 100644 --- a/ui/core/launched_sims.ts +++ b/ui/core/launched_sims.ts @@ -42,7 +42,7 @@ export const simLaunchStatuses: Record = { }, [Spec.SpecElementalShaman]: { phase: Phase.Phase1, - status: LaunchStatus.Unlaunched, + status: LaunchStatus.Alpha, }, [Spec.SpecEnhancementShaman]: { phase: Phase.Phase1, diff --git a/ui/core/player.ts b/ui/core/player.ts index 0c31b902d5..5456dc4bd3 100644 --- a/ui/core/player.ts +++ b/ui/core/player.ts @@ -244,12 +244,14 @@ export class Player { private healingModel: HealingModel = HealingModel.create(); private healingEnabled = false; - private isbUsingShadowflame = true; private isbSbFrequency = 3.0; private isbCrit = 25.0; private isbWarlocks = 1.0; private isbSpriests = 0; + private stormstrikeFrequency = 20.0; + private stormstrikeNatureAttackerFrequency = 4.0; + private readonly autoRotationGenerator: AutoRotationGenerator | null = null; private readonly simpleRotationGenerator: SimpleRotationGenerator | null = null; @@ -609,12 +611,8 @@ export class Player { this.consumesChangeEmitter.emit(eventID); } - canDualWield2H(): boolean { - return false; - } - equipItem(eventID: EventID, slot: ItemSlot, newItem: EquippedItem | null) { - this.setGear(eventID, this.gear.withEquippedItem(slot, newItem, this.canDualWield2H())); + this.setGear(eventID, this.gear.withEquippedItem(slot, newItem)); } getEquippedItem(slot: ItemSlot): EquippedItem | null { @@ -644,7 +642,7 @@ export class Player { } equipItemSwapitem(eventID: EventID, slot: ItemSlot, newItem: EquippedItem | null) { - this.setItemSwapGear(eventID, this.itemSwapGear.withEquippedItem(slot, newItem, this.canDualWield2H())); + this.setItemSwapGear(eventID, this.itemSwapGear.withEquippedItem(slot, newItem)); } getItemSwapItem(slot: ItemSlot): EquippedItem | null { @@ -1000,17 +998,6 @@ export class Player { this.healingModelChangeEmitter.emit(eventID); } - getIsbUsingShadowflame(): boolean { - return this.isbUsingShadowflame; - } - - setIsbUsingShadowflame(eventID: EventID, newValue: boolean) { - if (newValue === this.isbUsingShadowflame) return; - - this.isbUsingShadowflame = newValue; - this.changeEmitter.emit(eventID); - } - getIsbSbFrequency(): number { return this.isbSbFrequency; } @@ -1055,6 +1042,28 @@ export class Player { this.changeEmitter.emit(eventID); } + getStormstrikeFrequency(): number { + return this.stormstrikeFrequency; + } + + setStormstrikeFrequency(eventID: EventID, newStormstrikeFrequency: number) { + if (newStormstrikeFrequency === this.stormstrikeFrequency) return; + + this.stormstrikeFrequency = newStormstrikeFrequency; + this.changeEmitter.emit(eventID); + } + + getStormstrikeNatureAttackerFrequency(): number { + return this.stormstrikeNatureAttackerFrequency; + } + + setStormstrikeNatureAttackerFrequency(eventID: EventID, newStormstrikeNatureAttackerFrequency: number) { + if (newStormstrikeNatureAttackerFrequency === this.stormstrikeNatureAttackerFrequency) return; + + this.stormstrikeNatureAttackerFrequency = newStormstrikeNatureAttackerFrequency; + this.changeEmitter.emit(eventID); + } + computeStatsEP(stats?: Stats): number { if (stats === undefined) { return 0; @@ -1368,6 +1377,8 @@ export class Player { isbCrit: this.getIsbCrit(), isbWarlocks: this.getIsbWarlocks(), isbSpriests: this.getIsbSpriests(), + stormstrikeFrequency: this.getStormstrikeFrequency(), + stormstrikeNatureAttackerFrequency: this.getStormstrikeNatureAttackerFrequency(), }); player = withSpecProto(this.spec, player, this.getSpecOptions()); } @@ -1425,6 +1436,8 @@ export class Player { this.setIsbCrit(eventID, proto.isbCrit); this.setIsbWarlocks(eventID, proto.isbWarlocks); this.setIsbSpriests(eventID, proto.isbSpriests); + this.setStormstrikeFrequency(eventID, proto.stormstrikeFrequency); + this.setStormstrikeNatureAttackerFrequency(eventID, proto.stormstrikeNatureAttackerFrequency); } if (loadCategory(SimSettingCategories.External)) { this.setBuffs(eventID, proto.buffs || IndividualBuffs.create()); diff --git a/ui/core/proto_utils/gear.ts b/ui/core/proto_utils/gear.ts index 396ffc836c..4bf80e55f9 100644 --- a/ui/core/proto_utils/gear.ts +++ b/ui/core/proto_utils/gear.ts @@ -47,7 +47,7 @@ abstract class BaseGear { * * Checks for validity and removes/exchanges items/gems as needed. */ - protected withEquippedItemInternal(newSlot: ItemSlot, newItem: EquippedItem | null, canDualWield2H: boolean): Partial { + protected withEquippedItemInternal(newSlot: ItemSlot, newItem: EquippedItem | null): Partial { // Create a new identical set of gear const newInternalGear = this.asMap(); @@ -58,7 +58,7 @@ abstract class BaseGear { // Actually assign the new item. newInternalGear[newSlot] = newItem; - BaseGear.validateWeaponCombo(newInternalGear, newSlot, canDualWield2H); + BaseGear.validateWeaponCombo(newInternalGear, newSlot); return newInternalGear; } @@ -75,9 +75,9 @@ abstract class BaseGear { } } - private static validateWeaponCombo(gear: Partial, newSlot: ItemSlot, canDualWield2H: boolean) { + private static validateWeaponCombo(gear: Partial, newSlot: ItemSlot) { // Check for valid weapon combos. - if (!validWeaponCombo(gear[ItemSlot.ItemSlotMainHand]?.item, gear[ItemSlot.ItemSlotOffHand]?.item, canDualWield2H)) { + if (!validWeaponCombo(gear[ItemSlot.ItemSlotMainHand]?.item, gear[ItemSlot.ItemSlotOffHand]?.item)) { if (newSlot == ItemSlot.ItemSlotOffHand) { gear[ItemSlot.ItemSlotMainHand] = null; } else { @@ -120,8 +120,8 @@ export class Gear extends BaseGear { return getEnumValues(ItemSlot); } - withEquippedItem(newSlot: ItemSlot, newItem: EquippedItem | null, canDualWield2H: boolean): Gear { - return new Gear(this.withEquippedItemInternal(newSlot, newItem, canDualWield2H)); + withEquippedItem(newSlot: ItemSlot, newItem: EquippedItem | null): Gear { + return new Gear(this.withEquippedItemInternal(newSlot, newItem)); } getTrinkets(): Array { @@ -189,8 +189,8 @@ export class ItemSwapGear extends BaseGear { return [ItemSlot.ItemSlotMainHand, ItemSlot.ItemSlotOffHand, ItemSlot.ItemSlotRanged]; } - withEquippedItem(newSlot: ItemSlot, newItem: EquippedItem | null, canDualWield2H: boolean): ItemSwapGear { - return new ItemSwapGear(this.withEquippedItemInternal(newSlot, newItem, canDualWield2H)); + withEquippedItem(newSlot: ItemSlot, newItem: EquippedItem | null): ItemSwapGear { + return new ItemSwapGear(this.withEquippedItemInternal(newSlot, newItem)); } toProto(): ItemSwap { diff --git a/ui/core/proto_utils/utils.ts b/ui/core/proto_utils/utils.ts index b30dc62d0f..f127c3927b 100644 --- a/ui/core/proto_utils/utils.ts +++ b/ui/core/proto_utils/utils.ts @@ -1061,7 +1061,7 @@ export const specToEligibleRaces: Record> = { // Specs that can dual wield. This could be based on class, except that // Enhancement Shaman learn dual wield from a talent. -const dualWieldClasses: Array = [Class.ClassHunter, Class.ClassRogue, Class.ClassShaman, Class.ClassWarrior]; +const dualWieldClasses: Array = [Class.ClassHunter, Class.ClassRogue, Class.ClassWarrior]; export function canDualWield(player: Player): boolean { return dualWieldClasses.includes(player.getClass()); @@ -1520,28 +1520,13 @@ export function getEligibleItemSlots(item: Item): Array { throw new Error('Could not find item slots for item: ' + Item.toJsonString(item)); } -// Returns whether the given main-hand and off-hand items can be worn at the -// same time. -export function validWeaponCombo(mainHand: Item | null | undefined, offHand: Item | null | undefined, canDW2h: boolean): boolean { - if (mainHand == null || offHand == null) { +// Returns whether the given main-hand and off-hand items can be worn at the same time. +export function validWeaponCombo(mainHand: Item | null | undefined, offHand: Item | null | undefined): boolean { + if (!mainHand || !offHand) { return true; } - if (mainHand.handType == HandType.HandTypeTwoHand && !canDW2h) { - return false; - } else if ( - mainHand.handType == HandType.HandTypeTwoHand && - (mainHand.weaponType == WeaponType.WeaponTypePolearm || mainHand.weaponType == WeaponType.WeaponTypeStaff) - ) { - return false; - } - - if (offHand.handType == HandType.HandTypeTwoHand && !canDW2h) { - return false; - } else if ( - offHand.handType == HandType.HandTypeTwoHand && - (offHand.weaponType == WeaponType.WeaponTypePolearm || offHand.weaponType == WeaponType.WeaponTypeStaff) - ) { + if (mainHand.handType === HandType.HandTypeTwoHand) { return false; } diff --git a/ui/elemental_shaman/apls/default.apl.json b/ui/elemental_shaman/apls/default.apl.json new file mode 100644 index 0000000000..43ac4043a2 --- /dev/null +++ b/ui/elemental_shaman/apls/default.apl.json @@ -0,0 +1,9 @@ +{ + "type": "TypeAPL", + "priorityList": [ + {"action":{"autocastOtherCooldowns":{}}}, + {"action":{"condition":{"cmp":{"op":"OpGe","lhs":{"numberTargets":{}},"rhs":{"const":{"val":"2"}}}},"castSpell":{"spellId":{"spellId":10605,"rank":4}}}}, + {"action":{"condition":{"cmp":{"op":"OpGe","lhs":{"currentManaPercent":{}},"rhs":{"const":{"val":"30%"}}}},"castSpell":{"spellId":{"spellId":15208,"rank":10}}}}, + {"action":{"castSpell":{"spellId":{"spellId":915,"rank":4}}}} + ] +} diff --git a/ui/elemental_shaman/apls/phase_1.apl.json b/ui/elemental_shaman/apls/phase_1.apl.json deleted file mode 100644 index 046801244d..0000000000 --- a/ui/elemental_shaman/apls/phase_1.apl.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "type": "TypeAPL", - "prepullActions": [ - {"action":{"castSpell":{"spellId":{"spellId":5394,"rank":1}}},"doAtValue":{"const":{"val":"-7.55s"}}}, - {"action":{"castSpell":{"spellId":{"spellId":8160,"rank":2}}},"doAtValue":{"const":{"val":"-6.05s"}}}, - {"action":{"castSpell":{"spellId":{"spellId":6363,"rank":2}}},"doAtValue":{"const":{"val":"-4.55s"}}}, - {"action":{"castSpell":{"spellId":{"spellId":915,"rank":4}}},"doAtValue":{"const":{"val":"-3.05s"}}} - ], - "priorityList": [ - {"action":{"condition":{"cmp":{"op":"OpLe","lhs":{"currentManaPercent":{}},"rhs":{"const":{"val":"75%"}}}},"castSpell":{"spellId":{"spellId":425336}}}}, - {"action":{"condition":{"cmp":{"op":"OpLe","lhs":{"dotRemainingTime":{"spellId":{"spellId":8052,"rank":2}}},"rhs":{"const":{"val":"2"}}}},"castSpell":{"spellId":{"spellId":8052,"rank":2}}}}, - {"action":{"castSpell":{"spellId":{"spellId":408490}}}}, - {"action":{"condition":{"not":{"val":{"dotIsActive":{"spellId":{"spellId":6363,"rank":2}}}}},"castSpell":{"spellId":{"spellId":6363,"rank":2}}}}, - {"action":{"condition":{"cmp":{"op":"OpGt","lhs":{"dotRemainingTime":{"spellId":{"spellId":8052,"rank":2}}},"rhs":{"spellCastTime":{"spellId":{"spellId":915,"rank":4}}}}},"castSpell":{"spellId":{"spellId":915,"rank":4}}}} - ] -} diff --git a/ui/elemental_shaman/apls/phase_2.apl.json b/ui/elemental_shaman/apls/phase_2.apl.json deleted file mode 100644 index 821211215a..0000000000 --- a/ui/elemental_shaman/apls/phase_2.apl.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "TypeAPL", - "prepullActions": [ - {"action":{"castSpell":{"spellId":{"spellId":10495,"rank":2}}},"doAtValue":{"const":{"val":"-6.5s"}}}, - {"action":{"castSpell":{"spellId":{"spellId":8161,"rank":3}}},"doAtValue":{"const":{"val":"-5s"}}}, - {"action":{"castSpell":{"spellId":{"spellId":6365,"rank":4}}},"doAtValue":{"const":{"val":"-3.5s"}}}, - {"action":{"castSpell":{"spellId":{"spellId":10391,"rank":7}}},"doAtValue":{"const":{"val":"-2s"}}} - ], - "priorityList": [ - {"action":{"castSpell":{"spellId":{"spellId":437362}}}}, - {"action":{"condition":{"not":{"val":{"auraIsActive":{"auraId":{"spellId":437362}}}}},"autocastOtherCooldowns":{}}}, - {"action":{"condition":{"not":{"val":{"dotIsActive":{"spellId":{"spellId":10447,"rank":4}}}}},"castSpell":{"spellId":{"spellId":10447,"rank":4}}}}, - {"action":{"condition":{"cmp":{"op":"OpGe","lhs":{"dotRemainingTime":{"spellId":{"spellId":10447,"rank":4}}},"rhs":{"spellCastTime":{"spellId":{"spellId":408490}}}}},"castSpell":{"spellId":{"spellId":408490}}}}, - {"action":{"condition":{"cmp":{"op":"OpLe","lhs":{"currentManaPercent":{}},"rhs":{"const":{"val":"85%"}}}},"castSpell":{"spellId":{"spellId":425336}}}}, - {"action":{"condition":{"and":{"vals":[{"dotIsActive":{"spellId":{"spellId":10447,"rank":4}}},{"not":{"val":{"spellIsReady":{"spellId":{"spellId":408490}}}}}]}},"castSpell":{"spellId":{"spellId":16166}}}}, - {"action":{"castSpell":{"spellId":{"spellId":930,"rank":2}}}}, - {"action":{"condition":{"not":{"val":{"dotIsActive":{"spellId":{"spellId":6365,"rank":4}}}}},"castSpell":{"spellId":{"spellId":6365,"rank":4}}}}, - {"action":{"castSpell":{"spellId":{"spellId":10391,"rank":7}}}} - ] -} diff --git a/ui/elemental_shaman/apls/phase_3.apl.json b/ui/elemental_shaman/apls/phase_3.apl.json deleted file mode 100644 index 1362f276c1..0000000000 --- a/ui/elemental_shaman/apls/phase_3.apl.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "type": "TypeAPL", - "prepullActions": [ - {"action":{"castSpell":{"spellId":{"spellId":20572}}},"doAtValue":{"const":{"val":"-11.5s"}}}, - {"action":{"castSpell":{"spellId":{"spellId":10431,"rank":6}}},"doAtValue":{"const":{"val":"-10s"}}}, - {"action":{"activateAuraWithStacks":{"auraId":{"spellId":10431,"rank":6},"numStacks":"9"}},"doAtValue":{"const":{"val":"-10s"}}}, - {"action":{"castSpell":{"spellId":{"spellId":10496,"rank":3}}},"doAtValue":{"const":{"val":"-6.5s"}}}, - {"action":{"castSpell":{"spellId":{"spellId":8161,"rank":3}}},"doAtValue":{"const":{"val":"-5s"}}}, - {"action":{"castSpell":{"spellId":{"spellId":10437,"rank":5}}},"doAtValue":{"const":{"val":"-3.5s"}}}, - {"action":{"castSpell":{"spellId":{"spellId":15207,"rank":9}}},"doAtValue":{"const":{"val":"-2s"}}} - ], - "priorityList": [ - {"action":{"castSpell":{"spellId":{"spellId":437362}}}}, - {"action":{"condition":{"not":{"val":{"auraIsActive":{"auraId":{"spellId":437362}}}}},"autocastOtherCooldowns":{}}}, - {"action":{"condition":{"cmp":{"op":"OpLe","lhs":{"currentManaPercent":{}},"rhs":{"const":{"val":"85%"}}}},"castSpell":{"spellId":{"spellId":425336}}}}, - {"action":{"condition":{"not":{"val":{"dotIsActive":{"spellId":{"spellId":10447,"rank":4}}}}},"castSpell":{"spellId":{"spellId":10447,"rank":4}}}}, - {"action":{"condition":{"cmp":{"op":"OpGe","lhs":{"numberTargets":{}},"rhs":{"const":{"val":"2"}}}},"castSpell":{"spellId":{"spellId":2860,"rank":3}}}}, - {"action":{"condition":{"cmp":{"op":"OpGe","lhs":{"auraNumStacks":{"auraId":{"spellId":10431,"rank":6}}},"rhs":{"const":{"val":"8"}}}},"castSpell":{"spellId":{"spellId":10413,"rank":6}}}}, - {"action":{"condition":{"cmp":{"op":"OpGe","lhs":{"numberTargets":{}},"rhs":{"const":{"val":"5"}}}},"castSpell":{"spellId":{"spellId":408427}}}}, - {"action":{"condition":{"cmp":{"op":"OpGe","lhs":{"dotRemainingTime":{"spellId":{"spellId":10447,"rank":4}}},"rhs":{"spellCastTime":{"spellId":{"spellId":408490}}}}},"castSpell":{"spellId":{"spellId":408490}}}}, - {"action":{"condition":{"and":{"vals":[{"dotIsActive":{"spellId":{"spellId":10447,"rank":4}}},{"not":{"val":{"spellIsReady":{"spellId":{"spellId":408490}}}}}]}},"castSpell":{"spellId":{"spellId":16166}}}}, - {"action":{"condition":{"cmp":{"op":"OpGe","lhs":{"numberTargets":{}},"rhs":{"const":{"val":"3"}}}},"castSpell":{"spellId":{"spellId":408427}}}}, - {"action":{"condition":{"and":{"vals":[{"not":{"val":{"dotIsActive":{"spellId":{"spellId":10586,"rank":3}}}}},{"cmp":{"op":"OpGe","lhs":{"remainingTime":{}},"rhs":{"const":{"val":"10s"}}}},{"cmp":{"op":"OpGe","lhs":{"numberTargets":{}},"rhs":{"const":{"val":"3"}}}}]}},"castSpell":{"spellId":{"spellId":10586,"rank":3}}}}, - {"action":{"condition":{"and":{"vals":[{"not":{"val":{"dotIsActive":{"spellId":{"spellId":10437,"rank":5}}}}},{"cmp":{"op":"OpGe","lhs":{"remainingTime":{}},"rhs":{"const":{"val":"30s"}}}},{"cmp":{"op":"OpLe","lhs":{"numberTargets":{}},"rhs":{"const":{"val":"2"}}}}]}},"castSpell":{"spellId":{"spellId":10437,"rank":5}}}}, - {"action":{"castSpell":{"spellId":{"spellId":15207,"rank":9}}}}, - {"hide":true,"action":{"castSpell":{"spellId":{"spellId":20572}}}} - ] -} diff --git a/ui/elemental_shaman/apls/phase_4.apl.json b/ui/elemental_shaman/apls/phase_4.apl.json deleted file mode 100644 index 41937a96a3..0000000000 --- a/ui/elemental_shaman/apls/phase_4.apl.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "type": "TypeAPL", - "prepullActions": [ - {"action":{"castSpell":{"spellId":{"spellId":20572}}},"doAtValue":{"const":{"val":"-11.5s"}}}, - {"action":{"castSpell":{"spellId":{"spellId":10432,"rank":7}}},"doAtValue":{"const":{"val":"-10s"}}}, - {"action":{"activateAuraWithStacks":{"auraId":{"spellId":10432,"rank":7},"numStacks":"9"}},"doAtValue":{"const":{"val":"-10s"}}}, - {"action":{"castSpell":{"spellId":{"spellId":25359,"rank":3}}},"doAtValue":{"const":{"val":"-8s"}}}, - {"action":{"castSpell":{"spellId":{"spellId":25361,"rank":5}}},"doAtValue":{"const":{"val":"-6.5s"}}}, - {"action":{"castSpell":{"spellId":{"spellId":10497,"rank":4}}},"doAtValue":{"const":{"val":"-5s"}}}, - {"action":{"castSpell":{"spellId":{"spellId":10438,"rank":6}}},"doAtValue":{"const":{"val":"-3.5s"}}}, - {"action":{"castSpell":{"spellId":{"spellId":15208,"rank":10}}},"doAtValue":{"const":{"val":"-2s"}}} - ], - "priorityList": [ - {"action":{"castSpell":{"spellId":{"spellId":440580}}}}, - {"action":{"autocastOtherCooldowns":{}}}, - {"action":{"condition":{"cmp":{"op":"OpLe","lhs":{"currentManaPercent":{}},"rhs":{"const":{"val":"65%"}}}},"castSpell":{"spellId":{"spellId":425336}}}}, - {"action":{"condition":{"not":{"val":{"dotIsActive":{"spellId":{"spellId":29228,"rank":6}}}}},"castSpell":{"spellId":{"spellId":29228,"rank":6}}}}, - {"action":{"condition":{"cmp":{"op":"OpGe","lhs":{"numberTargets":{}},"rhs":{"const":{"val":"2"}}}},"castSpell":{"spellId":{"spellId":10605,"rank":4}}}}, - {"action":{"condition":{"cmp":{"op":"OpGe","lhs":{"dotRemainingTime":{"spellId":{"spellId":29228,"rank":6}}},"rhs":{"spellCastTime":{"spellId":{"spellId":408490}}}}},"castSpell":{"spellId":{"spellId":408490}}}}, - {"action":{"condition":{"cmp":{"op":"OpGe","lhs":{"auraNumStacks":{"auraId":{"spellId":10432,"rank":7}}},"rhs":{"const":{"val":"8"}}}},"castSpell":{"spellId":{"spellId":10414,"rank":7}}}}, - {"action":{"condition":{"cmp":{"op":"OpGe","lhs":{"numberTargets":{}},"rhs":{"const":{"val":"5"}}}},"castSpell":{"spellId":{"spellId":408427}}}}, - {"action":{"condition":{"and":{"vals":[{"dotIsActive":{"spellId":{"spellId":29228,"rank":6}}},{"not":{"val":{"spellIsReady":{"spellId":{"spellId":408490}}}}}]}},"castSpell":{"spellId":{"spellId":16166}}}}, - {"action":{"condition":{"cmp":{"op":"OpGe","lhs":{"numberTargets":{}},"rhs":{"const":{"val":"3"}}}},"castSpell":{"spellId":{"spellId":408427}}}}, - {"action":{"condition":{"and":{"vals":[{"not":{"val":{"dotIsActive":{"spellId":{"spellId":10587,"rank":4}}}}},{"cmp":{"op":"OpGe","lhs":{"remainingTime":{}},"rhs":{"const":{"val":"10s"}}}},{"cmp":{"op":"OpGe","lhs":{"numberTargets":{}},"rhs":{"const":{"val":"3"}}}}]}},"castSpell":{"spellId":{"spellId":10587,"rank":4}}}}, - {"action":{"condition":{"and":{"vals":[{"not":{"val":{"dotIsActive":{"spellId":{"spellId":10438,"rank":6}}}}},{"cmp":{"op":"OpGe","lhs":{"remainingTime":{}},"rhs":{"const":{"val":"30s"}}}},{"cmp":{"op":"OpLe","lhs":{"numberTargets":{}},"rhs":{"const":{"val":"2"}}}}]}},"castSpell":{"spellId":{"spellId":10438,"rank":6}}}}, - {"action":{"castSpell":{"spellId":{"spellId":15208,"rank":10}}}}, - {"hide":true,"action":{"castSpell":{"spellId":{"spellId":20572}}}} - ] -} diff --git a/ui/elemental_shaman/apls/phase_5.apl.json b/ui/elemental_shaman/apls/phase_5.apl.json deleted file mode 100644 index 2268973c71..0000000000 --- a/ui/elemental_shaman/apls/phase_5.apl.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "type": "TypeAPL", - "prepullActions": [ - {"action":{"castSpell":{"spellId":{"spellId":10432,"rank":7}}},"doAtValue":{"const":{"val":"-10s"}}}, - {"action":{"activateAuraWithStacks":{"auraId":{"spellId":10432,"rank":7},"numStacks":"9"}},"doAtValue":{"const":{"val":"-10s"}}}, - {"action":{"castSpell":{"spellId":{"spellId":25359,"rank":3}}},"doAtValue":{"const":{"val":"-8s"}}}, - {"action":{"castSpell":{"spellId":{"spellId":25361,"rank":5}}},"doAtValue":{"const":{"val":"-6.5s"}}}, - {"action":{"castSpell":{"spellId":{"spellId":10497,"rank":4}}},"doAtValue":{"const":{"val":"-5s"}}}, - {"action":{"castSpell":{"spellId":{"spellId":10438,"rank":6}}},"doAtValue":{"const":{"val":"-3.5s"}}}, - {"action":{"castSpell":{"spellId":{"spellId":15208,"rank":10}}},"doAtValue":{"const":{"val":"-2s"}}} - ], - "priorityList": [ - {"action":{"castSpell":{"spellId":{"spellId":440580}}}}, - {"action":{"autocastOtherCooldowns":{}}}, - {"action":{"condition":{"cmp":{"op":"OpGe","lhs":{"auraNumStacks":{"auraId":{"spellId":10432,"rank":7}}},"rhs":{"const":{"val":"8"}}}},"castSpell":{"spellId":{"itemId":231281}}}}, - {"action":{"condition":{"and":{"vals":[{"auraIsKnown":{"auraId":{"itemId":231281}}},{"auraIsActive":{"auraId":{"itemId":231281}}},{"cmp":{"op":"OpLe","lhs":{"auraRemainingTime":{"auraId":{"itemId":231281}}},"rhs":{"const":{"val":"2s"}}}}]}},"castSpell":{"spellId":{"spellId":10414,"rank":7}}}}, - {"action":{"condition":{"cmp":{"op":"OpLe","lhs":{"currentManaPercent":{}},"rhs":{"const":{"val":"65%"}}}},"castSpell":{"spellId":{"spellId":425336}}}}, - {"action":{"condition":{"and":{"vals":[{"not":{"val":{"dotIsActive":{"spellId":{"spellId":29228,"rank":6}}}}},{"or":{"vals":[{"not":{"val":{"auraIsKnown":{"auraId":{"itemId":231281}}}}},{"not":{"val":{"auraIsActive":{"auraId":{"itemId":231281}}}}},{"cmp":{"op":"OpGt","lhs":{"numberTargets":{}},"rhs":{"const":{"val":"2"}}}}]}}]}},"castSpell":{"spellId":{"spellId":29228,"rank":6}}}}, - {"action":{"condition":{"and":{"vals":[{"cmp":{"op":"OpGe","lhs":{"dotRemainingTime":{"spellId":{"spellId":29228,"rank":6}}},"rhs":{"spellCastTime":{"spellId":{"spellId":408490}}}}},{"or":{"vals":[{"not":{"val":{"auraIsKnown":{"auraId":{"itemId":231281}}}}},{"not":{"val":{"auraIsActive":{"auraId":{"itemId":231281}}}}},{"cmp":{"op":"OpGt","lhs":{"numberTargets":{}},"rhs":{"const":{"val":"2"}}}}]}}]}},"castSpell":{"spellId":{"spellId":408490}}}}, - {"action":{"condition":{"cmp":{"op":"OpGe","lhs":{"auraNumStacks":{"auraId":{"spellId":10432,"rank":7}}},"rhs":{"const":{"val":"8"}}}},"castSpell":{"spellId":{"spellId":10414,"rank":7}}}}, - {"action":{"condition":{"cmp":{"op":"OpGe","lhs":{"numberTargets":{}},"rhs":{"const":{"val":"5"}}}},"castSpell":{"spellId":{"spellId":408427}}}}, - {"action":{"condition":{"and":{"vals":[{"dotIsActive":{"spellId":{"spellId":29228,"rank":6}}},{"not":{"val":{"spellIsReady":{"spellId":{"spellId":408490}}}}}]}},"castSpell":{"spellId":{"spellId":16166}}}}, - {"action":{"condition":{"cmp":{"op":"OpGe","lhs":{"numberTargets":{}},"rhs":{"const":{"val":"3"}}}},"castSpell":{"spellId":{"spellId":408427}}}}, - {"action":{"condition":{"and":{"vals":[{"not":{"val":{"dotIsActive":{"spellId":{"spellId":10587,"rank":4}}}}},{"cmp":{"op":"OpGe","lhs":{"remainingTime":{}},"rhs":{"const":{"val":"10s"}}}},{"cmp":{"op":"OpGe","lhs":{"numberTargets":{}},"rhs":{"const":{"val":"3"}}}}]}},"castSpell":{"spellId":{"spellId":10587,"rank":4}}}}, - {"action":{"condition":{"and":{"vals":[{"not":{"val":{"dotIsActive":{"spellId":{"spellId":10438,"rank":6}}}}},{"cmp":{"op":"OpGe","lhs":{"remainingTime":{}},"rhs":{"const":{"val":"30s"}}}},{"cmp":{"op":"OpLe","lhs":{"numberTargets":{}},"rhs":{"const":{"val":"2"}}}}]}},"castSpell":{"spellId":{"spellId":10438,"rank":6}}}}, - {"action":{"castSpell":{"spellId":{"spellId":15208,"rank":10}}}}, - {"action":{"condition":{"const":{"val":"false"}},"castSpell":{"spellId":{"spellId":20572}}}} - ] -} diff --git a/ui/elemental_shaman/gear_sets/blank.gear.json b/ui/elemental_shaman/gear_sets/blank.gear.json deleted file mode 100644 index 4bcab0861e..0000000000 --- a/ui/elemental_shaman/gear_sets/blank.gear.json +++ /dev/null @@ -1 +0,0 @@ -{"items": []} \ No newline at end of file diff --git a/ui/elemental_shaman/gear_sets/phase_1.gear.json b/ui/elemental_shaman/gear_sets/phase_1.gear.json new file mode 100644 index 0000000000..4d913b7755 --- /dev/null +++ b/ui/elemental_shaman/gear_sets/phase_1.gear.json @@ -0,0 +1,21 @@ +{ + "items": [ + {"id":22267,"enchant":1509}, + {"id":18814}, + {"id":18829}, + {"id":17078,"enchant":256}, + {"id":19145,"enchant":1891}, + {"id":11765,"randomSuffix":2003,"enchant":1883}, + {"id":13253}, + {"id":19136}, + {"id":19165,"enchant":1509}, + {"id":11822,"enchant":911}, + {"id":19147}, + {"id":19147}, + {"id":18820}, + {"id":12930}, + {"id":17105,"enchant":2504}, + {"id":22329}, + {"id":23199} + ] +} diff --git a/ui/elemental_shaman/gear_sets/phase_2.gear.json b/ui/elemental_shaman/gear_sets/phase_2.gear.json new file mode 100644 index 0000000000..d5fa042bb6 --- /dev/null +++ b/ui/elemental_shaman/gear_sets/phase_2.gear.json @@ -0,0 +1,21 @@ +{ + "items": [ + {"id":22267,"enchant":2544}, + {"id":18814}, + {"id":18829}, + {"id":20697,"enchant":256}, + {"id":19145,"enchant":1891}, + {"id":19595,"enchant":1883}, + {"id":13253}, + {"id":19136}, + {"id":19165,"enchant":2544}, + {"id":19131,"enchant":911}, + {"id":19147}, + {"id":19147}, + {"id":18820}, + {"id":12930}, + {"id":17070,"enchant":2504}, + {"id":22329}, + {"id":23199} + ] +} diff --git a/ui/elemental_shaman/gear_sets/phase_3.gear.json b/ui/elemental_shaman/gear_sets/phase_3.gear.json new file mode 100644 index 0000000000..09c24f74d0 --- /dev/null +++ b/ui/elemental_shaman/gear_sets/phase_3.gear.json @@ -0,0 +1,21 @@ +{ + "items": [ + {"id":19375,"enchant":2544}, + {"id":18814}, + {"id":18829}, + {"id":19378,"enchant":256}, + {"id":19145,"enchant":1891}, + {"id":19374,"enchant":1883}, + {"id":13253}, + {"id":19400}, + {"id":16946,"enchant":2544}, + {"id":19131,"enchant":911}, + {"id":19403}, + {"id":19147}, + {"id":19344}, + {"id":19379}, + {"id":19360,"enchant":2504}, + {"id":22329}, + {"id":23199} + ] +} diff --git a/ui/elemental_shaman/gear_sets/phase_4.gear.json b/ui/elemental_shaman/gear_sets/phase_4.gear.json new file mode 100644 index 0000000000..eedca5ba23 --- /dev/null +++ b/ui/elemental_shaman/gear_sets/phase_4.gear.json @@ -0,0 +1,21 @@ +{ + "items": [ + {"id":19375,"enchant":2587}, + {"id":18814}, + {"id":18829,"enchant":2605}, + {"id":19857,"enchant":256}, + {"id":19682,"enchant":1891}, + {"id":19374,"enchant":1883}, + {"id":19929}, + {"id":19400}, + {"id":19683,"enchant":2587}, + {"id":19684,"enchant":911}, + {"id":19403}, + {"id":19147}, + {"id":19344}, + {"id":19379}, + {"id":19360,"enchant":2504}, + {"id":19891}, + {"id":23199} + ] +} diff --git a/ui/elemental_shaman/gear_sets/phase_5.gear.json b/ui/elemental_shaman/gear_sets/phase_5.gear.json new file mode 100644 index 0000000000..79dfe195cd --- /dev/null +++ b/ui/elemental_shaman/gear_sets/phase_5.gear.json @@ -0,0 +1,21 @@ +{ + "items": [ + {"id":19375,"enchant":2587}, + {"id":21608}, + {"id":18829,"enchant":2605}, + {"id":22731,"enchant":256}, + {"id":21838,"enchant":1891}, + {"id":21186,"enchant":1883}, + {"id":21585}, + {"id":22730}, + {"id":21461,"enchant":2587}, + {"id":21600,"enchant":911}, + {"id":21709}, + {"id":19403}, + {"id":19344}, + {"id":19379}, + {"id":19360,"enchant":2504}, + {"id":21597}, + {"id":23199} + ] +} diff --git a/ui/elemental_shaman/gear_sets/phase_6.gear.json b/ui/elemental_shaman/gear_sets/phase_6.gear.json new file mode 100644 index 0000000000..7de7d77a43 --- /dev/null +++ b/ui/elemental_shaman/gear_sets/phase_6.gear.json @@ -0,0 +1,21 @@ +{ + "items": [ + {"id":19375,"enchant":2587}, + {"id":21608}, + {"id":23664,"enchant":2721}, + {"id":23050,"enchant":256}, + {"id":21838,"enchant":1891}, + {"id":21186,"enchant":1883}, + {"id":21585}, + {"id":22730}, + {"id":23070,"enchant":2587}, + {"id":21600,"enchant":911}, + {"id":21709}, + {"id":23031}, + {"id":19344}, + {"id":23207}, + {"id":22988,"enchant":2504}, + {"id":23049}, + {"id":23199} + ] +} diff --git a/ui/elemental_shaman/index.ts b/ui/elemental_shaman/index.ts index 86535f75c2..2167e3b983 100644 --- a/ui/elemental_shaman/index.ts +++ b/ui/elemental_shaman/index.ts @@ -1,11 +1,10 @@ +import { Player } from '../core/player.js'; import { Spec } from '../core/proto/common.js'; import { Sim } from '../core/sim.js'; -import { Player } from '../core/player.js'; import { TypedEvent } from '../core/typed_event.js'; - import { ElementalShamanSimUI } from './sim.js'; const sim = new Sim(); const player = new Player(Spec.SpecElementalShaman, sim); sim.raid.setPlayer(TypedEvent.nextEventID(), 0, player); -const simUI = new ElementalShamanSimUI(document.body, player); +new ElementalShamanSimUI(document.body, player); diff --git a/ui/elemental_shaman/presets.ts b/ui/elemental_shaman/presets.ts index 51d9f9a1eb..d32e740632 100644 --- a/ui/elemental_shaman/presets.ts +++ b/ui/elemental_shaman/presets.ts @@ -2,6 +2,7 @@ import { Phase } from '../core/constants/other.js'; import * as PresetUtils from '../core/preset_utils.js'; import { AttackPowerBuff, + Conjured, Consumes, Debuffs, FirePowerBuff, @@ -21,12 +22,13 @@ import { } from '../core/proto/common.js'; import { ElementalShaman_Options as ElementalShamanOptions } from '../core/proto/shaman.js'; import { SavedTalents } from '../core/proto/ui.js'; -import Phase1APL from './apls/phase_1.apl.json'; -import Phase2APL from './apls/phase_2.apl.json'; -import Phase3APL from './apls/phase_3.apl.json'; -import Phase4APL from './apls/phase_4.apl.json'; -import Phase5APL from './apls/phase_5.apl.json'; -import BlankGear from './gear_sets/blank.gear.json'; +import DefaultAPLJson from './apls/default.apl.json'; +import Phase1GearJSON from './gear_sets/phase_1.gear.json'; +import Phase2GearJSON from './gear_sets/phase_2.gear.json'; +import Phase3GearJSON from './gear_sets/phase_3.gear.json'; +import Phase4GearJSON from './gear_sets/phase_4.gear.json'; +import Phase5GearJSON from './gear_sets/phase_5.gear.json'; +import Phase6GearJSON from './gear_sets/phase_6.gear.json'; // Preset options for this spec. // Eventually we will import these values for the raid sim too, so its good to @@ -36,50 +38,59 @@ import BlankGear from './gear_sets/blank.gear.json'; // Gear Presets /////////////////////////////////////////////////////////////////////////// -export const GearBlank = PresetUtils.makePresetGear('Blank', BlankGear); +export const GearPhase1 = PresetUtils.makePresetGear('Phase 1', Phase1GearJSON); +export const GearPhase2 = PresetUtils.makePresetGear('Phase 2', Phase2GearJSON); +export const GearPhase3 = PresetUtils.makePresetGear('Phase 3', Phase3GearJSON); +export const GearPhase4 = PresetUtils.makePresetGear('Phase 4', Phase4GearJSON); +export const GearPhase5 = PresetUtils.makePresetGear('Phase 5', Phase5GearJSON); +export const GearPhase6 = PresetUtils.makePresetGear('Phase 6', Phase6GearJSON); + +export const GearPresets = { + [Phase.Phase1]: [GearPhase1], + [Phase.Phase2]: [GearPhase2], + [Phase.Phase3]: [GearPhase3], + [Phase.Phase4]: [GearPhase4], + [Phase.Phase5]: [GearPhase5], + [Phase.Phase6]: [GearPhase6], -export const GearPresets = {}; +}; -export const DefaultGear = GearBlank; +export const DefaultGear = GearPresets[Phase.Phase2][0]; /////////////////////////////////////////////////////////////////////////// // APL Presets /////////////////////////////////////////////////////////////////////////// -export const APLPhase1 = PresetUtils.makePresetAPLRotation('Phase 1', Phase1APL); -export const APLPhase2 = PresetUtils.makePresetAPLRotation('Phase 2', Phase2APL); -export const APLPhase3 = PresetUtils.makePresetAPLRotation('Phase 3', Phase3APL); -export const APLPhase4 = PresetUtils.makePresetAPLRotation('Phase 4', Phase4APL); -export const APLPhase5 = PresetUtils.makePresetAPLRotation('Phase 5', Phase5APL); +export const APLDefault = PresetUtils.makePresetAPLRotation('Default', DefaultAPLJson); export const APLPresets = { - [Phase.Phase1]: [APLPhase1], - [Phase.Phase2]: [APLPhase2], - [Phase.Phase3]: [APLPhase3], - [Phase.Phase4]: [APLPhase4], - [Phase.Phase5]: [APLPhase5], + [Phase.Phase1]: [APLDefault], + [Phase.Phase2]: [], + [Phase.Phase3]: [], + [Phase.Phase4]: [], + [Phase.Phase5]: [], + [Phase.Phase6]: [], + }; -export const DefaultAPL = APLPresets[Phase.Phase5][0]; +export const DefaultAPL = APLPresets[Phase.Phase1][0]; /////////////////////////////////////////////////////////////////////////// // Talent Presets /////////////////////////////////////////////////////////////////////////// -export const TalentsPhase1 = PresetUtils.makePresetTalents('Level 25', SavedTalents.create({ talentsString: '25003105' })); -export const TalentsPhase2 = PresetUtils.makePresetTalents('Level 40', SavedTalents.create({ talentsString: '550031550000151' })); -export const TalentsPhase3 = PresetUtils.makePresetTalents('Level 50', SavedTalents.create({ talentsString: '550031550000151-500203' })); -export const TalentsPhase4 = PresetUtils.makePresetTalents('Level 60', SavedTalents.create({ talentsString: '550301550000151--50205300005' })); +export const TalentsLevel60 = PresetUtils.makePresetTalents('Level 60', SavedTalents.create({ talentsString: '550331050002151--50105301005' })); export const TalentPresets = { - [Phase.Phase1]: [TalentsPhase1], - [Phase.Phase2]: [TalentsPhase2], - [Phase.Phase3]: [TalentsPhase3], - [Phase.Phase4]: [TalentsPhase4], + [Phase.Phase1]: [TalentsLevel60], + [Phase.Phase2]: [], + [Phase.Phase3]: [], + [Phase.Phase4]: [], [Phase.Phase5]: [], + [Phase.Phase6]: [], }; -export const DefaultTalents = TalentPresets[Phase.Phase4][0]; +export const DefaultTalents = TalentPresets[Phase.Phase1][0]; /////////////////////////////////////////////////////////////////////////// // Options @@ -89,13 +100,13 @@ export const DefaultOptions = ElementalShamanOptions.create({}); export const DefaultConsumes = Consumes.create({ attackPowerBuff: AttackPowerBuff.JujuMight, + defaultConjured: Conjured.ConjuredDemonicRune, defaultPotion: Potions.MajorManaPotion, firePowerBuff: FirePowerBuff.ElixirOfGreaterFirepower, flask: Flask.FlaskOfSupremePower, food: Food.FoodRunnTumTuberSurprise, - mainHandImbue: WeaponImbue.FlametongueWeapon, + mainHandImbue: WeaponImbue.LesserWizardOil, manaRegenElixir: ManaRegenElixir.MagebloodPotion, - //offHandImbue: WeaponImbue.MagnificentTrollshine, spellPowerBuff: SpellPowerBuff.GreaterArcaneElixir, strengthBuff: StrengthBuff.JujuPower, zanzaBuff: ZanzaBuff.CerebralCortexCompound, diff --git a/ui/elemental_shaman/sim.ts b/ui/elemental_shaman/sim.ts index e1d43060d0..49803b148b 100644 --- a/ui/elemental_shaman/sim.ts +++ b/ui/elemental_shaman/sim.ts @@ -109,6 +109,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecElementalShaman, { presets: { // Preset talents that the user can quickly select. talents: [ + ...Presets.TalentPresets[Phase.Phase6], ...Presets.TalentPresets[Phase.Phase5], ...Presets.TalentPresets[Phase.Phase4], ...Presets.TalentPresets[Phase.Phase3], @@ -117,6 +118,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecElementalShaman, { ], // Preset rotations that the user can quickly select. rotations: [ + ...Presets.APLPresets[Phase.Phase6], ...Presets.APLPresets[Phase.Phase5], ...Presets.APLPresets[Phase.Phase4], ...Presets.APLPresets[Phase.Phase3], @@ -125,11 +127,16 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecElementalShaman, { ], // Preset gear configurations that the user can quickly select. gear: [ - Presets.DefaultGear, + ...Presets.GearPresets[Phase.Phase6], + ...Presets.GearPresets[Phase.Phase5], + ...Presets.GearPresets[Phase.Phase4], + ...Presets.GearPresets[Phase.Phase3], + ...Presets.GearPresets[Phase.Phase2], + ...Presets.GearPresets[Phase.Phase1], ], }, - autoRotation: player => { + autoRotation: () => { return Presets.DefaultAPL.rotation.rotation!; }, diff --git a/ui/index.html b/ui/index.html index 6e34ace359..b2d940aa08 100644 --- a/ui/index.html +++ b/ui/index.html @@ -180,13 +180,13 @@

Classic